~ubuntu-branches/ubuntu/vivid/click-reviewers-tools/vivid

« back to all changes in this revision

Viewing changes to clickreviews/cr_security.py

  • Committer: Package Import Robot
  • Author(s): Jamie Strandboge, Alexandre Abreu, Jamie Strandboge
  • Date: 2015-03-09 15:08:44 UTC
  • Revision ID: package-import@ubuntu.com-20150309150844-ks4tego6s8tklx19
Tags: 0.22
[ Alexandre Abreu ]
* Relax the rule that states that webapps with a model search path shouldn't
  have url patterns listed in the command line. In order to avoid confusion,
  we allow this to happen (and it already works fine the command line
  patterns being appended to the locally defined ones). (LP: #1406643)

[ Jamie Strandboge ]
* add testsuite test to verify apparmor-profile can't be specified with
  apparmor
* add apparmor-profile hook tests
* fix test_check_optional_domain_suffix_without_protocol2() to actually test
  with 'nonexistent' key
* debian/control:
  - add python3-yaml to Build-Depends and Depends
  - update Vcs-Bzr to point to lp:click-reviewers-tools
* add snappy-systemd hook tests and update the testsuite accordingly
* apparmor-profile hook may be used anywhere apparmor can be, but not with
  apparmor itself (apparmor-profile is still redflagged)
* implement snappy package.yaml lint tests
* implement snappy package.yaml services tests
* implement snappy readme.md lint tests
* implement snappy package.yaml binaries tests
* one more snappy workaround for check_package_filename()

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
'''cr_security.py: click security checks'''
2
2
#
3
 
# Copyright (C) 2013-2014 Canonical Ltd.
 
3
# Copyright (C) 2013-2015 Canonical Ltd.
4
4
#
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
16
16
 
17
17
from __future__ import print_function
18
18
 
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
22
22
import json
36
36
            ['pay-ui']
37
37
        peer_hooks[my_hook]['required'] = []
38
38
 
 
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'] = []
 
45
 
39
46
        ClickReview.__init__(self, fn, "security", peer_hooks=peer_hooks)
40
47
 
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)
124
131
 
 
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)
 
137
                continue
 
138
            if not isinstance(self.manifest['hooks'][app]['apparmor-profile'],
 
139
                              str):
 
140
                error("manifest malformed: hooks/%s/apparmor-profile is not "
 
141
                      "str" % app)
 
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)
 
146
 
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]
192
214
        return (f, m)
193
215
 
 
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']
 
221
 
 
222
        if not os.path.exists(fn):
 
223
            error("Could not find '%s'" % rel_fn)
 
224
 
 
225
        fh = open_file_read(fn)
 
226
        contents = ""
 
227
        for line in fh.readlines():
 
228
            contents += line
 
229
        fh.close()
 
230
 
 
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)
 
234
 
 
235
        return contents
 
236
 
 
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 "
 
243
                  "manifest" % app)
 
244
        f = self.manifest['hooks'][app]['apparmor-profile']
 
245
        p = self.security_profiles[f]
 
246
        return (f, p)
 
247
 
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:
662
716
                t = 'error'
663
717
                s = "missing required fields: %s" % ", ".join(not_found)
664
718
            self._add_result(t, n, s)
 
719
 
 
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)
 
724
 
 
725
            for v in ['###VAR###',
 
726
                      '###PROFILEATTACH###',
 
727
                      '@{CLICK_DIR}',
 
728
                      '@{APP_PKGNAME}',
 
729
                      '@{APP_VERSION}',
 
730
                      ]:
 
731
                t = 'info'
 
732
                n = 'apparmor_profile_%s (%s)' % (v, f)
 
733
                s = "OK"
 
734
                if v not in p:
 
735
                    self._add_result('warn', n,
 
736
                                     "could not find '%s' in profile" % v)
 
737
                    continue
 
738
                self._add_result(t, n, s)