4 # SFA Certificate Signing and management. Root authorities can use this script
5 # to sign the certificate of another authority and become its parent. Sub
6 # authorities (authorities that have had their cert signed by another authority)
7 # can use this script to update their registry hierarchy with the new cert
12 # sfa-ca.py --sign PEER_CERT_FILENAME -o OUTPUT_FILENAME
14 ## import a cert and update the registry hierarchy
15 # sfa-ca.py --import CERT_FILENAME
18 # sfa-ca.py --display CERT_FILENAME
23 from optparse import OptionParser
24 from sfa.trust.certificate import Keypair, Certificate
25 from sfa.trust.gid import GID, create_uuid
26 from sfa.trust.hierarchy import Hierarchy
27 from sfa.util.config import Config
28 from collections import defaultdict
33 parser = OptionParser(usage="%(script_name)s [options]" % locals())
34 parser.add_option("-d", "--display", dest="display", default=None,
35 help="print contents of specified gid")
36 parser.add_option("-s", "--sign", dest="sign", default=None,
38 parser.add_option("-k", "--key", dest="key", default=None,
39 help="keyfile to use for signing")
40 parser.add_option("-a", "--authority", dest="authority", default=None,
41 help="sign the gid using the specified authority ")
42 parser.add_option("-i", "--import", dest="importgid", default=None,
43 help="gid file to import into the registry")
44 parser.add_option("-e", "--export", dest="export",
45 help="name of gid to export from registry")
46 parser.add_option("-o", "--outfile", dest="outfile",
47 help="where to write the exprted gid")
48 parser.add_option("-v", "--verbose", dest="verbose", default=False,
49 action="store_true", help="be verbose")
51 (options, args) = parser.parse_args()
58 elif options.importgid:
69 Display the sepcified GID
71 gidfile = os.path.abspath(options.display)
72 if not gidfile or not os.path.isfile(gidfile):
73 print "No such gid: %s" % gidfile
75 gid = GID(filename=gidfile)
76 gid.dump(dump_parents=True)
78 def sign_gid(gid, parent_key, parent_gid):
79 gid.set_issuer(parent_key, parent_gid.get_hrn())
80 gid.set_parent(parent_gid)
81 gid.set_intermediate_ca(True)
82 gid.set_pubkey(gid.get_pubkey())
88 Sign the specified gid
90 hierarchy = Hierarchy()
92 default_authority = config.SFA_INTERFACE_HRN
93 auth_info = hierarchy.get_auth_info(default_authority)
96 gidfile = os.path.abspath(options.sign)
97 if not os.path.isfile(gidfile):
98 print "no such gid: %s" % gidfile
100 gid = GID(filename=gidfile)
102 # remove previous parent
103 gid = GID(string=gid.save_to_string(save_parents=False))
105 # load the parent private info
106 authority = options.authority
107 # if no pkey was specified, then use the this authority's key
109 authority = default_authority
111 if not hierarchy.auth_exists(authority):
112 print "no such authority: %s" % authority
114 # load the parent gid and key
115 auth_info = hierarchy.get_auth_info(authority)
116 pkeyfile = auth_info.privkey_filename
117 parent_key = Keypair(filename=pkeyfile)
118 parent_gid = auth_info.gid_object
121 outfile = options.outfile
123 outfile = os.path.abspath('./signed-%s.gid' % gid.get_hrn())
125 # check if gid already has a parent
129 print "Signing %s gid with parent %s" % \
130 (gid.get_hrn(), parent_gid.get_hrn())
131 gid = sign_gid(gid, parent_key, parent_gid)
132 # save the signed gid
134 print "Writing signed gid %s" % outfile
135 gid.save_to_file(outfile, save_parents=True)
138 def export_gid(options):
139 from sfa.util.table import SfaTable
140 # lookup the record for the specified hrn
143 # check sfa table first
145 records = table.find({'hrn': hrn, type: 'authority'})
147 # check the authorities hierarchy
148 hierarchy = Hierarchy()
150 auth_info = hierarchy.get_auth_info()
151 gid = auth_info.gid_object
153 print "Record: %s not found" % hrn
157 gid = GID(string=record['gid'])
160 outfile = options.outfile
162 outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
166 print "Writing %s gid to %s" % (gid.get_hrn(), outfile)
167 gid.save_to_file(outfile, save_parents=True)
169 def import_gid(options):
171 Import the specified gid into the registry (db and authorities
172 hierarchy) overwriting any previous gid.
174 from sfa.util.table import SfaTable
175 from sfa.util.record import SfaRecord
177 gidfile = os.path.abspath(options.importgid)
178 if not gidfile or not os.path.isfile(gidfile):
179 print "No such gid: %s" % gidfile
181 gid = GID(filename=gidfile)
183 # check if it exists within the hierarchy
184 hierarchy = Hierarchy()
185 if not hierarchy.auth_exists(gid.get_hrn()):
186 print "%s not found in hierarchy" % gid.get_hrn()
189 # check if record exists in db
191 records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
193 print "%s not found in record database" % get.get_hrn()
196 # update the database record
198 record['gid'] = gid.save_to_string(save_parents=True)
201 print "Imported %s gid into db" % record['hrn']
203 # update the hierarchy
204 auth_info = hierarchy.get_auth_info(gid.get_hrn())
205 filename = auth_info.gid_filename
206 gid.save_to_file(filename, save_parents=True)
208 print "Writing %s gid to %s" % (gid.get_hrn(), filename)
210 # re-sign all existing gids signed by this authority
211 # create a dictionary of records keyed on the record's authority
212 record_dict = defaultdict(list)
213 # only get regords that belong to this authority
214 # or any of its sub authorities
215 child_records = table.find({'hrn': '%s*' % gid.get_hrn()})
216 if not child_records:
219 for record in child_records:
220 record_dict[record['authority']].append(record)
222 # start with the authority we just imported
223 authorities = [gid.get_hrn()]
225 next_authorities = []
226 for authority in authorities:
227 # create a new signed gid for each record at this authority
228 # and update the registry
229 auth_info = hierarchy.get_auth_info(authority)
230 records = record_dict[authority]
231 for record in records:
232 record_gid = GID(string=record['gid'])
233 parent_pkey = Keypair(filename=auth_info.privkey_filename)
234 parent_gid = GID(filename=auth_info.gid_filename)
236 print "re-signing %s gid with parent %s" % \
237 (record['hrn'], parent_gid.get_hrn())
238 signed_gid = sign_gid(record_gid, parent_pkey, parent_gid)
239 record['gid'] = signed_gid.save_to_string(save_parents=True)
242 # if this is an authority then update the hierarchy
243 if record['type'] == 'authority':
244 record_info = hierarchy.get_auth_info(record['hrn'])
246 print "Writing %s gid to %s" % (record['hrn'], record_info.gid_filename)
247 signed_gid.save_to_file(filename=record_info.gid_filename, save_parents=True)
249 # update list of next authorities
250 tmp_authorities = set([record['hrn'] for record in records \
251 if record['type'] == 'authority'])
252 next_authorities.extend(tmp_authorities)
254 # move on to next set of authorities
255 authorities = next_authorities
257 if __name__ == '__main__':