Nos últimos dias estive procurando formas de garantir algumas práticas relacionadas à implantação de aplicações em um cluster de kubernetes. No caso, eu queria garantir que não fossem criados pods que estivessem rodando containers como root dentro do cluster por questões de segurança. Dentre as alternativas encontrei o gatekeeper que como o próprio nome sugere, é uma ferramenta para criar regras de implantação de recursos e garantir que essas regras serão respeitadas. Aqui ele funcionará como o “guardião do portão” de entrada do kubernetes. Vamos ver um exemplo.

Para utilizar o gatekeeper é necessária à sua instalação no cluster e fiz isso com o helm:

helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update

helm install -n gatekeeper-system gatekeeper gatekeeper/gatekeeper --create-namespace

Podemos ver os pods do gatekeeper rodando abaixo:

kubectl get pods -n gatekeeper-system
NAME READY STATUS RESTARTS AGE
gatekeeper-audit-7fc78ff6f-bn66g 1/1 Running 0 156m
gatekeeper-controller-manager-bd98746d7-8vng9 1/1 Running 0 156m
gatekeeper-controller-manager-bd98746d7-lb5lp 1/1 Running 0 156m
gatekeeper-controller-manager-bd98746d7-v4kst 1/1 Running 0 156m

Agora vamos criar uma constraint do gatekeeper que nos permite controlar os dados de permissões do pod

kubectl apply -f https://github.com/open-policy-agent/gatekeeper-library/blob/master/library/pod-security-policy/users/template.yaml
constrainttemplate.templates.gatekeeper.sh/k8spspallowedusers created

Isso agora nos permite especificar a regra que queremos que seja aplicada com relação aos usuários e grupos de execução do pod, vou criar um namespace e depois a regra apenas permitindo pods que não executem containers como root:

kubectl create ns teste-policy

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowedUsers
metadata:
name: pods-sem-root
namespace: teste-policy
spec:
match:
kinds:
apiGroups: [""]
kinds: ["Pod"]
parameters:
runAsUser:
rule: MustRunAsNonRoot

Agora no namespace teste-policy apenas poderão serem criados pods que não executem o container como root, abaixo vou criar um pod com um usuário root para ver o que acontece (o campo runAsUser = 0 significa rodar como root):

apiVersion: v1
kind: Pod
metadata:
name: nginx-users-disallowed
namespace: teste-policy
labels:
app: nginx-users
spec:
securityContext:
containers:
name: nginx
image: nginx
securityContext:
runAsUser: 0

kubectl apply -f pod-root-gatekeeper.yaml

Error from server ([pods-sem-root] Container nginx is attempting to run as disallowed user 0. Allowed runAsUser: {"rule": "MustRunAsNonRoot"}): error when creating ".\\pod-root-gatekeeper.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [pods-sem-root] Container nginx is attempting to run as disallowed user 0. Allowed runAsUser: {"rule": "MustRunAsNonRoot"}

Veja que o gatekeeper não deixou o pod ser criado por não satisfazer nossa política de implantação, vamos criar um pod agora com usuário diferente de root:

apiVersion: v1
kind: Pod
metadata:
name: pod-do-bem
namespace: teste-policy
labels:
app: nginx-users
spec:
securityContext:
containers:
name: nginx
image: nginx
securityContext:
runAsUser: 1

kubectl apply -f pod-nao-root-gatekeeper.yaml

pod/pod-do-bem created

Veja que legal! Com isso, conseguimos criar um guia de boas práticas a serem aplicadas para o cluster inteiro. Aqui nesse link tem diversos exemplos de políticas que podem ser aplicadas para os recursos do kubernetes e vale a olhada com calma para entender o que faz sentido aplicar à sua organização.