Skip to content

Commit 69769f5

Browse files
committed
macOS release: sign payload
Add step two of the macOS release process to download the unsigned payload, use ESRP to sign it, and upload the signed payload as an artifact. Additionally, genericize the existing run_esrp_signing.py script to allow for signing of macOS payload/pkg and Windows exes in addition to Debian packages.
1 parent ab91f00 commit 69769f5

File tree

3 files changed

+130
-41
lines changed

3 files changed

+130
-41
lines changed

.github/run_esrp_signing.py

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import argparse
12
import json
23
import os
34
import glob
@@ -6,62 +7,60 @@
67
import sys
78
import re
89

10+
parser = argparse.ArgumentParser(description='Sign binaries for Windows, macOS, and Linux')
11+
parser.add_argument('path', help='Path to file for signing')
12+
parser.add_argument('keycode', help='Platform-specific key code for signing')
13+
parser.add_argument('opcode', help='Platform-specific operation code for signing')
14+
# Setting nargs=argparse.REMAINDER allows us to pass in params that begin with `--`
15+
parser.add_argument('--params', nargs=argparse.REMAINDER, help='Parameters for signing')
16+
args = parser.parse_args()
17+
918
esrp_tool = os.path.join("esrp", "tools", "EsrpClient.exe")
1019

1120
aad_id = os.environ['AZURE_AAD_ID'].strip()
21+
# We temporarily need two AAD IDs, as we're using an SSL certificate associated
22+
# with an older App Registration until we have the required hardware to approve
23+
# the new certificate in SSL Admin.
24+
aad_id_ssl = os.environ['AZURE_AAD_ID_SSL'].strip()
1225
workspace = os.environ['GITHUB_WORKSPACE'].strip()
1326

14-
source_root_location = os.path.join(workspace, "deb", "Release")
15-
destination_location = os.path.join(workspace)
16-
17-
files = glob.glob(os.path.join(source_root_location, "*.deb"))
27+
source_location = args.path
28+
files = glob.glob(os.path.join(source_location, "*"))
1829

1930
print("Found files:")
2031
pprint.pp(files)
2132

22-
if len(files) < 1 or not files[0].endswith(".deb"):
23-
print("Error: cannot find .deb to sign")
24-
exit(1)
25-
26-
file_to_sign = os.path.basename(files[0])
27-
2833
auth_json = {
29-
"Version": "1.0.0",
30-
"AuthenticationType": "AAD_CERT",
31-
"TenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
32-
"ClientId": aad_id,
33-
"AuthCert": {
34-
"SubjectName": f"CN={aad_id}.microsoft.com",
35-
"StoreLocation": "LocalMachine",
36-
"StoreName": "My",
37-
},
38-
"RequestSigningCert": {
39-
"SubjectName": f"CN={aad_id}",
40-
"StoreLocation": "LocalMachine",
41-
"StoreName": "My",
42-
}
34+
"Version": "1.0.0",
35+
"AuthenticationType": "AAD_CERT",
36+
"TenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
37+
"ClientId": f"{aad_id}",
38+
"AuthCert": {
39+
"SubjectName": f"CN={aad_id_ssl}.microsoft.com",
40+
"StoreLocation": "LocalMachine",
41+
"StoreName": "My"
42+
},
43+
"RequestSigningCert": {
44+
"SubjectName": f"CN={aad_id}",
45+
"StoreLocation": "LocalMachine",
46+
"StoreName": "My"
47+
}
4348
}
4449

