As políticas de autorização integradas do Service Mesh (ASM) atendem a cenários comuns de controle de acesso. No entanto, algumas cargas de trabalho exigem lógica além de regras estáticas, como validar tokens em um provedor de identidade externo, aplicar políticas de acesso específicas do negócio ou integrar-se a um mecanismo de políticas como o Open Policy Agent (OPA).
Serviços de autorização personalizados permitem implementar essa lógica no seu próprio código, enquanto o ASM gerencia a aplicação no nível do proxy. O proxy do mesh intercepta cada requisição, encaminha os metadados para o seu serviço via HTTP e permite ou nega a requisição com base no código de status retornado.
Este guia aborda o contrato do protocolo HTTP, apresenta uma implementação de referência em Go e explica como registrar o serviço no ASM.
Como funciona a autorização personalizada
O ASM oferece várias camadas de segurança de requisições que funcionam em conjunto:
A autenticação JSON Web Token (JWT) no gateway verifica a identidade da requisição.
O TLS mútuo (mTLS) entre serviços autentica a identidade do serviço (ativado por padrão em uma instância do ASM).
As políticas de autorização restringem o comportamento da requisição após a confirmação da identidade.
Os serviços de autorização personalizada estendem essas camadas integradas. O diagrama a seguir ilustra o fluxo de ponta a ponta:
Um cliente envia uma requisição para um serviço por meio do proxy do mesh (gateway ou sidecar proxy).
O proxy do mesh extrai os metadados da requisição (método, caminho, cabeçalhos e corpo) e envia uma requisição de autorização HTTP para o seu serviço personalizado.
Seu serviço avalia a requisição e retorna um código de status HTTP:
|
Código de status |
Significado |
Comportamento do proxy |
|
200 |
Autorizado |
Encaminha a requisição original para o serviço upstream |
|
5xx |
Erro no serviço de autorização |
Permite ou nega conforme a configuração do modo de falha |
|
Qualquer outro código (ex.: 403) |
Negado |
Rejeita a requisição e retorna o código de status ao cliente |
Contrato de requisição e resposta HTTP
O proxy do mesh envia uma requisição HTTP padrão para o seu serviço de autorização contendo os metadados da requisição original. Seu serviço inspeciona esses campos e retorna um código de status.
Campos da requisição
|
Campo |
Descrição |
Exemplo |
|
|
Método HTTP da requisição original |
|
|
|
Cabeçalho Host da requisição original |
|
|
|
Caminho e string de consulta |
|
|
|
Todos os cabeçalhos HTTP encaminhados |
|
|
|
Corpo da requisição (se presente) |
|
Requisitos de resposta
Seu serviço de autorização deve seguir estas regras:
|
Resposta |
Código de status |
Quando usar |
|
Permitir |
|
A requisição passa nas verificações de autorização |
|
Negar |
Qualquer código não-2xx e não-5xx (ex.: |
A requisição falha nas verificações de autorização |
|
Erro |
|
O serviço encontra um erro interno |
Opcionalmente, defina cabeçalhos de resposta para o proxy encaminhar ao serviço upstream ou devolver ao cliente.
Desenvolver o serviço de autorização
O ASM é compatível com o Istio open-source. O projeto Istio fornece uma implementação de referência que lida com autorização HTTP e gRPC. A lógica HTTP reside na função ServeHTTP:
// ServeHTTP implements the HTTP check request.
func (s *ExtAuthzServer) ServeHTTP(response http.ResponseWriter, request *http.Request) {
body, err := io.ReadAll(request.Body)
if err != nil {
log.Printf("[HTTP] read body failed: %v", err)
}
l := fmt.Sprintf("%s %s%s, headers: %v, body: [%s]\n", request.Method, request.Host, request.URL, request.Header, returnIfNotTooLong(string(body)))
if allowedValue == request.Header.Get(checkHeader) {
log.Printf("[HTTP][allowed]: %s", l)
response.Header().Set(resultHeader, resultAllowed)
response.Header().Set(overrideHeader, request.Header.Get(overrideHeader))
response.Header().Set(receivedHeader, l)
response.WriteHeader(http.StatusOK)
} else {
log.Printf("[HTTP][denied]: %s", l)
response.Header().Set(resultHeader, resultDenied)
response.Header().Set(overrideHeader, request.Header.Get(overrideHeader))
response.Header().Set(receivedHeader, l)
response.WriteHeader(http.StatusForbidden)
_, _ = response.Write([]byte(denyBody))
}
}
Essa função lê a requisição recebida e verifica se um cabeçalho específico (checkHeader) contém o valor esperado (allowedValue):
Correspondência: Retorna
200 OKe o proxy permite a passagem da requisição original.Sem correspondência: Retorna
403 Forbiddencom uma mensagem de negação e o proxy rejeita a requisição original.
Ambos os caminhos registram os detalhes da requisição em log e definem cabeçalhos de resposta de diagnóstico (resultHeader, overrideHeader, receivedHeader) para rastreamento.
Adaptação para produção
A implementação de referência verifica um único valor de cabeçalho. Substitua essa lógica pelas suas regras reais de autorização. Padrões comuns incluem:
|
Padrão |
Descrição |
|
Validação de JWT |
Validar um JWT e verificar as claims em relação a uma lista de controle de acesso |
|
Provedor de identidade externo |
Consultar um provedor de identidade ou mecanismo de políticas, como OPA ou oauth2-proxy |
|
Regras de negócio |
Aplicar regras baseadas no caminho da requisição, método, conteúdo do corpo ou identidade do chamador |
Independentemente da lógica, o contrato permanece o mesmo: retorne 200 para permitir ou um código não-2xx (como 403) para negar.
Se uma solução open-source madura, como o OPA com Envoy, já atender aos seus requisitos de autorização, considere usá-la em vez de criar um serviço personalizado. O OPA com Envoy implementa o protocolo ext_authz compatível com o ASM.
Registrar e configure o serviço no ASM
Após implantar o serviço de autorização no seu cluster do Container Service for Kubernetes (ACK):
Registre o serviço no console do ASM, na página Define Custom Authorization Service.
Crie uma política de autorização que referencie o serviço registrado para especifique quais proxies do mesh devem utilizá-lo.
Para obter instruções detalhadas, consulte Implementar autorização personalizada usando o protocolo HTTP.
O serviço de autorização de exemplo verifica o cabeçalho especificado pela variável checkHeader. Ao registrar o serviço no ASM, ative o parâmetro Carry origin header within auth request. Sem essa configuração, o proxy não encaminha os cabeçalhos necessários ao serviço de autorização, causando falha nas verificações.
Considerações para produção
Ao executar um serviço de autorização personalizado em produção, considere os seguintes fatores:
Modo de falha: Defina se as requisições devem ser permitidas (fail open) ou negadas (fail closed) quando o serviço de autorização estiver indisponível. Configure esse comportamento nas configurações do mesh (ExtensionProvider).
Impacto na latência: Cada requisição adiciona um salto de rede até o serviço de autorização. Implante o serviço próximo às cargas de trabalho e defina timeouts adequados.
Logs e monitoramento: Registre todas as decisões de autorização com contexto suficiente para depurar problemas de acesso. Monitore taxas de erro e tempos de resposta para detectar interrupções rapidamente.
Segurança: Valide e sanitize todas as entradas provenientes dos cabeçalhos e do corpo da requisição. Não confie em dados fornecidos pelo cliente sem verificação prévia.
Próximos passos
Implementar autorização personalizada usando o protocolo HTTP — Registre e conecte o serviço de autorização no ASM
Referência de autorização externa do Istio — Código-fonte completo do exemplo de autorização HTTP e gRPC