hashicorp / vault-plugin-secrets-azure

Vault Azure Secrets plugin
Mozilla Public License 2.0
26 stars 20 forks source link

/config endpoint causes confusion and imposes limitations due to use of subscription_id field #102

Open natilik-mikeguy opened 1 year ago

natilik-mikeguy commented 1 year ago

Good evening!

I've been looking at the Azure secrets engine, and for people familiar with Azure I feel it is a little confusing and imposes unnecessary restrictions that hamper functionality and/or increase management overheads. I shall explain below - apologies if I have misunderstood anything.

The Issue

When writing data to /azure/config, you are essentially configuring the details of the service principal that Vault itself will use to authenticate to Azure AD (and generate further service principals). When configuring this in Vault, you MUST provide "subscription_id" for it to work (at least it seems this way from a quick test) - this has the following challenges:

Enhancement Request

Please consider de-coupling the service principal that Vault uses from the subscriptions it may (or may not) manage. i.e. to create a SP it may look like:

vault write azure/config \
     client_id=$CLIENT_ID \
     client_secret=$CLIENT_SECRET \
     tenant_id=$TENANT_ID \
     use_microsoft_graph_api=true

This sets up Vault to be able to securely talk to the Microsoft Graph API. With these credentials Vault may then be used to assign RBAC permissions to subscriptions or it may manage service principals that are in no way related to subscriptions.

I suspect the value subscription_id is used to populate parts of API calls. If this is the case, this logic would be better implemented under the role in my opinion - this feels like the logical place to reference subscription ID.

A further future enhancement may be to support multiple configs (e.g. /azure/config/tenant_1 and /azure/config/tenant_2) as you get for instance with database secrets engines.

I hope this makes sense, if it doesn't or you require further info, please let me know and I'd be happy to discuss further.

TimHodkin commented 1 year ago

Hi,

I just wanted to chime in a little here. Firstly I agree this engine is confusing when it comes to how the "vault_azure_secret_backend_role" work.

Lets confirm how I can see the functionality working and limitations. Configuring a role using the "application_object_id" set means you can pre-create an application registration with all the permissions required, both in AAD and on Azure resources and that you can then cycle the secret for. This is fine but requires more configuration initially to setup the service principle and means that you manage all the actual rights assignments through this SPN.

vault write azure/roles/my-role \
    application_object_id=<existing_app_obj_id> \
    ttl=1h

Configuring a role using the "azure_roles" means you can specify a role from a SUBSCRIPTION and not from AAD that you can use to generate an SPN that has access to the relevant subscription. This limitation on the roles you can specify, means you cannot use AzureAD roles to assign to the dynamic SPNs being created and HAVE to target a subscription. However you can target any subscription with a single engine, you just have to specify the full path to the role and ensure the engine has at least the role "User access Administrator" on the subscription being targeted.

vault write azure/roles/my-role ttl=1h azure_roles=-<<EOF
    [
        {
            "role_id": "/subscriptions/<Target subscription>/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7",
            "scope": "/subscriptions/<Target Subscription>
        }
    ]
EOF

So what we are left with is the "azure_groups" option when specifying a new role that you want to be dynamically created. With specifying groups you can pre-create the AzureAD groups and grant them the relevant roles that you want the SPN to have when it is created. The downside to this is you need a P2 AD licence to be able to assign roles to groups.

vault write azure/roles/my-role \
    ttl=1h \
    max_ttl=24h \
    azure_groups=<<EOF
[
  {
    "group_name": "foo"
  },
  {
    "group_name": "This won't matter as it will be overwritten",
    "object_id": "a6a834a6-36c3-4575-8e2b-05095963d603"
  }
]
EOF

limitation

What I would like to see is the ability to be able to scope the roles to AD and not just subscriptions. So being able to add an dynamic SPN to azure roles. Something like the below:

vault write azure/roles/my-role ttl=1h azure_roles=-<<EOF
    [
        {
            "role_name": "Global Reader",
            "scope": "/"
        }
    ]
EOF

Hopefully my understanding is all correct! I have only been working with vault for a short while.

I certainly dont understand the reason for the Subscription ID in the configuration and the limitation this seems to bring.

mike-guy commented 1 year ago

Thanks for the additional insight @TimHodkin - it seems regardless of the confusion, I need to hit the docs more and have a play! Appreciate the explanations.

ausfestivus commented 1 year ago

Thanks for writing this up @natilik-mikeguy. Ive raised a support case with Hashicorp to try and get this question answered. The answer will influence some decisions we are making about how we best deploy and configure this engine.

ausfestivus commented 1 year ago

TL;DR

If you want to use Azure Roles Names in your Vault Role definitions then operators MUST configure an Azure Secrets Enginer per Subscription.

If you would like to challenge this then please do reach out to your Hashicorp CSM or account rep and get your account tagged on FR#1204422123481069.

F21 commented 9 months ago

Agree that the current implementation is quite unwieldy. Massive +1 to @mike-guy's proposal, which makes a lot more sense.