127a267a723a5187b72927b2639ef5fe34438f96
[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     return gid 
69
70 def sign(options):
71     """
72     Sign the specified gid
73     """
74     hierarchy = Hierarchy()
75     config = Config()
76     default_authority = config.SFA_INTERFACE_HRN
77     auth_info = hierarchy.get_auth_info(default_authority)
78
79     # load the gid
80     gidfile = os.path.abspath(options.sign)
81     if not os.path.isfile(gidfile):
82         print "no such gid: %s" % gidfile
83         sys.exit(1)
84     gid = GID(filename=gidfile)
85
86     # load the parent private info
87     authority = options.authority    
88     # if no pkey was specified, then use the this authority's key
89     if not authority:
90         authority = default_authority 
91     
92     if not hierarchy.auth_exists(authority):
93         print "no such authority: %s" % authority    
94
95     # load the parent gid and key 
96     auth_info = hierarchy.get_auth_info(authority)
97     pkeyfile = auth_info.privkey_filename
98     parent_key = Keypair(filename=pkeyfile)
99     parent_gid = auth_info.gid_object
100
101     # get the outfile
102     outfile = options.outfile
103     if not outfile:
104         outfile = os.path.abspath('./signed-%s.gid' % gid.get_hrn())
105    
106     # check if gid already has a parent
107  
108     # sign the gid
109     gid = sign_gid(gid, parent_key, parent_gid)
110     # save the signed gid
111     gid.save_to_file(outfile, save_parents=True)
112     
113
114 def export_gid(options):
115     from sfa.util.table import SfaTable
116     # lookup the record for the specified hrn 
117     hrn = options.export
118
119     # check sfa table first    
120     table = SfaTable()
121     records = table.find({'hrn': hrn, type: 'authority'})
122     if not records:
123         # check the authorities hierarchy 
124         hierarchy = Hierarchy()
125         try:
126             auth_info = hierarchy.get_auth_info()
127             gid = auth_info.gid_object 
128         except:
129             print "Record: %s not found" % hrn
130             sys.exit(1)
131     else:
132         record = records[0]
133         gid = GID(string=record['gid'])
134         
135     # get the outfile
136     outfile = options.outfile
137     if not outfile:
138         outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
139
140     # save it
141     gid.save_to_file(outfile, save_parents=True)
142
143 def import_gid(options):
144     """
145     Import the specified gid into the registry (db and authorities 
146     hierarchy) overwriting any previous gid.
147     """
148     from sfa.util.table import SfaTable
149     from sfa.util.record import SfaRecord
150     # load the gid
151     gidfile = os.path.abspath(options.importgid)
152     if not gidfile or not os.path.isfile(gidfile):
153         print "No such gid: %s" % gidfile
154         sys.exit(1)
155     gid = GID(filename=gidfile)
156     
157     # check if it exists within the hierarchy
158     hierarchy = Hierarchy()
159     if not hierarchy.auth_exists(gid.get_hrn()):
160         print "%s not found in hierarchy" % gid.get_hrn()
161         sys.exit(1)
162
163     # check if record exists in db
164     table = SfaTable()
165     records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
166     if not records:
167         print "%s not found in record database" % get.get_hrn()  
168         sys.exit(1)
169
170     # update the database record
171     record = records[0]
172     record['gid'] = gid.save_to_string(save_parents=True)
173     table.update(record)
174
175     # update the hierarchy
176     auth_info = hierarchy.get_auth_info(gid.get_hrn())  
177     filename = auth_info.gid_filename
178     gid.save_to_file(filename, save_parents=True)
179
180     # re-sign all existing gids signed by this authority  
181     # create a dictionary of records keyed on the record's authority
182     record_dict = defaultdict(list)
183     # only get regords that belong to this authority 
184     # or any of its sub authorities   
185     all_records = table.find({'hrn': '%s*' % gid.get_hrn()})
186     for record in records:
187         record_dict[record['authority']].append(record) 
188
189     # start with the authority we just imported       
190     authorities = [gid.get_hrn()]
191     while authorities:
192         next_authorities = []
193         for authority in authorities:
194             # create a new signed gid for each record at this authority 
195             # and update the registry
196             auth_info = hierarchy.get_auth_info(authority)
197             records = record_dict[authority]
198             for record in records:
199                 record_gid = GID(string=record['gid'])
200                 parent_pkey = Keypair(filename=auth_info.privkey_filename)
201                 parent_gid = GID(filename=auth_info.gid_filename)
202                 signed_gid = sign_gid(record_gid, parent_pkey, parent_gid)
203                 record['gid'] = signed_gid.save_to_string(save_parents=True)
204                 table.update(record)
205                 
206                 # if this is an authority then update the hierarchy
207                 if record['type'] == 'authority':
208                     record_info = hierarchy.get_auth_info(record['hrn'])
209                     signed_gid.save_to_file(filename=record_info.gid_filename, save_parents=True)
210
211              # update list of next authorities
212             tmp_authorities = set([record['hrn'] for record in records \
213                                    if record['type'] == 'authority'])
214             next_authorities.extend(tmp_authorities)
215
216         # move on to next set of authorities
217         authorities = next_authorities     
218
219 if __name__ == '__main__':
220     main()