This repository has been archived by the owner on Apr 17, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1658 from timstclair/aa-loader
AppArmor loader DaemonSet
- Loading branch information
Showing
14 changed files
with
2,115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright 2016 The Kubernetes Authors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
FROM alpine:3.4 | ||
MAINTAINER [email protected] | ||
|
||
ENV GLIBC_VERSION "2.23-r3" | ||
|
||
RUN apk --no-cache add \ | ||
binutils-libs \ | ||
ca-certificates \ | ||
libgcc \ | ||
wget | ||
|
||
# Install the 3p glibc apk. | ||
RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://raw.githubusercontent.com/sgerrand/alpine-pkg-glibc/master/sgerrand.rsa.pub && \ | ||
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk && \ | ||
wget https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk && \ | ||
apk add glibc-${GLIBC_VERSION}.apk glibc-bin-${GLIBC_VERSION}.apk && \ | ||
rm -rf glibc{,-bin}-${GLIBC_VERSION}.apk | ||
|
||
# The apparmor package includes a lot of unnecessary dependencies, so we manually copy the necessary | ||
# files. | ||
ADD libapparmor.so.1 /usr/lib/libapparmor.so.1 | ||
ADD apparmor_parser /sbin/apparmor_parser | ||
|
||
# Reload the libraries. | ||
RUN /usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib | ||
|
||
# Main binary. | ||
ADD loader /usr/bin/loader | ||
|
||
ENTRYPOINT ["/usr/bin/loader", "-logtostderr", "-v=2"] | ||
|
||
# Default directory to watch. | ||
CMD ["/profiles"] |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Copyright 2016 The Kubernetes Authors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
VERSION ?= dev | ||
|
||
loader: loader.go | ||
CGO_ENABLED=0 go build | ||
|
||
.PHONY: docker | ||
docker: loader | ||
ifeq ("", "$(wildcard apparmor_parser)") | ||
$(error Missing required apparmor_parser binary) | ||
endif | ||
ifeq ("", "$(wildcard libapparmor.so.1)") | ||
$(error Missing required libapparmor.so.1 library) | ||
endif | ||
docker build -t google/apparmor-loader:$(VERSION) -f Dockerfile . | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -f loader |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# AppArmor Profile Loader | ||
|
||
This is a small proof-of-concept daemon to demonstrate how AppArmor profiles can be loaded onto | ||
nodes of a Kubernetes cluster. It is not considered production ready, nor will it be supported as a | ||
long-term solution. | ||
|
||
## Running the AppArmor Profile Loader | ||
|
||
The [example-daemon.yaml](example-daemon.yaml) provides an example manifest for running the loader | ||
as a cluster DaemonSet. In this example, the loader runs in a DaemonSet pod on each node in the | ||
cluster, and periodically (every 30 seconds) polls for new profiles in the `apparmor-profiles` | ||
configmap ([example manifest](example-configmap.yaml)). It is recommended to run the Daemon and | ||
ConfigMap in a separate, restricted namespace: | ||
|
||
$ kubectl create -f example-namespace.yaml | ||
$ kubectl create -f example-configmap.yaml # Includes the k8s-nginx profile | ||
$ kubectl create -f example-daemon.yaml | ||
|
||
Check that the profile was loaded: | ||
|
||
$ POD=$(kubectl --namespace apparmor get pod -o jsonpath="{.items[0].metadata.name}") | ||
$ kubectl --namespace apparmor logs $POD | ||
I0829 22:48:24.917263 1 loader.go:139] Polling /profiles every 30s | ||
I0829 22:48:24.954295 1 loader.go:196] Loading profiles from /profiles/k8s-nginx: | ||
Addition succeeded for "k8s-nginx". | ||
I0829 22:48:24.954328 1 loader.go:100] Successfully loaded profiles: [k8s-nginx] | ||
|
||
Trying running a pod with the loaded profile (requires Kubernetes >= v1.4): | ||
|
||
$ kubectl create -f example-pod.yaml | ||
# Verify that it's running with the new profile: | ||
$ kubectl exec nginx-apparmor cat /proc/1/attr/current | ||
k8s-nginx (enforce) | ||
$ kubectl exec nginx-apparmor touch /tmp/foo | ||
touch: cannot touch '/tmp/foo': Permission denied | ||
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1 | ||
|
||
|
||
### Standalone | ||
|
||
The loader go binary can also be run as a standalone binary on the host. It must be run with root | ||
priveledges: | ||
|
||
sudo loader -logtostderr /path/to/profile/dir | ||
|
||
Alternatively, it can be run with the supplied loader docker image: | ||
|
||
PROFILES_PATH=/path/to/profile/dir | ||
sudo docker run \ | ||
--privileged \ | ||
--detach=true \ | ||
--volume=/sys:/sys:ro \ | ||
--volume=/etc/apparmor.d:/etc/apparmor.d:ro \ | ||
--volume=$PROFILES_PATH:/profiles:ro \ | ||
--name=aa-loader \ | ||
google/apparmor-loader:latest | ||
|
||
## Build the loader | ||
|
||
The loader binary is a simple go program, and can be built with `make loader`. Building the Docker | ||
image requires you to supply an `apparmor_parser` binary and `libapparmor.so.1` library. These can | ||
be built from the source at https://code.launchpad.net/apparmor, or copied from a prebuilt package. | ||
|
||
## Limitations | ||
|
||
The loader will not unload profiles that are removed, and will not update profiles that are changed. | ||
This is by design, since there are nuanced issues with changing profiles that are in use. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# An example ConfigMap demonstrating how profiles can be stored as Kubernetes objects, and loaded by | ||
# the apparmor-loader DaemonSet. | ||
|
||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: apparmor-profiles | ||
namespace: apparmor | ||
data: | ||
# Filename k8s-nginx maps to the definition of the nginx profile. | ||
k8s-nginx: |- | ||
#include <tunables/global> | ||
# From https://github.com/jfrazelle/bane/blob/master/docker-nginx-sample | ||
profile k8s-nginx flags=(attach_disconnected,mediate_deleted) { | ||
#include <abstractions/base> | ||
network inet tcp, | ||
network inet udp, | ||
network inet icmp, | ||
deny network raw, | ||
deny network packet, | ||
file, | ||
umount, | ||
deny /bin/** wl, | ||
deny /boot/** wl, | ||
deny /dev/** wl, | ||
deny /etc/** wl, | ||
deny /home/** wl, | ||
deny /lib/** wl, | ||
deny /lib64/** wl, | ||
deny /media/** wl, | ||
deny /mnt/** wl, | ||
deny /opt/** wl, | ||
deny /proc/** wl, | ||
deny /root/** wl, | ||
deny /sbin/** wl, | ||
deny /srv/** wl, | ||
deny /tmp/** wl, | ||
deny /sys/** wl, | ||
deny /usr/** wl, | ||
audit /** w, | ||
/var/run/nginx.pid w, | ||
/usr/sbin/nginx ix, | ||
deny /bin/dash mrwklx, | ||
deny /bin/sh mrwklx, | ||
deny /usr/bin/top mrwklx, | ||
capability chown, | ||
capability dac_override, | ||
capability setuid, | ||
capability setgid, | ||
capability net_bind_service, | ||
deny @{PROC}/{*,**^[0-9*],sys/kernel/shm*} wkx, | ||
deny @{PROC}/sysrq-trigger rwklx, | ||
deny @{PROC}/mem rwklx, | ||
deny @{PROC}/kmem rwklx, | ||
deny @{PROC}/kcore rwklx, | ||
deny mount, | ||
deny /sys/[^f]*/** wklx, | ||
deny /sys/f[^s]*/** wklx, | ||
deny /sys/fs/[^c]*/** wklx, | ||
deny /sys/fs/c[^g]*/** wklx, | ||
deny /sys/fs/cg[^r]*/** wklx, | ||
deny /sys/firmware/efi/efivars/** rwklx, | ||
deny /sys/kernel/security/** rwklx, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# The example DaemonSet demonstrating how the profile loader can be deployed onto a cluster to | ||
# automatically load AppArmor profiles from a ConfigMap. | ||
|
||
apiVersion: extensions/v1beta1 | ||
kind: DaemonSet | ||
metadata: | ||
name: apparmor-loader | ||
# Namespace must match that of the ConfigMap. | ||
namespace: apparmor | ||
spec: | ||
template: | ||
metadata: | ||
name: apparmor-loader | ||
labels: | ||
daemon: apparmor-loader | ||
spec: | ||
containers: | ||
- name: apparmor-loader | ||
image: google/apparmor-loader:latest | ||
args: | ||
# Tell the loader to pull the /profiles directory every 30 seconds. | ||
- -poll | ||
- 30s | ||
- /profiles | ||
securityContext: | ||
# The loader requires root permissions to actually load the profiles. | ||
privileged: true | ||
volumeMounts: | ||
- name: sys | ||
mountPath: /sys | ||
readOnly: true | ||
- name: apparmor-includes | ||
mountPath: /etc/apparmor.d | ||
readOnly: true | ||
- name: profiles | ||
mountPath: /profiles | ||
readOnly: true | ||
volumes: | ||
# The /sys directory must be mounted to interact with the AppArmor module. | ||
- name: sys | ||
hostPath: | ||
path: /sys | ||
# The /etc/apparmor.d directory is required for most apparmor include templates. | ||
- name: apparmor-includes | ||
hostPath: | ||
path: /etc/apparmor.d | ||
# Map in the profile data. | ||
- name: profiles | ||
configMap: | ||
name: apparmor-profiles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# The example Namespace used by other example objects. | ||
|
||
apiVersion: v1 | ||
kind: Namespace | ||
metadata: | ||
name: apparmor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# The example Pod utilizing the profile loaded by the sample daemon. | ||
|
||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: nginx-apparmor | ||
# Note that the Pod does not need to be in the same namespace as the loader. | ||
labels: | ||
app: nginx | ||
annotations: | ||
# Tell Kubernetes to apply the AppArmor profile "k8s-nginx". | ||
# Note that this is ignored if the Kubernetes node is not running version 1.4 or greater. | ||
container.apparmor.security.alpha.kubernetes.io/nginx: localhost/k8s-nginx | ||
spec: | ||
containers: | ||
- name: nginx | ||
image: nginx | ||
ports: | ||
- containerPort: 80 |
Oops, something went wrong.