Last active
August 29, 2015 14:13
-
-
Save vfig/ad15ff7a70b0d5647bc2 to your computer and use it in GitHub Desktop.
Display a list of provisioning profiles with at least one valid code-signing identity.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2.7 | |
## Display a list of provisioning profiles with at least one valid code-signing identity. | |
## | |
## Displays the UUID and app identifier for each such provisioning profile, followed by the | |
## fingerprint and name of the matching code-signing identities. | |
import glob, os, plistlib, re, subprocess | |
PROVISIONING_PROFILES_DIR = os.path.expanduser('~/Library/MobileDevice/Provisioning Profiles') | |
OPENSSL = '/usr/bin/openssl' | |
SECURITY = '/usr/bin/security' | |
def profile_find(): | |
return glob.glob(os.path.join(PROVISIONING_PROFILES_DIR, '*.mobileprovision')) | |
def profile_extract_plist(profile_path): | |
return subprocess.check_output([SECURITY, 'cms', '-D', '-i', profile_path]) | |
def plist_get_uuid(plist_xml): | |
plist = plistlib.readPlistFromString(plist_xml) | |
return plist["UUID"] | |
def plist_get_application_identifier(plist_xml): | |
plist = plistlib.readPlistFromString(plist_xml) | |
return plist["Entitlements"]["application-identifier"] | |
def plist_iter_certificates(plist_xml): | |
plist = plistlib.readPlistFromString(plist_xml) | |
for cert in plist["DeveloperCertificates"]: | |
yield cert.data | |
def codesigning_find_identities(): | |
output = subprocess.check_output([SECURITY, 'find-identity', '-v', '-p', 'codesigning']) | |
for line in output.splitlines(): | |
if 'REVOKED' in line: continue | |
match = re.search(r'(?P<sha>(?:[0-9A-Fa-f][0-9A-Fa-f]){20}) "(?P<name>[^"]+)"', line) | |
if match: | |
yield match.group('sha'), match.group('name') | |
def plist_filter_certificates(plist, identities): | |
for cert in plist_iter_certificates(plist): | |
sha = certificate_get_sha(cert) | |
if sha in identities: | |
yield sha, identities[sha] | |
def certificate_get_sha(certificate_data): | |
args = [OPENSSL, 'x509', '-inform', 'der', '-noout', '-sha1', '-fingerprint'] | |
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
stdout, stderr = p.communicate(certificate_data) | |
match = re.search(r'(?:[0-9A-Fa-f][0-9A-Fa-f]:?){20}', stdout) | |
if not match: | |
raise ValueError("Could not find fingerprint in %r" % stdout) | |
fingerprint = match.group(0).replace(':', '') | |
return fingerprint | |
def main(): | |
identities = dict(codesigning_find_identities()) | |
for profile in profile_find(): | |
plist = profile_extract_plist(profile) | |
certs = list(plist_filter_certificates(plist, identities)) | |
if not certs: continue | |
print plist_get_uuid(plist), plist_get_application_identifier(plist) | |
for sha, identity in certs: | |
print " ", sha, identity | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment