Merge branch 'master' of ssh://git.f-lab.fr/git/sfa
[sfa.git] / sfa / server / sfa-ca.py
1 #!/usr/bin/python
2
3 #
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    
8
9 # Example usage: 
10 #
11 ## sign a peer cert
12 # sfa-ca.py --sign PEER_CERT_FILENAME -o OUTPUT_FILENAME 
13 #
14 ## import a cert and update the registry hierarchy
15 # sfa-ca.py --import CERT_FILENAME   
16 #
17 ## display a cert
18 # sfa-ca.py --display CERT_FILENAME
19
20
21 import os
22 import sys
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
29
30 def main():
31     args = sys.argv
32     script_name = args[0]
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, 
37                       help="gid to sign" )
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("-t", "--type", dest="type",
47                       help="record type", default=None)
48     parser.add_option("-o", "--outfile", dest="outfile",
49                       help="where to write the exprted gid") 
50     parser.add_option("-v", "--verbose", dest="verbose", default=False, 
51                       action="store_true", help="be verbose")           
52                 
53     (options, args) = parser.parse_args()
54
55
56     if options.display:
57         display(options)
58     elif options.sign:
59         sign(options)
60     elif options.importgid:
61         import_gid(options) 
62     elif options.export:
63         export_gid(options)  
64     else:
65         parser.print_help()
66         sys.exit(1)        
67
68
69 def display(options):
70     """
71     Display the sepcified GID
72     """
73     gidfile = os.path.abspath(options.display)
74     if not gidfile or not os.path.isfile(gidfile):
75         print "No such gid: %s" % gidfile
76         sys.exit(1)
77     gid = GID(filename=gidfile)
78     gid.dump(dump_parents=True)
79
80 def sign(options):
81     """
82     Sign the specified gid
83     """
84     hierarchy = Hierarchy()
85     config = Config()
86     default_authority = config.SFA_INTERFACE_HRN
87     auth_info = hierarchy.get_auth_info(default_authority)
88
89     # load the gid
90     gidfile = os.path.abspath(options.sign)
91     if not os.path.isfile(gidfile):
92         print "no such gid: %s" % gidfile
93         sys.exit(1)
94     gid = GID(filename=gidfile)
95
96     # extract pub_key and create new gid
97     pkey = gid.get_pubkey()
98     urn = gid.get_urn()
99     gid = hierarchy.create_gid(urn, create_uuid(), pkey)
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     # save the signed gid
107     if options.verbose:
108         print "Writing signed gid %s" % outfile  
109     gid.save_to_file(outfile, save_parents=True)
110     
111
112 def export_gid(options):
113     from sfa.util.table import SfaTable
114     # lookup the record for the specified hrn 
115     hrn = options.export
116     type = options.type
117     # check sfa table first
118     filter = {'hrn': hrn}
119     if type:
120         filter['type'] = type                    
121     table = SfaTable()
122     records = table.find(filter)
123     if not records:
124         # check the authorities hierarchy 
125         hierarchy = Hierarchy()
126         try:
127             auth_info = hierarchy.get_auth_info()
128             gid = auth_info.gid_object 
129         except:
130             print "Record: %s not found" % hrn
131             sys.exit(1)
132     else:
133         record = records[0]
134         gid = GID(string=record['gid'])
135         
136     # get the outfile
137     outfile = options.outfile
138     if not outfile:
139         outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
140
141     # save it
142     if options.verbose:
143         print "Writing %s gid to %s" % (gid.get_hrn(), outfile)
144     gid.save_to_file(outfile, save_parents=True)
145
146 def import_gid(options):
147     """
148     Import the specified gid into the registry (db and authorities 
149     hierarchy) overwriting any previous gid.
150     """
151     from sfa.util.table import SfaTable
152     from sfa.util.record import SfaRecord
153     # load the gid
154     gidfile = os.path.abspath(options.importgid)
155     if not gidfile or not os.path.isfile(gidfile):
156         print "No such gid: %s" % gidfile
157         sys.exit(1)
158     gid = GID(filename=gidfile)
159     
160     # check if it exists within the hierarchy
161     hierarchy = Hierarchy()
162     if not hierarchy.auth_exists(gid.get_hrn()):
163         print "%s not found in hierarchy" % gid.get_hrn()
164         sys.exit(1)
165
166     # check if record exists in db
167     table = SfaTable()
168     records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
169     if not records:
170         print "%s not found in record database" % get.get_hrn()  
171         sys.exit(1)
172
173     # update the database record
174     record = records[0]
175     record['gid'] = gid.save_to_string(save_parents=True)
176     table.update(record)
177     if options.verbose:
178         print "Imported %s gid into db" % record['hrn']
179
180     # update the hierarchy
181     auth_info = hierarchy.get_auth_info(gid.get_hrn())  
182     filename = auth_info.gid_filename
183     gid.save_to_file(filename, save_parents=True)
184     if options.verbose:
185         print "Writing %s gid to %s" % (gid.get_hrn(), filename)
186
187     # ending here
188     return
189
190 if __name__ == '__main__':
191     main()