]>
Commit | Line | Data |
---|---|---|
e2f91e34 | 1 | #!/usr/bin/env python3 |
198b363f SH |
2 | |
3 | import sys | |
4 | ||
5 | blocks = [] | |
c70de0ea | 6 | denies = [] |
198b363f SH |
7 | |
8 | # | |
9 | # blocks is an array of paths under which we want to block by | |
10 | # default. | |
11 | # | |
12 | # blocks[0] = ['path' = '/sys', 'children' = [A,B] ] | |
13 | # blocks[1] = ['path' = '/proc/sys', 'children' = [ E ] ] | |
14 | # A = [ 'path' = 'fs', children = [C] ] | |
15 | # C = [ 'path' = 'cgroup', children = [F] ] | |
16 | # B = [ 'path' = 'class', children = [D] ] | |
17 | # D = [ 'path' = 'net', children = [F] ] | |
18 | # E = [ 'path' = 'shm*' ] | |
19 | # F = [ 'path' = '**' ] | |
20 | ||
21 | ||
22 | def add_block(path): | |
23 | for b in blocks: | |
24 | if b['path'] == path: | |
25 | # duplicate | |
26 | return | |
27 | blocks.append({'path': path.strip(), 'children': []}) | |
28 | ||
94a77f3f SH |
29 | # @prev is an array of dicts which containing 'path' and |
30 | # 'children'. @path is a string. We are looking for an entry | |
31 | # in @prev which contains @path, and will return its | |
32 | # children array. | |
198b363f SH |
33 | def child_get(prev, path): |
34 | for p in prev: | |
35 | if p['path'] == path: | |
94a77f3f | 36 | return p['children'] |
198b363f SH |
37 | return None |
38 | ||
39 | ||
40 | def add_allow(path): | |
41 | # find which block we belong to | |
42 | found = None | |
43 | for b in blocks: | |
44 | l = len(b['path']) | |
45 | if len(path) <= l: | |
46 | continue | |
94a77f3f | 47 | # TODO - should we find the longest match? |
198b363f SH |
48 | if path[0:l] == b['path']: |
49 | found = b | |
50 | break | |
51 | if found is None: | |
52 | print("allow with no previous block at %s" % path) | |
53 | sys.exit(1) | |
54 | p = path[l:].strip() | |
55 | while p[:1] == "/": | |
56 | p = p[1:] | |
57 | prev = b['children'] | |
58 | for s in p.split('/'): | |
59 | n = {'path': s.strip(), 'children': []} | |
60 | tmp = child_get(prev, n['path']) | |
61 | if tmp is not None: | |
62 | prev = tmp | |
63 | else: | |
64 | prev.append(n) | |
65 | prev = n['children'] | |
66 | ||
198b363f SH |
67 | |
68 | def collect_chars(children, ref, index): | |
69 | r = "" | |
70 | for c in children: | |
71 | if index >= len(c['path']): | |
72 | continue | |
73 | if ref[0:index] != c['path'][0:index]: | |
74 | continue | |
75 | if c['path'][index] not in r: | |
76 | r = r + c['path'][index] | |
77 | return r | |
78 | ||
79 | ||
80 | def append_deny(s): | |
81 | s = "%s wklx," % s | |
82 | if s not in denies: | |
83 | denies.append(s) | |
84 | ||
85 | ||
86 | def gen_denies(pathsofar, children): | |
87 | for c in children: | |
88 | for char in range(len(c['path'])): | |
89 | if char == len(c['path'])-1 and c['path'][char] == '*': | |
90 | continue | |
91 | if char == len(c['path'])-2: | |
92 | if c['path'][char:char+2] == '**': | |
93 | continue | |
94 | x = collect_chars(children, c['path'], char) | |
95 | newdeny = "deny %s/%s[^%s]*{,/**}" % (pathsofar, | |
96 | c['path'][0:char], x) | |
97 | append_deny(newdeny) | |
98 | if c['path'] != '**' and c['path'][len(c['path'])-1] != '*': | |
99 | newdeny = "deny %s/%s?*{,/**}" % (pathsofar, c['path']) | |
100 | append_deny(newdeny) | |
101 | elif c['path'] != '**': | |
102 | newdeny = "deny %s/%s/**" % (pathsofar, c['path']) | |
103 | append_deny(newdeny) | |
104 | if len(c['children']) != 0: | |
105 | newpath = "%s/%s" % (pathsofar, c['path']) | |
106 | gen_denies(newpath, c['children']) | |
107 | ||
198b363f | 108 | |
c70de0ea HB |
109 | def main(): |
110 | config = "config" | |
111 | if len(sys.argv) > 1: | |
112 | config = sys.argv[1] | |
113 | ||
114 | lines = None | |
115 | try: | |
116 | with open(config) as f: | |
117 | lines = f.readlines() | |
118 | except FileNotFoundError as err: | |
119 | print("Config file not found") | |
120 | print(err) | |
121 | sys.exit(1) | |
122 | ||
123 | for line in lines: | |
124 | line.strip() | |
125 | if line.startswith('#'): | |
126 | continue | |
127 | try: | |
128 | (cmd, path) = line.split(' ') | |
129 | except: # blank line | |
130 | continue | |
131 | if cmd == "block": | |
132 | add_block(path) | |
133 | elif cmd == "allow": | |
134 | add_allow(path) | |
135 | else: | |
136 | print("Unknown command: %s" % cmd) | |
137 | sys.exit(1) | |
138 | for block in blocks: | |
139 | gen_denies(block['path'], block['children']) | |
140 | ||
141 | denies.sort() | |
142 | ||
143 | genby = " # generated by: lxc-generate-aa-rules.py" | |
144 | for a in sys.argv[1:]: | |
145 | genby += " %s" % a | |
146 | print(genby) | |
147 | for d in denies: | |
148 | print(" %s" % d) | |
149 | ||
198b363f | 150 | |
c70de0ea HB |
151 | if __name__ == "__main__": |
152 | main() |