• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5
6import argparse
7import os
8import subprocess
9import sys
10import re
11
12
13def Redact(value, from_nth_char=5):
14  """Redact value past the N-th character."""
15  return value[:from_nth_char] + '*' * (len(value) - from_nth_char)
16
17
18class Identity(object):
19  """Represents a valid identity."""
20
21  def __init__(self, identifier, name, team):
22    self.identifier = identifier
23    self.name = name
24    self.team = team
25
26  def redacted(self):
27    return Identity(Redact(self.identifier), self.name, Redact(self.team))
28
29  def format(self):
30    return '%s: "%s (%s)"' % (self.identifier, self.name, self.team)
31
32
33def ListIdentities():
34  return subprocess.check_output([
35      'xcrun',
36      'security',
37      'find-identity',
38      '-v',
39      '-p',
40      'codesigning',
41  ]).decode('utf8')
42
43
44def FindValidIdentity(pattern):
45  """Find all identities matching the pattern."""
46  lines = list(l.strip() for l in ListIdentities().splitlines())
47  # Look for something like
48  # 1) 123ABC123ABC123ABC****** "iPhone Developer: DeveloperName (Team)"
49  regex = re.compile('[0-9]+\) ([A-F0-9]+) "([^"(]*) \(([^)"]*)\)"')
50
51  result = []
52  for line in lines:
53    res = regex.match(line)
54    if res is None:
55      continue
56    identifier, developer_name, team = res.groups()
57    if pattern is None or pattern in '%s (%s)' % (developer_name, team):
58      result.append(Identity(identifier, developer_name, team))
59  return result
60
61
62def Main(args):
63  parser = argparse.ArgumentParser('codesign iOS bundles')
64  parser.add_argument('--matching-pattern',
65                      dest='pattern',
66                      help='Pattern used to select the code signing identity.')
67  parsed = parser.parse_args(args)
68
69  identities = FindValidIdentity(parsed.pattern)
70  if len(identities) == 1:
71    print(identities[0].identifier, end='')
72    return 0
73
74  all_identities = FindValidIdentity(None)
75
76  print('Automatic code signing identity selection was enabled but could not')
77  print('find exactly one codesigning identity matching "%s".' % parsed.pattern)
78  print('')
79  print('Check that the keychain is accessible and that there is exactly one')
80  print('valid codesigning identity matching the pattern. Here is the parsed')
81  print('output of `xcrun security find-identity -v -p codesigning`:')
82  print()
83  for i, identity in enumerate(all_identities):
84    print('  %d) %s' % (i + 1, identity.redacted().format()))
85  print('    %d valid identities found' % (len(all_identities)))
86  return 1
87
88
89if __name__ == '__main__':
90  sys.exit(Main(sys.argv[1:]))
91