added redeemticket
[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 import report
14 from cert import *
15 from gid import *
16 from misc import *
17 from config import *
18
19 class AuthInfo():
20     hrn = None
21     gid_filename = None
22     privkey_filename = None
23     dbinfo_filename = None
24
25     def __init__(self, hrn, gid_filename, privkey_filename, dbinfo_filename):
26         self.hrn = hrn
27         self.gid_filename = gid_filename
28         self.privkey_filename = privkey_filename
29         self.dbinfo_filename = dbinfo_filename
30
31     def get_gid_object(self):
32         return GID(filename = self.gid_filename)
33
34     def get_pkey_object(self):
35         return Keypair(filename = self.privkey_filename)
36
37     def get_dbinfo(self):
38         f = file(self.dbinfo_filename)
39         dict = eval(f.read())\r
40         f.close()\r
41         return dict\r
42
43 class Hierarchy():
44     def __init__(self, basedir="."):
45         self.basedir = basedir
46
47     def get_auth_filenames(self, hrn):
48         leaf = get_leaf(hrn)
49         parent_hrn = get_authority(hrn)
50         directory = os.path.join(self.basedir, hrn.replace(".", "/"))
51
52         gid_filename = os.path.join(directory, leaf+".gid")
53         privkey_filename = os.path.join(directory, leaf+".pkey")
54         dbinfo_filename = os.path.join(directory, leaf+".dbinfo")
55
56         return (directory, gid_filename, privkey_filename, dbinfo_filename)
57
58     def auth_exists(self, hrn):
59         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
60             self.get_auth_filenames(hrn)
61
62         return os.path.exists(gid_filename) and \
63                os.path.exists(privkey_filename) and \
64                os.path.exists(dbinfo_filename)
65
66     def create_auth(self, hrn, create_parents=False):
67         report.trace("Hierarchy: creating authority: " + hrn)
68
69         # create the parent authority if necessary
70         parent_hrn = get_authority(hrn)
71         if (parent_hrn) and (not self.auth_exists(parent_hrn)) and (create_parents):
72             self.create_auth(parent_hrn, create_parents)
73
74         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
75             self.get_auth_filenames(hrn)
76
77         # create the directory to hold the files
78         try:
79             os.makedirs(directory)\r
80         # if the path already exists then pass\r
81         except OSError, (errno, strerr):\r
82             if errno == 17:\r
83                 pass
84
85         pkey = Keypair(create = True)
86         pkey.save_to_file(privkey_filename)
87
88         gid = self.create_gid(hrn, create_uuid(), pkey)
89         gid.save_to_file(gid_filename)
90
91         # XXX TODO: think up a better way for the dbinfo to work
92
93         dbinfo = get_default_dbinfo()
94         dbinfo_file = file(dbinfo_filename, "w")
95         dbinfo_file.write(str(dbinfo))\r
96         dbinfo_file.close()
97
98     def get_auth_info(self, hrn):
99         #report.trace("Hierarchy: getting authority: " + hrn)
100
101         if not self.auth_exists(hrn):
102             raise MissingAuthority(hrn)
103
104         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
105             self.get_auth_filenames(hrn)
106
107         auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename)
108
109         return auth_info
110
111     def create_gid(self, hrn, uuid, pkey):
112         parent_hrn = get_authority(hrn)
113
114         gid = GID(subject=hrn, uuid=uuid, hrn=hrn)
115
116         if not parent_hrn:
117             # if there is no parent hrn, then it must be self-signed. this
118             # is where we terminate the recursion
119             gid.set_issuer(pkey, hrn)
120         else:
121             # we need the parent's private key in order to sign this GID
122             parent_auth_info = self.get_auth_info(parent_hrn)
123             gid.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
124             gid.set_parent(parent_auth_info.get_gid_object())
125
126         gid.set_pubkey(pkey)
127         gid.encode()
128         gid.sign()
129
130         return gid
131
132     def refresh_gid(self, gid, hrn=None, uuid=None, pubkey=None):
133         # TODO: compute expiration time of GID, refresh it if necessary
134         gid_is_expired = False
135
136         # update the gid if we need to
137         if gid_is_expired or hrn or uuid or pubkey:
138             if not hrn:
139                 hrn = gid.get_hrn()
140             if not uuid:
141                 uuid = gid.get_uuid()
142             if not pubkey:
143                 pubkey = gid.get_pubkey()
144
145             gid = self.create_gid(hrn, uuid, pubkey)
146
147         return gid
148