Merge lp:~jdstrand/click-reviewers-tools/click-reviewers-tools.modern-yaml into lp:click-reviewers-tools
- click-reviewers-tools.modern-yaml
- Merge into trunk
Proposed by
Jamie Strandboge
on 2015-05-11
| Status: | Merged |
|---|---|
| Merged at revision: | 461 |
| Proposed branch: | lp:~jdstrand/click-reviewers-tools/click-reviewers-tools.modern-yaml |
| Merge into: | lp:click-reviewers-tools |
| Diff against target: |
1552 lines (+1312/-22) 8 files modified
clickreviews/cr_framework.py (+6/-7) clickreviews/cr_lint.py (+32/-0) clickreviews/cr_security.py (+464/-7) clickreviews/cr_tests.py (+50/-5) clickreviews/tests/test_cr_lint.py (+77/-0) clickreviews/tests/test_cr_security.py (+675/-1) debian/changelog (+2/-0) run-pep8 (+6/-2) |
| To merge this branch: | bzr merge lp:~jdstrand/click-reviewers-tools/click-reviewers-tools.modern-yaml |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Daniel Holbach (community) | 2015-05-11 | Approve on 2015-05-18 | |
|
Review via email:
|
|||
Commit Message
Description of the Change
* add security yaml checks
* cr_lint.py: don't allow same key in 'binaries' and 'services'
To post a comment you must log in.
| Ricardo Kirkner (ricardokirkner) wrote : | # |
I didn't see anything obvious that would prevent from landing this branch, but I think it would be very beneficial to start spending some time improving the readability of this code base. I'd be happy to work on it provided Martin can approve of the time spent to do so.
lp:~jdstrand/click-reviewers-tools/click-reviewers-tools.modern-yaml
updated
on 2015-05-18
- 449. By Jamie Strandboge on 2015-05-18
-
merge with trunk
- 450. By Jamie Strandboge on 2015-05-18
-
clickreviews/
cr_security. py: implement feedback from MP review
- remove commented out code
- use more descriptive variable name - 451. By Jamie Strandboge on 2015-05-18
-
update comment in check_security_
caps() - 452. By Jamie Strandboge on 2015-05-18
-
clickreviews/
tests/test_ cr_lint. py: update to include test on the error
string too
| Jamie Strandboge (jdstrand) wrote : | # |
Thanks for the reviews, I've updated the branch based on Ricardo's feedback.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === modified file 'clickreviews/cr_framework.py' |
| 2 | --- clickreviews/cr_framework.py 2015-04-03 20:51:02 +0000 |
| 3 | +++ clickreviews/cr_framework.py 2015-05-18 21:07:49 +0000 |
| 4 | @@ -66,12 +66,12 @@ |
| 5 | def _extract_framework_policy(self): |
| 6 | '''Get framework policy files''' |
| 7 | policy_dict = dict() |
| 8 | - unknown_dict = dict() |
| 9 | + unknown = [] |
| 10 | fpdir = os.path.join(self.unpack_dir, "meta", "framework-policy") |
| 11 | for i in glob.glob("%s/*" % fpdir): |
| 12 | rel_i = os.path.basename(i) |
| 13 | if not os.path.isdir(i) or rel_i not in self.framework_policy_dirs: |
| 14 | - unknown_dict.append(os.path.relpath(i, self.unpack_dir)) |
| 15 | + unknown.append(os.path.relpath(i, self.unpack_dir)) |
| 16 | continue |
| 17 | |
| 18 | policy_dict[rel_i] = dict() |
| 19 | @@ -79,21 +79,20 @@ |
| 20 | rel_j = os.path.basename(j) |
| 21 | if not os.path.isdir(j) or \ |
| 22 | rel_j not in self.framework_policy_subdirs: |
| 23 | - unknown_dict.append(os.path.relpath(j, self.unpack_dir)) |
| 24 | + unknown.append(os.path.relpath(j, self.unpack_dir)) |
| 25 | continue |
| 26 | |
| 27 | policy_dict[rel_i][rel_j] = dict() |
| 28 | for k in glob.glob("%s/*" % j): |
| 29 | rel_k = os.path.basename(k) |
| 30 | if not os.path.isfile(k): |
| 31 | - unknown_dict.append(os.path.relpath(k, |
| 32 | - self.unpack_dir)) |
| 33 | + unknown.append(os.path.relpath(k, self.unpack_dir)) |
| 34 | continue |
| 35 | |
| 36 | fh = open_file_read(k) |
| 37 | policy_dict[rel_i][rel_j][rel_k] = fh.read() |
| 38 | fh.close() |
| 39 | - return (policy_dict, unknown_dict) |
| 40 | + return (policy_dict, unknown) |
| 41 | |
| 42 | def _has_framework_in_metadir(self): |
| 43 | '''Check if snap has meta/<name>.framework''' |
| 44 | @@ -223,7 +222,7 @@ |
| 45 | if j not in self.framework_policy[other] or \ |
| 46 | k not in self.framework_policy[other][j]: |
| 47 | t = 'error' |
| 48 | - s = "Could not find mathcing '%s/%s/%s'" % (other, |
| 49 | + s = "Could not find matching '%s/%s/%s'" % (other, |
| 50 | j, k) |
| 51 | self._add_result(t, n, s) |
| 52 | |
| 53 | |
| 54 | === modified file 'clickreviews/cr_lint.py' |
| 55 | --- clickreviews/cr_lint.py 2015-05-01 15:18:50 +0000 |
| 56 | +++ clickreviews/cr_lint.py 2015-05-18 21:07:49 +0000 |
| 57 | @@ -1055,3 +1055,35 @@ |
| 58 | t = 'warn' |
| 59 | s = "meta/readme.md is too short" |
| 60 | self._add_result(t, n, s) |
| 61 | + |
| 62 | + def check_snappy_services_and_binaries(self): |
| 63 | + '''Services and binaries should not overlap''' |
| 64 | + if not self.is_snap: |
| 65 | + return |
| 66 | + for exe_t in ['binaries', 'services']: |
| 67 | + if exe_t not in self.pkg_yaml: |
| 68 | + break |
| 69 | + if exe_t == 'binaries': |
| 70 | + other_exe_t = 'services' |
| 71 | + else: |
| 72 | + other_exe_t = 'binaries' |
| 73 | + |
| 74 | + if other_exe_t not in self.pkg_yaml: |
| 75 | + break |
| 76 | + |
| 77 | + for a in self.pkg_yaml[exe_t]: |
| 78 | + if 'name' not in a: |
| 79 | + continue |
| 80 | + # handle 'exec' in binaries |
| 81 | + app = os.path.basename(a['name']) |
| 82 | + |
| 83 | + t = 'info' |
| 84 | + n = 'snappy_%s_in_%s' % (app, other_exe_t) |
| 85 | + s = 'OK' |
| 86 | + for other_a in self.pkg_yaml[other_exe_t]: |
| 87 | + other_app = os.path.basename(other_a['name']) |
| 88 | + if app == other_app: |
| 89 | + t = 'error' |
| 90 | + s = "'%s' in both 'services' and 'binaries'" % app |
| 91 | + break |
| 92 | + self._add_result(t, n, s) |
| 93 | |
| 94 | === modified file 'clickreviews/cr_security.py' |
| 95 | --- clickreviews/cr_security.py 2015-05-04 18:29:04 +0000 |
| 96 | +++ clickreviews/cr_security.py 2015-05-18 21:07:49 +0000 |
| 97 | @@ -19,6 +19,7 @@ |
| 98 | from clickreviews.cr_common import ClickReview, error, open_file_read |
| 99 | import clickreviews.cr_common as cr_common |
| 100 | import clickreviews.apparmor_policy as apparmor_policy |
| 101 | +import copy |
| 102 | import json |
| 103 | import os |
| 104 | |
| 105 | @@ -68,8 +69,7 @@ |
| 106 | 'comment', |
| 107 | 'copyright', |
| 108 | 'name'] |
| 109 | - self.required_fields = ['policy_groups', |
| 110 | - 'policy_version'] |
| 111 | + self.required_fields = ['policy_version'] |
| 112 | self.redflag_fields = ['abstractions', |
| 113 | 'binary', |
| 114 | 'read_path', |
| 115 | @@ -147,6 +147,9 @@ |
| 116 | self._extract_security_profile(app) |
| 117 | self.security_apps_profiles.append(app) |
| 118 | |
| 119 | + # snappy |
| 120 | + self.sec_skipped_types = ['oem'] # these don't need security items |
| 121 | + |
| 122 | def _override_framework_policies(self, overrides): |
| 123 | # override major framework policies |
| 124 | self.major_framework_policy.update(overrides) |
| 125 | @@ -464,7 +467,27 @@ |
| 126 | continue |
| 127 | self._add_result(t, n, s) |
| 128 | |
| 129 | - if m['template'] not in self._get_templates(vendor, version): |
| 130 | + found = False |
| 131 | + if m['template'] in self._get_templates(vendor, version): |
| 132 | + found = True |
| 133 | + elif self.is_snap: |
| 134 | + frameworks = [] |
| 135 | + if 'framework' in self.pkg_yaml: |
| 136 | + frameworks = [x.strip() for x in |
| 137 | + self.pkg_yaml['framework'].split(',')] |
| 138 | + elif 'frameworks' in self.pkg_yaml: |
| 139 | + frameworks = self.pkg_yaml['frameworks'] |
| 140 | + elif 'type' in self.pkg_yaml and \ |
| 141 | + self.pkg_yaml['type'] == 'framework': |
| 142 | + # frameworks may reference their own policy groups |
| 143 | + frameworks.append(self.pkg_yaml['name']) |
| 144 | + |
| 145 | + for f in frameworks: |
| 146 | + if m['template'].startswith("%s_" % f): |
| 147 | + found = True |
| 148 | + break |
| 149 | + |
| 150 | + if not found: |
| 151 | t = 'error' |
| 152 | s = "specified unsupported template '%s'" % m['template'] |
| 153 | |
| 154 | @@ -590,7 +613,7 @@ |
| 155 | n = 'policy_groups_exists_%s (%s)' % (app, f) |
| 156 | if 'policy_groups' not in m: |
| 157 | # If template not specified, we just use the default |
| 158 | - self._add_result('warn', n, 'no policy groups specified') |
| 159 | + self._add_result('info', n, 'no policy groups specified') |
| 160 | continue |
| 161 | elif 'policy_version' not in m: |
| 162 | self._add_result('error', n, |
| 163 | @@ -625,6 +648,18 @@ |
| 164 | s = 'duplicate policy groups found: %s' % ", ".join(tmp) |
| 165 | self._add_result(t, n, s) |
| 166 | |
| 167 | + frameworks = [] |
| 168 | + if self.is_snap: |
| 169 | + if 'framework' in self.pkg_yaml: |
| 170 | + frameworks = [x.strip() for x in |
| 171 | + self.pkg_yaml['framework'].split(',')] |
| 172 | + elif 'frameworks' in self.pkg_yaml: |
| 173 | + frameworks = self.pkg_yaml['frameworks'] |
| 174 | + elif 'type' in self.pkg_yaml and \ |
| 175 | + self.pkg_yaml['type'] == 'framework': |
| 176 | + # frameworks may reference their own policy groups |
| 177 | + frameworks.append(self.pkg_yaml['name']) |
| 178 | + |
| 179 | # If we got here, we can see if valid policy groups were specified |
| 180 | for i in m['policy_groups']: |
| 181 | t = 'info' |
| 182 | @@ -640,10 +675,20 @@ |
| 183 | continue |
| 184 | |
| 185 | found = False |
| 186 | + framework_found = False |
| 187 | for j in policy_groups: |
| 188 | if i == os.path.basename(j): |
| 189 | found = True |
| 190 | break |
| 191 | + else: |
| 192 | + for f in frameworks: |
| 193 | + if i.startswith("%s_" % f): |
| 194 | + framework_found = True |
| 195 | + break |
| 196 | + if framework_found: |
| 197 | + found = True |
| 198 | + break |
| 199 | + |
| 200 | if not found: |
| 201 | t = 'error' |
| 202 | s = "unsupported policy_group '%s'" % i |
| 203 | @@ -656,7 +701,11 @@ |
| 204 | l = None |
| 205 | manual_review = False |
| 206 | |
| 207 | - aa_type = self._get_policy_group_type(vendor, version, i) |
| 208 | + if framework_found: |
| 209 | + aa_type = 'framework' |
| 210 | + else: |
| 211 | + aa_type = self._get_policy_group_type(vendor, version, |
| 212 | + i) |
| 213 | if i == "debug": |
| 214 | t = 'error' |
| 215 | s = "(REJECT) %s policy group " % aa_type + \ |
| 216 | @@ -668,9 +717,11 @@ |
| 217 | if i == "debug": |
| 218 | l = 'http://askubuntu.com/a/562123/94326' |
| 219 | manual_review = True |
| 220 | + elif aa_type == 'framework': |
| 221 | + s = "OK (matches '%s' framework)" % i.split('_')[0] |
| 222 | elif aa_type != "common": |
| 223 | t = 'error' |
| 224 | - s = "policy group '%s' has" % i + \ |
| 225 | + s = "policy group '%s' has " % i + \ |
| 226 | "unknown type '%s'" % (aa_type) |
| 227 | self._add_result(t, n, s, l, manual_review=manual_review) |
| 228 | |
| 229 | @@ -720,7 +771,7 @@ |
| 230 | (f, m) = self._get_security_manifest(app) |
| 231 | |
| 232 | t = 'info' |
| 233 | - n = 'ignored_fields (%s)' % f |
| 234 | + n = 'required_fields (%s)' % f |
| 235 | s = "OK" |
| 236 | not_found = [] |
| 237 | for i in self.required_fields: |
| 238 | @@ -751,3 +802,409 @@ |
| 239 | "could not find '%s' in profile" % v) |
| 240 | continue |
| 241 | self._add_result(t, n, s) |
| 242 | + |
| 243 | + # This will be really nice to get rid of when the click compat manifest |
| 244 | + # is gone |
| 245 | + def _compare_security_yamls(self, yaml, click_m): |
| 246 | + '''Compare two security yamls''' |
| 247 | + def find_match(name, key, value, my_dict): |
| 248 | + if 'name' in my_dict and my_dict['name'] == name and \ |
| 249 | + key in my_dict and my_dict[key] == value: |
| 250 | + return True |
| 251 | + return False |
| 252 | + |
| 253 | + for first in [yaml, click_m]: |
| 254 | + if first == yaml: |
| 255 | + second = click_m |
| 256 | + second_m = "click-manifest" |
| 257 | + first_m = "package.yaml" |
| 258 | + else: |
| 259 | + second = yaml |
| 260 | + first_m = "click-manifest" |
| 261 | + second_m = "package.yaml" |
| 262 | + for exe_t in ['binaries', 'services']: |
| 263 | + t = 'info' |
| 264 | + n = 'yaml_%s' % exe_t |
| 265 | + s = 'OK' |
| 266 | + if exe_t in first and exe_t not in second: |
| 267 | + t = 'error' |
| 268 | + s = "%s missing '%s'" % (second_m, exe_t) |
| 269 | + elif exe_t not in first and exe_t in second: |
| 270 | + t = 'error' |
| 271 | + s = "%s has extra '%s'" % (second_m, exe_t) |
| 272 | + self._add_result(t, n, s) |
| 273 | + |
| 274 | + if t == 'error': |
| 275 | + continue |
| 276 | + elif exe_t not in first and exe_t not in second: |
| 277 | + continue |
| 278 | + |
| 279 | + t = 'info' |
| 280 | + n = 'yaml_%s_entries' % exe_t |
| 281 | + s = 'OK' |
| 282 | + if len(first[exe_t]) < len(second[exe_t]): |
| 283 | + t = 'error' |
| 284 | + s = "%s has extra '%s' entries" % (second_m, exe_t) |
| 285 | + self._add_result(t, n, s) |
| 286 | + |
| 287 | + for fapp in first[exe_t]: |
| 288 | + t = 'info' |
| 289 | + n = 'yaml_%s_%s' % (exe_t, fapp['name']) |
| 290 | + s = 'OK' |
| 291 | + sapp = None |
| 292 | + for tmp in second[exe_t]: |
| 293 | + if tmp['name'] == fapp['name']: |
| 294 | + sapp = tmp |
| 295 | + if sapp is None: |
| 296 | + t = 'error' |
| 297 | + s = "%s missing '%s'" % (second_m, fapp['name']) |
| 298 | + self._add_result(t, n, s) |
| 299 | + continue |
| 300 | + elif first == yaml and "security-override" in fapp or \ |
| 301 | + second == yaml and "security-override" in sapp: |
| 302 | + # no reason to check security-override since apparmor |
| 303 | + # hook entry will point to this file |
| 304 | + continue |
| 305 | + elif first == yaml and "security-policy" in fapp or \ |
| 306 | + second == yaml and "security-policy" in sapp: |
| 307 | + # no reason to check security-policy since apparmor |
| 308 | + # profile hook is used instead |
| 309 | + continue |
| 310 | + elif 'caps' not in fapp and 'caps' not in sapp and \ |
| 311 | + second == yaml and 'security-template' not in sapp: |
| 312 | + # no caps in yaml, policy_groups is empty in click |
| 313 | + # manifest, unless security-template is in yaml |
| 314 | + t = 'error' |
| 315 | + s = "'policy_groups' not found in click manifest " + \ |
| 316 | + "(should default to ['networking'])" |
| 317 | + self._add_result(t, n, s) |
| 318 | + continue |
| 319 | + self._add_result(t, n, s) |
| 320 | + |
| 321 | + for key in ['security-template', 'caps']: |
| 322 | + t = 'info' |
| 323 | + n = 'yaml_%s_%s' % (exe_t, second_m) |
| 324 | + s = 'OK' |
| 325 | + |
| 326 | + if key not in fapp: |
| 327 | + continue |
| 328 | + |
| 329 | + if key == 'caps': |
| 330 | + fapp['caps'] = set(fapp['caps']) |
| 331 | + if 'caps' in sapp: |
| 332 | + sapp['caps'] = set(sapp['caps']) |
| 333 | + |
| 334 | + if not find_match(fapp['name'], key, fapp[key], sapp): |
| 335 | + # handle snappy defaults for security-template |
| 336 | + # and caps |
| 337 | + if key == 'security-template' and \ |
| 338 | + second == yaml and key not in sapp and \ |
| 339 | + key in fapp and fapp[key] == 'default': |
| 340 | + # if yaml missing security-template, click may |
| 341 | + # specify 'default' |
| 342 | + self._add_result(t, n, s) |
| 343 | + continue |
| 344 | + elif key == 'caps' and second == yaml and \ |
| 345 | + 'security-template' in sapp and \ |
| 346 | + key not in sapp and \ |
| 347 | + (key not in fapp or key in fapp and |
| 348 | + fapp[key] == set([])): |
| 349 | + # when security-template is specified, then |
| 350 | + # caps won't default to 'networking' when |
| 351 | + # missing, so click manifest can omit or be [] |
| 352 | + self._add_result(t, n, s) |
| 353 | + continue |
| 354 | + elif key == 'caps' and second == yaml and \ |
| 355 | + 'security-template' not in sapp and \ |
| 356 | + key not in sapp and key in fapp and \ |
| 357 | + fapp[key] == set(['networking']): |
| 358 | + # no caps in yaml, policy_groups is networking |
| 359 | + # in click manifest wen security-template not |
| 360 | + # specified in yaml |
| 361 | + self._add_result(t, n, s) |
| 362 | + continue |
| 363 | + elif key == 'caps' and second == click_m and \ |
| 364 | + key not in sapp and key in fapp and \ |
| 365 | + fapp[key] == set([]): |
| 366 | + # no caps in click manifest, caps is [] in yaml |
| 367 | + self._add_result(t, n, s) |
| 368 | + continue |
| 369 | + t = 'error' |
| 370 | + s = "%s has different '%s' for '%s'" % \ |
| 371 | + (second_m, key, fapp['name']) + \ |
| 372 | + " - '%s:%s' vs '%s:%s'" % (first_m, fapp, |
| 373 | + second_m, sapp) |
| 374 | + self._add_result(t, n, s) |
| 375 | + |
| 376 | + def _convert_click_security_to_yaml(self): |
| 377 | + '''Convert click manifest to yaml''' |
| 378 | + converted = dict() |
| 379 | + for app in sorted(self.security_apps): |
| 380 | + if 'snappy-systemd' in self.manifest['hooks'][app]: |
| 381 | + key = 'services' |
| 382 | + elif 'bin-path' in self.manifest['hooks'][app]: |
| 383 | + key = 'binaries' |
| 384 | + else: |
| 385 | + t = 'error' |
| 386 | + n = 'yaml_click_%s' % app |
| 387 | + s = "click manifest missing 'snappy-systemd/bin-path' for " + \ |
| 388 | + "'%s'" % app |
| 389 | + self._add_result(t, n, s) |
| 390 | + continue |
| 391 | + |
| 392 | + if key not in converted: |
| 393 | + converted[key] = [] |
| 394 | + tmp = dict() |
| 395 | + tmp['name'] = app |
| 396 | + |
| 397 | + (f, m) = self._get_security_manifest(app) |
| 398 | + if 'template' in m: |
| 399 | + tmp['security-template'] = m['template'] |
| 400 | + |
| 401 | + if 'policy_groups' in m: |
| 402 | + tmp['caps'] = m['policy_groups'] |
| 403 | + |
| 404 | + converted[key].append(copy.deepcopy(tmp)) |
| 405 | + |
| 406 | + for app in sorted(self.security_apps_profiles): |
| 407 | + if 'snappy-systemd' in self.manifest['hooks'][app]: |
| 408 | + key = 'services' |
| 409 | + elif 'bin-path' in self.manifest['hooks'][app]: |
| 410 | + key = 'binaries' |
| 411 | + else: |
| 412 | + t = 'error' |
| 413 | + n = 'yaml_click_%s' % app |
| 414 | + s = "click manifest missing 'snappy-systemd/bin-path' for " + \ |
| 415 | + "'%s'" % app |
| 416 | + self._add_result(t, n, s) |
| 417 | + continue |
| 418 | + |
| 419 | + if key not in converted: |
| 420 | + converted[key] = [] |
| 421 | + tmp = dict() |
| 422 | + tmp['name'] = app |
| 423 | + |
| 424 | + (f, p) = self._get_security_profile(app) |
| 425 | + tmp['security-policy'] = {'apparmor': f} |
| 426 | + |
| 427 | + converted[key].append(copy.deepcopy(tmp)) |
| 428 | + |
| 429 | + return copy.deepcopy(converted) |
| 430 | + |
| 431 | + def check_security_yaml_and_click(self): |
| 432 | + '''Verify click and security yaml are in sync (not including |
| 433 | + override) |
| 434 | + ''' |
| 435 | + if not self.is_snap or self.pkg_yaml['type'] in self.sec_skipped_types: |
| 436 | + return |
| 437 | + |
| 438 | + # setup a small dict that is a subset of self.pkg_yaml |
| 439 | + yml = dict() |
| 440 | + for exe_t in ['binaries', 'services']: |
| 441 | + if exe_t not in self.pkg_yaml: |
| 442 | + continue |
| 443 | + yml[exe_t] = copy.deepcopy(self.pkg_yaml[exe_t]) |
| 444 | + for item in yml[exe_t]: |
| 445 | + # account for binaries doing different things with 'name/exec' |
| 446 | + if exe_t == 'binaries' and 'exec' not in item and \ |
| 447 | + '/' in item['name']: |
| 448 | + item['name'] = os.path.basename(item['name']) |
| 449 | + |
| 450 | + converted = self._convert_click_security_to_yaml() |
| 451 | + self._compare_security_yamls(yml, converted) |
| 452 | + |
| 453 | + def check_security_yaml_override_and_click(self): |
| 454 | + '''Verify click and security yaml override are in sync''' |
| 455 | + if not self.is_snap or self.pkg_yaml['type'] in self.sec_skipped_types: |
| 456 | + return |
| 457 | + |
| 458 | + for exe_t in ['services', 'binaries']: |
| 459 | + if exe_t not in self.pkg_yaml: |
| 460 | + continue |
| 461 | + |
| 462 | + for item in self.pkg_yaml[exe_t]: |
| 463 | + if 'name' not in item: |
| 464 | + t = 'error' |
| 465 | + n = 'yaml_override_click_name' |
| 466 | + s = "package.yaml malformed. Could not find 'name' " + \ |
| 467 | + "for entry in '%s'" % item |
| 468 | + self._add_result(t, n, s) |
| 469 | + continue |
| 470 | + |
| 471 | + app = item['name'] |
| 472 | + t = 'info' |
| 473 | + n = 'yaml_override_click_%s' % app |
| 474 | + s = "OK" |
| 475 | + if 'security-override' not in item: |
| 476 | + s = "OK (skipping unspecified override)" |
| 477 | + elif 'apparmor' not in item['security-override']: |
| 478 | + t = 'error' |
| 479 | + s = "'apparmor' not specified in 'security-override' " + \ |
| 480 | + "for '%s'" % app |
| 481 | + elif item['security-override']['apparmor'] not in \ |
| 482 | + self.security_manifests: |
| 483 | + t = 'error' |
| 484 | + s = "'%s' not found in click manifest for '%s'" % \ |
| 485 | + (item['security-override']['apparmor'], app) |
| 486 | + # NOTE: we skip 'seccomp' because there isn't currently a |
| 487 | + # click hook for it |
| 488 | + self._add_result(t, n, s) |
| 489 | + |
| 490 | + def check_security_yaml_override(self): |
| 491 | + '''Verify security yaml override''' |
| 492 | + for exe_t in ['services', 'binaries']: |
| 493 | + if exe_t not in self.pkg_yaml: |
| 494 | + continue |
| 495 | + |
| 496 | + for item in self.pkg_yaml[exe_t]: |
| 497 | + if 'name' not in item: |
| 498 | + t = 'error' |
| 499 | + n = 'yaml_override_name' |
| 500 | + s = "package.yaml malformed. Could not find 'name' " + \ |
| 501 | + "for entry in '%s'" % item |
| 502 | + self._add_result(t, n, s) |
| 503 | + continue |
| 504 | + |
| 505 | + app = item['name'] |
| 506 | + t = 'info' |
| 507 | + n = 'yaml_override_format_%s' % app |
| 508 | + s = "OK" |
| 509 | + if 'security-override' not in item: |
| 510 | + s = "OK (skipping unspecified override)" |
| 511 | + elif 'apparmor' not in item['security-override']: |
| 512 | + t = 'error' |
| 513 | + s = "'apparmor' not specified in 'security-override' " + \ |
| 514 | + "for '%s'" % app |
| 515 | + elif 'seccomp' not in item['security-override']: |
| 516 | + t = 'error' |
| 517 | + s = "'seccomp' not specified in 'security-override' " + \ |
| 518 | + "for '%s'" % app |
| 519 | + self._add_result(t, n, s) |
| 520 | + |
| 521 | + def check_security_yaml_policy(self): |
| 522 | + '''Verify security yaml policy''' |
| 523 | + for exe_t in ['services', 'binaries']: |
| 524 | + if exe_t not in self.pkg_yaml: |
| 525 | + continue |
| 526 | + |
| 527 | + for item in self.pkg_yaml[exe_t]: |
| 528 | + if 'name' not in item: |
| 529 | + t = 'error' |
| 530 | + n = 'yaml_policy_name' |
| 531 | + s = "package.yaml malformed. Could not find 'name' " + \ |
| 532 | + "for entry in '%s'" % item |
| 533 | + self._add_result(t, n, s) |
| 534 | + continue |
| 535 | + |
| 536 | + app = item['name'] |
| 537 | + t = 'info' |
| 538 | + n = 'yaml_policy_format_%s' % app |
| 539 | + s = "OK" |
| 540 | + if 'security-policy' not in item: |
| 541 | + s = "OK (skipping unspecified policy)" |
| 542 | + elif 'apparmor' not in item['security-policy']: |
| 543 | + t = 'error' |
| 544 | + s = "'apparmor' not specified in 'security-policy' " + \ |
| 545 | + "for '%s'" % app |
| 546 | + elif 'seccomp' not in item['security-policy']: |
| 547 | + t = 'error' |
| 548 | + s = "'seccomp' not specified in 'security-policy' for " + \ |
| 549 | + "'%s'" % app |
| 550 | + self._add_result(t, n, s) |
| 551 | + |
| 552 | + # TODO: error if specified |
| 553 | + |
| 554 | + def check_security_yaml_combinations(self): |
| 555 | + '''Verify security yaml uses valid combinations''' |
| 556 | + if not self.is_snap or self.pkg_yaml['type'] in self.sec_skipped_types: |
| 557 | + return |
| 558 | + |
| 559 | + for exe_t in ['services', 'binaries']: |
| 560 | + if exe_t not in self.pkg_yaml: |
| 561 | + continue |
| 562 | + for item in self.pkg_yaml[exe_t]: |
| 563 | + if 'name' not in item: |
| 564 | + t = 'error' |
| 565 | + n = 'yaml_combinations_name' |
| 566 | + s = "package.yaml malformed. Could not find 'name' " + \ |
| 567 | + "for entry in '%s'" % item |
| 568 | + self._add_result(t, n, s) |
| 569 | + continue |
| 570 | + |
| 571 | + app = item['name'] |
| 572 | + |
| 573 | + t = 'info' |
| 574 | + n = 'yaml_combinations_%s' % app |
| 575 | + s = "OK" |
| 576 | + if "security-policy" in item: |
| 577 | + for i in ['security-override', 'security-template', |
| 578 | + 'caps']: |
| 579 | + if i in item: |
| 580 | + t = 'error' |
| 581 | + s = "Found '%s' with 'security-policy'" % (i) |
| 582 | + break |
| 583 | + elif "security-override" in item: |
| 584 | + for i in ['security-policy', 'security-template', 'caps']: |
| 585 | + if i in item: |
| 586 | + t = 'error' |
| 587 | + s = "Found '%s' with 'security-override'" % (i) |
| 588 | + break |
| 589 | + self._add_result(t, n, s) |
| 590 | + |
| 591 | + def check_security_template(self): |
| 592 | + '''Check snap security-template''' |
| 593 | + if not self.is_snap or self.pkg_yaml['type'] in self.sec_skipped_types: |
| 594 | + return |
| 595 | + |
| 596 | + for exe_t in ['services', 'binaries']: |
| 597 | + if exe_t not in self.pkg_yaml: |
| 598 | + continue |
| 599 | + for item in self.pkg_yaml[exe_t]: |
| 600 | + if 'security-template' not in item: |
| 601 | + tmpl = "" |
| 602 | + else: |
| 603 | + tmpl = item['security-template'] |
| 604 | + |
| 605 | + if 'name' not in item: |
| 606 | + t = 'error' |
| 607 | + n = 'yaml_security-template_name' |
| 608 | + s = "package.yaml malformed. Could not find 'name' " + \ |
| 609 | + "for entry in '%s'" % item |
| 610 | + self._add_result(t, n, s) |
| 611 | + continue |
| 612 | + |
| 613 | + # Handle bin/exec concept with bianries |
| 614 | + app = os.path.basename(item['name']) |
| 615 | + |
| 616 | + t = 'info' |
| 617 | + n = 'yaml_security-template_%s' % app |
| 618 | + s = "OK" |
| 619 | + if not isinstance(tmpl, str): |
| 620 | + t = 'error' |
| 621 | + s = "'%s/%s' malformed: '%s' is not str" % (exe_t, app, |
| 622 | + tmpl) |
| 623 | + self._add_result(t, n, s) |
| 624 | + continue |
| 625 | + self._add_result(t, n, s) |
| 626 | + |
| 627 | + t = 'info' |
| 628 | + n = 'yaml_security-template_in_manifest_%s' % app |
| 629 | + s = "OK" |
| 630 | + if app not in self.manifest['hooks']: |
| 631 | + t = 'error' |
| 632 | + s = "'%s' not found in click manifest" % app |
| 633 | + self._add_result(t, n, s) |
| 634 | + continue |
| 635 | + elif 'apparmor' not in self.manifest['hooks'][app] and \ |
| 636 | + 'apparmor-profile' not in self.manifest['hooks'][app]: |
| 637 | + t = 'error' |
| 638 | + s = "'apparmor' not found in click manifest for '%s'" % app |
| 639 | + self._add_result(t, n, s) |
| 640 | + continue |
| 641 | + |
| 642 | + # TODO: error if not 'common' or is 'unconfined' |
| 643 | + |
| 644 | + def check_security_caps(self): |
| 645 | + '''Check snap caps''' |
| 646 | + # TODO - check caps on their own instead of just via compat click |
| 647 | + # manifest |
| 648 | |
| 649 | === modified file 'clickreviews/cr_tests.py' |
| 650 | --- clickreviews/cr_tests.py 2015-04-03 22:17:04 +0000 |
| 651 | +++ clickreviews/cr_tests.py 2015-05-18 21:07:49 +0000 |
| 652 | @@ -745,12 +745,57 @@ |
| 653 | self._update_test_readme_md() |
| 654 | |
| 655 | def set_test_security_manifest(self, app, key, value): |
| 656 | - '''Set key in security manifest to value. If value is None, remove |
| 657 | - key''' |
| 658 | + '''Set key in security manifest and package.yaml to value. If value is |
| 659 | + None, remove key, if key is None, remove app. |
| 660 | + ''' |
| 661 | + # package.yaml - we don't know if it is a service or a binary with |
| 662 | + # these values, so just use 'binaries' |
| 663 | + if key is None: |
| 664 | + if 'binaries' in self.test_pkg_yaml: |
| 665 | + for b in self.test_pkg_yaml['binaries']: |
| 666 | + if 'name' in b and b['name'] == app: |
| 667 | + self.test_pkg_yaml['binaries'].remove(b) |
| 668 | + break |
| 669 | + elif value is None: |
| 670 | + if 'binaries' in self.test_pkg_yaml: |
| 671 | + found = False |
| 672 | + for b in self.test_pkg_yaml['binaries']: |
| 673 | + if 'name' in b and b['name'] == app: |
| 674 | + if key in b: |
| 675 | + b.remove(key) |
| 676 | + found = True |
| 677 | + break |
| 678 | + else: |
| 679 | + found = False |
| 680 | + k = key |
| 681 | + if key == 'template': |
| 682 | + k = 'security-template' |
| 683 | + elif key == 'policy_groups': |
| 684 | + k = 'caps' |
| 685 | + if 'binaries' in self.test_pkg_yaml: |
| 686 | + for b in self.test_pkg_yaml['binaries']: |
| 687 | + if 'name' in b and b['name'] == app: |
| 688 | + # Found the entry, so update key/value |
| 689 | + b[k] = value |
| 690 | + found = True |
| 691 | + break |
| 692 | + # Did not find the entry, so create one |
| 693 | + if not found: |
| 694 | + if 'binaries' not in self.test_pkg_yaml: |
| 695 | + self.test_pkg_yaml['binaries'] = [] |
| 696 | + self.test_pkg_yaml['binaries'].append({'name': app, |
| 697 | + k: value}) |
| 698 | + self._update_test_pkg_yaml() |
| 699 | + |
| 700 | + # click manifest |
| 701 | if app not in self.test_security_manifests: |
| 702 | self.test_security_manifests[app] = dict() |
| 703 | |
| 704 | - if value is None: |
| 705 | + if key is None: |
| 706 | + if app in self.test_security_manifests: |
| 707 | + del self.test_security_manifests[app] |
| 708 | + del self.test_manifest["hooks"][app] |
| 709 | + elif value is None: |
| 710 | if key in self.test_security_manifests[app]: |
| 711 | self.test_security_manifests[app].pop(key, None) |
| 712 | else: |
| 713 | @@ -973,8 +1018,8 @@ |
| 714 | self._update_test_framework_policy_unknown() |
| 715 | |
| 716 | def set_test_systemd(self, app, key, value): |
| 717 | - '''Set systemd entries. If key is None, snappy-systemd from manifest |
| 718 | - and yaml. |
| 719 | + '''Set systemd entries. If key is None, remove snappy-systemd from |
| 720 | + manifest and yaml. |
| 721 | |
| 722 | Note the click manifest and the package.yaml use different |
| 723 | storage types. pkg_yaml['services'] is a list of dictionaries where |
| 724 | |
| 725 | === modified file 'clickreviews/tests/test_cr_lint.py' |
| 726 | --- clickreviews/tests/test_cr_lint.py 2015-05-01 15:18:50 +0000 |
| 727 | +++ clickreviews/tests/test_cr_lint.py 2015-05-18 21:07:49 +0000 |
| 728 | @@ -1357,3 +1357,80 @@ |
| 729 | r = c.click_report |
| 730 | expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 731 | self.check_results(r, expected_counts) |
| 732 | + |
| 733 | + def test_check_snappy_services_and_binaries1(self): |
| 734 | + '''Test check_snappy_services_and_binaries() - different''' |
| 735 | + self.set_test_pkg_yaml("name", self.test_name.split('_')[0]) |
| 736 | + self.set_test_pkg_yaml("services", [{"name": "foo", |
| 737 | + "start": "bin/foo"}]) |
| 738 | + self.set_test_pkg_yaml("binaries", [{"name": "bar"}]) |
| 739 | + c = ClickReviewLint(self.test_name) |
| 740 | + c.check_snappy_services_and_binaries() |
| 741 | + r = c.click_report |
| 742 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 743 | + self.check_results(r, expected_counts) |
| 744 | + |
| 745 | + def test_check_snappy_services_and_binaries2(self): |
| 746 | + '''Test check_snappy_services_and_binaries() - different (exec)''' |
| 747 | + self.set_test_pkg_yaml("name", self.test_name.split('_')[0]) |
| 748 | + self.set_test_pkg_yaml("services", [{"name": "foo", |
| 749 | + "start": "bin/foo"}]) |
| 750 | + self.set_test_pkg_yaml("binaries", [{"name": "bar", |
| 751 | + "exec": "bin/foo"}]) |
| 752 | + c = ClickReviewLint(self.test_name) |
| 753 | + c.check_snappy_services_and_binaries() |
| 754 | + r = c.click_report |
| 755 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 756 | + self.check_results(r, expected_counts) |
| 757 | + |
| 758 | + def test_check_snappy_services_and_binaries3(self): |
| 759 | + '''Test check_snappy_services_and_binaries() - same''' |
| 760 | + self.set_test_pkg_yaml("name", self.test_name.split('_')[0]) |
| 761 | + self.set_test_pkg_yaml("services", [{"name": "foo", |
| 762 | + "start": "bin/foo"}]) |
| 763 | + self.set_test_pkg_yaml("binaries", [{"name": "foo"}]) |
| 764 | + c = ClickReviewLint(self.test_name) |
| 765 | + c.check_snappy_services_and_binaries() |
| 766 | + r = c.click_report |
| 767 | + expected_counts = {'info': 0, 'warn': 0, 'error': 2} |
| 768 | + self.check_results(r, expected_counts) |
| 769 | + |
| 770 | + m = r['error']['lint_snappy_foo_in_services']['text'] |
| 771 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 772 | + m = r['error']['lint_snappy_foo_in_binaries']['text'] |
| 773 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 774 | + |
| 775 | + def test_check_snappy_services_and_binaries4(self): |
| 776 | + '''Test check_snappy_services_and_binaries() - same (subdir)''' |
| 777 | + self.set_test_pkg_yaml("name", self.test_name.split('_')[0]) |
| 778 | + self.set_test_pkg_yaml("services", [{"name": "foo", |
| 779 | + "start": "bin/foo"}]) |
| 780 | + self.set_test_pkg_yaml("binaries", [{"name": "bin/foo"}]) |
| 781 | + c = ClickReviewLint(self.test_name) |
| 782 | + c.check_snappy_services_and_binaries() |
| 783 | + r = c.click_report |
| 784 | + expected_counts = {'info': 0, 'warn': 0, 'error': 2} |
| 785 | + self.check_results(r, expected_counts) |
| 786 | + |
| 787 | + m = r['error']['lint_snappy_foo_in_services']['text'] |
| 788 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 789 | + m = r['error']['lint_snappy_foo_in_binaries']['text'] |
| 790 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 791 | + |
| 792 | + def test_check_snappy_services_and_binaries5(self): |
| 793 | + '''Test check_snappy_services_and_binaries() - same (exec, subdir)''' |
| 794 | + self.set_test_pkg_yaml("name", self.test_name.split('_')[0]) |
| 795 | + self.set_test_pkg_yaml("services", [{"name": "foo", |
| 796 | + "start": "bin/foo"}]) |
| 797 | + self.set_test_pkg_yaml("binaries", [{"name": "foo", |
| 798 | + "exec": "bin/foo"}]) |
| 799 | + c = ClickReviewLint(self.test_name) |
| 800 | + c.check_snappy_services_and_binaries() |
| 801 | + r = c.click_report |
| 802 | + expected_counts = {'info': 0, 'warn': 0, 'error': 2} |
| 803 | + self.check_results(r, expected_counts) |
| 804 | + |
| 805 | + m = r['error']['lint_snappy_foo_in_services']['text'] |
| 806 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 807 | + m = r['error']['lint_snappy_foo_in_binaries']['text'] |
| 808 | + self.assertIn("'foo' in both 'services' and 'binaries'", m) |
| 809 | |
| 810 | === modified file 'clickreviews/tests/test_cr_security.py' |
| 811 | --- clickreviews/tests/test_cr_security.py 2015-05-01 15:03:57 +0000 |
| 812 | +++ clickreviews/tests/test_cr_security.py 2015-05-18 21:07:49 +0000 |
| 813 | @@ -32,6 +32,16 @@ |
| 814 | self.default_security_json = "%s.apparmor" % \ |
| 815 | self.default_appname |
| 816 | |
| 817 | + def _set_yaml_binary(self, entries, name=None): |
| 818 | + d = dict() |
| 819 | + if name is None: |
| 820 | + d['name'] = self.default_appname |
| 821 | + else: |
| 822 | + d['name'] = name |
| 823 | + for (key, value) in entries: |
| 824 | + d[key] = value |
| 825 | + self.set_test_pkg_yaml("binaries", [d]) |
| 826 | + |
| 827 | def test_check_policy_version_vendor(self): |
| 828 | '''Test check_policy_version() - valid''' |
| 829 | for v in [1.0]: # update when have more vendor policy |
| 830 | @@ -482,6 +492,52 @@ |
| 831 | expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 832 | self.check_results(report, expected_counts) |
| 833 | |
| 834 | + def test_check_template_snappy_framework_deprecated(self): |
| 835 | + '''Test check_template() - in deprecated framework declaration''' |
| 836 | + self.set_test_pkg_yaml("framework", "fwk") |
| 837 | + c = ClickReviewSecurity(self.test_name) |
| 838 | + self.set_test_security_manifest(self.default_appname, |
| 839 | + "template", "fwk_foo") |
| 840 | + c.check_template() |
| 841 | + report = c.click_report |
| 842 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 843 | + self.check_results(report, expected_counts) |
| 844 | + |
| 845 | + def test_check_template_snappy_framework_deprecated2(self): |
| 846 | + '''Test check_template() - in deprecated framework declaration list''' |
| 847 | + self.set_test_pkg_yaml("framework", "fwk, somethingelse") |
| 848 | + c = ClickReviewSecurity(self.test_name) |
| 849 | + self.set_test_security_manifest(self.default_appname, |
| 850 | + "template", "fwk_foo") |
| 851 | + c.check_template() |
| 852 | + report = c.click_report |
| 853 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 854 | + self.check_results(report, expected_counts) |
| 855 | + |
| 856 | + def test_check_template_snappy_frameworks(self): |
| 857 | + '''Test check_template() - in frameworks declaration''' |
| 858 | + self.set_test_pkg_yaml("frameworks", ["fwk"]) |
| 859 | + c = ClickReviewSecurity(self.test_name) |
| 860 | + self.set_test_security_manifest(self.default_appname, |
| 861 | + "template", "fwk_foo") |
| 862 | + c.check_template() |
| 863 | + report = c.click_report |
| 864 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 865 | + self.check_results(report, expected_counts) |
| 866 | + |
| 867 | + def test_check_template_snappy_framework_type(self): |
| 868 | + '''Test check_template() - type framework''' |
| 869 | + self.set_test_pkg_yaml("type", "framework") |
| 870 | + c = ClickReviewSecurity(self.test_name) |
| 871 | + self.set_test_security_manifest(self.default_appname, |
| 872 | + "template", |
| 873 | + "%s_foo" % |
| 874 | + self.test_name.split('_')[0]) |
| 875 | + c.check_template() |
| 876 | + report = c.click_report |
| 877 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 878 | + self.check_results(report, expected_counts) |
| 879 | + |
| 880 | def test_check_template_webapp(self): |
| 881 | '''Test check_template() - webapp''' |
| 882 | c = ClickReviewSecurity(self.test_name) |
| 883 | @@ -762,7 +818,7 @@ |
| 884 | c = ClickReviewSecurity(self.test_name) |
| 885 | c.check_policy_groups() |
| 886 | report = c.click_report |
| 887 | - expected_counts = {'info': 0, 'warn': 1, 'error': 0} |
| 888 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 889 | self.check_results(report, expected_counts) |
| 890 | |
| 891 | def test_check_policy_groups_bad_policy_version(self): |
| 892 | @@ -833,6 +889,54 @@ |
| 893 | expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 894 | self.check_results(report, expected_counts) |
| 895 | |
| 896 | + def test_check_policy_groups_snappy_framework_deprecated(self): |
| 897 | + '''Test check_policy_groups() - in deprecated framework declaration''' |
| 898 | + self.set_test_pkg_yaml("framework", "fwk") |
| 899 | + c = ClickReviewSecurity(self.test_name) |
| 900 | + self.set_test_security_manifest(self.default_appname, |
| 901 | + "policy_groups", ["fwk_foo"]) |
| 902 | + c.check_policy_groups() |
| 903 | + report = c.click_report |
| 904 | + expected_counts = {'info': 4, 'warn': 0, 'error': 0} |
| 905 | + self.check_results(report, expected_counts) |
| 906 | + |
| 907 | + def test_check_policy_groups_snappy_framework_deprecated2(self): |
| 908 | + '''Test check_policy_groups() - in deprecated framework declaration |
| 909 | + list |
| 910 | + ''' |
| 911 | + self.set_test_pkg_yaml("framework", "fwk, somethingelse") |
| 912 | + c = ClickReviewSecurity(self.test_name) |
| 913 | + self.set_test_security_manifest(self.default_appname, |
| 914 | + "policy_groups", ["fwk_foo"]) |
| 915 | + c.check_policy_groups() |
| 916 | + report = c.click_report |
| 917 | + expected_counts = {'info': 4, 'warn': 0, 'error': 0} |
| 918 | + self.check_results(report, expected_counts) |
| 919 | + |
| 920 | + def test_check_policy_groups_snappy_frameworks(self): |
| 921 | + '''Test check_policy_groups() - in frameworks declaration''' |
| 922 | + self.set_test_pkg_yaml("frameworks", ["fwk"]) |
| 923 | + c = ClickReviewSecurity(self.test_name) |
| 924 | + self.set_test_security_manifest(self.default_appname, |
| 925 | + "policy_groups", ["fwk_foo"]) |
| 926 | + c.check_policy_groups() |
| 927 | + report = c.click_report |
| 928 | + expected_counts = {'info': 4, 'warn': 0, 'error': 0} |
| 929 | + self.check_results(report, expected_counts) |
| 930 | + |
| 931 | + def test_check_policy_groups_snappy_framework_type(self): |
| 932 | + '''Test check_policy_groups() - type framework''' |
| 933 | + self.set_test_pkg_yaml("type", "framework") |
| 934 | + c = ClickReviewSecurity(self.test_name) |
| 935 | + self.set_test_security_manifest(self.default_appname, |
| 936 | + "policy_groups", |
| 937 | + ["%s_foo" % |
| 938 | + self.test_name.split('_')[0]]) |
| 939 | + c.check_policy_groups() |
| 940 | + report = c.click_report |
| 941 | + expected_counts = {'info': 4, 'warn': 0, 'error': 0} |
| 942 | + self.check_results(report, expected_counts) |
| 943 | + |
| 944 | def test_check_policy_groups_pushhelper_no_hook(self): |
| 945 | '''Test check_policy_groups_pushhelper() - no hook''' |
| 946 | c = ClickReviewSecurity(self.test_name) |
| 947 | @@ -1154,3 +1258,573 @@ |
| 948 | report = c.click_report |
| 949 | expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 950 | self.check_results(report, expected_counts) |
| 951 | + |
| 952 | + def test_check_security_template_default(self): |
| 953 | + '''Test check_security_template() - default''' |
| 954 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 955 | + self._set_yaml_binary([]) |
| 956 | + c = ClickReviewSecurity(self.test_name) |
| 957 | + c.check_security_template() |
| 958 | + report = c.click_report |
| 959 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 960 | + self.check_results(report, expected_counts) |
| 961 | + |
| 962 | + def test_check_security_template_default_with_exec(self): |
| 963 | + '''Test check_security_template() - default with exec''' |
| 964 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 965 | + self._set_yaml_binary([('exec', 'bin/%s' % self.default_appname)]) |
| 966 | + c = ClickReviewSecurity(self.test_name) |
| 967 | + c.check_security_template() |
| 968 | + report = c.click_report |
| 969 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 970 | + self.check_results(report, expected_counts) |
| 971 | + |
| 972 | + def test_check_security_template_nondefault(self): |
| 973 | + '''Test check_security_template() - nondefault''' |
| 974 | + self.set_test_security_manifest(self.default_appname, |
| 975 | + "template", "nondefault") |
| 976 | + self._set_yaml_binary([('security-template', 'nondefault')]) |
| 977 | + c = ClickReviewSecurity(self.test_name) |
| 978 | + c.check_security_template() |
| 979 | + report = c.click_report |
| 980 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 981 | + self.check_results(report, expected_counts) |
| 982 | + |
| 983 | + def test_check_security_template_bad(self): |
| 984 | + '''Test check_security_template() - {}''' |
| 985 | + self._set_yaml_binary([('security-template', {})]) |
| 986 | + c = ClickReviewSecurity(self.test_name) |
| 987 | + c.check_security_template() |
| 988 | + report = c.click_report |
| 989 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 990 | + self.check_results(report, expected_counts) |
| 991 | + |
| 992 | + def test_check_security_yaml_and_click_name_relative(self): |
| 993 | + '''Test check_security_yaml_and_click() - relative path''' |
| 994 | + self._set_yaml_binary([('caps', ['networking'])], |
| 995 | + name="bin/%s" % self.default_appname) |
| 996 | + c = ClickReviewSecurity(self.test_name) |
| 997 | + |
| 998 | + # update the manifest and test_manifest |
| 999 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1000 | + |
| 1001 | + c.check_security_yaml_and_click() |
| 1002 | + report = c.click_report |
| 1003 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 1004 | + self.check_results(report, expected_counts) |
| 1005 | + |
| 1006 | + def test_check_security_yaml_and_click_name_exec(self): |
| 1007 | + '''Test check_security_yaml_and_click() - uses exec''' |
| 1008 | + self._set_yaml_binary([('caps', ['networking']), |
| 1009 | + ('exec', "bin/%s" % self.default_appname)], |
| 1010 | + name=self.default_appname) |
| 1011 | + c = ClickReviewSecurity(self.test_name) |
| 1012 | + |
| 1013 | + # update the manifest and test_manifest |
| 1014 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1015 | + |
| 1016 | + c.check_security_yaml_and_click() |
| 1017 | + report = c.click_report |
| 1018 | + expected_counts = {'info': 6, 'warn': 0, 'error': 0} |
| 1019 | + self.check_results(report, expected_counts) |
| 1020 | + |
| 1021 | + def test_check_security_yaml_and_click_matching_template(self): |
| 1022 | + '''Test check_security_yaml_and_click() - matching default template''' |
| 1023 | + self._set_yaml_binary([('caps', ['networking'])]) |
| 1024 | + self.set_test_security_manifest(self.default_appname, |
| 1025 | + "template", "default") |
| 1026 | + c = ClickReviewSecurity(self.test_name) |
| 1027 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1028 | + del c.pkg_yaml['binaries'][0]['security-template'] |
| 1029 | + c.check_security_yaml_and_click() |
| 1030 | + report = c.click_report |
| 1031 | + expected_counts = {'info': 6, 'warn': 0, 'error': 0} |
| 1032 | + self.check_results(report, expected_counts) |
| 1033 | + |
| 1034 | + def test_check_security_yaml_and_click_security_override(self): |
| 1035 | + '''Test check_security_yaml_and_click() - security-override''' |
| 1036 | + self._set_yaml_binary([('security-template', 'default')]) |
| 1037 | + self._set_yaml_binary([('security-override', {})]) |
| 1038 | + self.set_test_security_manifest(self.default_appname, |
| 1039 | + "template", "default") |
| 1040 | + c = ClickReviewSecurity(self.test_name) |
| 1041 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1042 | + c.check_security_yaml_and_click() |
| 1043 | + report = c.click_report |
| 1044 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 1045 | + self.check_results(report, expected_counts) |
| 1046 | + |
| 1047 | + def test_check_security_yaml_and_click_security_policy(self): |
| 1048 | + '''Test check_security_yaml_and_click() - security-policy''' |
| 1049 | + self._set_yaml_binary([('security-template', 'default')]) |
| 1050 | + self._set_yaml_binary([('security-policy', {})]) |
| 1051 | + self.set_test_security_manifest(self.default_appname, |
| 1052 | + "template", "default") |
| 1053 | + c = ClickReviewSecurity(self.test_name) |
| 1054 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1055 | + c.check_security_yaml_and_click() |
| 1056 | + report = c.click_report |
| 1057 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 1058 | + self.check_results(report, expected_counts) |
| 1059 | + |
| 1060 | + def test_check_security_yaml_and_click_matching_caps(self): |
| 1061 | + '''Test check_security_yaml_and_click() - matching default caps''' |
| 1062 | + self._set_yaml_binary([('caps', [])]) |
| 1063 | + self.set_test_security_manifest(self.default_appname, |
| 1064 | + "policy_groups", ['networking']) |
| 1065 | + c = ClickReviewSecurity(self.test_name) |
| 1066 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1067 | + del c.pkg_yaml['binaries'][0]['caps'] |
| 1068 | + c.check_security_yaml_and_click() |
| 1069 | + report = c.click_report |
| 1070 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 1071 | + self.check_results(report, expected_counts) |
| 1072 | + |
| 1073 | + def test_check_security_yaml_and_click_matching_no_caps(self): |
| 1074 | + '''Test check_security_yaml_and_click() - matching no caps''' |
| 1075 | + self._set_yaml_binary([('caps', [])]) |
| 1076 | + self.set_test_security_manifest(self.default_appname, |
| 1077 | + "policy_groups", None) |
| 1078 | + c = ClickReviewSecurity(self.test_name) |
| 1079 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1080 | + c.check_security_yaml_and_click() |
| 1081 | + report = c.click_report |
| 1082 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 1083 | + self.check_results(report, expected_counts) |
| 1084 | + |
| 1085 | + def test_check_security_yaml_and_click_matching_no_caps_template(self): |
| 1086 | + '''Test check_security_yaml_and_click() - matching no caps with |
| 1087 | + template |
| 1088 | + ''' |
| 1089 | + self._set_yaml_binary([('security-template', 'nondefault')]) |
| 1090 | + self.set_test_security_manifest(self.default_appname, |
| 1091 | + "policy_groups", None) |
| 1092 | + self.set_test_security_manifest(self.default_appname, |
| 1093 | + "template", "nondefault") |
| 1094 | + c = ClickReviewSecurity(self.test_name) |
| 1095 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1096 | + c.check_security_yaml_and_click() |
| 1097 | + report = c.click_report |
| 1098 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 1099 | + self.check_results(report, expected_counts) |
| 1100 | + |
| 1101 | + def test_check_security_yaml_and_click_mismatch0(self): |
| 1102 | + '''Test check_security_yaml_and_click() - missing app in hooks''' |
| 1103 | + self._set_yaml_binary([]) |
| 1104 | + self.set_test_security_manifest(self.default_appname, |
| 1105 | + "template", None) |
| 1106 | + c = ClickReviewSecurity(self.test_name) |
| 1107 | + |
| 1108 | + del c.manifest["hooks"][self.default_appname] |
| 1109 | + self._update_test_manifest() |
| 1110 | + c.security_apps.remove(self.default_appname) |
| 1111 | + |
| 1112 | + c.check_security_yaml_and_click() |
| 1113 | + report = c.click_report |
| 1114 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1115 | + self.check_results(report, expected_counts) |
| 1116 | + |
| 1117 | + def test_check_security_yaml_and_click_mismatch1(self): |
| 1118 | + '''Test check_security_yaml_and_click() - missing bin-path in hooks''' |
| 1119 | + self._set_yaml_binary([]) |
| 1120 | + c = ClickReviewSecurity(self.test_name) |
| 1121 | + |
| 1122 | + c.check_security_yaml_and_click() |
| 1123 | + report = c.click_report |
| 1124 | + expected_counts = {'info': None, 'warn': 0, 'error': 2} |
| 1125 | + self.check_results(report, expected_counts) |
| 1126 | + |
| 1127 | + def test_check_security_yaml_and_click_mismatch2(self): |
| 1128 | + '''Test check_security_yaml_and_click() - missing apparmor in hooks''' |
| 1129 | + self._set_yaml_binary([]) |
| 1130 | + c = ClickReviewSecurity(self.test_name) |
| 1131 | + |
| 1132 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1133 | + del c.manifest["hooks"][self.default_appname]['apparmor'] |
| 1134 | + c.security_apps.remove(self.default_appname) |
| 1135 | + self._update_test_manifest() |
| 1136 | + |
| 1137 | + c.check_security_yaml_and_click() |
| 1138 | + report = c.click_report |
| 1139 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1140 | + self.check_results(report, expected_counts) |
| 1141 | + |
| 1142 | + def test_check_security_yaml_and_click_mismatch3(self): |
| 1143 | + '''Test check_security_yaml_and_click() - missing security-template''' |
| 1144 | + self._set_yaml_binary([('caps', ['networking'])]) |
| 1145 | + self.set_test_security_manifest(self.default_appname, |
| 1146 | + "template", "nondefault") |
| 1147 | + c = ClickReviewSecurity(self.test_name) |
| 1148 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1149 | + del c.pkg_yaml['binaries'][0]['security-template'] |
| 1150 | + c.check_security_yaml_and_click() |
| 1151 | + report = c.click_report |
| 1152 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1153 | + self.check_results(report, expected_counts) |
| 1154 | + |
| 1155 | + def test_check_security_yaml_and_click_mismatch4(self): |
| 1156 | + '''Test check_security_yaml_and_click() - missing click template''' |
| 1157 | + self._set_yaml_binary([("security-template", "nondefault"), |
| 1158 | + ('caps', ['networking'])], |
| 1159 | + name=self.default_appname) |
| 1160 | + self.set_test_security_manifest(self.default_appname, |
| 1161 | + "template", None) |
| 1162 | + c = ClickReviewSecurity(self.test_name) |
| 1163 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1164 | + c.check_security_yaml_and_click() |
| 1165 | + report = c.click_report |
| 1166 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1167 | + self.check_results(report, expected_counts) |
| 1168 | + |
| 1169 | + def test_check_security_yaml_and_click_mismatch5(self): |
| 1170 | + '''Test check_security_yaml_and_click() - different templates''' |
| 1171 | + self.set_test_security_manifest(self.default_appname, |
| 1172 | + "template", "other") |
| 1173 | + self._set_yaml_binary([("security-template", "nondefault"), |
| 1174 | + ('caps', ['networking'])], |
| 1175 | + name=self.default_appname) |
| 1176 | + c = ClickReviewSecurity(self.test_name) |
| 1177 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1178 | + c.check_security_yaml_and_click() |
| 1179 | + report = c.click_report |
| 1180 | + expected_counts = {'info': None, 'warn': 0, 'error': 2} |
| 1181 | + self.check_results(report, expected_counts) |
| 1182 | + |
| 1183 | + def test_check_security_yaml_and_click_mismatch6(self): |
| 1184 | + '''Test check_security_yaml_and_click() - missing caps in yaml''' |
| 1185 | + self._set_yaml_binary([('caps', [])]) |
| 1186 | + self.set_test_security_manifest(self.default_appname, |
| 1187 | + "policy_groups", ["1", "2"]) |
| 1188 | + c = ClickReviewSecurity(self.test_name) |
| 1189 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1190 | + del c.pkg_yaml['binaries'][0]['caps'] |
| 1191 | + c.check_security_yaml_and_click() |
| 1192 | + report = c.click_report |
| 1193 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1194 | + self.check_results(report, expected_counts) |
| 1195 | + |
| 1196 | + def test_check_security_yaml_and_click_mismatch7(self): |
| 1197 | + '''Test check_security_yaml_and_click() - missing policy_groups''' |
| 1198 | + self._set_yaml_binary([('caps', ['networking'])], |
| 1199 | + name=self.default_appname) |
| 1200 | + self.set_test_security_manifest(self.default_appname, |
| 1201 | + "policy_groups", None) |
| 1202 | + c = ClickReviewSecurity(self.test_name) |
| 1203 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1204 | + c.check_security_yaml_and_click() |
| 1205 | + report = c.click_report |
| 1206 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1207 | + self.check_results(report, expected_counts) |
| 1208 | + |
| 1209 | + def test_check_security_yaml_and_click_mismatch8(self): |
| 1210 | + '''Test check_security_yaml_and_click() - different caps/groups''' |
| 1211 | + self.set_test_security_manifest(self.default_appname, |
| 1212 | + "policy_groups", ["1", "2"]) |
| 1213 | + self._set_yaml_binary([('caps', ["3"])], |
| 1214 | + name=self.default_appname) |
| 1215 | + c = ClickReviewSecurity(self.test_name) |
| 1216 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1217 | + c.check_security_yaml_and_click() |
| 1218 | + report = c.click_report |
| 1219 | + expected_counts = {'info': None, 'warn': 0, 'error': 2} |
| 1220 | + self.check_results(report, expected_counts) |
| 1221 | + |
| 1222 | + def test_check_security_yaml_and_click_mismatch9(self): |
| 1223 | + '''Test check_security_yaml_and_click() - unordered caps/groups''' |
| 1224 | + self.set_test_security_manifest(self.default_appname, |
| 1225 | + "policy_groups", ["1", "2"]) |
| 1226 | + self._set_yaml_binary([('caps', ["2", "1"])], |
| 1227 | + name=self.default_appname) |
| 1228 | + c = ClickReviewSecurity(self.test_name) |
| 1229 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1230 | + c.check_security_yaml_and_click() |
| 1231 | + report = c.click_report |
| 1232 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 1233 | + self.check_results(report, expected_counts) |
| 1234 | + |
| 1235 | + def test_check_security_yaml_and_click_mismatch10(self): |
| 1236 | + '''Test check_security_yaml_and_click() - missing caps in both''' |
| 1237 | + self._set_yaml_binary([('caps', [])]) |
| 1238 | + self.set_test_security_manifest(self.default_appname, |
| 1239 | + "policy_groups", None) |
| 1240 | + c = ClickReviewSecurity(self.test_name) |
| 1241 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1242 | + del c.pkg_yaml['binaries'][0]['caps'] |
| 1243 | + c.check_security_yaml_and_click() |
| 1244 | + report = c.click_report |
| 1245 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1246 | + self.check_results(report, expected_counts) |
| 1247 | + |
| 1248 | + def test_check_security_yaml_and_click_mismatch11(self): |
| 1249 | + '''Test check_security_yaml_and_click() - default caps with template''' |
| 1250 | + self._set_yaml_binary([('security-template', 'nondefault')]) |
| 1251 | + self.set_test_security_manifest(self.default_appname, |
| 1252 | + "policy_groups", ['networking']) |
| 1253 | + self.set_test_security_manifest(self.default_appname, |
| 1254 | + "template", "nondefault") |
| 1255 | + c = ClickReviewSecurity(self.test_name) |
| 1256 | + c.manifest["hooks"][self.default_appname]['bin-path'] = "bin/path" |
| 1257 | + del c.pkg_yaml['binaries'][0]['caps'] |
| 1258 | + c.check_security_yaml_and_click() |
| 1259 | + report = c.click_report |
| 1260 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1261 | + self.check_results(report, expected_counts) |
| 1262 | + |
| 1263 | + def test_check_security_yaml_combinations(self): |
| 1264 | + '''Test check_security_yaml_combinations()''' |
| 1265 | + self._set_yaml_binary([], name=self.default_appname) |
| 1266 | + c = ClickReviewSecurity(self.test_name) |
| 1267 | + c.check_security_yaml_combinations() |
| 1268 | + report = c.click_report |
| 1269 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1270 | + self.check_results(report, expected_counts) |
| 1271 | + |
| 1272 | + def test_check_security_yaml_combinations1(self): |
| 1273 | + '''Test check_security_yaml_combinations() - template''' |
| 1274 | + self._set_yaml_binary([('security-template', 'foo')], |
| 1275 | + name=self.default_appname) |
| 1276 | + c = ClickReviewSecurity(self.test_name) |
| 1277 | + c.check_security_yaml_combinations() |
| 1278 | + report = c.click_report |
| 1279 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1280 | + self.check_results(report, expected_counts) |
| 1281 | + |
| 1282 | + def test_check_security_yaml_combinations2(self): |
| 1283 | + '''Test check_security_yaml_combinations() - caps''' |
| 1284 | + self._set_yaml_binary([('caps', ['networking'])], |
| 1285 | + name=self.default_appname) |
| 1286 | + c = ClickReviewSecurity(self.test_name) |
| 1287 | + c.check_security_yaml_combinations() |
| 1288 | + report = c.click_report |
| 1289 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1290 | + self.check_results(report, expected_counts) |
| 1291 | + |
| 1292 | + def test_check_security_yaml_combinations3(self): |
| 1293 | + '''Test check_security_yaml_combinations() - template,caps''' |
| 1294 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1295 | + ('caps', ['networking'])], |
| 1296 | + name=self.default_appname) |
| 1297 | + c = ClickReviewSecurity(self.test_name) |
| 1298 | + c.check_security_yaml_combinations() |
| 1299 | + report = c.click_report |
| 1300 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1301 | + self.check_results(report, expected_counts) |
| 1302 | + |
| 1303 | + def test_check_security_yaml_combinations4(self): |
| 1304 | + '''Test check_security_yaml_combinations() - override''' |
| 1305 | + self._set_yaml_binary([('security-override', {'apparmor': 'foo.aa', |
| 1306 | + 'seccomp': 'foo.sc'})], |
| 1307 | + name=self.default_appname) |
| 1308 | + c = ClickReviewSecurity(self.test_name) |
| 1309 | + c.check_security_yaml_combinations() |
| 1310 | + report = c.click_report |
| 1311 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1312 | + self.check_results(report, expected_counts) |
| 1313 | + |
| 1314 | + def test_check_security_yaml_combinations5(self): |
| 1315 | + '''Test check_security_yaml_combinations() - override, template''' |
| 1316 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1317 | + ('security-override', {'apparmor': 'foo.aa', |
| 1318 | + 'seccomp': 'foo.sc'})], |
| 1319 | + name=self.default_appname) |
| 1320 | + c = ClickReviewSecurity(self.test_name) |
| 1321 | + c.check_security_yaml_combinations() |
| 1322 | + report = c.click_report |
| 1323 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1324 | + self.check_results(report, expected_counts) |
| 1325 | + |
| 1326 | + def test_check_security_yaml_combinations6(self): |
| 1327 | + '''Test check_security_yaml_combinations() - override, caps''' |
| 1328 | + self._set_yaml_binary([('caps', ['networking']), |
| 1329 | + ('security-override', {'apparmor': 'foo.aa', |
| 1330 | + 'seccomp': 'foo.sc'})], |
| 1331 | + name=self.default_appname) |
| 1332 | + c = ClickReviewSecurity(self.test_name) |
| 1333 | + c.check_security_yaml_combinations() |
| 1334 | + report = c.click_report |
| 1335 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1336 | + self.check_results(report, expected_counts) |
| 1337 | + |
| 1338 | + def test_check_security_yaml_combinations7(self): |
| 1339 | + '''Test check_security_yaml_combinations() - override, caps, template |
| 1340 | + ''' |
| 1341 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1342 | + ('caps', ['networking']), |
| 1343 | + ('security-override', {'apparmor': 'foo.aa', |
| 1344 | + 'seccomp': 'foo.sc'})], |
| 1345 | + name=self.default_appname) |
| 1346 | + c = ClickReviewSecurity(self.test_name) |
| 1347 | + c.check_security_yaml_combinations() |
| 1348 | + report = c.click_report |
| 1349 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1350 | + self.check_results(report, expected_counts) |
| 1351 | + |
| 1352 | + def test_check_security_yaml_combinations8(self): |
| 1353 | + '''Test check_security_yaml_combinations() - override, caps, template, |
| 1354 | + policy |
| 1355 | + ''' |
| 1356 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1357 | + ('caps', ['networking']), |
| 1358 | + ('security-policy', {'apparmor': 'foo.aa', |
| 1359 | + 'seccomp': 'foo.sc'}), |
| 1360 | + ('security-override', {'apparmor': 'foo.aa', |
| 1361 | + 'seccomp': 'foo.sc'})], |
| 1362 | + name=self.default_appname) |
| 1363 | + c = ClickReviewSecurity(self.test_name) |
| 1364 | + c.check_security_yaml_combinations() |
| 1365 | + report = c.click_report |
| 1366 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1367 | + self.check_results(report, expected_counts) |
| 1368 | + |
| 1369 | + def test_check_security_yaml_combinations9(self): |
| 1370 | + '''Test check_security_yaml_combinations() - policy''' |
| 1371 | + self._set_yaml_binary([('security-policy', {'apparmor': 'foo.aa', |
| 1372 | + 'seccomp': 'foo.sc'})], |
| 1373 | + name=self.default_appname) |
| 1374 | + c = ClickReviewSecurity(self.test_name) |
| 1375 | + c.check_security_yaml_combinations() |
| 1376 | + report = c.click_report |
| 1377 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1378 | + self.check_results(report, expected_counts) |
| 1379 | + |
| 1380 | + def test_check_security_yaml_combinations10(self): |
| 1381 | + '''Test check_security_yaml_combinations() - policy, template''' |
| 1382 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1383 | + ('security-policy', {'apparmor': 'foo.aa', |
| 1384 | + 'seccomp': 'foo.sc'})], |
| 1385 | + name=self.default_appname) |
| 1386 | + c = ClickReviewSecurity(self.test_name) |
| 1387 | + c.check_security_yaml_combinations() |
| 1388 | + report = c.click_report |
| 1389 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1390 | + self.check_results(report, expected_counts) |
| 1391 | + |
| 1392 | + def test_check_security_yaml_combinations11(self): |
| 1393 | + '''Test check_security_yaml_combinations() - policy, caps''' |
| 1394 | + self._set_yaml_binary([('caps', ['networking']), |
| 1395 | + ('security-policy', {'apparmor': 'foo.aa', |
| 1396 | + 'seccomp': 'foo.sc'})], |
| 1397 | + name=self.default_appname) |
| 1398 | + c = ClickReviewSecurity(self.test_name) |
| 1399 | + c.check_security_yaml_combinations() |
| 1400 | + report = c.click_report |
| 1401 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1402 | + self.check_results(report, expected_counts) |
| 1403 | + |
| 1404 | + def test_check_security_yaml_combinations12(self): |
| 1405 | + '''Test check_security_yaml_combinations() - policy, caps, template |
| 1406 | + ''' |
| 1407 | + self._set_yaml_binary([('security-template', 'foo'), |
| 1408 | + ('caps', ['networking']), |
| 1409 | + ('security-policy', {'apparmor': 'foo.aa', |
| 1410 | + 'seccomp': 'foo.sc'})], |
| 1411 | + name=self.default_appname) |
| 1412 | + c = ClickReviewSecurity(self.test_name) |
| 1413 | + c.check_security_yaml_combinations() |
| 1414 | + report = c.click_report |
| 1415 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1416 | + self.check_results(report, expected_counts) |
| 1417 | + |
| 1418 | + def test_check_security_yaml_override_and_click(self): |
| 1419 | + '''Test check_security_yaml_override_and_click()''' |
| 1420 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 1421 | + self._set_yaml_binary([]) |
| 1422 | + c = ClickReviewSecurity(self.test_name) |
| 1423 | + c.check_security_yaml_override_and_click() |
| 1424 | + report = c.click_report |
| 1425 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1426 | + self.check_results(report, expected_counts) |
| 1427 | + |
| 1428 | + def test_check_security_yaml_override_and_click_bad(self): |
| 1429 | + '''Test check_security_yaml_override_and_click() - bad''' |
| 1430 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 1431 | + self._set_yaml_binary([('security-override', {'apparmor': |
| 1432 | + 'something.else'})], |
| 1433 | + name=self.default_appname) |
| 1434 | + c = ClickReviewSecurity(self.test_name) |
| 1435 | + c.check_security_yaml_override_and_click() |
| 1436 | + report = c.click_report |
| 1437 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1438 | + self.check_results(report, expected_counts) |
| 1439 | + |
| 1440 | + def test_check_security_yaml_override(self): |
| 1441 | + '''Test check_security_yaml_override()''' |
| 1442 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 1443 | + self._set_yaml_binary([]) |
| 1444 | + c = ClickReviewSecurity(self.test_name) |
| 1445 | + c.check_security_yaml_override() |
| 1446 | + report = c.click_report |
| 1447 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1448 | + self.check_results(report, expected_counts) |
| 1449 | + |
| 1450 | + def test_check_security_yaml_override2(self): |
| 1451 | + '''Test check_security_yaml_override() - seccomp/apparmor specified''' |
| 1452 | + self._set_yaml_binary([('security-override', {'apparmor': 'aa', |
| 1453 | + 'seccomp': 'sc'})], |
| 1454 | + name=self.default_appname) |
| 1455 | + c = ClickReviewSecurity(self.test_name) |
| 1456 | + c.check_security_yaml_override() |
| 1457 | + report = c.click_report |
| 1458 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1459 | + self.check_results(report, expected_counts) |
| 1460 | + |
| 1461 | + def test_check_security_yaml_override_missing1(self): |
| 1462 | + '''Test check_security_yaml_override() - missing apparmor''' |
| 1463 | + self._set_yaml_binary([('security-override', {'seccomp': 'sc'})], |
| 1464 | + name=self.default_appname) |
| 1465 | + c = ClickReviewSecurity(self.test_name) |
| 1466 | + c.check_security_yaml_override() |
| 1467 | + report = c.click_report |
| 1468 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1469 | + self.check_results(report, expected_counts) |
| 1470 | + |
| 1471 | + def test_check_security_yaml_override_missing2(self): |
| 1472 | + '''Test check_security_yaml_override() - missing seccomp''' |
| 1473 | + self._set_yaml_binary([('security-override', {'apparmor': 'aa'})], |
| 1474 | + name=self.default_appname) |
| 1475 | + c = ClickReviewSecurity(self.test_name) |
| 1476 | + c.check_security_yaml_override() |
| 1477 | + report = c.click_report |
| 1478 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1479 | + self.check_results(report, expected_counts) |
| 1480 | + |
| 1481 | + def test_check_security_yaml_policy(self): |
| 1482 | + '''Test check_security_yaml_policy()''' |
| 1483 | + self.set_test_security_manifest(self.default_appname, "template", None) |
| 1484 | + self._set_yaml_binary([]) |
| 1485 | + c = ClickReviewSecurity(self.test_name) |
| 1486 | + c.check_security_yaml_policy() |
| 1487 | + report = c.click_report |
| 1488 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1489 | + self.check_results(report, expected_counts) |
| 1490 | + |
| 1491 | + def test_check_security_yaml_policy2(self): |
| 1492 | + '''Test check_security_yaml_policy() - seccomp/apparmor specified''' |
| 1493 | + self._set_yaml_binary([('security-policy', {'apparmor': 'aa', |
| 1494 | + 'seccomp': 'sc'})], |
| 1495 | + name=self.default_appname) |
| 1496 | + c = ClickReviewSecurity(self.test_name) |
| 1497 | + c.check_security_yaml_policy() |
| 1498 | + report = c.click_report |
| 1499 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1500 | + self.check_results(report, expected_counts) |
| 1501 | + |
| 1502 | + def test_check_security_yaml_policy_missing1(self): |
| 1503 | + '''Test check_security_yaml_policy() - missing apparmor''' |
| 1504 | + self._set_yaml_binary([('security-policy', {'seccomp': 'sc'})], |
| 1505 | + name=self.default_appname) |
| 1506 | + c = ClickReviewSecurity(self.test_name) |
| 1507 | + c.check_security_yaml_policy() |
| 1508 | + report = c.click_report |
| 1509 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1510 | + self.check_results(report, expected_counts) |
| 1511 | + |
| 1512 | + def test_check_security_yaml_policy_missing2(self): |
| 1513 | + '''Test check_security_yaml_policy() - missing seccomp''' |
| 1514 | + self._set_yaml_binary([('security-policy', {'apparmor': 'aa'})], |
| 1515 | + name=self.default_appname) |
| 1516 | + c = ClickReviewSecurity(self.test_name) |
| 1517 | + c.check_security_yaml_policy() |
| 1518 | + report = c.click_report |
| 1519 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1520 | + self.check_results(report, expected_counts) |
| 1521 | |
| 1522 | === modified file 'debian/changelog' |
| 1523 | --- debian/changelog 2015-05-14 14:42:37 +0000 |
| 1524 | +++ debian/changelog 2015-05-18 21:07:49 +0000 |
| 1525 | @@ -3,6 +3,8 @@ |
| 1526 | [ Jamie Strandboge ] |
| 1527 | * Makefile: perform run-pyflakes in check target |
| 1528 | * cr_systemd.py: add bus-name checks and update testsuite |
| 1529 | + * add security yaml checks |
| 1530 | + * cr_lint.py: don't allow same key in 'binaries' and 'services' |
| 1531 | |
| 1532 | [ Marcus Tomlinson ] |
| 1533 | * cr_scope.py: add "keywords" to the list of optional scope .ini keys |
| 1534 | |
| 1535 | === modified file 'run-pep8' |
| 1536 | --- run-pep8 2014-08-22 13:22:48 +0000 |
| 1537 | +++ run-pep8 2015-05-18 21:07:49 +0000 |
| 1538 | @@ -2,8 +2,12 @@ |
| 1539 | set -e |
| 1540 | |
| 1541 | echo "= pep8 =" |
| 1542 | -for i in ./bin/update-* ./bin/click-check-* ./bin/click-show-files ./bin/click-review \ |
| 1543 | - ./clickreviews/*py ./clickreviews/tests/*py ; do |
| 1544 | +for i in ./clickreviews/*py \ |
| 1545 | + ./clickreviews/tests/*py \ |
| 1546 | + ./bin/update-* \ |
| 1547 | + ./bin/click-check-* \ |
| 1548 | + ./bin/click-show-files \ |
| 1549 | + ./bin/click-review ; do |
| 1550 | echo "Checking $i" |
| 1551 | pep8 $i |
| 1552 | done |

+1. Pinged Martin Albisetti to see if somebody on their team can give another review.