-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcodesign.py
231 lines (200 loc) · 9.24 KB
/
codesign.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/usr/bin/env python
"""Codesign utility"""
import argparse
import subprocess
import os
import time
import shutil
import json
parser = argparse.ArgumentParser(description = 'Codesign utility for Ninja builds')
parser.add_argument('file', type=str,
help = 'Bundle/package to sign')
parser.add_argument('--target', type=str,
help = 'Target',
choices = ['macos', 'ios', 'android'],
default = '')
parser.add_argument('--bundle', type=str,
help = 'Bundle identifier (OSX/iOS)',
default = '')
parser.add_argument('--organisation', type=str,
help = 'Organisation identifier (OSX/iOS)',
default = '')
parser.add_argument('--provisioning', type=str,
help = 'Provisioning profile (OSX/iOS)',
default = '')
parser.add_argument('--builddir', type=str,
help = 'Build directory (OSX/iOS)',
default = '')
parser.add_argument('--binname', type=str,
help = 'Binary name (OSX/iOS)',
default = '')
parser.add_argument('--zipfile', type=str,
help = 'Zip file (Android)',
default = '')
parser.add_argument('--tsacert', type=str,
help = 'TSA cert (Android)',
default = '')
parser.add_argument('--tsa', type=str,
help = 'TSA (Android)',
default = '')
parser.add_argument('--keystore', type=str,
help = 'Keystore (Android)',
default = '')
parser.add_argument('--keystorepass', type=str,
help = 'Keystore password (Android)',
default = '')
parser.add_argument('--keyalias', type=str,
help = 'Key alias (Android)',
default = '')
parser.add_argument('--keypass', type=str,
help = 'Key password (Android)',
default = '')
parser.add_argument('--jarsigner', type=str,
help = 'JAR signer (Android)',
default = 'jarsigner')
parser.add_argument('--prefs', type=str,
help = 'Preferences file',
default = '')
parser.add_argument('--config', type=str,
help = 'Build configuration',
default = '')
parser.add_argument('--entitlements', type=str,
help = 'Entitlements file',
default = '')
options = parser.parse_args()
androidprefs = {}
iosprefs = {}
macosprefs = {}
def parse_prefs( prefsfile ):
global androidprefs
global iosprefs
global macosprefs
if not os.path.isfile( prefsfile ):
return
file = open( prefsfile, 'r' )
prefs = json.load( file )
file.close()
if 'android' in prefs:
androidprefs = prefs['android']
if 'ios' in prefs:
iosprefs = prefs['ios']
if 'macos' in prefs:
macosprefs = prefs['macos']
def codesign_ios():
if not 'organisation' in iosprefs:
iosprefs['organisation'] = options.organisation
if not 'bundleidentifier' in iosprefs:
iosprefs['bundleidentifier'] = options.bundle
if not 'provisioning' in iosprefs:
iosprefs['provisioning'] = options.provisioning
sdkdir = subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '--show-sdk-path' ] ).decode().strip().splitlines()[-1]
entitlements = os.path.join( sdkdir, 'Entitlements.plist' )
plistpath = os.path.join( options.builddir, 'Entitlements.xcent' )
platformpath = subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '--show-sdk-platform-path' ] ).decode().strip().splitlines()[-1]
localpath = platformpath + "/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
plutil = "PATH=" + localpath + " " + subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '-f', 'plutil' ] ).decode().strip().splitlines()[-1]
shutil.copyfile( entitlements, plistpath )
os.system( plutil + ' -convert xml1 ' + plistpath )
f = open( plistpath, 'r' )
lines = [ line.strip( '\n\r' ) for line in f ]
f.close()
for i in range( 0, len( lines ) ):
if lines[i].find( '$(AppIdentifierPrefix)' ) != -1:
lines[i] = lines[i].replace( '$(AppIdentifierPrefix)', iosprefs['organisation'] + '.' )
if lines[i].find( '$(CFBundleIdentifier)' ) != -1:
lines[i] = lines[i].replace( '$(CFBundleIdentifier)', iosprefs['bundleidentifier'] )
if lines[i].find( '$(binname)' ) != -1:
lines[i] = lines[i].replace( '$(binname)', options.binname )
with open( plistpath, 'w' ) as plist_file:
for line in lines:
if options.config != 'deploy' and line == '</dict>':
plist_file.write( '\t<key>get-task-allow</key>\n' )
plist_file.write( '\t<true/>\n' )
plist_file.write( line + '\n' )
plist_file.close()
if os.path.isfile( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) ):
os.remove( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) )
os.system( '/usr/bin/codesign --force --sign "' + iosprefs['signature'] + '" --entitlements ' + plistpath + ' ' + options.file )
if os.path.isfile( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) ):
os.utime( os.path.join( options.file, '_CodeSignature', 'CodeResources' ), None )
os.utime( os.path.join( options.file, '_CodeSignature' ), None )
os.utime( options.file, None )
def codesign_macos():
if not 'organisation' in macosprefs:
macosprefs['organisation'] = options.organisation
if not 'bundleidentifier' in macosprefs:
macosprefs['bundleidentifier'] = options.bundle
if not 'provisioning' in macosprefs:
macosprefs['provisioning'] = options.provisioning
if not 'entitlements' in macosprefs:
macosprefs['entitlements'] = options.entitlements
codesign_allocate = subprocess.check_output( [ 'xcrun', '--sdk', 'macosx', '-f', 'codesign_allocate' ] ).decode().strip().splitlines()[-1]
sdkdir = subprocess.check_output( [ 'xcrun', '--sdk', 'macosx', '--show-sdk-path' ] ).decode().strip().splitlines()[-1]
entitlements = os.path.join( sdkdir, 'Entitlements.plist' )
if os.path.isfile( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) ):
os.remove( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) )
if 'signature' in macosprefs:
command = 'export CODESIGN_ALLOCATE=' + codesign_allocate + '; /usr/bin/codesign --force --sign "' + macosprefs['signature'] + '" -o runtime '
if ('entitlements' in macosprefs) and (macosprefs['entitlements'] != '') and (macosprefs['entitlements'] != 'none'):
command = command + '--entitlements ' + macosprefs['entitlements'] + ' --generate-entitlement-der '
command = command + options.file
# print(command)
os.system(command)
if os.path.isfile( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) ):
os.utime( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ), None )
os.utime( os.path.join( options.file, 'Contents', '_CodeSignature' ), None )
os.utime( os.path.join( options.file, 'Contents' ), None )
os.utime( options.file, None )
def codesign_android():
if not 'tsacert' in androidprefs:
androidprefs['tsacert'] = options.tsacert
if not 'tsa' in androidprefs:
androidprefs['tsa'] = options.tsa
if not 'keystore' in androidprefs:
androidprefs['keystore'] = options.keystore
if not 'keystorepass' in androidprefs:
androidprefs['keystorepass'] = options.keystorepass
if not 'keyalias' in androidprefs:
androidprefs['keyalias'] = options.keyalias
if not 'keypass' in androidprefs:
androidprefs['keypass'] = options.keypass
if not 'jarsigner' in androidprefs:
androidprefs['jarsigner'] = options.jarsigner
timestamp = ''
if androidprefs['tsacert'] != '':
timestamp = '-tsacert ' + androidprefs['tsacert']
elif androidprefs['tsa'] != '':
timestamp = '-tsa ' + androidprefs['tsa']
proxy = ''
if 'proxy' in androidprefs and androidprefs['proxy'] != '' and androidprefs['proxy'] != 'None':
proxy = androidprefs['proxy']
if proxy != '' and proxy != 'None':
defstr = "-J-Dhttp.proxy"
url = urlparse.urlparse(proxy)
if url.scheme == 'https':
defstr = "-J-Dhttps.proxy"
host = url.netloc
port = ''
username = ''
password = ''
if '@' in host:
username, host = host.split(':', 1)
password, host = host.split('@', 1)
if ':' in host:
host, port = host.split(':', 1)
proxy = defstr + "Host=" + host
if port != '':
proxy += " " + defstr + "Port=" + port
if username != '':
proxy += " " + defstr + "User=" + username
if password != '':
proxy += " " + defstr + "Password=" + password
signcmd = androidprefs['jarsigner'] + ' ' + timestamp + ' -sigalg SHA1withRSA -digestalg SHA1 -keystore ' + androidprefs['keystore'] + ' -storepass ' + androidprefs['keystorepass'] + ' -keypass ' + androidprefs['keypass'] + ' -signedjar ' + options.file + ' ' + options.zipfile + ' ' + androidprefs['keyalias'] + ' ' + proxy
os.system(signcmd)
parse_prefs( options.prefs )
if options.target == 'ios':
codesign_ios()
elif options.target == 'macos':
codesign_macos()
elif options.target == 'android':
codesign_android()