Support the new security-override semantics #222

Merged
merged 1 commit into from Jan 12, 2016
Jump to file or symbol
Failed to load files and symbols.
+145 −15
Split
View
@@ -1,7 +1,7 @@
$schema: http://json-schema.org/draft-04/schema#
definitions:
- security:
+ security-policy:
type: object
required:
- apparmor
@@ -13,6 +13,47 @@ definitions:
seccomp:
type: string
format: file-path
+ security-override:
+ type: object
+ properties:
+ read-paths:
+ type: array
+ description: a list of additional paths that the app can read.
+ minItems: 1
+ uniqueItems: true
+ items:
+ type: string
+ write-paths:
+ type: array
+ description: a list of additional paths that the app can write.
+ minItems: 1
+ uniqueItems: true
+ items:
+ type: string
+ abstractions:
+ type: array
+ description: a list of additional AppArmor abstractions for the app.
+ minItems: 1
+ uniqueItems: true
+ items:
+ type: string
+ syscalls:
+ type: array
+ description: a list of additional syscalls the app can use.
+ minItems: 1
+ uniqueItems: true
+ items:
+ type: string
+ security-caps:
+ type: array
+ description: Security caps.
+ minItems: 1
+ uniqueItems: true
+ items:
+ type: string
+ security-template:
+ type: string
+ description: alternate security template to use instead of default.
title: snapcraft schema
type: object
@@ -86,6 +127,16 @@ properties:
dependencies:
stop-command: ["daemon"]
additionalProperties: false
+ not:
+ anyOf:
+ - required:
+ - security-policy
+ - security-override
+ - security-template
+ - caps
+ - required: [security-policy, security-override]
+ - required: [security-policy, security-template]
+ - required: [security-policy, caps]
properties:
command:
type: string
@@ -102,16 +153,13 @@ properties:
- simple
- forking
security-policy:
- $ref: "#definitions/security"
+ $ref: "#definitions/security-policy"
security-override:
- $ref: "#definitions/security"
+ $ref: "#definitions/security-override"
+ security-template:
+ $ref: "#definitions/security-template"
caps:
- type: array
- description: Security caps.
- minItems: 1
- uniqueItems: true
- items:
- type: string
+ $ref: "#definitions/security-caps"
parts:
type: object
minProperties: 1
View
@@ -144,12 +144,11 @@ def _copy(meta_dir, relpath, new_relpath=None):
def _copy_security_profiles(meta_dir, apps):
# TODO: remove once capabilities are implemented.
for app in apps:
- for entry in ('security-policy', 'security-override'):
- if entry in apps[app]:
- apps[app][entry]['apparmor'] = \
- _copy(meta_dir, apps[app][entry]['apparmor'])
- apps[app][entry]['seccomp'] = \
- _copy(meta_dir, apps[app][entry]['seccomp'])
+ if 'security-policy' in apps[app]:
+ apps[app]['security-policy']['apparmor'] = \
+ _copy(meta_dir, apps[app]['security-policy']['apparmor'])
+ apps[app]['security-policy']['seccomp'] = \
+ _copy(meta_dir, apps[app]['security-policy']['seccomp'])
return apps
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import copy
import logging
import os
import unittest
@@ -614,6 +615,88 @@ def test_license_version_without_license_raises_exception(self):
self.assertEqual(raised.exception.message, expected_message,
msg=self.data)
+ def test_valid_security_policy_for_apps(self):
+ self.data['apps'] = {
+ 'app1': {
+ 'command': 'binary',
+ 'security-policy': {
+ 'seccomp': 'file.seccomp',
+ 'apparmor': 'file.apparmor',
+ },
+ },
+ }
+
+ snapcraft.yaml._validate_snapcraft_yaml(self.data)
+
+ def test_valid_security_override_for_apps(self):
+ self.data['apps'] = {
+ 'app1': {
+ 'command': 'binary',
+ 'security-override': {
+ 'read-paths': ['path1', 'path2'],
+ 'write-paths': ['path1', 'path2'],
+ 'abstractions': ['abstraction1', 'abstraction2'],
+ 'syscalls': ['open', 'close'],
+ },
+ },
+ }
+
+ snapcraft.yaml._validate_snapcraft_yaml(self.data)
+
+ def test_valid_security_template_for_apps(self):
+ self.data['apps'] = {
+ 'app1': {
+ 'command': 'binary',
+ 'security-template': 'unconfined',
+ },
+ }
+
+ snapcraft.yaml._validate_snapcraft_yaml(self.data)
+
+ def test_valid_caps_for_apps(self):
+ self.data['apps'] = {
+ 'app1': {
+ 'command': 'binary',
+ 'caps': ['cap1', 'cap2'],
+ },
+ }
+
+ snapcraft.yaml._validate_snapcraft_yaml(self.data)
+
+ def test_invalid_security_override_combinations(self):
+ self.data['apps'] = {
+ 'app1': {
+ 'command': 'binary',
+ 'security-override': {
+ 'read-paths': ['path1', 'path2'],
+ 'write-paths': ['path1', 'path2'],
+ 'abstractions': ['abstraction1', 'abstraction2'],
+ 'syscalls': ['open', 'close'],
+ },
+ 'caps': ['cap1', 'cap2'],
+ 'security-policy': {
+ 'seccomp': 'file.seccomp',
+ 'apparmor': 'file.apparmor',
+ },
+ 'security-template': 'undefined',
+ },
+ }
@kyrofa

kyrofa Jan 12, 2016

Member

You're missing three combos here, right? Worth adding them?

@sergiusens

sergiusens Jan 12, 2016

Collaborator

what combos? with subTest I cover

  • all
  • caps & security-policy
  • security-override & security-policy
  • security-override & caps
@kyrofa

kyrofa Jan 12, 2016

Member

Ah, I read too quickly. However, I can break your code above by removing all but one invalid combo and this test would still pass, correct? Should you be explicitly testing each invalid combination rather than throwing them all together?

@kyrofa

kyrofa Jan 12, 2016

Member

Ah, I missed the deletion below. You do exactly as I ask, just by altering the app on the fly a few times. It could be a bit clearer, but I'm fine with this.

+
+ with self.subTest(key='all'):
+ with self.assertRaises(Exception) as r:
+ snapcraft.yaml._validate_snapcraft_yaml(self.data)
+
+ self.assertTrue('is not allowed' in str(r.exception))
+
+ for sec in ['security-override', 'security-template', 'caps']:
+ data = copy.deepcopy(self.data)
+ del data['apps']['app1'][sec]
+ with self.subTest(key=sec):
+ with self.assertRaises(Exception) as r:
+ snapcraft.yaml._validate_snapcraft_yaml(data)
+
+ self.assertTrue('is not allowed' in str(r.exception))
+
class TestFilesets(tests.TestCase):