Ao implantar centenas de aplicações conteinerizadas, incorporar credenciais estáticas em cada imagem cria um risco de segurança do tipo "last key" e aumenta a sobrecarga de manutenção. Implante o KMS Agent como sidecar no seu cluster ACK para recuperar secrets dinamicamente do Key Management Service (KMS) usando o mecanismo RRSA, eliminando a necessidade de integração com SDK no código da aplicação.
Conceitos principais
Familiarize-se com os seguintes conceitos antes de prosseguir:
What is KMS Agent: o KMS Agent é um service de proxy HTTP que recupera secrets do KMS e os armazena em cache na memória. As aplicações recuperam secrets do agente por meio de requisições HTTP.
RAM Roles for Service Accounts (RRSA): o RRSA permite isolar permissões de aplicações em um cluster ACK vinculando diferentes funções RAM a diferentes Pods. Cada aplicação assume uma função RAM independente para acessar as APIs do alibaba cloud.
Casos de uso
Use o KMS Agent com RRSA nos seguintes cenários:
Eliminar o problema do "last key"
Armazenar credenciais sensíveis no KMS melhora a segurança, mas acessar o próprio KMS requer autenticação. Depender de um AccessKey estático para acessar o KMS cria um novo risco de segurança.
Ao ativar o RRSA em um cluster ACK, cada Pod pode assumir uma função RAM diferente e usar credenciais de segurança temporárias para acessar o KMS. Isso implementa o princípio do menor privilégio e elimina a necessidade de AccessKeys estáticos, prevenindo vazamentos de credenciais.
Isolar o acesso a secrets entre aplicações e ambientes
É necessário restringir o acesso a secrets entre os ambientes de teste e produção, ou entre diferentes aplicações, para evitar escalonamento de privilégios e acesso não autorizado a secrets.
Com o RRSA, cada aplicação é executada em um namespace separado com sua própria service account e função RAM. Atribuir permissões diferentes a cada função RAM garante controle de acesso granular aos secrets do KMS.
Reduzir os custos de integração com KMS em escala
A integração com o SDK do KMS não escala bem para empresas com centenas de aplicações. Garantir padrões consistentes de cache, recuperação de desastres e segurança em todas as aplicações é difícil, especialmente quando as equipes de segurança, operações e desenvolvimento são separadas.
O KMS Agent resolve esse problema executando como sidecar no mesmo Pod da aplicação. Após ativar o RRSA, o agente autentica-se no KMS automaticamente e armazena os secrets em cache na memória. A aplicação recupera os secrets do agente local sem qualquer integração com SDK.
Arquitetura da solução
A figura a seguir mostra um exemplo com duas aplicações: dev e prod. Cada aplicação pode acessar apenas seus próprios secrets do KMS.
Limitações
Tipos de cluster ACK suportados: ACK managed clusters, ACK dedicated clusters, ACK registered clusters e ACK Serverless clusters.
O cluster ACK e a instância do KMS devem estar na mesma região.
Pré-requisitos
O Docker está instalado e configurado na máquina de build.
O kubectl está configurado com acesso ao seu cluster ACK.
Você possui uma conta do alibaba cloud com as permissões de RAM e KMS necessárias.
Uma instância do KMS existe na mesma região que o seu cluster ACK.
Go 1.18 ou versão posterior está instalado.
Git está instalado.
Procedimento
Este procedimento descreve as configurações de ACK, RAM e KMS necessárias para que uma aplicação recupere secrets via KMS Agent. Os desenvolvedores precisam apenas crie um secret no KMS e lê-lo localmente — as equipes de operações e segurança cuidam da configuração da infraestrutura com antecedência. O código da aplicação não requer integração com SDK, lógica de autenticação nem projeto de mecanismos de cache.
Etapa 1: Compilar o executável do KMS Agent
Instale o Go. Para obter instruções, consulte o guia de instalação do Go.
Baixe o código-fonte e as dependências.
Baixe e instale o Git no site oficial do Git.
Execute os seguintes comandos para clonar o repositório e baixar as dependências:
git clone https://github.com/aliyun/alibabacloud-kms-agent go mod download
No diretório raiz do projeto, execute
go build .para compilar o executável. O nome padrão do executável éalibabacloud-kms-agent, salvo no diretório raiz do projeto.Se o ambiente de build e o ambiente de implantação forem os mesmos, execute
go build .diretamente. Para builds multiplataforma, use os seguintes comandos para gerar um executável de 64 bits:Ambiente de build
Implantar no macOS
Implantar no Linux
Implantar no Windows
macOS
go build .CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .Linux
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build .go build .CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .Windows
SET CGO_ENABLED=0 && SET GOOS=darwin && SET GOARCH=amd64 && go build .SET CGO_ENABLED=0 && SET GOOS=linux && SET GOARCH=amd64 && go build .go build .No diretório raiz do projeto, confirme que o executável
alibabacloud-kms-agentexiste.
Etapa 2: Ativar o RRSA e autorizar o acesso a secrets
Ative o RRSA para o seu cluster ACK.
Enable during cluster creation
Ao criar o ACK managed cluster e o ACK Edge cluster, ative o RRSA na seção Advanced Options (Optional) da configuração do cluster.
Enable on the cluster info page
Acesse o ACK console. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique no nome do seu cluster. No painel de navegação à esquerda, clique em Cluster Information.
Na aba Basic Information, na seção Security and Auditing, clique em Enable ao lado de RRSA OIDC.
Na caixa de diálogo Enable RRSA, clique em OK.
NotaNa página Basic Information, quando o status do cluster mudar de Updating para Running, o recurso RRSA estará ativado para o cluster.
Acesse a página de detalhes do cluster. Na aba Basic Information, na seção Security and Auditing, passe o cursor sobre o status ativo ao lado de RRSA OIDC para visualize o Provider URL e o ARN. Após ativar o RRSA, essa seção exibe o Provider URL e o Provider ARN do RRSA OIDC. Você precisará de ambos os valores ao configurar a política de confiança da função RAM.
Crie uma função RAM com um provedor de identidade como entidade confiável.
Faça login no RAM console como administrador RAM. No painel de navegação à esquerda, selecione .
Clique em Create Role. Na página de criação, clique em Switch to Policy Editor no canto superior direito.
No editor, especifique o provedor de identidade OIDC. Selecione o modo Visual Editor e configure os seguintes parâmetros:
NotaPara mais informações sobre outros modos, consulte Create a RAM role for an OIDC identity provider.
Na seção Principal, selecione IdP e clique em Edit.
Na caixa de diálogo Add Principal, configure os seguintes parâmetros:
IdP Type: selecione OIDC.
IdP: após ativar o RRSA, o ACK crie um provedor de identidade padrão chamado
ack-rrsa-<cluster_id>, onde<cluster_id>é o ID do seu cluster.Action: mantenha o valor padrão
sts:AssumeRole.Condition: adicione uma nova condição junto às condições padrão
oidc:isseoidc:aud:Condition key: selecione oidc:sub.
Operator: selecione StringEquals.
Condition value: insira
system:serviceaccount:<namespace>:<serviceAccountName>.<namespace>: o namespace onde a aplicação reside.<serviceAccountName>: o nome da service account.
Este exemplo usa
system:serviceaccount:rrsa-dev:dev-sa, onderrsa-devé o namespace do Kubernetes edev-saé a service account que você crie na Etapa 3.
Na caixa de diálogo Create Role, defina um nome para a função e clique em OK. Este exemplo usa
dev-role-for-rrsa.Revise a política de confiança de
dev-role-for-rrsa. A política permite que uma service account específica assuma a função RAM por meio do RRSA após passar pela autenticação OIDC.{ "Statement": [ { "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "oidc:aud": [ "sts.aliyuncs.com" ], "oidc:iss": [ "https://oidc-ack-cn-hongkong.oss-cn-hongkong.aliyuncs.com/cf01******" ], "oidc:sub": [ "system:serviceaccount:rrsa-dev:dev-sa" ] } }, "Effect": "Allow", "Principal": { "Federated": [ "acs:ram::5269************:oidc-provider/ack-rrsa-cf01******" ] } } ], "Version": "1" }
Crie uma política de permissões e anexe-a à função RAM.
Crie uma política de permissões. Este exemplo usa o nome de política
dev-role-for-rrsa-kms-policye permite acesso apenas a secrets com a tagenv:dev.
O conteúdo da política é o seguinte:
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:GetSecretValue" ], "Resource": "*", "Condition": { "StringEqualsIgnoreCase": { "kms:tag/env": [ "dev" ] } } } ] }Anexe a política
dev-role-for-rrsa-kms-policyà funçãodev-role-for-rrsa.
Etapa 3: Criar um namespace e uma service account
Um namespace divide um cluster ACK em espaços virtuais logicamente isolados para diferentes ambientes, como desenvolvimento, teste e produção. Por padrão, aplicações em namespaces diferentes não podem acessar os recursos umas das outras. Uma service account fornece uma identidade para um Pod e se vincula dinamicamente a uma função RAM por meio do RRSA.
Crie um arquivo YAML de namespace.
Crie um arquivo chamado
namespace.yamlcom o seguinte conteúdo. Este exemplo crie um namespace chamadorrsa-dev.apiVersion: v1 kind: Namespace metadata: name: rrsa-devExecute o seguinte comando para criar o namespace:
kubectl apply -f namespace.yamlVerifique se o namespace foi criado:
kubectl get namespacesSe a saída incluir
rrsa-dev, o namespace foi criado com sucesso.Crie um arquivo YAML de service account.
Crie um arquivo chamado
serviceaccount.yamlcom o seguinte conteúdo. Este exemplo crie uma service account chamadadev-sano namespacerrsa-dev.apiVersion: v1 kind: ServiceAccount metadata: name: dev-sa namespace: rrsa-devExecute o seguinte comando para criar a service account:
kubectl apply -f serviceaccount.yamlVerifique se a service account foi criada:
kubectl get serviceaccount -n rrsa-devSe a saída incluir
dev-sa, a service account foi criada com sucesso.
Etapa 4: Compilar a imagem de contêiner do sidecar
Empacote o KMS Agent como um contêiner sidecar para implantar junto à sua aplicação no ACK.
Configure os parâmetros de runtime do KMS Agent em
config.toml.NotaO arquivo
config.tomlestá localizado no diretórioconfigsdo código-source do alibabacloud-kms-agent obtido na Etapa 1.[Server] HttpPort = 2025 [KMS] Region = "cn-hangzhou" [Cache] CacheType = "InMemory" CacheSize = 1000 TtlSeconds = 300 [Log] LogLevel = "Debug" LogPath = "./logs/" MaxSize = 100 MaxBackups = 2Crie um
Dockerfile.Por exemplo, crie um Dockerfile em
deploy/ack/agentpara implantar o agente. Para o conteúdo do arquivo, consulte agent_Dockerfile.# Use the centos image as the base FROM centos:centos7 # Set the working directory inside the container WORKDIR /usr/local/alibabacloudkmsagent # Copy the binary and config to the container COPY alibabacloud-kms-agent . COPY config.toml . # Set the entry point to run the kms agent ENTRYPOINT ["./alibabacloud-kms-agent", "agent", "./config.toml"]Copie o executável e a configuração para o diretório
deploy/ack/agent:deploy/ack/agent ├── alibabacloud-kms-agent ├── config.toml ├── Dockerfile.agentCompile a imagem do sidecar e envie-a para o Container Registry:
# Build the image. docker build -t registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0 . # Push the image. docker push registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0
Etapa 5: Compilar a imagem de contêiner da aplicação
Para uma aplicação implantada em
deploy/ack/app, crie um Dockerfile nesse diretório:# Use the centos image as the base FROM centos:centos7 # Set the working directory inside the container WORKDIR / # Set the entry point to run the kms agent ENTRYPOINT ["sleep", "360000"]Compile a imagem da aplicação e envie-a para o Container Registry:
# Build the image. docker build -t registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0 . # Push the image. docker push registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0
Etapa 6: Implantar a aplicação
Custom deployment template
Defina um Deployment personalizado que execute o KMS Agent como sidecar junto ao contêiner da aplicação no mesmo Pod. Para mais informações sobre como execute aplicações conteinerizadas, consulte Create a stateless workload Deployment.
KMS_TOKEN: o caminho de armazenamento do arquivo de token SSRF gerado pelo agente na inicialização.ALIBABA_CLOUD_ROLE_ARN: o ARN da função RAM.ALIBABA_CLOUD_OIDC_PROVIDER_ARN: o ARN do provedor de identidade OIDC (o ARN do cluster ACK).ALIBABA_CLOUD_OIDC_TOKEN_FILE: o caminho para o arquivo que contém o token OIDC.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: rrsa-dev
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
serviceAccountName: dev-sa
containers:
- name: kmsagent
image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0
env:
- name: ALIBABA_CLOUD_ROLE_ARN
value: acs:ram::<uid>:role/dev-role-for-rrsa
- name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN
value: acs:ram::<uid>:oidc-provider/ack-rrsa-<ackClusterId>
- name: ALIBABA_CLOUD_OIDC_TOKEN_FILE
value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
- name: KMS_TOKEN
value: file:///var/run/kmstoken/token
volumeMounts:
- name: shared-volume
mountPath: /var/run/kmstoken
- name: rrsa-oidc-token
mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens
readOnly: true
command: ["/bin/sh", "-c", "./alibabacloud-kms-agent token /var/run/kmstoken/token && ./alibabacloud-kms-agent agent config.toml"]
- name: my-app
image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0
volumeMounts:
- name: shared-volume
mountPath: /var/run/kmstoken
volumes:
- name: shared-volume
emptyDir: {}
- name: rrsa-oidc-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: sts.aliyuncs.com
expirationSeconds: 3600
path: tokenOpenKruise injection
O OpenKruise é uma extensão padrão do Kubernetes que gerencie com eficiência contêineres de aplicações, contêineres sidecar e distribuição de imagens. Para mais informações, consulte Deploy a cloud-native application by using OpenKruise.
Instale o OpenKruise.
Acesse o ACK console. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique no nome do seu cluster. No painel de navegação à esquerda, clique em Components and Add-ons .
Na página Add-ons, clique na aba Manage Applications e pesquise por ack-kruise.
Na coluna Actions, clique em Install Now.
Na página Install Component, confirme as informações do componente e clique em OK.
Configure a regra de injeção do sidecar.
Defina um SidecarSet que injete o sidecar do KMS Agent nos Pods com o rótulo
app.Variáveis de ambiente:
KMS_TOKEN: o caminho de armazenamento do arquivo de token SSRF gerado pelo agente na inicialização.ALIBABA_CLOUD_ROLE_ARN: o ARN da função RAM.ALIBABA_CLOUD_OIDC_PROVIDER_ARN: o ARN do provedor de identidade OIDC (o ARN do cluster ACK).ALIBABA_CLOUD_OIDC_TOKEN_FILE: o caminho para o arquivo que contém o token OIDC.
selector: selecione os Pods nos quais o sidecar será injetado. Ajuste o seletor de rótulos para corresponder à sua aplicação.
apiVersion: apps.kruise.io/v1alpha1 kind: SidecarSet metadata: name: kms-agent-sidecarset namespace: rrsa-dev spec: serviceAccountName: dev-sa containers: - name: kms-agent image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0 env: - name: ALIBABA_CLOUD_ROLE_ARN value: acs:ram::<uid>:role/dev-role-for-rrsa - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN value: acs:ram::<uid>:oidc-provider/ack-rrsa-<ackClusterId> - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token - name: KMS_TOKEN value: file:///var/run/kmstoken/token volumeMounts: - name: shared-volume mountPath: /var/run/kmstoken - name: rrsa-oidc-token mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens readOnly: true command: ["/bin/sh", "-c", "./alibabacloud-kms-agent token /var/run/kmstoken/token && ./alibabacloud-kms-agent agent config.toml"] # Modify the selector to match your application Pods. selector: matchLabels: app: app volumes: - name: shared-volume emptyDir: {} - name: rrsa-oidc-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: sts.aliyuncs.com expirationSeconds: 3600 path: tokenImplante a aplicação com injeção automática do KMS Agent.
Crie um Deployment com o rótulo
app: apppara que o sidecar seja injetado automaticamente.apiVersion: apps/v1 kind: Deployment metadata: name: app-with-kmsagent namespace: rrsa-dev spec: replicas: 1 selector: matchLabels: app: app template: metadata: labels: app: app spec: serviceAccountName: dev-sa containers: - name: my-app image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0 volumeMounts: - name: shared-volume mountPath: /var/run/kmstoken volumes: - name: shared-volume emptyDir: {}Execute a aplicação conteinerizada. Para mais informações, consulte Create a stateless workload Deployment.
Após a inicialização da aplicação, o sidecar do KMS Agent é injetado no Pod.
Na página Stateless, localize um Deployment cujo nome começa com
ack-kms-agent. A contagem de pods exibe 2/2, indicando que o contêiner sidecar foi injetado e está em execução corretamente.
Etapa 7: Criar e recuperar um secret
Crie um secret no KMS.
Adicione a tag
env:devao criar o secret. O contêiner da aplicação só pode acessar secrets com essa tag.Faça login no Key Management service console. Na barra de navegação superior, selecione uma região. No painel de navegação à esquerda, selecione .
Clique na aba Generic Secrets, selecione um Instance ID e clique em Create Secret. Configure os parâmetros e clique em OK.
Parâmetro
Descrição
Secret Name
Um nome de credencial personalizado. Deve ser único dentro da região atual.
Secret Value
Selecione Secret Key/Value ou Plain Text e insira os dados sensíveis a armazenar. O valor pode ter no máximo 30.720 bytes (30 KB).
Initial Version
O número da versão inicial. Valor padrão: v1. Valores personalizados são suportados.
CMK
Selecione a chave simétrica usada para criptografar o valor da credencial. A chave e a credencial devem pertencer à mesma instância do KMS.
ImportanteA chave e a credencial devem pertencer à mesma instância do KMS, e a chave deve ser uma chave simétrica. Para mais informações sobre as chaves simétricas suportadas pelo KMS, consulte Key types and specifications.
Se um usuário RAM ou uma função RAM for utilizado, ele deve ter permissões para execute a operação GenerateDataKey usando a chave mestra de criptografia.
Description
Uma descrição opcional da credencial para identificação e gerenciamento.
Defina a política de acesso para a credencial, controlando quais usuários ou funções RAM podem lê-la ou modifique-a.
Selecione a política padrão primeiro e modifique-a posteriormente conforme necessário.
Recupere o valor do secret.
Use o comando
curl:curl -v -H "X-KMS-Token:$(</var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=app/dev/secret-1'Recupere o secret no código da aplicação por meio de uma requisição HTTP GET:
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s", "app/dev/secret-1") token, err := ioutil.ReadFile("/var/run/kmstoken/token") if err != nil { fmt.Printf("error reading token file: %v\n", err) } req, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Printf("error creating request: %v\n", err) } req.Header.Add("X-KMS-Token", string(token)) client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("error sending request: %v \n", err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("status code %d - %s \n", resp.StatusCode, string(body)) }