creating tag sfa-0.9-11
[sfa.git] / sfa / server / sfa-ca.py
diff --git a/sfa/server/sfa-ca.py b/sfa/server/sfa-ca.py
new file mode 100755 (executable)
index 0000000..c76b985
--- /dev/null
@@ -0,0 +1,242 @@
+#!/usr/bin/python
+
+#
+# SFA Certificate Signing and management 
+#   
+
+import os
+import sys
+from optparse import OptionParser
+from sfa.trust.certificate import Keypair, Certificate
+from sfa.trust.gid import GID, create_uuid
+from sfa.trust.hierarchy import Hierarchy
+from sfa.util.config import Config
+from collections import defaultdict
+
+def main():
+    args = sys.argv
+    script_name = args[0]
+    parser = OptionParser(usage="%(script_name)s [options]" % locals())
+    parser.add_option("-d", "--display", dest="display", default=None,
+                      help="print contents of specified gid")           
+    parser.add_option("-s", "--sign", dest="sign", default=None, 
+                      help="gid to sign" )
+    parser.add_option("-k", "--key", dest="key", default=None, 
+                      help="keyfile to use for signing")
+    parser.add_option("-a", "--authority", dest="authority", default=None, 
+                      help="sign the gid using the specified authority ")
+    parser.add_option("-i", "--import", dest="importgid", default=None,
+                      help="gid file to import into the registry")
+    parser.add_option("-e", "--export", dest="export", 
+                      help="name of gid to export from registry")
+    parser.add_option("-o", "--outfile", dest="outfile",
+                      help="where to write the exprted gid") 
+    parser.add_option("-v", "--verbose", dest="verbose", default=False, 
+                      action="store_true", help="be verbose")           
+                
+    (options, args) = parser.parse_args()
+
+
+    if options.display:
+        display(options)
+    elif options.sign:
+        sign(options)
+    elif options.importgid:
+        import_gid(options) 
+    elif options.export:
+        export_gid(options)  
+    else:
+        parser.print_help()
+        sys.exit(1)        
+
+
+def display(options):
+    """
+    Display the sepcified GID
+    """
+    gidfile = os.path.abspath(options.display)
+    if not gidfile or not os.path.isfile(gidfile):
+        print "No such gid: %s" % gidfile
+        sys.exit(1)
+    gid = GID(filename=gidfile)
+    gid.dump(dump_parents=True)
+
+def sign_gid(gid, parent_key, parent_gid):
+    gid.set_issuer(parent_key, parent_gid.get_hrn())
+    gid.set_parent(parent_gid)
+    gid.sign()
+    return gid 
+
+def sign(options):
+    """
+    Sign the specified gid
+    """
+    hierarchy = Hierarchy()
+    config = Config()
+    default_authority = config.SFA_INTERFACE_HRN
+    auth_info = hierarchy.get_auth_info(default_authority)
+
+    # load the gid
+    gidfile = os.path.abspath(options.sign)
+    if not os.path.isfile(gidfile):
+        print "no such gid: %s" % gidfile
+        sys.exit(1)
+    gid = GID(filename=gidfile)
+
+    # remove previous parent
+    gid = GID(string=gid.save_to_string(save_parents=False))
+
+    # load the parent private info
+    authority = options.authority    
+    # if no pkey was specified, then use the this authority's key
+    if not authority:
+        authority = default_authority 
+    
+    if not hierarchy.auth_exists(authority):
+        print "no such authority: %s" % authority    
+
+    # load the parent gid and key 
+    auth_info = hierarchy.get_auth_info(authority)
+    pkeyfile = auth_info.privkey_filename
+    parent_key = Keypair(filename=pkeyfile)
+    parent_gid = auth_info.gid_object
+
+    # get the outfile
+    outfile = options.outfile
+    if not outfile:
+        outfile = os.path.abspath('./signed-%s.gid' % gid.get_hrn())
+   
+    # check if gid already has a parent
+    # sign the gid
+    if options.verbose:
+        print "Signing %s gid with parent %s" % \
+              (gid.get_hrn(), parent_gid.get_hrn())
+    gid = sign_gid(gid, parent_key, parent_gid)
+    # save the signed gid
+    if options.verbose:
+        print "Writing signed gid %s" % outfile  
+    gid.save_to_file(outfile, save_parents=True)
+    
+
+def export_gid(options):
+    from sfa.util.table import SfaTable
+    # lookup the record for the specified hrn 
+    hrn = options.export
+
+    # check sfa table first    
+    table = SfaTable()
+    records = table.find({'hrn': hrn, type: 'authority'})
+    if not records:
+        # check the authorities hierarchy 
+        hierarchy = Hierarchy()
+        try:
+            auth_info = hierarchy.get_auth_info()
+            gid = auth_info.gid_object 
+        except:
+            print "Record: %s not found" % hrn
+            sys.exit(1)
+    else:
+        record = records[0]
+        gid = GID(string=record['gid'])
+        
+    # get the outfile
+    outfile = options.outfile
+    if not outfile:
+        outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
+
+    # save it
+    if options.verbose:
+        print "Writing %s gid to %s" % (gid.get_hrn(), outfile)
+    gid.save_to_file(outfile, save_parents=True)
+
+def import_gid(options):
+    """
+    Import the specified gid into the registry (db and authorities 
+    hierarchy) overwriting any previous gid.
+    """
+    from sfa.util.table import SfaTable
+    from sfa.util.record import SfaRecord
+    # load the gid
+    gidfile = os.path.abspath(options.importgid)
+    if not gidfile or not os.path.isfile(gidfile):
+        print "No such gid: %s" % gidfile
+        sys.exit(1)
+    gid = GID(filename=gidfile)
+    
+    # check if it exists within the hierarchy
+    hierarchy = Hierarchy()
+    if not hierarchy.auth_exists(gid.get_hrn()):
+        print "%s not found in hierarchy" % gid.get_hrn()
+        sys.exit(1)
+
+    # check if record exists in db
+    table = SfaTable()
+    records = table.find({'hrn': gid.get_hrn(), 'type': 'authority'})
+    if not records:
+        print "%s not found in record database" % get.get_hrn()  
+        sys.exit(1)
+
+    # update the database record
+    record = records[0]
+    record['gid'] = gid.save_to_string(save_parents=True)
+    table.update(record)
+    if options.verbose:
+        print "Imported %s gid into db" % record['hrn']
+
+    # update the hierarchy
+    auth_info = hierarchy.get_auth_info(gid.get_hrn())  
+    filename = auth_info.gid_filename
+    gid.save_to_file(filename, save_parents=True)
+    if options.verbose:
+        print "Writing %s gid to %s" % (gid.get_hrn(), filename)
+
+    # re-sign all existing gids signed by this authority  
+    # create a dictionary of records keyed on the record's authority
+    record_dict = defaultdict(list)
+    # only get regords that belong to this authority 
+    # or any of its sub authorities   
+    child_records = table.find({'hrn': '%s*' % gid.get_hrn()})
+    if not child_records:
+        return
+  
+    for record in child_records:
+        record_dict[record['authority']].append(record) 
+
+    # start with the authority we just imported       
+    authorities = [gid.get_hrn()]
+    while authorities:
+        next_authorities = []
+        for authority in authorities:
+            # create a new signed gid for each record at this authority 
+            # and update the registry
+            auth_info = hierarchy.get_auth_info(authority)
+            records = record_dict[authority]
+            for record in records:
+                record_gid = GID(string=record['gid'])
+                parent_pkey = Keypair(filename=auth_info.privkey_filename)
+                parent_gid = GID(filename=auth_info.gid_filename)
+                if options.verbose:
+                    print "re-signing %s gid with parent %s" % \
+                           (record['hrn'], parent_gid.get_hrn())  
+                signed_gid = sign_gid(record_gid, parent_pkey, parent_gid)
+                record['gid'] = signed_gid.save_to_string(save_parents=True)
+                table.update(record)
+                
+                # if this is an authority then update the hierarchy
+                if record['type'] == 'authority':
+                    record_info = hierarchy.get_auth_info(record['hrn'])
+                    if options.verbose:
+                        print "Writing %s gid to %s" % (record['hrn'], record_info.gid_filename) 
+                    signed_gid.save_to_file(filename=record_info.gid_filename, save_parents=True)
+
+             # update list of next authorities
+            tmp_authorities = set([record['hrn'] for record in records \
+                                   if record['type'] == 'authority'])
+            next_authorities.extend(tmp_authorities)
+
+        # move on to next set of authorities
+        authorities = next_authorities     
+
+if __name__ == '__main__':
+    main()