4550
input_json = {
4651
"Version": "1.0.0",
4752
"SignBatches": [
4853
{
4954
"SourceLocationType": "UNC",
50-
"SourceRootDirectory": source_root_location,
55+
"SourceRootDirectory": source_location,
5156
"DestinationLocationType": "UNC",
52-
"DestinationRootDirectory": destination_location,
53-
"SignRequestFiles": [
54-
{
55-
"CustomerCorrelationId": "01A7F55F-6CDD-4123-B255-77E6F212CDAD",
56-
"SourceLocation": file_to_sign,
57-
"DestinationLocation": os.path.join("Signed", file_to_sign),
58-
}
59-
],
57+
"DestinationRootDirectory": workspace,
58+
"SignRequestFiles": [],
6059
"SigningInfo": {
6160
"Operations": [
6261
{
63-
"KeyCode": "CP-450779-Pgp",
64-
"OperationCode": "LinuxSign",
62+
"KeyCode": f"{args.keycode}",
63+
"OperationCode": f"{args.opcode}",
6564
"Parameters": {},
6665
"ToolName": "sign",
6766
"ToolVersion": "1.0",
@@ -72,10 +71,27 @@
7271
]
7372
}
7473

74+
# add files to sign
75+
for f in files:
76+
name = os.path.basename(f)
77+
input_json["SignBatches"][0]["SignRequestFiles"].append(
78+
{
79+
"SourceLocation": name,
80+
"DestinationLocation": os.path.join("signed", name),
81+
}
82+
)
83+
84+
# add parameters to input.json (e.g. enabling the hardened runtime for macOS)
85+
if args.params is not None:
86+
i = 0
87+
while i < len(args.params):
88+
input_json["SignBatches"][0]["SigningInfo"]["Operations"][0]["Parameters"][args.params[i]] = args.params[i + 1]
89+
i += 2
90+
7591
policy_json = {
7692
"Version": "1.0.0",
7793
"Intent": "production release",
78-
"ContentType": "Debian package",
94+
"ContentType": "binary",
7995
}
8096

8197
configs = [
@@ -106,7 +122,7 @@
106122
'***',
107123
result.stdout,
108124
flags=re.IGNORECASE|re.MULTILINE)
109-
printf(log)
125+
print(log)
110126

111127
if result.returncode != 0:
112128
print("Failed to run ESRPClient.exe")
@@ -117,6 +133,6 @@
117133
with open(esrp_out, 'r') as fp:
118134
pprint.pp(json.load(fp))
119135

120-
signed_file = os.path.join(destination_location, "Signed", file_to_sign)
121-
if os.path.isfile(signed_file):
122-
print(f"Success!\nSigned {signed_file}")
136+
for file in files:
137+
if os.path.isfile(os.path.join("signed", file)):
138+
print(f"Success!\nSigned {file}")

.github/set_up_esrp.ps1

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Install ESRP client
2+
az storage blob download --file esrp.zip --account-key "$env:AZURE_STORAGE_KEY" --account-name gcmesrp --container microsoft-esrp-client --name microsoft.esrpclient.1.2.76.nupkg
3+
Expand-Archive -Path esrp.zip -DestinationPath .\esrp
4+
5+
# Install certificates
6+
az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:AUTH_CERT" --file out.pfx
7+
certutil -f -importpfx out.pfx
8+
Remove-Item out.pfx
9+
10+
az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:REQUEST_SIGNING_CERT" --file out.pfx
11+
certutil -f -importpfx out.pfx
12+
Remove-Item out.pfx

.github/workflows/release.yml

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,65 @@ jobs:
6161
name: tmp.osx-build
6262
path: |
6363
payload
64-
symbols
64+
symbols
65+
66+
osx-payload-sign:
67+
name: Sign macOS payload
68+
# ESRP service requires signing to run on Windows
69+
runs-on: windows-latest
70+
needs: osx-build
71+
steps:
72+
- name: Check out repository
73+
uses: actions/checkout@v3
74+
75+
- name: Download payload
76+
uses: actions/download-artifact@v3
77+
with:
78+
name: tmp.osx-build
79+
80+
- name: Zip unsigned payload
81+
shell: pwsh
82+
run: |
83+
Compress-Archive -Path payload payload/payload.zip
84+
cd payload
85+
Get-ChildItem -Exclude payload.zip | Remove-Item -Recurse -Force
86+
87+
- uses: azure/login@v1
88+
with:
89+
creds: ${{ secrets.AZURE_CREDENTIALS }}
90+
91+
- name: Set up ESRP client
92+
shell: pwsh
93+
env:
94+
AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
95+
AZURE_VAULT: ${{ secrets.AZURE_VAULT }}
96+
AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }}
97+
REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }}
98+
run: |
99+
.github\set_up_esrp.ps1
100+
101+
- name: Run ESRP client
102+
shell: pwsh
103+
env:
104+
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }}
105+
# We temporarily need two AAD IDs, as we're using an SSL certificate associated
106+
# with an older App Registration until we have the required hardware to approve
107+
# the new certificate in SSL Admin.
108+
AZURE_AAD_ID_SSL: ${{ secrets.AZURE_AAD_ID_SSL }}
109+
APPLE_KEY_CODE: ${{ secrets.APPLE_KEY_CODE }}
110+
APPLE_SIGNING_OP_CODE: ${{ secrets.APPLE_SIGNING_OPERATION_CODE }}
111+
run: |
112+
python .github\run_esrp_signing.py payload $env:APPLE_KEY_CODE $env:APPLE_SIGNING_OP_CODE --params 'Hardening' '--options=runtime'
113+
114+
- name: Unzip signed payload
115+
shell: pwsh
116+
run: |
117+
Expand-Archive signed/payload.zip -DestinationPath signed
118+
Remove-Item signed/payload.zip
119+
120+
- name: Upload signed payload
121+
uses: actions/upload-artifact@v3
122+
with:
123+
name: osx-payload-sign
124+
path: |
125+
signed

0 commit comments

Comments
 (0)