Azure · Key Vault · Segurança

Azure Managed HSM – AccessDenied ao criar uma Role Assignment

Recentemente precisei permitir que equipes de desenvolvimento gerenciassem o acesso às suas próprias chaves em um Azure Key Vault Managed HSM, sem conceder permissões no HSM inteiro.

Em resumo, a ideia era utilizar a função Managed HSM Policy Administrator no scope de uma chave. Desta forma, cada equipe poderia criar e remover Role Assignments apenas na chave que estivesse sob sua responsabilidade.

Foi quando recebi um AccessDenied utilizando o Azure CLI, mas, ao verificar a chave, notei que a permissão havia sido criada mesmo assim.

Vou mostrar o que aconteceu.

Cenário

O usuário que executava o comando tinha a função Managed HSM Policy Administrator no scope /keys/my-key.

De acordo com a documentação, essa função permite criar e remover Role Assignments. Quando ela é atribuída em /keys/<nome-da-chave>, a permissão fica limitada àquela chave.

Então, executei o seguinte comando para conceder Managed HSM Crypto User a uma Managed Identity:

az keyvault role assignment create \
  --hsm-name <hsm-name> \
  --assignee-object-id <object-id> \
  --assignee-principal-type ServicePrincipal \
  --role "Managed HSM Crypto User" \
  --scope "/keys/my-key"

Erro

Mesmo com a permissão no scope da chave, recebi o seguinte erro:

ERROR: (AccessDenied) Not authorized to access
Microsoft.KeyVault/managedHsm/roleAssignments/read/action on /

Olhando para a mensagem, notei que o acesso negado aconteceu em /, que é o scope raiz do HSM, e não em /keys/my-key, que foi o scope utilizado no comando.

Até aí, imaginei que a Role Assignment não tivesse sido criada.

Mas, ao consultar as permissões da chave, a nova Role Assignment estava lá.

Ou seja, o Azure CLI mostrou um erro, mas a operação foi concluída.

Verificar se a Role Assignment foi criada

Para confirmar, você pode listar as permissões utilizando o mesmo scope da chave:

az keyvault role assignment list \
  --hsm-name <hsm-name> \
  --scope "/keys/my-key" \
  --query "[?principalId=='<object-id>'].{role:roleName, scope:scope, principalId:principalId}" \
  --output table

Se a identidade, a função e o scope aparecerem no resultado, a permissão foi criada, mesmo que o comando anterior tenha retornado AccessDenied.

O que aconteceu

Ao analisar o código do Azure CLI, encontrei o motivo do erro.

Durante a execução, o comando:

  1. procura a definição da função;
  2. cria a Role Assignment no scope informado;
  3. consulta novamente as definições de função para montar a resposta que será exibida.

O problema acontece no terceiro passo.

Depois de criar a permissão no scope correto, o código chama list_role_definitions sem informar o scope. Com isso, a consulta é feita em /.

Como o usuário tinha Managed HSM Policy Administrator apenas em /keys/my-key, ele podia criar a permissão naquela chave, mas não podia consultar as definições no HSM inteiro.

Então, a criação funcionou e a consulta realizada depois falhou.

Cuidado com scripts e pipelines

Esse comportamento pode causar um problema em scripts e pipelines, pois o comando será interpretado como uma falha e poderá ser executado novamente.

Antes de fazer uma nova tentativa:

  • consulte as Role Assignments utilizando --scope "/keys/<nome-da-chave>";
  • confirme se a identidade, a função e o scope estão corretos;
  • execute o comando novamente apenas se a permissão realmente não existir.

Cada execução pode criar uma nova Role Assignment para a mesma identidade, função e scope. Por isso, não basta confiar apenas no erro apresentado pelo Azure CLI.

Também seria possível conceder ao usuário permissão no scope raiz, mas isso daria acesso além do necessário e eliminaria a separação que eu queria manter entre as equipes.

O que aprendi

Neste caso, o AccessDenied não significa que a criação da Role Assignment falhou.

A permissão é criada no scope da chave e o erro acontece depois, quando o Azure CLI tenta fazer uma consulta em /.

Então, se você encontrar o mesmo comportamento, verifique primeiro as permissões diretamente em /keys/<nome-da-chave> antes de executar o comando novamente.

Abri uma issue no repositório do Azure CLI e, no momento em que escrevo este artigo, ela ainda está aberta.

Referências

Azure CLIAzure Key VaultManaged HSMRBAC
Azure Managed HSM – AccessDenied ao criar uma Role Assignment — Vinicius Deschamps