738171f4cc53d18fc493d0c17a017b7163052cdc
[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     def get_auth_filenames(self, hrn):
47         leaf = get_leaf(hrn)
48         parent_hrn = get_authority(hrn)
49         directory = os.path.join(self.basedir, hrn.replace(".", "/"))
50
51         gid_filename = os.path.join(directory, leaf+".gid")
52         privkey_filename = os.path.join(directory, leaf+".pkey")
53         dbinfo_filename = os.path.join(directory, leaf+".dbinfo")
54
55         return (directory, gid_filename, privkey_filename, dbinfo_filename)
56
57     def auth_exists(self, hrn):
58         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
59             self.get_auth_filenames(hrn)
60
61         return os.path.exists(gid_filename) and \
62                os.path.exists(privkey_filename) and \
63                os.path.exists(dbinfo_filename)
64
65     def create_auth(self, hrn):
66         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
67             self.get_auth_filenames(hrn)
68
69         # create the directory to hold the files
70         try:
71             os.makedirs(directory)\r
72         # if the path already exists then pass\r
73         except OSError, (errno, strerr):\r
74             if errno == 17:\r
75                 pass
76
77         pkey = Keypair(create = True)
78         pkey.save_to_file(privkey_filename)
79
80         gid = self.create_gid(hrn, create_uuid(), pkey)
81         gid.save_to_file(gid_filename)
82
83         # XXX TODO: think up a better way for the dbinfo to work
84
85         dbinfo = get_default_dbinfo()
86         dbinfo_file = file(dbinfo_filename, "w")
87         dbinfo_file.write(str(dbinfo))\r
88         dbinfo_file.close()
89
90     def get_auth_info(self, hrn, can_create=True):
91         if not self.auth_exists(hrn):
92             if not can_create:
93                 return MissingAuthority(hrn)
94
95             self.create_auth(hrn)
96
97         (directory, gid_filename, privkey_filename, dbinfo_filename) = \
98             self.get_auth_filenames(hrn)
99
100         auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename)
101
102         return auth_info
103
104     def create_gid(self, hrn, uuid, pkey):
105         parent_hrn = get_authority(hrn)
106
107         gid = GID(subject=hrn, uuid=uuid)
108
109         if not parent_hrn:
110             # if there is no parent hrn, then it must be self-signed. this
111             # is where we terminate the recursion
112             gid.set_issuer(pkey, hrn)
113         else:
114             # we need the parent's private key in order to sign this GID
115             parent_auth_info = self.get_auth_info(parent_hrn)
116             gid.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
117             gid.set_parent(parent_auth_info.get_gid_object())
118
119         gid.set_pubkey(pkey)
120         gid.sign()
121
122         return gid
123
124     def refresh_gid(self, gid, hrn=None, uuid=None, pubkey=None):
125         # TODO: compute expiration time of GID, refresh it if necessary
126         gid_is_expired = False
127
128         # update the gid if we need to
129         if gid_is_expired or hrn or uuid or pubkey:
130             if not hrn:
131                 hrn = gid.get_hrn()
132             if not uuid:
133                 uuid = gid.get_uuid()
134             if not pubkey:
135                 pubkey = gid.get_pubkey()
136
137             gid = self.create_gid(hrn, uuid, pubkey)
138
139         return gid
140