Hardening
Hardening é reduzir o que existe: menos pacote instalado, menos porta aberta, menos permissão concedida, menos processo com privilégio. Cada coisa removida é uma coisa que não pode ser explorada, não precisa ser corrigida e não aparece no relatório de vulnerabilidade do mês que vem.
O erro comum é tratar hardening como uma varredura anual que gera trezentos itens. O que funciona é escolher poucos controles de alto impacto, aplicá-los por padrão no template que todo mundo usa, e verificar continuamente.
Baselines: use uma, não invente a sua
Seção intitulada “Baselines: use uma, não invente a sua”CIS Benchmarks e o STIG existem e cobrem host, Docker e Kubernetes. Adote uma delas como referência, documente os desvios com justificativa e pare de discutir item por item.
kube-bench run --targets node,policies # CIS para Kubernetesdocker run --rm --net host --pid host --cap-add audit_control \ -v /var/lib:/var/lib:ro -v /var/run/docker.sock:/var/run/docker.sock:ro \ docker/docker-bench-securityTrate o resultado como backlog priorizado, não como lista a zerar. Alguns itens não fazem sentido no seu contexto — registre a decisão em vez de deixá-los reaparecendo.
Host: superfície mínima
Seção intitulada “Host: superfície mínima”Se você ainda administra máquina, o essencial cabe em poucos pontos:
- SSH: só chave (
PasswordAuthentication no), sem login direto de root (PermitRootLogin no), acesso restrito por rede e, de preferência, via bastion ou acesso por identidade. - Pacotes: instale o mínimo; imagem de nó gerenciada e descartável é melhor que máquina de estimação corrigida à mão.
- Atualização: automática para correção de segurança, com reinício planejado.
- Firewall: negue por padrão na entrada, permita o necessário; e sim, também dentro da VPC.
- Auditoria:
auditdou equivalente, com log enviado para fora da máquina — log que fica só no host comprometido não serve de evidência.
ss -tulpn # o que está escutando, e quemsystemctl list-units --type=service --state=running | wc -l # menos é melhorsudo lastb | head # tentativas de login que falharamContainer: usuário, capabilities e sistema de arquivos
Seção intitulada “Container: usuário, capabilities e sistema de arquivos”O securityContext abaixo é o padrão que deveria vir no template de todo serviço:
securityContext: # no Pod runAsNonRoot: true runAsUser: 10001 fsGroup: 10001 seccompProfile: { type: RuntimeDefault }containers: - name: loja securityContext: # no container allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } volumeMounts: - { name: tmp, mountPath: /tmp } # com root read-only, dê um /tmp gravávelSome a isso o que vem da imagem: base mínima (distroless ou Alpine), sem shell e sem gerenciador de pacotes, build multi-stage para não carregar compilador para produção, e nenhum segredo em camada intermediária.
Nunca use privileged: true para resolver permissão negada — ele desliga praticamente
todo o isolamento. Descubra a capability específica que falta e conceda só ela.
Cluster: os controles que mais importam
Seção intitulada “Cluster: os controles que mais importam”Em ordem de retorno pelo esforço:
- Pod Security Admission em
restrictedpara todo namespace de aplicação. - RBAC mínimo: nada de
cluster-adminpara pipeline ou operador; audite comkubectl auth can-i --list --as=…. - NetworkPolicy padrão negando entrada, com liberação explícita — sem isso, qualquer Pod fala com qualquer Pod.
- API server sem exposição pública, ou restrita por origem.
- Criptografia do etcd e backup criptografado.
- Sem token de ServiceAccount montado onde não é usado
(
automountServiceAccountToken: false).
apiVersion: v1kind: Namespacemetadata: name: loja labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/warn: restrictedapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: { name: negar-entrada-padrao, namespace: loja }spec: podSelector: {} # todos os Pods do namespace policyTypes: [Ingress] # nenhuma regra de allow: nega tudo que entraVerificação contínua
Seção intitulada “Verificação contínua”Configuração segura sem verificação vira configuração insegura em três meses — alguém precisa “só para testar” e o teste fica. Automatize três coisas:
- Política de admissão bloqueando o que você acabou de padronizar (Pod Security e Kyverno).
- Varredura periódica do que já está rodando, não só do que vai entrar.
- Alerta de mudança sensível:
ClusterRoleBindingnovo, Pod privilegiado, porta exposta.
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].securityContext.privileged == true) | "\(.metadata.namespace)/\(.metadata.name)"'Mudança de baseline entra por pull request, como qualquer código, e vale para o template que gera novos serviços — hardening que não está no template se perde no próximo projeto.
Próximo passo: para os requisitos que vêm de lei e não de ameaça técnica, siga para Compliance e LGPD para infraestrutura.