Segurança - Apache Ozone
Para conceitos transversais a todos os componentes TDP — como gestão de Secrets, rotação de credenciais, NetworkPolicy, rate limiting e auditoria — consulte Segurança — Padrões Gerais.
Visão geral
O S3 Gateway do Apache Ozone no TDP usa autenticação AWS Signature Version 4 em modo simples, sem Kerberos. Nesse modo, os clientes assinam cada requisição com um access key e um secret key, e o chart injeta as credenciais no S3 Gateway por meio de Secret Kubernetes.
A segurança efetiva combina quatro controles: credenciais por aplicação ou usuário técnico, TLS quando houver tráfego fora do cluster, restrição de rede com NetworkPolicy ou controles equivalentes e auditoria operacional por logs.
Arquitetura de segurança
┌─────────────────────────┐
│ Cliente │
│ (AWS CLI / SDK / Spark)│
└──────────┬──────────────┘
│ AWS Signature v4
│ (Access Key + Secret Key)
▼
┌──────────────────────────┐
│ S3 Gateway (porta 9878) │
│ - Valida assinatura │
│ - Verifica credenciais │
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ Ozone Manager │
│ (Autorização) │
└──────────────────────────┘
AWS Signature v4 sem Kerberos
Níveis de segurança disponíveis
| Nível | Descrição | Uso recomendado |
|---|---|---|
| None | Sem autenticação | Desenvolvimento isolado apenas |
| Simple | AWS Signature v4 sem Kerberos | Produção (recomendado) |
| Kerberos | Segurança Ozone completa | Ambientes enterprise com Kerberos existente |
Configuração no values.yaml
ozone:
s3g:
auth:
enabled: true
type: simple
secretName: ozone-s3-credentials
env:
- name: OZONE-SITE.XML_ozone.s3g.authentication
value: "simple"
- name: OZONE-SITE.XML_ozone.security.enabled
value: "false"
- name: OZONE-SITE.XML_ozone.s3g.secret.http.enabled
value: "false"
| Parâmetro | Descrição | Padrão |
|---|---|---|
ozone.s3g.auth.enabled | Habilita autenticação S3 no S3 Gateway | true |
ozone.s3g.auth.secretName | Secret com as chaves aws_access_key_id e aws_secret_access_key | ozone-s3-credentials |
Com autenticação habilitada, clientes como AWS CLI, SDKs, Spark S3A e Trino precisam usar a mesma região, endpoint e credenciais esperadas pelo S3 Gateway. Use us-east-1 como região padrão quando não houver outra convenção no ambiente.
Use ozone.s3g.auth.enabled: false somente em ambientes de desenvolvimento ou laboratório isolado. Em ambientes compartilhados ou produtivos, mantenha autenticação habilitada e proteja o endpoint S3 REST com TLS e controle de rede.
Modelo de credenciais
Crie credenciais separadas por aplicação, pipeline ou utilizador técnico sempre que possível. Evite partilhar a mesma credencial entre consumidores com perfis de acesso diferentes.
kubectl -n <NAMESPACE> create secret generic ozone-s3-credentials \
--from-literal=aws_access_key_id="<AWS_ACCESS_KEY_ID>" \
--from-literal=aws_secret_access_key="<AWS_SECRET_ACCESS_KEY>"
O Secret deve existir no namespace em que o Ozone está instalado e deve ser referenciado pelo valor ozone.s3g.auth.secretName:
ozone:
s3g:
auth:
enabled: true
secretName: ozone-s3-credentials
Não versionar credenciais reais em repositórios Git, ficheiros de valores, notebooks ou DAGs. Distribua as credenciais aos consumidores por Secrets Kubernetes, variáveis de ambiente geridas ou mecanismos equivalentes do componente.
Gerenciamento de usuários S3
Quando o ambiente utiliza credenciais separadas por pessoa, aplicação ou serviço técnico, padronize um fluxo operacional para criar, listar e remover utilizadores S3.
Criação via script
O script scripts/generate-s3-credentials.sh fica dentro do chart tdp-ozone.
Para usá-lo, execute o comando a partir da raiz do chart, ou ajuste o caminho para o local onde o chart foi extraído.
O utilitário gera pares de access key e secret key e os registra como Secrets Kubernetes:
NAMESPACE=<NAMESPACE> ./scripts/generate-s3-credentials.sh create <APPLICATION_NAME>
Saída esperada:
AWS_ACCESS_KEY_ID=a1b2c3d4e5f6g7h8i9j0
AWS_SECRET_ACCESS_KEY=aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890ABCD
Criação manual
Se preferir criar as credenciais manualmente sem o script:
ACCESS_KEY=$(openssl rand -hex 10)
SECRET_KEY=$(openssl rand -base64 32)
kubectl create secret generic ozone-s3-credentials-<APPLICATION_NAME> \
--from-literal=aws_access_key_id="$ACCESS_KEY" \
--from-literal=aws_secret_access_key="$SECRET_KEY" \
-n <NAMESPACE>
Depois de criar o Secret, registe o accessId no Ozone Manager para o associar a um utilizador do tenant — sem este passo, as credenciais existem no Kubernetes mas não são reconhecidas pelo S3 Gateway:
kubectl exec -n <NAMESPACE> <RELEASE_NAME>-om-0 -- \
ozone sh tenant assignusertoaccessid \
--accessid="$ACCESS_KEY" --tenant-id=default --user-principal=<APPLICATION_NAME>
Listagem
./scripts/generate-s3-credentials.sh list
Para listar os Secrets do S3 Gateway directamente no cluster:
kubectl get secrets -n <NAMESPACE> -l app.kubernetes.io/component=s3g
Remoção
./scripts/generate-s3-credentials.sh delete <APPLICATION_NAME>
Para auditoria operacional, mantenha registo de qual Secret Kubernetes distribui cada credencial e quais workloads consomem esse Secret.
Controle de acesso (ACLs)
O Ozone oferece ACLs ao nível de volume e bucket. Utilize o CLI ozone sh para definir e consultar permissões:
# Definir ACL de bucket (alice com leitura/escrita, bob somente leitura)
kubectl exec -n <NAMESPACE> <RELEASE_NAME>-om-0 -- \
ozone sh bucket setacl \
--acl user:alice:rw,user:bob:r \
/volume1/bucket1
# Consultar ACLs de um bucket
kubectl exec -n <NAMESPACE> <RELEASE_NAME>-om-0 -- \
ozone sh bucket getacl /volume1/bucket1
Rotação e revogação
Para rodar as credenciais, actualize ou recrie o Secret e reinicie os pods que consomem essas variáveis ou ficheiros. Isto inclui o S3 Gateway e os clientes que mantêm credenciais em memória.
kubectl -n <NAMESPACE> rollout restart statefulset/<RELEASE_NAME>-s3g
A revogação prática em modo simples é operacional: remover ou substituir Secrets dos namespaces consumidores, reiniciar workloads e bloquear caminhos de rede quando necessário.
LDAP/AD sem Kerberos
O LDAP ou Active Directory podem ser utilizados como referência de ciclo de vida e nomenclatura de contas, por exemplo para padronizar utilizadores técnicos.
Com ozone.security.enabled=false (sem Kerberos), desactivar uma conta no LDAP/AD não revoga automaticamente credenciais S3 já distribuídas. As chaves S3 são credenciais de cliente que distribui — a revogação é responsabilidade operacional.
Processo recomendado para gestão de ciclo de vida com LDAP/AD:
- Mantenha um identificador estável por conta (ex.:
uiddo LDAP ousAMAccountNamedo AD). - Para cada conta LDAP, gere um par de chaves S3 e armazene como Kubernetes Secret.
- Injete o Secret nos workloads que precisam de acesso (env vars ou ficheiros montados).
- Quando uma conta for desactivada no LDAP, remova o Secret Kubernetes correspondente de todos os namespaces e reimplante os workloads.
- Rotacione chaves periodicamente ou imediatamente após comprometimento.
Controles compensatórios recomendados:
- Restrinja o acesso ao endpoint S3 com NetworkPolicy ou security groups
- Use TLS para o tráfego S3
- Crie service accounts separados (chaves distintas) por aplicação
- Active o audit logging no Ozone
TLS e exposição do S3 REST
Utilize TLS para qualquer acesso ao S3 Gateway REST fora do cluster ou em redes partilhadas. O TLS é normalmente terminado no Ingress Controller ou no Gateway configurado para o hostname https://<OZONE_S3_REST_HOSTNAME>.
tdp-ozone:
ingress:
s3g:
rest:
enabled: true
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: <OZONE_S3_REST_HOSTNAME>
paths:
- path: /
pathType: Prefix
tls:
- secretName: ozone-s3-rest-tls
hosts:
- <OZONE_S3_REST_HOSTNAME>
Exponha OM, SCM e S3 Web UI apenas para redes administrativas. O S3 Gateway REST é plano de dados e exige atenção adicional a TLS, autenticação S3, DNS e políticas de rede.
Rate limiting
Para proteger o endpoint S3 REST contra utilização abusiva, configure limites de pedidos no Ingress Controller NGINX:
tdp-ozone:
ingress:
s3g:
rest:
annotations:
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-connections: "10"
NetworkPolicy e segurança de rede
Restrinja quem pode alcançar o Service <RELEASE_NAME>-s3g-rest na porta 9878. Em clusters com NetworkPolicy, permita apenas os namespaces e ServiceAccounts dos consumidores autorizados, como Spark, Trino, Hive Metastore, Airflow, NiFi ou Jupyter quando aplicável.
Reveja também a exposição externa: se todos os consumidores estão dentro do cluster, prefira Service interno em vez de Ingress para o S3 REST.
Auditoria e logs
Active o audit logging no values.yaml:
ozone:
s3g:
env:
- name: OZONE-SITE.XML_ozone.audit.enabled
value: "true"
- name: OZONE-SITE.XML_ozone.audit.log.file
value: "/var/log/ozone/s3-audit.log"
Para consultar entradas de auditoria nos logs do S3 Gateway:
kubectl logs -n <NAMESPACE> statefulset/<RELEASE_NAME>-s3g | grep AUDIT
Utilize logs do S3 Gateway e dos consumidores para investigar acessos, falhas de assinatura e erros de autorização. Quando o audit logging estiver activo, dirija esses logs para a solução de observabilidade adoptada pelo TDP.
Checklist de produção
Antes de expor o S3 Gateway REST a utilizadores ou integrações fora do cluster, valide:
- Credenciais padrão substituídas por credenciais próprias do ambiente
- TLS habilitado para o hostname público do S3 REST
- Anotação cert-manager ou certificado provisionado manualmente
- Política de rotação definida para credenciais S3
- Procedimento de revogação e recuperação de credenciais documentado
- NetworkPolicy, regras de firewall ou controles equivalentes restringindo o acesso ao endpoint
- Rate limiting configurado no Ingress (se exposto externamente)
- Audit logging activo e logs direccionados para observabilidade
- Teste de criação, leitura, gravação e remoção de objectos com as credenciais finais
Migração de acesso aberto para autenticado
Se o ambiente está a migrar de uma instalação sem autenticação (auth.enabled: false) para autenticação activada:
-
Crie as credenciais antes de habilitar a autenticação:
Terminal inputNAMESPACE=<NAMESPACE> ./scripts/generate-s3-credentials.sh create <APPLICATION_NAME> -
Atualize o
values.yamlhabilitandoozone.s3g.auth.enabled: truee referenciando o Secret criado. -
Aplique a atualização do chart:
Terminal inputhelm upgrade <RELEASE_NAME> oci://registry.tecnisys.com.br/tdp/charts/tdp-ozone \
--namespace <NAMESPACE> \
-f values.yaml -
Atualize todos os consumidores (Spark, Trino, Airflow, etc.) com as novas credenciais antes ou imediatamente após o upgrade.
-
Verifique que todas as aplicações estão operando com as novas credenciais antes de remover o acesso aberto.
Teste de acesso
Verifique a autenticação com e sem credenciais:
# Sem credenciais — deve retornar erro de autenticação
curl http://<RELEASE_NAME>-s3g-rest.<NAMESPACE>.svc.cluster.local:9878/
# Com credenciais — deve retornar lista de buckets
aws configure set aws_access_key_id <AWS_ACCESS_KEY_ID>
aws configure set aws_secret_access_key <AWS_SECRET_ACCESS_KEY>
aws configure set region us-east-1
aws s3 ls --endpoint-url=http://<RELEASE_NAME>-s3g-rest.<NAMESPACE>.svc.cluster.local:9878
Solução de problemas
SignatureDoesNotMatch
-
Verifique que as credenciais no Secret estão correctas:
Terminal inputkubectl get secret ozone-s3-credentials-<APPLICATION_NAME> -n <NAMESPACE> -o jsonpath='{.data}' -
Confirme que o relógio do nó está sincronizado (AWS Signature v4 é sensível a desvio de tempo).
-
Verifique que o endpoint utilizado pelo cliente é exactamente o mesmo utilizado na assinatura.
-
Confirme que a região está configurada como
us-east-1.
Credenciais não reconhecidas (AccessDenied ou 403)
./scripts/generate-s3-credentials.sh create <APPLICATION_NAME>
Reinicie os pods consumidores após recriar o Secret.
Conexão recusada
-
Verifique se o Ingress está configurado correctamente.
-
Teste resolução DNS interna:
Terminal inputkubectl exec -it <POD_NAME> -n <NAMESPACE> -- nslookup <RELEASE_NAME>-s3g-rest.<NAMESPACE>.svc.cluster.local -
Teste via port-forward:
Terminal inputkubectl port-forward -n <NAMESPACE> svc/<RELEASE_NAME>-s3g-rest 9878:9878
aws s3 ls --endpoint-url=http://localhost:9878
AccessDenied com credencial válida
Verifique as ACLs do volume ou bucket:
kubectl exec -n <NAMESPACE> <RELEASE_NAME>-om-0 -- \
ozone sh bucket getacl /<VOLUME_NAME>/<S3_BUCKET>
Ajuste as permissões conforme necessário com ozone sh bucket setacl.
| Sintoma | Causa provável | Correcção |
|---|---|---|
SignatureDoesNotMatch | Credencial incorreta, endpoint divergente, região errada ou clock drift | Confira Secret, URL exata, região us-east-1 e sincronização de horário |
AccessDenied ou 403 | Credenciais não reconhecidas ou política do cliente inconsistente | Valide o Secret e reinicie os pods consumidores |
AccessDenied com credencial válida | ACL de volume ou bucket não permite a operação | Verifique as ACLs com ozone sh bucket getacl |
| Cliente conecta por HTTP mas falha por HTTPS | Certificado, CA ou truststore ausente no consumidor | Configure CA/truststore e use o mesmo esquema da URL publicada |
| Funciona via port-forward, falha via Ingress | DNS, TLS, IngressClass ou regra de rota incorreta | Verifique hostname, certificado, Ingress e logs do controller |
| Consumidor interno não alcança o endpoint | NetworkPolicy ou namespace bloqueando tráfego | Libere o tráfego necessário para <RELEASE_NAME>-s3g-rest:9878 |