[apparmor] [patch] [2/3] Make ProfileStorage a class
Christian Boltz
apparmor at cboltz.de
Sun Jul 9 19:32:55 UTC 2017
Hello,
this patch moves ProfileStorage() from aa.py to the new profile_storage.py
and makes it a class. The variable name in __init__() changes (profile
-> self.data), but the content stays the same.
The ProfileStorage class acts like a dict(), but has some additional
checks for unknown keys in place.
Also add some tests to make sure unknown keys really raise an exception.
[ 03-ProfileStorage-class.diff ]
=== modified file ./utils/apparmor/aa.py
--- utils/apparmor/aa.py 2017-07-09 17:33:29.044202432 +0200
+++ utils/apparmor/aa.py 2017-07-09 16:33:42.196851342 +0200
@@ -49,19 +49,21 @@
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
strip_quotes, parse_profile_start_line, re_match_include )
+from apparmor.profile_storage import ProfileStorage
+
import apparmor.rules as aarules
-from apparmor.rule.capability import CapabilityRuleset, CapabilityRule
-from apparmor.rule.change_profile import ChangeProfileRuleset, ChangeProfileRule
-from apparmor.rule.dbus import DbusRuleset, DbusRule
-from apparmor.rule.file import FileRuleset, FileRule
-from apparmor.rule.network import NetworkRuleset, NetworkRule
-from apparmor.rule.ptrace import PtraceRuleset, PtraceRule
-from apparmor.rule.rlimit import RlimitRuleset, RlimitRule
-from apparmor.rule.signal import SignalRuleset, SignalRule
+from apparmor.rule.capability import CapabilityRule
+from apparmor.rule.change_profile import ChangeProfileRule
+from apparmor.rule.dbus import DbusRule
+from apparmor.rule.file import FileRule
+from apparmor.rule.network import NetworkRule
+from apparmor.rule.ptrace import PtraceRule
+from apparmor.rule.rlimit import RlimitRule
+from apparmor.rule.signal import SignalRule
from apparmor.rule import quote_if_needed
ruletypes = ['capability', 'change_profile', 'dbus', 'file', 'network', 'ptrace', 'rlimit', 'signal']
# setup module translations
_ = init_translation()
@@ -428,60 +430,6 @@
return {local_profile: extras[local_profile]}
return dict()
-def ProfileStorage(profilename, hat, calledby):
- # keys used in aa[profile][hat]:
- # a) rules (as dict): alias, include, lvar
- # b) rules (as hasher): allow, deny
- # c) one for each rule class
- # d) other: external, flags, name, profile, attachment, initial_comment, filename, info,
- # profile_keyword, header_comment (these two are currently only set by set_profile_flags())
-
- profile = dict()
-
- # profile['info'] isn't used anywhere, but can be helpful in debugging.
- profile['info'] = {'profile': profilename, 'hat': hat, 'calledby': calledby}
-
- profile['capability'] = CapabilityRuleset()
- profile['dbus'] = DbusRuleset()
- profile['file'] = FileRuleset()
- profile['change_profile'] = ChangeProfileRuleset()
- profile['network'] = NetworkRuleset()
- profile['ptrace'] = PtraceRuleset()
- profile['rlimit'] = RlimitRuleset()
- profile['signal'] = SignalRuleset()
-
- profile['alias'] = dict()
- profile['include'] = dict()
- profile['localinclude'] = dict()
- profile['repo'] = dict()
- profile['lvar'] = dict()
-
- profile['filename'] = ''
- profile['name'] = ''
- profile['attachment'] = ''
- profile['flags'] = ''
- profile['external'] = False
- profile['header_comment'] = ''
- profile['initial_comment'] = ''
- profile['profile_keyword'] = False
- profile['profile'] = False # profile or hat?
-
- profile['allow'] = dict()
- profile['deny'] = dict()
-
- profile['allow']['link'] = hasher()
- profile['deny']['link'] = hasher()
-
- # mount, pivot_root, unix have a .get() fallback to list() - initialize them nevertheless
- profile['allow']['mount'] = list()
- profile['deny']['mount'] = list()
- profile['allow']['pivot_root'] = list()
- profile['deny']['pivot_root'] = list()
- profile['allow']['unix'] = list()
- profile['deny']['unix'] = list()
-
- return profile
-
def create_new_profile(localfile, is_stub=False):
local_profile = hasher()
local_profile[localfile] = ProfileStorage('NEW', localfile, 'create_new_profile()')
=== modified file ./utils/apparmor/profile_storage.py
--- utils/apparmor/profile_storage.py 2017-07-09 18:27:33.212757482 +0200
+++ utils/apparmor/profile_storage.py 2017-07-09 18:05:30.321558068 +0200
@@ -1 +1,102 @@
+# ----------------------------------------------------------------------
+# Copyright (C) 2013 Kshitij Gupta <kgupta8592 at gmail.com>
+# Copyright (C) 2014-2017 Christian Boltz <apparmor at cboltz.de>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# ----------------------------------------------------------------------
+
+
+from apparmor.common import AppArmorBug, hasher
+
+from apparmor.rule.capability import CapabilityRuleset
+from apparmor.rule.change_profile import ChangeProfileRuleset
+from apparmor.rule.dbus import DbusRuleset
+from apparmor.rule.file import FileRuleset
+from apparmor.rule.network import NetworkRuleset
+from apparmor.rule.ptrace import PtraceRuleset
+from apparmor.rule.rlimit import RlimitRuleset
+from apparmor.rule.signal import SignalRuleset
+
+class ProfileStorage:
+ '''class to store the content (header, rules, comments) of a profilename
+
+ Acts like a dict(), but has some additional checks.
+ '''
+
+ def __init__(self, profilename, hat, calledby):
+ data = dict()
+
+ # self.data['info'] isn't used anywhere, but can be helpful in debugging.
+ data['info'] = {'profile': profilename, 'hat': hat, 'calledby': calledby}
+
+ data['capability'] = CapabilityRuleset()
+ data['dbus'] = DbusRuleset()
+ data['file'] = FileRuleset()
+ data['change_profile'] = ChangeProfileRuleset()
+ data['network'] = NetworkRuleset()
+ data['ptrace'] = PtraceRuleset()
+ data['rlimit'] = RlimitRuleset()
+ data['signal'] = SignalRuleset()
+
+ data['alias'] = dict()
+ data['include'] = dict()
+ data['localinclude'] = dict()
+ data['lvar'] = dict()
+ data['repo'] = dict()
+
+ data['filename'] = ''
+ data['name'] = ''
+ data['attachment'] = ''
+ data['flags'] = ''
+ data['external'] = False
+ data['header_comment'] = '' # currently only set by set_profile_flags()
+ data['initial_comment'] = ''
+ data['profile_keyword'] = False # currently only set by set_profile_flags()
+ data['profile'] = False # profile or hat?
+
+ data['allow'] = dict()
+ data['deny'] = dict()
+
+ data['allow']['link'] = hasher()
+ data['deny']['link'] = hasher()
+
+ # mount, pivot_root, unix have a .get() fallback to list() - initialize them nevertheless
+ data['allow']['mount'] = list()
+ data['deny']['mount'] = list()
+ data['allow']['pivot_root'] = list()
+ data['deny']['pivot_root'] = list()
+ data['allow']['unix'] = list()
+ data['deny']['unix'] = list()
+
+ self.data = data
+
+ def __getitem__(self, key):
+ if key in self.data:
+ return self.data[key]
+ else:
+ raise AppArmorBug('attemp to read unknown key %s' % key)
+
+ def __setitem__(self, key, value):
+ # TODO: Most of the keys (containing *Ruleset, dict(), list() or hasher()) should be read-only.
+ # Their content needs to be changed, but the container shouldn't
+ # Note: serialize_profile_from_old_profile.write_prior_segments() and write_prior_segments() expect the container to be writeable!
+ # TODO: check if value has the expected type
+ if key in self.data:
+ self.data[key] = value
+ else:
+ raise AppArmorBug('attemp to set unknown key %s' % key)
+
+ def get(self, key, fallback=None):
+ if key in self.data:
+ return self.data.get(key, fallback)
+ else:
+ raise AppArmorBug('attemp to read unknown key %s' % key)
--- utils/test/test-profile-storage.py 2017-07-09 18:29:04.376428223 +0200
+++ utils/test/test-profile-storage.py 2017-07-09 18:30:59.520012608 +0200
@@ -0,0 +1,41 @@
+#! /usr/bin/python3
+# ------------------------------------------------------------------
+#
+# Copyright (C) 2017 Christian Boltz <apparmor at cboltz.de>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License published by the Free Software Foundation.
+#
+# ------------------------------------------------------------------
+
+import unittest
+from common_test import AATest, setup_all_loops
+
+from apparmor.common import AppArmorBug
+from apparmor.profile_storage import ProfileStorage
+
+class TestUnknownKey(AATest):
+ def AASetup(self):
+ self.storage = ProfileStorage('/test/foo', 'hat', 'TEST')
+
+ def test_read(self):
+ with self.assertRaises(AppArmorBug):
+ self.storage['foo']
+
+ def test_get(self):
+ with self.assertRaises(AppArmorBug):
+ self.storage.get('foo')
+
+ def test_get_with_fallback(self):
+ with self.assertRaises(AppArmorBug):
+ self.storage.get('foo', 'bar')
+
+ def test_set(self):
+ with self.assertRaises(AppArmorBug):
+ self.storage['foo'] = 'bar'
+
+
+setup_all_loops(__name__)
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
Regards,
Christian Boltz
--
A pair of extra monkeys under Coolo's charge would probably help
more... It's clear to us that Coolo's days have now 36 hours...
[Nelson Marques in opensuse-factory]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20170709/2f97dba4/attachment-0001.pgp>
More information about the AppArmor
mailing list