1# securitypolicy
2
3Takes a configuration to a TOML file and outputs a Base64 encoded string of the
4generated security policy.
5
6`securitypolicy` exists as a tool to make it easier to generate security policies
7for developers working functionality related to security policy in this repository.
8It is not intended to be used by "end users" but could be used as a basis for
9such a tool.
10
11A Base64 encoded version of policy is sent as an annotation to GCS for processing.
12The `securitypolicy` tool will, by default, output Base64 encoded JSON.
13
14Running the tool can take a long time as each layer for each container must
15be downloaded, turned into an ext4, and finally a dm-verity root hash calculated.
16
17## Example TOML configuration file
18
19```toml
20allow_capability_dropping = true
21
22[[container]]
23image_name = "rust:1.52.1"
24command = ["rustc", "--help"]
25working_dir = "/home/user"
26allow_elevated = true
27
28[container.capabilities]
29bounding = ["CAP_SYS_ADMIN"]
30effective = ["CAP_SYS_ADMIN"]
31inheritable = ["CAP_SYS_ADMIN"]
32permitted = ["CAP_SYS_ADMIN"]
33ambient = ["CAP_SYS_ADMIN"]
34
35[[container.env_rule]]
36strategy = "re2"
37rule = "PREFIX_.+=.+"
38
39[[container.mount]]
40host_path = "sandbox:///host/path/one"
41container_path = "/container/path/one"
42readonly = false
43
44[[container.mount]]
45host_path = "sandbox:///host/path/two"
46container_path = "/container/path/two"
47readonly = true
48
49[[container.exec_process]]
50command = ["top"]
51working_dir = "/home/user"
52
53[[container.exec_process.env_rule]]
54strategy = "string"
55rule = "FOO=bar"
56
57[[external_process]]
58command = ["bash"]
59working_dir = "/"
60
61[[fragment]]
62issuer = "did:web:contoso.com"
63feed = "contoso.azurecr.io/infra"
64minimum_svn = "1"
65include = ["containers"]
66```
67
68### Converted to JSON
69
70The result of the command:
71
72 securitypolicytool -c sample.toml -t json -r
73
74The above TOML configuration gets translated into the appropriate policy that is
75represented in JSON.
76
77```json
78{
79 "allow_all": false,
80 "containers": {
81 "length": 2,
82 "elements": {
83 "0": {
84 "command": {
85 "length": 2,
86 "elements": {
87 "0": "rustc",
88 "1": "--help"
89 }
90 },
91 "env_rules": {
92 "length": 6,
93 "elements": {
94 "0": {
95 "strategy": "string",
96 "rule": "PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
97 "required": false
98 },
99 "1": {
100 "strategy": "string",
101 "rule": "RUSTUP_HOME=/usr/local/rustup",
102 "required": false
103 },
104 "2": {
105 "strategy": "string",
106 "rule": "CARGO_HOME=/usr/local/cargo",
107 "required": false
108 },
109 "3": {
110 "strategy": "string",
111 "rule": "RUST_VERSION=1.52.1",
112 "required": false
113 },
114 "4": {
115 "strategy": "string",
116 "rule": "TERM=xterm",
117 "required": false
118 },
119 "5": {
120 "strategy": "re2",
121 "rule": "PREFIX_.+=.+",
122 "required": false
123 }
124 }
125 },
126 "layers": {
127 "length": 6,
128 "elements": {
129 "0": "fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a",
130 "1": "4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c",
131 "2": "41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156",
132 "3": "eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79",
133 "4": "e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c",
134 "5": "1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"
135 }
136 },
137 "working_dir": "/home/user",
138 "mounts": {
139 "length": 2,
140 "elements": {
141 "0": {
142 "source": "sandbox:///host/path/one",
143 "destination": "/container/path/one",
144 "type": "bind",
145 "options": {
146 "length": 3,
147 "elements": {
148 "0": "rbind",
149 "1": "rshared",
150 "2": "rw"
151 }
152 }
153 },
154 "1": {
155 "source": "sandbox:///host/path/two",
156 "destination": "/container/path/two",
157 "type": "bind",
158 "options": {
159 "length": 3,
160 "elements": {
161 "0": "rbind",
162 "1": "rshared",
163 "2": "ro"
164 }
165 }
166 }
167 }
168 },
169 "allow_elevated": true
170 },
171 "1": {
172 "command": {
173 "length": 1,
174 "elements": {
175 "0": "/pause"
176 }
177 },
178 "env_rules": {
179 "length": 2,
180 "elements": {
181 "0": {
182 "strategy": "string",
183 "rule": "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
184 "required": false
185 },
186 "1": {
187 "strategy": "string",
188 "rule": "TERM=xterm",
189 "required": false
190 }
191 }
192 },
193 "layers": {
194 "length": 1,
195 "elements": {
196 "0": "16b514057a06ad665f92c02863aca074fd5976c755d26bff16365299169e8415"
197 }
198 },
199 "working_dir": "/",
200 "mounts": {
201 "length": 0,
202 "elements": {}
203 },
204 "allow_elevated": false
205 }
206 }
207 }
208}
209```
210
211## Converted to Rego Policy
212
213The result of the command:
214
215 securitypolicytool -c sample.toml -t rego -r
216
217Is the following Rego policy:
218
219``` rego
220package policy
221
222api_version := "0.10.0"
223framework_version := "0.3.0"
224
225fragments := [
226 {"issuer": "did:web:contoso.com", "feed": "contoso.azurecr.io/infra", "minimum_svn": 1, "includes": ["containers"]},
227]
228containers := [
229 {
230 "command": ["rustc","--help"],
231 "env_rules": [{"pattern": `PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `RUSTUP_HOME=/usr/local/rustup`, "strategy": "string", "required": true},{"pattern": `CARGO_HOME=/usr/local/cargo`, "strategy": "string", "required": true},{"pattern": `RUST_VERSION=1.52.1`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false},{"pattern": `PREFIX_.+=.+`, "strategy": "re2", "required": false}],
232 "layers": ["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],
233 "mounts": [{"destination": "/container/path/one", "options": ["rbind","rshared","rw"], "source": "sandbox:///host/path/one", "type": "bind"},{"destination": "/container/path/two", "options": ["rbind","rshared","ro"], "source": "sandbox:///host/path/two", "type": "bind"}],
234 "exec_processes": [{"command": ["top"], "signals": []}],
235 "signals": [],
236 "user": {
237 "user_idname": {"pattern": ``, "strategy": "any"},
238 "group_idnames": [{"pattern": ``, "strategy": "any"}],
239 "umask": "0022"
240 },
241 "capabilities": {
242 "bounding": ["CAP_SYS_ADMIN"],
243 "effective": ["CAP_SYS_ADMIN"],
244 "inheritable": ["CAP_SYS_ADMIN"],
245 "permitted": ["CAP_SYS_ADMIN"],
246 "ambient": ["CAP_SYS_ADMIN"],
247 },
248 "seccomp_profile_sha256": "",
249 "allow_elevated": true,
250 "working_dir": "/home/user",
251 "allow_stdio_access": false,
252 "no_new_privileges": true,
253 },
254 {
255 "command": ["/pause"],
256 "env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false}],
257 "layers": ["16b514057a06ad665f92c02863aca074fd5976c755d26bff16365299169e8415"],
258 "mounts": [],
259 "exec_processes": [],
260 "signals": [],
261 "user": {
262 "user_idname": {"pattern": ``, "strategy": "any"},
263 "group_idnames": [{"pattern": ``, "strategy": "any"}],
264 "umask": "0022"
265 },
266 "capabilities": null,
267 "seccomp_profile_sha256": "",
268 "allow_elevated": false,
269 "working_dir": "/",
270 "allow_stdio_access": false,
271 "no_new_privileges": true,
272 },
273]
274external_processes := [
275 {"command": ["bash"], "env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true}], "working_dir": "/", "allow_stdio_access": false},
276]
277allow_properties_access := false
278allow_dump_stacks := false
279allow_runtime_logging := false
280allow_environment_variable_dropping := false
281allow_unencrypted_scratch := false
282allow_capability_dropping := true
283
284
285mount_device := data.framework.mount_device
286unmount_device := data.framework.unmount_device
287mount_overlay := data.framework.mount_overlay
288unmount_overlay := data.framework.unmount_overlay
289create_container := data.framework.create_container
290exec_in_container := data.framework.exec_in_container
291exec_external := data.framework.exec_external
292shutdown_container := data.framework.shutdown_container
293signal_container_process := data.framework.signal_container_process
294plan9_mount := data.framework.plan9_mount
295plan9_unmount := data.framework.plan9_unmount
296get_properties := data.framework.get_properties
297dump_stacks := data.framework.dump_stacks
298runtime_logging := data.framework.runtime_logging
299load_fragment := data.framework.load_fragment
300scratch_mount := data.framework.scratch_mount
301scratch_unmount := data.framework.scratch_unmount
302reason := {
303 "errors": data.framework.errors,
304 "error_objects": data.framework.error_objects,
305}
306```
307
308## Converted to Rego Fragment
309
310The result of the command
311
312 securitypolicytool -c sample.toml -t fragment -n sample -v 1 -r
313
314is the following Rego fragment:
315
316``` rego
317package sample
318
319svn := 1
320framework_version := "0.3.0"
321
322fragments := [
323 {"issuer": "did:web:contoso.com", "feed": "contoso.azurecr.io/infra", "minimum_svn": 1, "includes": ["containers"]},
324]
325containers := [
326 {
327 "command": ["rustc","--help"],
328 "env_rules": [{"pattern": `PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `RUSTUP_HOME=/usr/local/rustup`, "strategy": "string", "required": true},{"pattern": `CARGO_HOME=/usr/local/cargo`, "strategy": "string", "required": true},{"pattern": `RUST_VERSION=1.52.1`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false},{"pattern": `PREFIX_.+=.+`, "strategy": "re2", "required": false}],
329 "layers": ["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],
330 "mounts": [{"destination": "/container/path/one", "options": ["rbind","rshared","rw"], "source": "sandbox:///host/path/one", "type": "bind"},{"destination": "/container/path/two", "options": ["rbind","rshared","ro"], "source": "sandbox:///host/path/two", "type": "bind"}],
331 "exec_processes": [{"command": ["top"], "signals": []}],
332 "signals": [],
333 "user": {
334 "user_idname": {"pattern": ``, "strategy": "any"},
335 "group_idnames": [{"pattern": ``, "strategy": "any"}],
336 "umask": "0022"
337 },
338 "capabilities": {
339 "bounding": ["CAP_SYS_ADMIN"],
340 "effective": ["CAP_SYS_ADMIN"],
341 "inheritable": ["CAP_SYS_ADMIN"],
342 "permitted": ["CAP_SYS_ADMIN"],
343 "ambient": ["CAP_SYS_ADMIN"],
344 },
345 "seccomp_profile_sha256": "",
346 "allow_elevated": true,
347 "working_dir": "/home/user",
348 "allow_stdio_access": false,
349 "no_new_privileges": true,
350 },
351 {
352 "command": ["/pause"],
353 "env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false}],
354 "layers": ["16b514057a06ad665f92c02863aca074fd5976c755d26bff16365299169e8415"],
355 "mounts": [],
356 "exec_processes": [],
357 "signals": [],
358 "user": {
359 "user_idname": {"pattern": ``, "strategy": "any"},
360 "group_idnames": [{"pattern": ``, "strategy": "any"}],
361 "umask": "0022"
362 },
363 "capabilities": null,
364 "seccomp_profile_sha256": "",
365 "allow_elevated": false,
366 "working_dir": "/",
367 "allow_stdio_access": false,
368 "no_new_privileges": true,
369 },
370]
371external_processes := [
372 {"command": ["bash"], "env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true}], "working_dir": "/", "allow_stdio_access": false},
373]
374```
375
376## CLI Options
377
378### `-c`
379
380TOML configuration file to process (required)
381
382### `-r`
383
384output raw marshaled policy in addition to the base64
385
386### `-t`
387
388one of:
389- `rego`: outputs a Rego policy
390- `json`: outputs a legacy JSON policy (NOTE: some TOML elements are not supported in the legacy format)
391- `fragment`: outputs a Rego fragment. The `-n` and `-v` are required for this option.
392
393### `-n`
394
395Required for `-t fragment`. Specifies the fragment Rego namespace.
396
397### `-v`
398
399Required for `-t fragment`. Specified the fragment SVN as a semantic versioning number, *e.g.*, "1.0.0"
400
401## Authorization
402
403Some images will be pulled from registries that require authorization. To add
404authorization information for a given image, you would add an `[auth]` object
405to the TOML definition for that image. For example:
406
407```toml
408[[container]]
409image_name = "rust:1.52.1"
410command = ["rustc", "--help"]
411
412[auth]
413username = "my username"
414password = "my password"
415```
416
417Authorization information needs to be added on a per-image basis as it can vary
418from image to image and their respective registries.
419
420To pull an image using anonymous access, no `[auth]` object is required.
421
422## Pause container
423
424All LCOW pods require a pause container to run. The pause container must be
425included in the policy. As this tool is aimed at LCOW developers, a default
426version of the pause container is automatically added to policy even though it
427isn't in the TOML configuration.
428
429If the version of the pause container changes from 3.1, you will need to update
430the hardcoded root hash by running the `dmverity-vhd` to compute the root hash
431for the new container and update this tool accordingly.
View as plain text