Os ambientes em nuvem oferecem diversos recursos que aceleram o desenvolvimento de soluções distribuídas complexas. Mas o aumento da complexidade pode criar, ou intensificar, vários desafios. Por exemplo, a manutenção das credenciais necessárias para aumentar a segurança na comunicação entre os componentes pode se tornar um pesadelo. A expiração de uma única credencial mal gerenciada pode causar a queda de serviços críticos com consequências potencialmente catastróficas.
Nesse artigo veremos como uma funcionalidade do Azure AD e AKS pode nos ajudar a resolver esse desafio.
Autenticação sem senhas
Nos últimos anos, Microsoft, Apple e Google vêm trabalhando em tecnologias para permitir a autenticação de seus usuários sem senhas. Além de aumentar a segurança, essa nova forma de autenticação é mais conveniente para os usuários, pois eles não precisam mais memorizar e gerenciar senhas.
Voltando para o desafio de autenticação de aplicações, a Microsoft deu um passo importante com o lançamento do projeto de código aberto Azure AD Workload Identity para o AKS. Com essa tecnologia, suas aplicações Kubernetes podem acessar recursos protegidos sem a necessidade de compartilhar segredos. Para isso, basta que o seu cluster Kubernetes disponibilize um emissor OpenID Connect (OIDC).
Como funciona
Nesse modelo de autenticação, o cluster AKS emite um token confiado pelo Azure AD. Após validar esse token, é feita a troca do token emitido pelo AKS por um emitido pelo Azure AD, o que permite que sua aplicação acesse os recursos protegidos.
Como utilizar
Para utilizar o Workload Identity no AKS, precisamos criar um cluster com as funcionalidades de emissor OIDC e Workload Identity habilitadas.
- Os exemplos nesse artigo estão escritos em PowerShell com Azure CLI e C#.
$rg = "<Nome do grupo de recursos criado previamente>"
$aks = "<Nome do cluster AKS>"
az aks create `
-g $rg `
-n $aks `
--tier free `
--enable-oidc-issuer `
--enable-workload-identity
# O comando abaixo armazena a URL de configuração do emissor OIDC do AKS na
# variável $oidcConfigURL
$oidcConfigURL = (az aks show `
-g $rg `
-n $aks `
--query "oidcIssuerProfile.issuerUrl" `
-o tsv)
$oidcConfigURL
Caso o cluster AKS já exista, você pode usar o comando az aks update
com as opções enable-oidc-issuer
e enable-workload-identity
para habilitar essas funcionalidades.
Com o cluster criado, precisamos registrar a aplicação no Azure AD que irá proteger o acesso aos recursos, e associá-la a um service principal:
$nomeApp = "<Nome da aplicação>"
az ad app create --display-name $nomeApp
$clientID = (az ad app list --display-name $nomeApp --query [].appId -o tsv)
az ad sp create --id $clientID
O próximo passo é criar a conta de serviço do Kubernetes que será confiada pela aplicação do Azure AD que acabamos de criar.
- A conta de serviço precisa definir a anotação
azure.workload.identity/client-id
com oclient id
da aplicação registrada no Azure AD.
- Os exemplos PowerShell utilizam here-strings para definir strings de múltiplas linhas.
$contaServicoK8s = "<Nome da conta de serviço do Kubernetes>"
$namespaceK8s = "<Nome do namespace do Kubernetes>"
az aks get-credentials -g $rg -n $aks
@"
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: "$clientID"
name: "$contaServicoK8s"
namespace: "$namespaceK8s"
"@ | kubectl apply -f -
# Confirme se a conta de serviço foi criada:
kubectl describe serviceaccounts -n $namespaceK8s $contaServicoK8s
Com as duas identidades criadas, podemos federá-las:
@"
{
"name": "WorkloadIdentityDemo",
"issuer": "$oidcConfigURL",
"subject": "system:serviceaccount:$namespaceK8S`:$contaServicoK8s",
"description": "Workload identity demo",
"audiences": [
"api://AzureADTokenExchange"
]
}
"@ > parametros.json
az ad app federated-credential create `
--id $clientID `
--parameters parametros.json
Remove-Item parametros.json
Com tudo configurado, podemos subir um pod no nosso cluster para verificar se o token da conta de serviço está sendo apresentado corretamente.
- O pod precisa ser configurado para executar na conta de serviço federada e definir o label
azure.workload.identity/use
com valortrue
.
@"
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: $namespaceK8s
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: $contaServicoK8s
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
"@ | kubectl apply -f -
kubectl get pod nginx -n $namespaceK8s -o=jsonpath='{.spec.containers[0].env}'
Se tudo deu certo, o último comando retornará as variáveis de ambiente injetadas pelo Azure AD Workload Identity:
[
{
"name": "AZURE_CLIENT_ID",
"value": "<guid>"
},
{
"name": "AZURE_TENANT_ID",
"value": "<guid>"
},
{
"name": "AZURE_FEDERATED_TOKEN_FILE",
"value": "/var/run/secrets/azure/tokens/azure-identity-token"
},
{
"name": "AZURE_AUTHORITY_HOST",
"value":"https://login.microsoftonline.com/"
}
]
Como requisitar um token de acesso
Para requisitar um token de acesso, podemos utilizar a biblioteca Azure Identity, que disponibiliza a classe DefaultAzureCredential
. Com as informações injetadas pelo Azure AD Workload Identity, essa classe consegue requisitar um token de acesso do Azure AD, como ilustrado no próximo exemplo. Com o token em mãos, basta injetá-lo no cabeçalho Authorization das suas requisições HTTP para ter acesso às APIs protegidas.
using Azure.Core;
using Azure.Identity;
var credential = new DefaultAzureCredential();
var context = new TokenRequestContext(new string[] {
"<Escopo>",
});
var token = await credential.GetTokenAsync(context);
var jwt = token.Token;
Para consumir um serviço protegido do Azure que o nosso service principal tenha acesso, é possível usar a mesma classe. Isso porque ela é derivada da classe TokenCredential
, e grande parte dos clientes disponibilizados pelos SDKs do Azure a aceitam para se autenticar nos serviços.
Por exemplo, se você precisar ler uma configuração do Azure App Configuration, crie o cliente ConfigurationClient
com o construtor que aceita o TokenCredential
como parâmetro.
using Azure.Data.AppConfiguration;
using Azure.Identity;
var credential = new DefaultAzureCredential();
var client = new ConfigurationClient(
new Uri("<Endpoint do App Configuration>"), credential);
var setting = await client.GetConfigurationSettingAsync("chave");
- Note que em nenhum momento foi necessário compartilhar segredos ou chaves de acesso para ter acesso aos recursos protegidos.
Conclusão
Nesse artigo vimos como o Azure AD Workload Identity permite a autenticação de aplicações no seu cluster Kubernetes sem a necessidade de compartilhar segredos. Assim, eliminamos os riscos e custos de manter uma operação para gerenciá-los.
No repositório https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity tem exemplos para várias plataformas de desenvolvimento caso tenha interesse em testar essa funcionalidade.
Updated May 25, 2023
Version 2.0ateoi
Microsoft
Joined July 29, 2021
Desenvolvedores BR
Follow this blog board to get notified when there's new activity