fix typos
[sfa.git] / sfa / server / sfa-ca.py
1 #!/usr/bin/python
2
3 #
4 # SFA Certificate Signing and management 
5 #   
6
7 import os
8 import sys
9 from optparse import OptionParser
10 from sfa.trust.certificate import Keypair, Certificate
11 from sfa.trust.gid import GID, create_uuid
12 from sfa.trust.hierarchy import Hierarchy
13 from sfa.util.config import Config
14 from collections import defaultdict
15
16 def main():
17     args = sys.argv
18     script_name = args[0]
19     parser = OptionParser(usage="%(script_name)s [options]" % locals())
20     parser.add_option("-d", "--display", dest="display", default=None,
21                       help="print contents of specified gid")           
22     parser.add_option("-s", "--sign", dest="sign", default=None, 
23                       help="gid to sign" )
24     parser.add_option("-k", "--key", dest="key", default=None, 
25                       help="keyfile to use for signing")
26     parser.add_option("-a", "--authority", dest="authority", default=None, 
27                       help="sign the gid using the specified authority ")
28     parser.add_option("-i", "--import", dest="importgid", default=None,
29                       help="gid file to import into the registry")
30     parser.add_option("-e", "--export", dest="export", 
31                       help="name of gid to export from registry")
32     parser.add_option("-o", "--outfile", dest="outfile",
33                       help="where to write the exprted gid") 
34     parser.add_option("-v", "--verbose", dest="verobse", 
35                       help="be verbose")           
36                 
37     (options, args) = parser.parse_args()
38
39
40     if options.display:
41         display(options)
42     elif options.sign:
43         sign(options)
44     elif options.importgid:
45         import_gid(options) 
46     elif options.export:
47         export_gid(options)  
48     else:
49         parser.print_help()
50         sys.exit(1)        
51
52
53 def display(options):
54     """
55     Display the sepcified GID
56     """
57     gidfile = os.path.abspath(options.display)
58     if not gidfile or not os.path.isfile(gidfile):
59         print "No such gid: %s" % gidfile
60         sys.exit(1)
61     gid = GID(filename=gidfile)
62     gid.dump(dump_parents=True)
63
64 def sign_gid(gid, parent_key, parent_gid):
65     gid.set_issuer(parent_key, parent_gid.get_hrn())
66     gid.set_parent(parent_gid)
67     gid.sign()
68     gid.save_to_file(outfile, save_parents=True)
69     return gid 
70
71 def sign(options):
72     """
73     Sign the specified gid
74     """
75     hierarchy = Hierarchy()
76     config = Config()
77     default_authority = config.SFA_INTERFACE_HRN
78     auth_info = hierarchy.get_auth_info(parent_hrn)
79
80     # load the gid
81     gidfile = os.path.abspath(options.sign)
82     if not os.path.isfile(gidfile):
83         print "no such gid: %s" % gidfile
84         sys.exit(1)
85     gid = GID(filename=gidfile)
86
87     # load the parent private info
88     authority = options.authority    
89     # if no pkey was specified, then use the this authority's key
90     if not authority:
91         authority = default_authority 
92     
93     if not hierarchy.auth_exists(authority):
94         print "no such authority: %s" % authority    
95
96     # load the parent gid and key 
97     auth_info = hierarchy.get_auth_info(authority)
98     pkeyfile = auth_info.privkey_filename
99     parent_key = Keypair(filename=pkeyfile)
100     parent_gid = auth_info.gid_object
101
102     # get the outfile
103     outfile = options.outfile
104     if not outfile:
105         outfile = os.path.abspath('./signed-%s.gid' % gid.get_hrn())
106    
107     # check if gid already has a parent
108  
109     # sign the gid
110     sign_gid(gid, parent_key, parent_gid)
111     
112
113 def export_gid(options):
114     from sfa.util.table import SfaTable
115     # lookup the record for the specified hrn 
116     hrn = options.export
117
118     # check sfa table first    
119     table = SfaTable()
120     records = table.find({'hrn': hrn, type: 'authority'})
121     if not records:
122         # check the authorities hierarchy 
123         hierarchy = Hierarchy()
124         try:
125             auth_info = hierarchy.get_auth_info()
126             gid = auth_info.gid_object 
127         except:
128             print "Record: %s not found" % hrn
129             sys.exit(1)
130     else:
131         record = records[0]
132         gid = GID(string=record['gid'])
133         
134     # get the outfile
135     outfile = options.outfile
136     if not outfile:
137         outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
138
139     # save it
140     gid.save_to_file(outfile, save_parents=True)
141
142 def import_gid(options):
143     """
144     Import the specified gid into the registry (db and authorities 
145     hierarchy) overwriting any previous gid.
146     """
147     from sfa.util.table import SfaTable
148     from sfa.util.record import SfaRecord
149     # load the gid
150     gidfile = os.path.abspath(options.importgid)
151     if not gidfile or not os.path.isfile(gidfile):
152         print "No such gid: %s" % gidfile
153         sys.exit(1)
154     gid = GID(filename=gidfile)
155     
156     # check if it exists within the hierarchy
157     hierarchy = Hierarchy()
158     if not hierarchy.auth_exists(gid.get_hrn()):
159         print "%s not found in hierarchy" % gid.get_hrn()
160         sys.exit(1)
161
162     # check if record exists in db
163     table = SfaTable()
164     records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
165     if not records:
166         print "%s not found in record database" % get.get_hrn()  
167         sys.exit(1)
168
169     # update the database record
170     record = records[0]
171     record['gid'] = gid.save_to_string(save_parents=True)
172     table.update(record)
173
174     # update the hierarchy
175     auth_info = hierarchy.get_auth_info(gid.get_hrn())  
176     filename = auth_info.gid_filename
177     gid.save_to_file(filename, save_parents=True)
178
179     # re-sign all existing gids signed by this authority  
180     # create a dictionary of records keyed on the record's authority
181     record_dict = defaultdict(list)
182     # only get regords that belong to this authority 
183     # or any of its sub authorities   
184     all_records = table.find({'hrn': '%s*' % gid.get_hrn()})
185     for record in records:
186         record_dict[record['authority']].append(record) 
187
188     # start with the authority we just imported       
189     authorities = [gid.get_hrn()]
190     while authorities:
191         next_authorities = []
192         for authority in authorities:
193             # create a new signed gid for each record at this authority 
194             # and update the registry
195             auth_info = hierarchy.get_auth_info(authority)
196             records = record_dict[authority]
197             for record in records:
198                 record_gid = GID(string=record['gid'])
199                 parent_pkey = Keypair(filename=auth_info.privkey_filename)
200                 parent_gid = GID(filename=auth_info.gid_filename)
201                 signed_gid = sign_gid(record_gid, parent_pkey, parent_gid)
202                 record['gid'] = signed_gid.save_to_string(save_parents=True)
203                 table.update(record)
204                 
205                 # if this is an authority then update the hierarchy
206                 if record['type'] == 'authority':
207                     record_info = hierarchy.get_auth_info(record['hrn'])
208                     signed_gid.save_to_file(filename=record_info.gid_filename, save_parents=True)
209
210              # update list of next authorities
211             tmp_authorities = set([record['hrn'] for record in records \
212                                    if record['type'] == 'authority'])
213             next_authorities.extend(tmp_authorities)
214
215         # move on to next set of authorities
216         authorities = next_authorities     
217
218 if __name__ == '__main__':
219     main()