You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: security/README.md
+10-2
Original file line number
Diff line number
Diff line change
@@ -2,10 +2,18 @@
2
2
3
3
This directory contains tutorials on how to take advantage of a non-exhaustive collection of Docker security features. Moreover, the tutorials are designed to explain and demonstrate the strong security defaults in Docker for each feature.
4
4
5
+
## Docker
6
+
*[Content Trust](trust/README.md)
7
+
*[Content Trust Basics](trust-basics/README.md)
8
+
*[Secrets Management](secrets/README.md)
9
+
*[Secrets Management with Docker Datacenter](secrets-ddc/README.md)
Copy file name to clipboardExpand all lines: security/apparmor/README.md
+58-39
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
5
5
> **Time**: Approximately 25 minutes
6
6
7
-
AppArmor (Application Armor) is a Linux Security Module (LSM). It protects the operating system by applying profiles to individual applications. In contrast to managing *capabilities* with `CAP_DROP` and syscalls with *seccomp*, AppArmor allows for much finer-grained control. For example, AppArmor can restrict file operations on specified paths.
7
+
AppArmor (Application Armor) is a Linux Security Module (LSM). It protects the operating system by applying profiles to individual applications or containers. In contrast to managing *capabilities* with `CAP_DROP` and syscalls with *seccomp*, AppArmor allows for much finer-grained control. For example, AppArmor can restrict file operations on specified paths.
8
8
9
9
In this lab you will learn the basics of AppArmor and how to use it with Docker for improved security.
10
10
@@ -24,7 +24,7 @@ You will need all of the following to complete this lab:
24
24
- A Linux-based Docker Host with AppArmor enabled in the kernel (most Debian-based distros)
25
25
- Docker 1.12 or higher
26
26
27
-
The following command shows you how to check if AppArmor is enabled in your system's kernel:
27
+
The following command shows you how to check if AppArmor is enabled in your system's kernel and available to Docker:
28
28
29
29
Check from Docker 1.12 or higher
30
30
```
@@ -36,11 +36,11 @@ The following command shows you how to check if AppArmor is enabled in your syst
36
36
37
37
# <aname="primer"></a>Step 1: AppArmor primer
38
38
39
-
By default, Docker applies the `docker-default` AppArmor profile to new containers. This profile is located in `/etc/apparmor.d/docker/` and you can find more information about it in the [documentation](https://docs.docker.com/engine/security/apparmor/#understand-the-policies).
39
+
By default, Docker applies the `docker-default` AppArmor profile to new **containers**. In Docker 1.13 and later this is profile is created in `tmpfs` and then loaded into the kernel. On Docker 1.12 and earlier it is located in `/etc/apparmor.d/docker/`. You can find more information about it in the [documentation](https://docs.docker.com/engine/security/apparmor/#understand-the-policies).
40
40
41
41
Here are some quick pointers for how to understand AppArmor profiles:
42
42
43
-
-`Include` statements, such as `#include <abstractions/base>`, behave just like their `C` counterparts by expanding to additional AppArmor profile contents.
43
+
-`include` statements, such as `#include <abstractions/base>`, behave just like their `C` counterparts by expanding to additional AppArmor profile contents.
44
44
45
45
- AppArmor `deny` rules have precedence over `allow` and `owner` rules. This means that `deny` rules cannot be overridden by subsequent `allow` or `owner` rules for the same resource. Moreover, an `allow` will be overridden by a subsequent `deny` on the same resource
46
46
@@ -52,7 +52,7 @@ For more information, see the [official AppArmor documentation wiki](http://wiki
52
52
53
53
In this step you will check the status of AppArmor on your Docker Host and learn how to identify whether or not Docker containers are running with an AppArmor profile.
54
54
55
-
1. View the status of AppArmor on your Docker Host with the `apparmor_status` command.
55
+
1. View the status of AppArmor on your Docker Host with the `apparmor_status` command. You may need to preceed the command with `sudo`.
56
56
57
57
```
58
58
$ apparmor_status
@@ -77,22 +77,20 @@ In this step you will check the status of AppArmor on your Docker Host and learn
77
77
0 processes are unconfined but have a profile defined.
78
78
```
79
79
80
-
The command may require admin credentials.
81
-
82
80
Notice the `docker-default` profile is in enforce mode. This is the AppArmor profile that will be applied to new containers unless overridden with the `--security-opts` flag.
83
81
84
82
2. Run a new container and put it in the back ground.
85
83
86
84
```
87
-
$ sudo docker run -dit alpine sh
85
+
$ docker container run -dit --name apparmor1 alpine sh
88
86
```
89
87
90
88
3. Confirm that the container is running.
91
89
92
90
```
93
-
$ sudo docker ps
94
-
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95
-
1bb16561bc06alpine "sh" 2 seconds ago Up 2 seconds sick_booth
91
+
$ docker container ls
92
+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
93
+
1bb16561bc06 alpine "sh" 2 secs ago Up 2 seconds apparmor1
96
94
```
97
95
98
96
4. Run the `apparmor_status` command again.
@@ -120,10 +118,8 @@ In this step you will check the status of AppArmor on your Docker Host and learn
120
118
121
119
5. Stop and remove the container started in the previous steps.
122
120
123
-
The example below uses the Container ID "1bb16561bc06". This will be different in your environment.
124
-
125
121
```
126
-
$ sudo docker rm -f 1bb16561bc06
122
+
$ docker container rm -f appamror1
127
123
1bb16561bc06
128
124
```
129
125
@@ -136,22 +132,24 @@ In this step you will see how to run a new container without an AppArmor profile
136
132
1. If you haven't already done so, stop and remove all containers on your system.
137
133
138
134
```
139
-
$ sudo docker rm -f $(docker ps -aq)
135
+
$ docker container rm -f $(docker container ls -aq)
140
136
```
141
137
142
138
2. Use the `--security-opt apparmor=unconfined` flag to start a new container in the background without an AppArmor profile.
143
139
144
140
```
145
-
$ sudo docker run -dit --security-opt apparmor=unconfined alpine sh
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
154
-
ace79581a19aalpine "sh" 41 seconds ago Up 40 seconds sharp_knuth
150
+
$ docker container ls
151
+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
152
+
ace79581a19a alpine "sh" 41 secs ago Up 40 secsapparmor2
155
153
```
156
154
157
155
4. Use the `apparmor_status` command to verify that the new container is not running with an AppArmor profile.
@@ -170,31 +168,29 @@ ace79581a19a alpine "sh" 41 seconds ago
170
168
171
169
5. Stop and remove the container started in the previous steps.
172
170
173
-
The example below uses the Container ID "ace79581a19a". This will be different in your environment.
174
-
175
171
```
176
-
$ sudo docker rm -f ace79581a19a
172
+
$ docker container rm -f apparmor2
177
173
ace79581a19a
178
174
```
179
175
180
176
In this step you learned that the `--security-opt apparmor=unconfined` flag will start a new container without an AppArmor profile.
181
177
182
178
# <aname="depth"></a>Step 4: AppArmor and defense in depth
183
179
184
-
Defense in depth is a model where multiple different lines of defense work together to provide increased overall defensive capabilities. Docker uses AppArmor, seccomp, and Capabilities to form a deep defense system.
180
+
Defense in depth is a model where multiple different lines of defense work together to provide increased overall defensive capabilities. Docker uses many Linux technologies, such as AppArmor, seccomp, and Capabilities, to form a deep defense system.
185
181
186
182
In this step you will see how AppArmor can protect a Docker Host even when other lines of defense such as seccomp and Capabilities are not effective.
187
183
188
184
1. If you haven't already done so, stop and remove all containers on your system.
189
185
190
186
```
191
-
$ sudo docker rm -f $(docker ps -aq)
187
+
$ docker container rm -f $(docker container ls -aq)
192
188
```
193
189
194
190
2. Start a new Ubuntu container with seccomp disabled and the `SYS_ADMIN`*capability* added.
195
191
196
192
```
197
-
$ sudo docker run --rm -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined ubuntu sh
193
+
$ docker container run --rm -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined ubuntu sh
198
194
#
199
195
```
200
196
@@ -211,12 +207,12 @@ In this step you will see how AppArmor can protect a Docker Host even when other
211
207
212
208
The operation failed because the `default-docker` AppArmor profile denied the operation.
213
209
214
-
4. Exit the container.
210
+
4. Exit the container using the `exit` command.
215
211
216
212
5. Confirm that it was the `default-docker` AppArmor profile that denied the operation by starting a new container without an AppArmor profile and retrying the same operation.
217
213
218
214
```
219
-
$ sudo docker run --rm -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu sh
215
+
$ docker container run --rm -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu sh
220
216
221
217
# mkdir 1; mkdir 2; mount --bind 1 2
222
218
# ls -l
@@ -230,6 +226,8 @@ In this step you will see how AppArmor can protect a Docker Host even when other
230
226
231
227
The operation succeeded this time. This proves that it was the `default-docker` AppArmor profile that prevented the operation in the previous attempt.
232
228
229
+
6. Exit the container with the `exit` command.
230
+
233
231
In this step you have seen how AppArmor works together with seccomp and Capabilities to form a defense in depth security model for Docker. You saw a scenario where even with seccomp and Capabilities not preventing an action, AppArmor still prevented it.
@@ -265,7 +263,7 @@ In this step we'll show how a custom AppArmor profile could have protected Docke
265
263
3. View the contents of the Docker Compose YAML file.
266
264
267
265
```
268
-
cat docker-compose.yml
266
+
$ cat docker-compose.yml
269
267
wordpress:
270
268
image: endophage/wordpress:lean
271
269
links:
@@ -299,8 +297,12 @@ mysql:
299
297
300
298
4. Bring the application up.
301
299
300
+
It may take a minute or two to bring the application up. Once the application is up you will need to hit the <Return> key to bring the prompt to the foreground.
301
+
302
+
You may need to install `docker-compose` to complete this step. If your lab machine does not already have Docker Compose isntalled, you can install it with the following commands `sudo apt-get update` and `sudo apt-get install docker-compose`.
303
+
302
304
```
303
-
$ sudo docker-compose up &
305
+
$ docker-compose up &
304
306
Pulling mysql (mariadb:10.1.10)...
305
307
10.1.10: Pulling from library/mariadb
306
308
03e1855d4f31: Pull complete
@@ -330,19 +332,28 @@ In the next few steps you'll apply a new Apparmor profile to a new WordPress con
330
332
331
333
9. Bring the WordPress application down.
332
334
333
-
Run this command from the shell of your Docker Host, not the shell of the `wordpress` container.
335
+
Run these commands from the shell of your Docker Host, not the shell of the `wordpress` container.
334
336
335
337
```
336
-
$ sudo docker-compose down
337
-
Stopping wordpress_wordpress_1 ...
338
-
Stopping wordpress_mysql_1 ...
339
-
<SNIP>
338
+
$ docker-compose stop
339
+
Stopping wordpress_wordpress_1 ... done
340
340
Stopping wordpress_mysql_1 ... done
341
+
$
342
+
$ docker-compose rm
343
+
Going to remove wordpress_wordpress_1, wordpress_mysql_1
344
+
Are you sure? [yN] y
341
345
Removing wordpress_wordpress_1 ... done
342
346
Removing wordpress_mysql_1 ... done
343
347
```
344
348
345
-
10. Add the `wparmor` profile to the `wordpress` service in the `docker-compose.yml` file.
349
+
10. Add the `wparmor` profile to the `wordpress` service in the `docker-compose.yml` file. You do this by deleting the two lines starting with `#` and replacing them with the following two lines:
350
+
351
+
```
352
+
security_opt:
353
+
- apparmor=wparmor
354
+
```
355
+
356
+
Be sure to add the lines with the correct indentation as shown below.
346
357
347
358
```
348
359
wordpress:
@@ -387,7 +398,7 @@ In the next few steps you'll apply a new Apparmor profile to a new WordPress con
387
398
13. Bring the Docker Compose WordPress app back up.
388
399
389
400
```
390
-
$ sudo docker-compose up &
401
+
$ docker-compose up &
391
402
Pulling mysql (mariadb:10.1.10)...
392
403
10.1.10: Pulling from library/mariadb
393
404
03e1855d4f31: Pull complete
@@ -401,7 +412,7 @@ In the next few steps you'll apply a new Apparmor profile to a new WordPress con
Copy file name to clipboardExpand all lines: security/capabilities/README.md
+10-10
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ You will complete the following steps as part of this lab.
17
17
18
18
You will need all of the following to complete this lab:
19
19
20
-
- A Linux-based Docker Host running Docker 1.12 or higher
20
+
- A Linux-based Docker Host running Docker 1.13 or higher
21
21
22
22
# <aname="cap_intro"></a>Step 1: Introduction to capabilities
23
23
@@ -87,23 +87,23 @@ In this step you will start various new containers. Each time you will use the c
87
87
1. Start a new container and prove that the container's root account can change the ownership of files.
88
88
89
89
```
90
-
$ sudo docker run --rm -it alpine chown nobody /
90
+
$ docker container run --rm -it alpine chown nobody /
91
91
```
92
92
93
93
The command gives no return code indicating that the operation succeeded. The command works because the default behavior is for new containers to be started with a root user. This root user has the CAP_CHOWN capability by default.
94
94
95
95
2. Start another new container and drop all capabilities for the containers root account other than the CAP\_CHOWN capability. Remember that Docker does not use the "CAP_" prefix when addressing capability constants.
96
96
97
97
```
98
-
$ sudo docker run --rm -it --cap-drop ALL --cap-add CHOWN alpine chown nobody /
98
+
$ docker container run --rm -it --cap-drop ALL --cap-add CHOWN alpine chown nobody /
99
99
```
100
100
101
101
This command also gives no return code, indicating a successful run. The operation succeeds because although you dropped all capabilities for the container's `root` account, you added the `chown` capability back. The `chown` capability is all that is needed to change the ownership of a file.
102
102
103
103
3. Start another new container and drop only the `CHOWN` capability form its root account.
@@ -112,7 +112,7 @@ In this step you will start various new containers. Each time you will use the c
112
112
4. Create another new container and try adding the `CHOWN` capability to the non-root user called `nobody`. As part of the same command try and change the ownership of a file or folder.
@@ -130,7 +130,7 @@ There are two main sets of tools for managing capabilities:
130
130
131
131
Below are some useful commands from both.
132
132
133
-
> You may need to manually install the packages required for some of these commands.
133
+
> You may need to manually install the packages required for some of these commands.`sudo apt-get install libcap-dev`, `sudo apt-get install libcap-ng-dev`, `sudo apt-get install libcap-ng-utils`.
134
134
135
135
## **libcap**
136
136
@@ -151,7 +151,7 @@ The remainder of this step will show you some examples of `libcap` and `libcap-n
151
151
The following command will start a new container using Alpine Linux, install the `libcap` package and then list capabilities.
152
152
153
153
```
154
-
$ sudo docker run --rm -it alpine sh -c 'apk add -U libcap; capsh --print'
154
+
$ docker container run --rm -it alpine sh -c 'apk add -U libcap; capsh --print'
155
155
156
156
(1/1) Installing libcap (2.25-r0)
157
157
Executing busybox-1.24.2-r9.trigger
@@ -167,7 +167,7 @@ The following command will start a new container using Alpine Linux, install the
**Current** is multiple sets separated by spaces. Multiple capabilities within the same set are separated by commas `,`. The letters following the `+` at the end of each set are as follows:
170
+
In the output above, **Current** is multiple sets separated by spaces. Multiple capabilities within the same *set* are separated by commas `,`. The letters following the `+` at the end of each set are as follows:
171
171
-`e` is effective
172
172
-`i` is inheritable
173
173
-`p` is permitted
@@ -203,7 +203,7 @@ usage: capsh [args ...]
203
203
```
204
204
205
205
> Warning:
206
-
> `--drop` sounds like what you want to do, but it only affects the bounding set. This can be very confusing because it doesn't actually take away the capability from the effective or inheritable set. You almost always want to use `--caps`.
206
+
> `--drop` sounds like what you want to do, but it only affects the bounding set. This can be very confusing because it doesn't actually take away the capability from the effective or inheritable set. You almost always want to use `--caps`, `sudo apt-get install attr`.
207
207
208
208
### Modifying capabilities
209
209
@@ -214,7 +214,7 @@ Libcap and libcap-ng can both be used to modify capabilities.
214
214
The command below shows how to set the CAP_NET_RAW capability as *effective* and *permitted* on the file represented by `$file`. The `setcap` command calls on libcap to do this.
215
215
216
216
```
217
-
$ setcap cap_net_raw=ep $file
217
+
$ sudo setcap cap_net_raw=ep $file
218
218
```
219
219
220
220
2. Use libcap-ng to set the capabilities of a file.
0 commit comments