lxc-generate-aa-rules.py revision e2f91e3434ddf2d4cb85d2385057a492eb462166
7cb14f34a92e0a8eae07db027344126bf5c901c9KATOH Yasufumi#!/usr/bin/env python3
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo
7cb14f34a92e0a8eae07db027344126bf5c901c9KATOH Yasufumiimport sys
7cb14f34a92e0a8eae07db027344126bf5c901c9KATOH Yasufumi
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yooblocks = []
7cb14f34a92e0a8eae07db027344126bf5c901c9KATOH Yasufumi
892bd61e0fcc788390abfadd32b1897943290879dlezcano#
953e611ceabed9ccf986e0b234379c2af4bb331aJames Hunt# blocks is an array of paths under which we want to block by
953e611ceabed9ccf986e0b234379c2af4bb331aJames Hunt# default.
953e611ceabed9ccf986e0b234379c2af4bb331aJames Hunt#
953e611ceabed9ccf986e0b234379c2af4bb331aJames Hunt# blocks[0] = ['path' = '/sys', 'children' = [A,B] ]
5c320b769229d713e84b02ed6b7ae1309ac31dbbGuido Trotter# blocks[1] = ['path' = '/proc/sys', 'children' = [ E ] ]
55fc19a1042bca36ae431cb4a51c2abc0ca4d801Stéphane Graber# A = [ 'path' = 'fs', children = [C] ]
55fc19a1042bca36ae431cb4a51c2abc0ca4d801Stéphane Graber# C = [ 'path' = 'cgroup', children = [F] ]
c13c0e08da7dbfecb52e85233ac6cd17afa5d818Stéphane Graber# B = [ 'path' = 'class', children = [D] ]
892bd61e0fcc788390abfadd32b1897943290879dlezcano# D = [ 'path' = 'net', children = [F] ]
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano# E = [ 'path' = 'shm*' ]
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano# F = [ 'path' = '**' ]
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber
a6adab20ff4b58887ff1d4314c5736f54e139386Stéphane Graber
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graberdef add_block(path):
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber for b in blocks:
735f2c6e504a541cbb2592a3f94858bf337a24ffTycho Andersen if b['path'] == path:
ff5e27510540a2ee3c66d8496996313d01bb848fStéphane Graber # duplicate
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber return
2b47bac3f81af9eb8ba392867c78fe3dec40a36aChristian Brauner blocks.append({'path': path.strip(), 'children': []})
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano# @prev is an array of dicts which containing 'path' and
03f09a8ada8dcf15923b5913ec832e005179f962Wolfgang Bumiller# 'children'. @path is a string. We are looking for an entry
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano# in @prev which contains @path, and will return its
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# children array.
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graberdef child_get(prev, path):
94891ea3e44961f4369a7cc67d38c3a98a0e4c54Stéphane Graber for p in prev:
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if p['path'] == path:
813a4837659d5d7a2c0d0abe03c87196747217e9Serge Hallyn return p['children']
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano return None
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano
e71549fc7e1455d7bb8d7bdb26b9276093fd27c6Stéphane Graber
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcanodef add_allow(path):
810567bbbe283c547e4ac837545d1e592916df26Serge Hallyn # find which block we belong to
df3415e02282317348bbd5f9ce66d03e1c81eeecSerge Hallyn found = None
adade80c7e74c5185f63ff009116bf9d30c79876Serge Hallyn for b in blocks:
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano l = len(b['path'])
8a67a2b2eaf28033962a432c214bd3303c29c54cdlezcano if len(path) <= l:
8b8b04f80adf21480c25deb1aae263049ddd6754dlezcano continue
55fc19a1042bca36ae431cb4a51c2abc0ca4d801Stéphane Graber # TODO - should we find the longest match?
55fc19a1042bca36ae431cb4a51c2abc0ca4d801Stéphane Graber if path[0:l] == b['path']:
df3415e02282317348bbd5f9ce66d03e1c81eeecSerge Hallyn found = b
8b8b04f80adf21480c25deb1aae263049ddd6754dlezcano break
8b8b04f80adf21480c25deb1aae263049ddd6754dlezcano if found is None:
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano print("allow with no previous block at %s" % path)
d0a6bd39400a6d14cfec94ad647f3af1bda1e321Christian Brauner sys.exit(1)
d0a6bd39400a6d14cfec94ad647f3af1bda1e321Christian Brauner p = path[l:].strip()
6a85cf91247b7dd9c3faeddceca8dacb96d02cd6Stéphane Graber while p[:1] == "/":
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber p = p[1:]
6a85cf91247b7dd9c3faeddceca8dacb96d02cd6Stéphane Graber prev = b['children']
d0a6bd39400a6d14cfec94ad647f3af1bda1e321Christian Brauner for s in p.split('/'):
d1de19abd0067f38bc08a4a3357de701a4e5571ddlezcano n = {'path': s.strip(), 'children': []}
aa8d013ec5b09cd1cd904173d6234ef126eb2126Peter Simons tmp = child_get(prev, n['path'])
7822022c4c72cee06905b540b89b653491d6f6b2Stéphane Graber if tmp is not None:
6a85cf91247b7dd9c3faeddceca8dacb96d02cd6Stéphane Graber prev = tmp
8a67a2b2eaf28033962a432c214bd3303c29c54cdlezcano else:
aa8d013ec5b09cd1cd904173d6234ef126eb2126Peter Simons prev.append(n)
7822022c4c72cee06905b540b89b653491d6f6b2Stéphane Graber prev = n['children']
6a85cf91247b7dd9c3faeddceca8dacb96d02cd6Stéphane Graber
8a67a2b2eaf28033962a432c214bd3303c29c54cdlezcanoconfig = "config"
aa8d013ec5b09cd1cd904173d6234ef126eb2126Peter Simonsif len(sys.argv) > 1:
7822022c4c72cee06905b540b89b653491d6f6b2Stéphane Graber config = sys.argv[1]
6a85cf91247b7dd9c3faeddceca8dacb96d02cd6Stéphane Graberwith open(config) as f:
99e4008cad9e959b683c6f48411fcf15a92be3b5Michel Normand for x in f.readlines():
10fba81b9d0221b8e47aa1e0b43236413b7d28dfMichel Normand x.strip()
8b8b04f80adf21480c25deb1aae263049ddd6754dlezcano if x[:1] == '#':
9a42db48e0bcf4f34b05a3de1cda23e06f51d131Stéphane Graber continue
3b9246c4aae3f7602c0ad64f5b1204eb559e5b07Daniel Lezcano try:
892bd61e0fcc788390abfadd32b1897943290879dlezcano (cmd, path) = x.split(' ')
except: # blank line
continue
if cmd == "block":
add_block(path)
elif cmd == "allow":
add_allow(path)
else:
print("Unknown command: %s" % cmd)
sys.exit(1)
denies = []
def collect_chars(children, ref, index):
r = ""
for c in children:
if index >= len(c['path']):
continue
if ref[0:index] != c['path'][0:index]:
continue
if c['path'][index] not in r:
r = r + c['path'][index]
return r
def append_deny(s):
s = "%s wklx," % s
if s not in denies:
denies.append(s)
def gen_denies(pathsofar, children):
for c in children:
for char in range(len(c['path'])):
if char == len(c['path'])-1 and c['path'][char] == '*':
continue
if char == len(c['path'])-2:
if c['path'][char:char+2] == '**':
continue
x = collect_chars(children, c['path'], char)
newdeny = "deny %s/%s[^%s]*{,/**}" % (pathsofar,
c['path'][0:char], x)
append_deny(newdeny)
if c['path'] != '**' and c['path'][len(c['path'])-1] != '*':
newdeny = "deny %s/%s?*{,/**}" % (pathsofar, c['path'])
append_deny(newdeny)
elif c['path'] != '**':
newdeny = "deny %s/%s/**" % (pathsofar, c['path'])
append_deny(newdeny)
if len(c['children']) != 0:
newpath = "%s/%s" % (pathsofar, c['path'])
gen_denies(newpath, c['children'])
for b in blocks:
gen_denies(b['path'], b['children'])
denies.sort()
genby = " # generated by: lxc-generate-aa-rules.py"
for a in sys.argv[1:]:
genby += " %s" % a
print(genby)
for d in denies:
print(" %s" % d)