Pare de sofrer com REGO, vá de YAML

A criação de políticas de Segurança no Kubernetes é uma busca incessante da área de Segurança para evitar que incidentes exponham os negócios a riscos, como o de vazamento de dados.Até aí, a gente sabe que o negócio é aplicar políticas de segurança nos clusters Kubernetes para impedir ao máximo qualquer exposição a riscos e, no mercado, há várias alternativas de Security Policies para isso: OPA, Gatekeeper, Syra, AWS Opa, Azure Policy e etc.No entanto, o desafio para nós, kuberneteiros de plantão, está em implementar e manter essas políticas na linguagem em que estão escritas, REGO. Por estarmos acostumados a trabalhar com YAML, ferramentas que usam uma nova linguagem, nesse caso REGO, só dificultam a nossa vida! É como dar um passo para trás no que que estamos fazendo para aprender uma nova linguagem e, daí, aplicá-la nas políticas de segurança do cluster K8s.Cansado de sofrer com isso, fui atrás de uma saída e achei o Kyverno. O Kyverno é um controller de Kubernetes capaz de criar a sua própria política de segurança com YAML.Ainda, se mudar de cloud provider, as suas regras já farão parte de seu CI/CD ou de um backup velero ou, no pior cenário, nos YAMLS files do seu diretório escondido no seu drive. Em resumo, é fácil de escrever, entender, ficam num único lugar e podem migrar de cloud provider ou, até mesmo, para on-premise, evitando o lock-in com as operadoras cloud.Você consegue quase tudo com o Kyverno, veja só:

  • Bloquear remoção de resources, principalmente, o próprio Kyverno;

  • Rastrear o que estão executando que possa infringir na segurança dos nós;

  • Automatizar e policiar a criação de labels pra cobrar $$ dos times, quando for um K8s multi tenant;

  • Automatizar a criação de Network Policy e quem pode mexer nelas;

  • Bloquear o uso de recursos específicos, por exemplo, só quero que subam Ingress usando meu ingress-nginx ou o meu kong e o traefik são só do time X;

  • Automagicamente saber que qualquer deploy tem que ter um mínimo de:. recursos de cpu/memória. labels. réplicas

  • Distribuir secrets e configmaps para qualquer namespace criado;

  • Restringir uso de services LoadBalancer e/ou NodePort;

  • Impossibilitar a galera de subir coisas no namespace Default;

  • Forçar todo recurso a usar tag nas imagens e sempre do mesmo registry;

  • Aplicar NetworkPolicy quando um novo namespace é criado;

  • Criar um namespace, gerar todas as políticas e gerar um report do que é aplicado.

Ainda, dá para gerar relatórios de infração, inspeção e aplicação — tudo em YAML — para você extrair com aquele “-o json” e brincar de converter pra HTML. Tem CLI pra quem gosta também.Instalando o Kyverno

Quer instalar o Kyverno, brincar com políticas iniciais e ver como funciona?

A instalação não é intrusiva! Nada vai parar, nenhum erro vai ser gerado pela instalação e não há regra default que force qualquer política. Isso é, pode aplicar o Kyverno no seu cluster de produção, pois ele vai gerar no máximo policies reports indicando onde existe problema a ser tratado, com base nas regras default que não interferem, só aferem. Quer instalar o Kyverno, brincar com políticas iniciais e ver como funciona?Apenas atente-se para o fato de que quanto mais workloads você tem em seu cluster, mais recursos de cpu e memória seu Kyverno vai precisar para analisar, gerar e manter políticas e reports. Se for seu caso, aumente esses valores no deploy do Kyverno.Vamos ao que interessa!Você vai precisar:

* kubectl

* helm => 3.23

* 1 cluster k8s

* git

* kyverno cli, https://kyverno.io/docs/kyverno-cli/ (opcional, só se quiser mesmo, para validar politicas, etc)$ helm repo add kyverno https://kyverno.github.io/kyverno/

$ helm repo update

$ helm install kyverno -n kyverno kyverno/kyverno --create-namespaceVerifique se o pod do Kyverno está instalado:$ kubectl get pod -n kyvernoNAME READY STATUS RESTARTS AGE

pod/kyverno-6868bc56fb-gfcqn 1/1 Running 0 114s

$

$ kubectl get cpolNAME BACKGROUND ACTION

disallow-add-capabilities true audit

disallow-host-namespaces true audit

disallow-host-path true audit

disallow-host-ports true audit

Disallow-privileged-containers true audit

disallow-selinux true audit

require-default-proc-mount true audit

restrict-apparmor-profiles true audit

restrict-sysctls true audit

$

$ kubectl get polr -AO get pod vai trazer seu pod; aguarde até estar “running”.A partir desse momento, o “get cpol vai trazer as políticas aplicadas ao cluster, no âmbito de cluster.O “get polr -A” trará os reports por namespaces, se você tiver namespaces criados e com workloads em execução.Veja que todas as políticas criadas por default estão em audit na coluna action, ou seja, só auditam os workloads. A partir do momento em que se deseja que se apliquem e impeçam alguma execução ou configuração, basta alterar a regra validationFailureAction: enforce e isso impedirá o próximo pod de seguir “quebrando a política”.$ kubectl edit cpol disallow-add-capabilities

