Azure · Key Vault · Seguridad

Azure Managed HSM – AccessDenied al crear una Role Assignment

Recientemente necesité permitir que equipos de desarrollo gestionaran el acceso a sus propias claves en un Azure Key Vault Managed HSM, sin conceder permisos en todo el HSM.

En resumen, la idea era utilizar la función Managed HSM Policy Administrator en el scope de una clave. De esta forma, cada equipo podría crear y eliminar Role Assignments solo en la clave que estuviera bajo su responsabilidad.

Fue cuando recibí un AccessDenied utilizando el Azure CLI, pero, al revisar la clave, noté que el permiso había sido creado aun así.

Voy a mostrar lo que ocurrió.

Escenario

El usuario que ejecutaba el comando tenía la función Managed HSM Policy Administrator en el scope /keys/my-key.

De acuerdo con la documentación, esta función permite crear y eliminar Role Assignments. Cuando se le atribuye en /keys/<nombre-de-la-clave>, el permiso queda limitado a esa clave.

Entonces, ejecuté el siguiente comando para conceder Managed HSM Crypto User a una 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"

Error

Aunque había permiso en el scope de la clave, recibí el siguiente error:

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

Al mirar el mensaje, vi que el acceso negado ocurrió en /, que es el scope raíz del HSM, y no en /keys/my-key, que fue el scope utilizado en el comando.

Hasta ese momento, pensé que la Role Assignment no se había creado.

Pero, al consultar los permisos de la clave, la nueva Role Assignment estaba allí.

O sea, Azure CLI mostró un error, pero la operación se había completado.

Verificar si se creó la Role Assignment

Para confirmar, puedes listar los permisos utilizando el mismo scope de la clave:

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

Si la identidad, la función y el scope aparecen en el resultado, el permiso fue creado, aun cuando el comando anterior haya retornado AccessDenied.

Qué ocurrió

Al analizar el código del Azure CLI, encontré la razón del error.

Durante la ejecución, el comando:

  1. busca la definición de la función;
  2. crea la Role Assignment en el scope informado;
  3. consulta de nuevo las definiciones de función para montar la respuesta que se mostrará.

El problema ocurre en el tercer paso.

Después de crear el permiso en el scope correcto, el código llama list_role_definitions sin informar el scope. Con eso, la consulta se realiza en /.

Como el usuario tenía Managed HSM Policy Administrator solo en /keys/my-key, podía crear el permiso en esa clave, pero no podía consultar las definiciones en el HSM entero.

Entonces, la creación funcionó y la consulta realizada después falló.

Cuidado con scripts y pipelines

Este comportamiento puede causar un problema en scripts y pipelines, ya que el comando se interpretará como un fallo y podría ejecutarse de nuevo.

Antes de intentar de nuevo:

  • consulta las Role Assignments utilizando --scope "/keys/<nombre-de-la-clave>";
  • confirma si la identidad, la función y el scope están correctos;
  • ejecuta el comando de nuevo solo si el permiso realmente no existe.

Cada ejecución puede crear una nueva Role Assignment para la misma identidad, función y scope. Por eso, no basta con confiar solo en el error mostrado por Azure CLI.

También sería posible otorgar al usuario permiso en el scope raíz, pero eso daría acceso además de lo necesario y eliminaría la separación que quería mantener entre los equipos.

Lo que aprendí

En este caso, el AccessDenied no significa que la creación de la Role Assignment haya fallado.

El permiso se crea en el scope de la clave y el error ocurre después, cuando el Azure CLI intenta hacer una consulta en /.

Entonces, si encuentras el mismo comportamiento, verifica primero los permisos directamente en /keys/<nombre-de-la-clave> antes de ejecutar el comando de nuevo.

Abrí una issue en el repositorio del Azure CLI y, en el momento en que escribo este artículo, todavía está abierta.

Referencias

Azure CLIAzure Key VaultManaged HSMRBAC
Azure Managed HSM – AccessDenied al crear una Role Assignment — Vinicius Deschamps