hierarchy support
[sfa.git] / util / hierarchy.py
1 # hierarchy.py
2 #
3 # hierarchy of GENI authorities
4 #
5 # This correspond's almost identically to the functionality of Soner's
6 # "tree" module. Each component of an HRN is stored in a different subdirectory.
7 # Inside this subdirectory are:
8 #      *.GID - GID file
9 #      *.PKEY - private key file
10 #      *.DBINFO - database info
11
12 import os
13 from cert import *
14 from gid import *
15 from misc import *
16 from config import *
17
18 class AuthInfo():
19     hrn = None
20     gid_filename = None
21     privkey_filename = None
22     dbinfo_filename = None
23
24     def __init__(self, hrn, gid_filename, privkey_filename, dbinfo_filename):
25         self.hrn = hrn
26         self.gid_filename = gid_filename
27         self.privkey_filename = privkey_filename
28         self.dbinfo_filename = dbinfo_filename
29
30     def get_gid_object(self):
31         return GID(filename = self.gid_filename)
32
33     def get_pkey_object(self):
34         return Keypair(filename = self.privkey_filename)
35
36     def get_dbinfo(self):
37         f = file(self.dbinfo_filename)
38         dict = eval(f.read())\r
39         f.close()\r
40         return dict\r
41
42 class Hierarchy():
43     def __init__(self, basedir="."):
44         self.basedir = basedir
45
46     # type = sa|ma
47     def get_auth_info(self, hrn, type, can_create=True):
48         leaf = get_leaf(hrn)
49         parent_hrn = get_authority(hrn)
50         directory = os.path.join(self.basedir,
51                         os.path.join(type, hrn.replace(".", "/")))
52
53         gid_filename = os.path.join(directory, leaf+".gid")
54         privkey_filename = os.path.join(directory, leaf+".pkey")
55         dbinfo_filename = os.path.join(directory, leaf+".dbinfo")
56
57         if (not os.path.exists(gid_filename)) or \
58            (not os.path.exists(privkey_filename)) or \
59            (not os.path.exists(dbinfo_filename)):
60             if not can_create:
61                 return MissingAuthorityFiles(hrn)
62
63             # create the directory to hold the files
64             try:
65                 os.makedirs(directory)\r
66             # if the path already exists then pass\r
67             except OSError, (errno, strerr):\r
68                 if errno == 17:\r
69                     pass
70
71             pkey = Keypair(create = True)
72             pkey.save_to_file(privkey_filename)
73
74             gid = self.create_gid(type, hrn, create_uuid(), pkey)
75             gid.save_to_file(gid_filename)
76
77             # XXX TODO: think up a better way for the dbinfo to work
78
79             dbinfo = get_default_dbinfo()
80             dbinfo_file = file(dbinfo_filename, "w")
81             dbinfo_file.write(str(dbinfo))\r
82             dbinfo_file.close()\r
83
84         auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename)
85
86         return auth_info
87
88     def create_gid(self, type, hrn, uuid, pkey):
89         parent_hrn = get_authority(hrn)
90
91         gid = GID(subject=hrn, uuid=uuid)
92
93         if not parent_hrn:
94             # if there is no parent hrn, then it must be self-signed. this
95             # is where we terminate the recursion
96             gid.set_issuer(pkey, hrn)
97         else:
98             # we need the parent's private key in order to sign this GID
99             parent_auth_info = self.get_auth_info(parent_hrn, type)
100             gid.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
101             gid.set_parent(parent_auth_info.get_gid_object())
102
103         gid.set_pubkey(pkey)
104         gid.sign()
105
106         return gid
107
108     def refresh_gid(self, type, gid, hrn=None, uuid=None, pubkey=None):
109         # TODO: compute expiration time of GID, refresh it if necessary
110         gid_is_expired = False
111
112         # update the gid if we need to
113         if gid_is_expired or hrn or uuid or pubkey:
114             if not hrn:
115                 hrn = gid.get_hrn()
116             if not uuid:
117                 uuid = gid.get_uuid()
118             if not pubkey:
119                 pubkey = gid.get_pubkey()
120
121             gid = self.create_gid(type, hrn, uuid, pubkey)
122
123         return gid
124