Skip to content

Commit 7dec857

Browse files
committed
PIE-1057: Merge branch 'azure' to main
2 parents 4dfa8f0 + 60d03a3 commit 7dec857

File tree

2 files changed

+64
-100
lines changed

2 files changed

+64
-100
lines changed

sign-pkg-windows/action.yaml

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@ description:
33
Sign and package the Windows Linden viewer.
44

55
inputs:
6-
certificate:
7-
description: "path to certificate file"
8-
type: string
6+
vault_uri:
7+
description: "Azure key vault URI"
8+
required: true
9+
cert_name:
10+
description: "Name of certificate on Azure"
11+
required: true
12+
client_id:
13+
description: "Azure signer app clientId"
14+
required: true
15+
client_secret:
16+
description: "Azure signer app clientSecret"
17+
required: true
18+
tenant_id:
19+
description: "Azure signer app tenantId"
920
required: true
10-
services:
11-
description: "space-separated list of timestamp service URLs"
12-
type: string
13-
required: false
14-
default: "http://timestamp.globalsign.com/scripts/timstamp.dll http://timestamp.comodoca.com/authenticode"
1521

1622
runs:
1723
using: composite
@@ -24,7 +30,11 @@ runs:
2430

2531
- name: Install Python dependencies
2632
shell: bash
27-
run: pip install pyng autobuild
33+
run: pip install pyng
34+
35+
- name: Install AzureSignTool
36+
shell: bash
37+
run: dotnet tool install --global AzureSignTool
2838

2939
- name: Sign the executables
3040
shell: bash
@@ -34,8 +44,11 @@ runs:
3444
.app/llplugin/dullahan_host.exe
3545
do
3646
python "${{ github.action_path }}/sign.py" \
37-
--service ${{ inputs.services }} \
38-
--certificate "${{ inputs.certificate }}" \
47+
--vault_uri "${{ inputs.vault_uri }}" \
48+
--cert_name "${{ inputs.cert_name }}" \
49+
--client_id "${{ inputs.client_id }}" \
50+
--client_secret "${{ inputs.client_secret }}" \
51+
--tenant_id "${{ inputs.tenant_id }}" \
3952
"$exe"
4053
done
4154
@@ -80,8 +93,11 @@ runs:
8093
# pass installer to next step
8194
echo "installer=$installer" >> "$GITHUB_ENV"
8295
python "${{ github.action_path }}/sign.py" \
83-
--service ${{ inputs.services }} \
84-
--certificate "${{ inputs.certificate }}" \
96+
--vault_uri "${{ inputs.vault_uri }}" \
97+
--cert_name "${{ inputs.cert_name }}" \
98+
--client_id "${{ inputs.client_id }}" \
99+
--client_secret "${{ inputs.client_secret }}" \
100+
--tenant_id "${{ inputs.tenant_id }}" \
85101
"$installer"
86102
87103
- name: Post the installer

sign-pkg-windows/sign.py

Lines changed: 35 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
@file sign.py
44
@author Nat Goodspeed
55
@date 2023-09-14
6-
@brief Sign the designated executable using Windows signtool.
6+
@brief Sign the designated executable using Microsoft AzureSignTool.
77
88
$LicenseInfo:firstyear=2023&license=viewerlgpl$
99
Copyright (c) 2023, Linden Research, Inc.
@@ -20,7 +20,6 @@
2020
from datetime import datetime, timedelta
2121
from pathlib import Path
2222

23-
from autobuild.autobuild_tool_source_environment import SourceEnvError, _available_vsvers, load_vsvars
2423
from pyng.commands import Commands
2524

2625

@@ -38,94 +37,42 @@ class Error(Exception):
3837

