1
1
'''cr_security.py: click security checks'''
3
# Copyright (C) 2013-2014 Canonical Ltd.
3
# Copyright (C) 2013-2015 Canonical Ltd.
5
5
# This program is free software: you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
17
17
from __future__ import print_function
19
from clickreviews.cr_common import ClickReview, error
19
from clickreviews.cr_common import ClickReview, error, open_file_read
20
20
import clickreviews.cr_common as cr_common
21
21
import clickreviews.apparmor_policy as apparmor_policy
37
37
peer_hooks[my_hook]['required'] = []
39
my_hook2 = 'apparmor-profile'
40
peer_hooks[my_hook2] = dict()
41
# Basically, everything except frameworks
42
peer_hooks[my_hook2]['allowed'] = \
43
ClickReview.service_allowed_peer_hooks
44
peer_hooks[my_hook2]['required'] = []
39
46
ClickReview.__init__(self, fn, "security", peer_hooks=peer_hooks)
41
48
local_copy = os.path.join(os.path.dirname(__file__),
122
129
self._extract_security_manifest(app)
123
130
self.security_apps.append(app)
132
self.security_profiles = dict()
133
self.security_apps_profiles = []
134
for app in self.manifest['hooks']:
135
if 'apparmor-profile' not in self.manifest['hooks'][app]:
136
# msg("Skipped missing apparmor hook for '%s'" % app)
138
if not isinstance(self.manifest['hooks'][app]['apparmor-profile'],
140
error("manifest malformed: hooks/%s/apparmor-profile is not "
142
rel_fn = self.manifest['hooks'][app]['apparmor-profile']
143
self.security_profiles[rel_fn] = \
144
self._extract_security_profile(app)
145
self.security_apps_profiles.append(app)
125
147
def _override_framework_policies(self, overrides):
126
148
# override major framework policies
127
149
self.major_framework_policy.update(overrides)
191
213
m = self.security_manifests[f]
216
def _extract_security_profile(self, app):
217
'''Extract security profile'''
218
d = self.manifest['hooks'][app]['apparmor-profile']
219
fn = os.path.join(self.unpack_dir, d)
220
rel_fn = self.manifest['hooks'][app]['apparmor-profile']
222
if not os.path.exists(fn):
223
error("Could not find '%s'" % rel_fn)
225
fh = open_file_read(fn)
227
for line in fh.readlines():
231
# We could try to run this through apparmor_parser, but that is going
232
# to be system dependent (eg, a profile may reference features on a
233
# new parser and fail here on the local parser)
237
def _get_security_profile(self, app):
238
'''Get the security profile for app'''
239
if app not in self.manifest['hooks']:
240
error("Could not find '%s' in click manifest" % app)
241
elif 'apparmor-profile' not in self.manifest['hooks'][app]:
242
error("Could not find apparmor-profile hook for '%s' in click "
244
f = self.manifest['hooks'][app]['apparmor-profile']
245
p = self.security_profiles[f]
194
248
def _get_policy_versions(self, vendor):
195
249
'''Get the supported AppArmor policy versions'''
196
250
if vendor not in self.aa_policy:
663
717
s = "missing required fields: %s" % ", ".join(not_found)
664
718
self._add_result(t, n, s)
720
def check_apparmor_profile(self):
721
'''Check apparmor-profile'''
722
for app in sorted(self.security_apps_profiles):
723
(f, p) = self._get_security_profile(app)
725
for v in ['###VAR###',
726
'###PROFILEATTACH###',
732
n = 'apparmor_profile_%s (%s)' % (v, f)
735
self._add_result('warn', n,
736
"could not find '%s' in profile" % v)
738
self._add_result(t, n, s)