(...)

spec:

validationFailureAction: audit #ou enforce para forçar a regra

(...)Primeiro exemplo:Bloqueio de workloads sem label específica:$ cat require-pod-ns-svc-ing-label-required.yaml

apiVersion: kyverno.io/v1

kind: ClusterPolicy

metadata:

name: require-certain-labels

spec:

validationFailureAction: audit

rules:

- name: validate-name-labels

exclude:

resources:

namespaces:

- kube-system

- app1

- workloads-x

match:

resources:

kinds:

- Pod

- Namespace

- Service

- Ingress

validate:

message: "The label `app.kubernetes.io/name` and is required."

pattern:

metadata:

labels:

app.kubernetes.io/name: "?*"

- name: validate-component-labels

exclude:

resources:

namespaces:

- kube-system

- app1

- workloads-x

match:

resources:

kinds:

- Pod

- Namespace

- Service

- Ingress

validate:

message: "The label `app.kubernetes.io/component` is required."

pattern:

metadata:

labels:

app.kubernetes.io/component: "?*"Aplique essa política:$ kubectl apply -f require-pod-ns-svc-ing-label-required.yamlVerifique nos logs do pod do Kyverno e nos objetos de ClusterPolicy:$ kubectl get cpolNAME BACKGROUND ACTION

disallow-add-capabilities true audit

disallow-host-namespaces true audit

disallow-host-path true audit

disallow-host-ports true audit

disallow-privileged-containers true audit

disallow-selinux true audit

require-default-proc-mount true audit

restrict-apparmor-profiles true audit

restrict-sysctls true audit

require-certain-labels true auditAqui, já se observa que nossa regra exigindo as labels informadas sejam aplicadas a qualquer workload em qualquer namespace, com exceção dos namespaces app1, kube-system e workloads-x.Crie um deploy de teste:$ cat web.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

app: web

app.kubernetes.io/name: web

name: web

namespace: default

spec:

replicas: 1

selector:

matchLabels:

app: web

strategy: {}

template:

metadata:

labels:

app: web

app.kubernetes.io/name: web

spec:

containers:

- image: nginx

name: nginx

resources: {}

status: {}$ kubectl apply -f web.yamldeployment.apps/web createdPerceba aqui que só criei uma label app.kubernetes.io/name: web, o que não satisfaz na íntegra minha política recém-criada. Para visualizar as auditorias FAIL dos reports, execute:$ kubectl get polr -n default -o yaml | grep “status: fail” -B14

---

scored: true

status: pass

- message: 'validation error: The label`app.kubernetes.io/component`

is required. Rule validate-certain-labels[0] failed at path

/metadata/labels/app.kubernetes.io/component/.

Rule validate-certain-labels[1] failed at path /metadata/labels

/app.kubernetes.io/component/.'

policy: require-certain-labels

resources:

- apiVersion: apps/v1

kind: Deployment

name: web

namespace: default

uid: cbe8ecc1-71f8-4b2c-819d-59417039fc77

rule: validate-ccomponent-labels

scored: true

status: fail

(...)O policyReport vai mostrar o service kubernetes e o namespace default com a mesma falta de labels que indicamos na política. Se essa política estiver enforce, então será obrigatória a adição dessas labels nesses resources e o pod não será criado até ser resolvida essa pendência.Existem dezenas de outras políticas que podem ser aplicadas no quesito cluster, o que não te impede de aplicá-las somente a um namespace específico, usando o kind: ClusterPolicy ou para namespace, usando o Kind: Policy. Elas estão disponíveis em https://github.com/kyverno/policies.Uma que gosto bastante é a que limita a utilização de recursos e obriga todo pod a obedecer uma regra pré-definida de resources limits/requests:$ cat require-and-set-requests-limits.yaml

apiVersion: kyverno.io/v1

kind: ClusterPolicy

metadata:

name: require-requests-limits

annotations:

policies.kyverno.io/title: Require Limits and Requests

policies.kyverno.io/category: Multi-Tenancy

spec:

validationFailureAction: audit

rules:

- name: validate-resources

exclude:

resources:

namespaces:

- linkerd

- kube-system

match:

resources:

kinds:

- Pod

validate:

message: "CPU and memory resource requests and limits are required."

pattern:

spec:

containers:

- resources:

requests:

memory: "<=1000Mi"

cpu: "<=500m"

limits:

memory: "<=2000Mi"

cpu: "<=1000m"

$

$ kubectl apply -f require-and-set-requests-limits.yamlCom isso, qualquer pod, em qualquer namespace, com exceção do Kube-system, terá que declarar a utilização de resources e, ainda, respeitar os limites para requests e limits. Como diria meu irmão: “existem mil maneiras de preparar Neston, invente a sua”.Baseando-se nos modelos e exemplos do repositório e na documentação, fica fácil criarmos as políticas que precisamos aplicar, sem precisar aprender uma nova linguagem ou nos debruçar sobre vários recursos do K8s para troubleshooting ou evolução.É isso aí, galera! Recomendo que corram pra se atualizar. Kyverno é uma maravilha e a curva de aprendizado é de algumas horas.Qualquer dúvida, sugestão ou crítica, podem me chamar: adonai@getup.io.

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos