source: tools/policy/policy.py @ d83ee5a

gec13
Last change on this file since d83ee5a was d83ee5a, checked in by Ted Faber <faber@…>, 12 years ago

Load policies

  • Property mode set to 100644
File size: 6.9 KB
Line 
1#!/usr/local/bin/python
2
3import sys
4import os
5import os.path
6import re
7
8import ABAC
9import Creddy
10import zipfile
11import tempfile
12from util import *
13
14class policy:
15    def __init__(self):
16        self.ctxt = ABAC.Context()
17        self.translate = 'keyids'
18        self.names = { }
19        self.keyids = { }
20        self.issuers = { }
21        self.roles = set()
22        self.filename = None
23
24    def read_identity(self, cf):
25        cid = None
26        issuer = False
27        ct = abac_pem_type(cf)
28        if ct is None or ct =='cert':
29            cid = Creddy.ID(cf)
30        elif ct == 'both':
31            tkf = None
32            tcf = None
33            try:
34                tkf, tcf = abac_split_cert(cf)
35                cid = Creddy.ID(tcf)
36                cid.load_privkey(tkf)
37                issuer = True
38            finally:
39                if tkf: os.remove(tkf)
40                if tcf: os.remove(tcf)
41        return (cid, issuer)
42
43    def remember_credentials(self):
44        self.roles = set()
45        for c in self.ctxt.credentials():
46            h = c.head()
47            t = c.tail()
48
49            if h.is_role():
50                self.roles.add(h.role_name())
51
52            if t.is_role():
53                self.roles.add(t.role_name())
54            elif t.is_linking():
55                self.roles.add(re.sub('.*\.', '', t.linked_role()))
56                self.roles.add(t.role_name())
57
58    def read_directory(self, dirname):
59        self.names = { }
60        self.keyids = { }
61        self.issuers = { }
62        self.roles = set()
63        self.filename = None
64        attrs = [ ]
65        for p, dirs, files in os.walk(dirname):
66            for f in files:
67                if not f.endswith('.pem') and not f.endswith('.der'):
68                    continue
69                cf = os.path.join(p, f)
70                try:
71                    cid, issuer = self.read_identity(cf)
72                except RuntimeError, e:
73                    attrs.append(cf)
74                    cid = None
75
76                if cid: 
77                    n = re.sub('_ID.pem', '', cid.cert_filename())
78                    self.names[cid.keyid()] = n
79                    self.keyids[n] = cid.keyid()
80                    if issuer: self.issuers[cid.keyid()] = cid
81                    err = self.ctxt.load_id_chunk(cid.cert_chunk())
82                    if err != ABAC.ABAC_CERT_SUCCESS:
83                        print >>sys.stderr, \
84                                "Cannot load chunk from %s: %d" % (cf, err)
85            for cf in attrs:
86                if self.ctxt.load_attribute_file(cf) != ABAC.ABAC_CERT_SUCCESS:
87                    print >>sys.stderr, "Cannot load %s" % cf
88
89        self.remember_credentials()
90
91    def read_zip(self, zipname):
92        d = tempfile.mkdtemp()
93        zf = zipfile.ZipFile(zipname)
94        zf.extractall(d)
95        self.read_directory(d)
96        remove_dirs(d)
97        self.filename = zipname
98
99    def write_zip(self, zipname):
100        old = os.getcwd()
101        d = tempfile.mkdtemp()
102        z = zipfile.ZipFile(zipname, 'w')
103        os.chdir(d)
104        os.mkdir('creds')
105        seenit = set()
106        issuer_no = 0
107        attr_no = 0
108        for cid in self.issuers.values():
109            if cid not in seenit:
110                try:
111                    f = open(os.path.join('creds', 
112                        'issuer%03d.pem' % issuer_no), 'w')
113                    issuer_no += 1
114                    cid.write_cert(f)
115                    cid.write_privkey(f)
116                    f.close()
117                    seenit.add(cid.cert_chunk())
118                except RuntimeError, e:
119                    print >>sys.stderr, 'Error writing issuer %s' % e
120        for cred in self.ctxt.credentials():
121            issuer_cert = cred.issuer_cert()
122            if issuer_cert not in seenit:
123                try:
124                    f = open(os.path.join('creds', 
125                        'issuer%03d.der' % issuer_no), 'w')
126                    issuer_no += 1
127                    f.write(issuer_cert)
128                    f.close()
129                    seenit.add(issuer_cert)
130                except:
131                    print >>sys.stderr, 'Error writing issuer'
132            attr_cert = cred.attribute_cert()
133            if attr_cert not in seenit:
134                try:
135                    f = open(os.path.join('creds', 
136                        'attr%03d.der' % attr_no), 'w')
137                    attr_no += 1
138                    f.write(attr_cert)
139                    f.close()
140                    seenit.add(attr_cert)
141                except:
142                    print >>sys.stderr, 'Error writing attribute'
143        for p, dirs, files in os.walk('.'):
144            for f in files:
145                z.write(os.path.join(p, f))
146        z.close()
147        self.filename = zipname
148        os.chdir(old)
149        remove_dirs(d)
150
151    def translate_cred_roles(self, cred):
152        h = cred.head()
153        t = cred.tail()
154        issuer = h.principal()
155        role = h.role_name()
156
157        if t.is_principal():
158            return self.replace_keyids("%s says %s acts in role %s" % \
159                    ( issuer, t.principal(), role))
160        elif t.is_role():
161            return self.replace_keyids(("%s says any principal that %s " + \
162                    "says acts in role %s acts in role %s") % \
163                    (issuer, t.principal(), t.role_name(), role))
164        else:
165            lr = re.sub('.*\.', '', t.linked_role())
166            return self.replace_keyids(("%s says any principal that a " + \
167                    "principal that %s says acts in the role of %s " + \
168                    "says acts in role %s acts in role %s") % \
169                    (issuer, t.principal(), lr, t.role_name(), role))
170
171    def translate_cred_sets(self, cred):
172        h = cred.head()
173        t = cred.tail()
174        issuer = h.principal()
175        role = h.role_name()
176
177        if t.is_principal():
178            return self.replace_keyids("%s says %s is in its %s set" % \
179                    ( issuer, t.principal(), role))
180        elif t.is_role():
181            return self.replace_keyids(("%s says any principal in %s's " + \
182                    "%s set is in %s's %s set") % \
183                    (issuer, t.principal(), t.role_name(), issuer, role))
184        else:
185            lr = re.sub('.*\.', '', t.linked_role())
186            return self.replace_keyids(("%s says any principal in %s's " + \
187                    "%s set can put a principal in %s's %s set by putting " + \
188                    " that principal in %s") % \
189                    (issuer, t.principal(), lr, issuer, role, t.role_name()))
190
191    def translate_cred_keyids(self, cred):
192        return self.replace_keyids("%s<-%s" % \
193                (cred.head().string(), cred.tail().string()))
194
195    def translate_cred_null(self, cred):
196        return "%s<-%s" % (cred.head().string(), cred.tail().string())
197
198    def translate_cred(self, cred):
199        if self.translate == 'sets': return self.translate_cred_sets(cred)
200        elif self.translate == 'roles': return self.translate_cred_roles(cred)
201        elif self.translate == 'keyids': return self.translate_cred_keyids(cred)
202        elif self.translate == 'none': return self.translate_cred_null(cred)
203        else: return 'Bad type of translation (%s)???' % self.translate
204
205    @staticmethod
206    def is_issuer(cid):
207        tf = tempfile.TemporaryFile()
208        try:
209            cid.write_privkey(tf)
210            return True
211        except:
212            return False
213
214    def add_credential(self, cert):
215        '''
216        Cert is a Creddy.Credential
217        '''
218        rv = self.ctxt.load_attribute_chunk(cert.cert_chunk())
219        self.remember_credentials()
220        return rv
221
222    def remove_credentials(self, creds):
223        if isinstance(creds, list):
224            cs = set(["%s<-%s" % (c.head().string, c.tail.string()) \
225                    for c in creds])
226        else:
227            cs = set(["%s<-%s" % (creds.head().string, creds.tail.string())])
228
229        nc = ABAC.Context()
230        for c in self.ctxt.credentials():
231            crid = "%s<-%s" % (c.head().string, c.tail.string())
232            if crid not in cs:
233                nc.load_id_chunk(c.issuer_cert())
234                nc.load_attribute_chunk(c.attribute_cert())
235        self.ctxt = nc
236
237    def add_identity(self, cid):
238        '''
239        cid is a Creddy.ID
240        '''
241        rv = self.ctxt.load_attribute_chunk(cid.cert_chunk())
242        if self.is_issuer(cid):
243            self.issuers[cid.keyid()] = cid
244        n = re.sub('_ID.pem', '', cid.cert_filename())
245        self.names[cid.keyid()] = n
246        self.keyids[n] = cid.keyid()
247
248    def credentials(self):
249        return self.ctxt.credentials()
250
251    def query(self, role, principal):
252        return self.ctxt.query(role, principal)
253
254    def principal_names(self):
255        return self.names.keys()
256
257    def principal_items(self):
258        return self.names.items()
259
260    def replace_keyids(self, s):
261        for k,r in self.names.items():
262            s = re.sub(k, r, s)
263        return s
264
265    def name_to_keyid(self, n):
266        return self.keyids.get(n, n)
Note: See TracBrowser for help on using the repository browser.