3938
# Interactively, don't print our int return value
4039
@command.format(lambda ret: None)
41-
def sign(executable, *, service: Iterable, certificate,
42-
delay=5, retries=6, backoff=1.5, certwarning=14,
43-
description='Second Life Setup'):
40+
def sign(executable, *, vault_uri, cert_name, client_id, client_secret, tenant_id,
41+
certwarning=14):
4442
"""
45-
Sign the designated executable using Windows signtool.
43+
Sign the designated executable using Microsoft AzureSignTool.
4644
4745
Pass:
4846
49-
executable: path to executable to sign
50-
certificate: path to certificate file with authentication
51-
service: iterable of URLs to timestamp services
52-
delay: initial delay before signing attempt
53-
retries: number of times to attempt the signing operation
54-
backoff: scale factor by which to multiply delay for each retry
55-
certwarning: warn if certificate will expire in fewer than this many days
56-
description: pass to signtool
47+
executable: path to executable to sign
48+
vault_uri: Azure key vault URI
49+
cert_name: Name of certificate on Azure
50+
client_id: Azure signer app clientId
51+
client_secret: Azure signer app clientSecret
52+
tenant_id: Azure signer app tenantId
53+
certwarning: warn if certificate will expire in fewer than this many days
5754
"""
58-
# First, locate signtool.
59-
# Don't even pretend to support 32-bit any more.
60-
os.environ['AUTOBUILD_ADDRSIZE'] = '64'
61-
try:
62-
vsver = _available_vsvers()[-1]
63-
except SourceEnvError as err:
64-
raise Error(str(err)) from err
65-
except IndexError:
66-
raise Error("Can't determine latest Visual Studio version, is it installed?")
67-
68-
try:
69-
vsvars = load_vsvars(vsver)
70-
except SourceEnvError as err:
71-
raise Error(str(err)) from err
72-
73-
try:
74-
# load_vsvars() returns an ordinary Python dict, that is,
75-
# case-sensitive. Empirically the keys are all uppercase. We could go
76-
# through the exercise of loading this data into a case-insensitive
77-
# dict, but it's simpler to use an uppercase key.
78-
VerBinPath = vsvars['WINDOWSSDKVERBINPATH']
79-
except KeyError:
80-
from pprint import pprint
81-
pprint({key: value for key, value in vsvars.items() if 'Kits' in value})
82-
raise Error(f"WindowsSdkVerBinPath not set by VS version {vsver}")
83-
84-
signtool = Path(VerBinPath) / 'X64' / 'signtool.exe'
85-
assert signtool.is_file()
86-
8755
name = Path(executable).name
8856

89-
# If we bang on the timestamp server too hard by signing executables
90-
# back-to-back, we may get throttled.
91-
# "Error: SignerSign() failed. (-1073700864/0xc000a000)"
92-
# may be throttle-related, and it somehow fails the build despite the
93-
# backoff loop meant to deal with it. (???)
94-
# At any rate, a small fixed delay may keep us out of throttle trouble.
95-
done = None
96-
for retry in range(retries):
97-
if retry:
98-
print(f'{name} signing {retry} failed, ', end='')
99-
print(f'waiting {delay:.1f} seconds')
100-
time.sleep(delay)
101-
delay *= backoff
102-
# round-robin between listed services
103-
svc = service[retry % len(service)]
104-
command = [str(signtool), 'sign',
105-
'/f', certificate,
106-
'/t', svc,
107-
'/d', description,
108-
'/fd', 'sha256',
109-
'/v',
110-
executable]
111-
try:
112-
print(f'{name} attempt {retry+1}:', shlex.join(command))
113-
except TypeError:
114-
print(repr(command))
115-
raise
116-
done = subprocess.run(command,
117-
stdout=subprocess.PIPE,
118-
stderr=subprocess.STDOUT,
119-
text=True)
120-
print(done.stdout, end='')
121-
if done.returncode == 0:
122-
break
123-
else:
124-
raise Error(f'{name} signing failed after {retries} attempts, giving up')
125-
126-
# Here the last of the retries succeeded, setting 'done'
57+
command = ['AzureSignTool', 'sign',
58+
'-kvu', vault_uri,
59+
'-kvi', client_id,
60+
'-kvt', tenant_id,
61+
'-kvs', client_secret,
62+
'-kvc', cert_name,
63+
'-tr', 'http://timestamp.digicert.com',
64+
'-v', executable]
65+
print(name, 'signing:', shlex.join(command))
66+
done = subprocess.run(command,
67+
stdout=subprocess.PIPE,
68+
stderr=subprocess.STDOUT,
69+
text=True)
70+
print(done.stdout, end='')
12771
rc = done.returncode
128-
print('Signing succeeded')
72+
if rc != 0:
73+
raise Error(name + ' signing failed')
74+
75+
print(name, 'signing succeeded')
12976
# Check the certificate expiration date in the output to warn of imminent expiration
13077
for line in done.stdout.splitlines():
13178
found = ExpiresLine.search(line)
@@ -136,13 +83,14 @@ def sign(executable, *, service: Iterable, certificate,
13683
except ValueError:
13784
raise Error('failed to parse expiration from: ' + line)
13885
else:
86+
expires = expiration - datetime.now()
87+
print(f'Certificate expires in {expires.days} days')
88+
if expires < timedelta(certwarning):
89+
print(f'::warning::Certificate expires in {expires.days} days: {expiration}')
13990
break
14091
else:
141-
raise Error('Failed to find certificate expiration date')
142-
expires = expiration - datetime.now()
143-
print(f'Certificate expires in {expires.days} days')
144-
if expires < timedelta(certwarning):
145-
print(f'::warning::Certificate expires in {expires.days} days: {expiration}')
92+
## raise Error('Failed to find certificate expiration date')
93+
print('::warning::Failed to find certificate expiration date')
14694
return rc
14795

14896

0 commit comments

Comments
 (0)