This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Community Hub.
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.