DEV Community

Cover image for Import AzureAD app role assignments into Terraform state
Ivica Kolenkaš
Ivica Kolenkaš

Posted on

Import AzureAD app role assignments into Terraform state

This article shows how to import AzureAD app role assignments into the Terraform state. With app role assignments, AzureAD users, groups, or service principals are assigned a role in an application. Source.

In the use case I'm writing about, AzureAD groups are assigned a role "User" in the AzureAD enterprise application for Snowflake, allowing members of those AzureAD groups to single sign-on to Snowflake.

In short

Context

Creating and managing a data platform involves managing its infrastructure and user access among other things. In the data platform my team is managing, we use Snowflake for analytical data warehousing and user access is managed from AzureAD (Microsoft Entra).

This setup allows us to use existing AzureAD users and groups and grant them access to roles inside of Snowflake. In short, adding a group named "ECOM_SALES" will allow any member of that group to log in to Snowflake and use a functional role named ECOM_SALES.

Below is a screenshot of the Snowflake enterprise application showing multiple groups assigned the role "User":

Snowflake enterprise application showing added groups

Being strong believers in infrastructure-as-code, my team manages the entire platform with Terraform. However, during the very early days, some changes were done manually, such as adding AzureAD groups to the enterprise application for Snowflake single sign-on.

Access management is an important part of the overall platform security and as such should be managed through code. Manual configuration can be overlooked during migrations, it does not follow the four-eyes principle which can cause outages and does not provide a stable foundation for a data platform.

The problem

With the understanding of why we want to manage all AzureAD app role assignments with Terraform, let's see how those added manually can be imported and managed with Terraform.

The docs state that app role assignments are imported with:

terraform import \
  azuread_app_role_assignment.example \
  00000000-0000-0000-0000-000000000000/appRoleAssignment/aaBBcDDeFG6h5JKLMN2PQrrssTTUUvWWxxxxxyyyzzz
Enter fullscreen mode Exit fullscreen mode

where:

  • 00000000-0000-0000-0000-000000000000 is the object ID of the service principal object associated with your AzureAD enterprise application for Snowflake.
  • aaBBcDDeFG6h5JKLMN2PQrrssTTUUvWWxxxxxyyyzzz is the app role assignment ID.

I had absolutely no idea where to find the real value of aaBBcDDeFG6h5JKLMN2PQrrssTTUUvWWxxxxxyyyzzz in the UI.

Since Terraform providers communicate with 3rd party APIs (AWS, AzureAD etc...) I figured I could do the same.

Get Microsoft Graph API token

Microsoft's Graph API allows programmatic access to the Microsoft Cloud service resources.

To use it, you must authenticate and obtain a JWT:

TOKEN=$(curl -d grant_type=client_credentials \
  -d client_id=$CLIENT_ID \
  -d client_secret=$CLIENT_SECRET \
  -d scope=https://graph.microsoft.com/.default \
  -d resource=https://graph.microsoft.com  \
  https://login.microsoftonline.com/$TENANT_ID/oauth2/token  |
  jq -j .access_token)
Enter fullscreen mode Exit fullscreen mode

Of course, export CLIENT_ID, CLIENT_SECRET and TENANT_ID first.

List existing app role assignments using the Graph API

Having the JWT in the TOKEN variable, we can list the existing app role assignment for group ECOM_SALES in the AzureAD enterprise application for Snowflake with ID 1ab2c3de-f456-7890-fghi-j12345k67lm8:

ASSIGNMENT_ID=$(curl -sX GET \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  https://graph.microsoft.com/v1.0/servicePrincipals/1ab2c3de-f456-7890-fghi-j12345k67lm8/appRoleAssignedTo |
  jq '.value[] | select(.principalDisplayName =="ECOM_SALES").id')
Enter fullscreen mode Exit fullscreen mode

The API returns:

{
    "@odata.context": "LINK_HERE",
    "@odata.nextLink": "LINK_HERE",
    "value": [
        {
            "id": "ZMW3ujNOGUuENMLa2k6-mVWFENfBHbVDlwQJg1ui848",
            "deletedDateTime": null,
            "appRoleId": "33c0d484-efdc-4e65-b6fc-470f4bcb4f46",
            "createdDateTime": "2023-02-17T08:48:17.1803369Z",
            "principalDisplayName": "ECOM_SALES",
            "principalId": "bab7c564-4e33-4b19-8434-c2dada4ebe99",
            "principalType": "Group",
            "resourceDisplayName": "Snowflake AAD",
            "resourceId": "1ab2c3de-f456-7890-fghi-j12345k67lm8"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

and our variable ASSIGNMENT_ID has the value ZMW3ujNOGUuENMLa2k6-mVWFENfBHbVDlwQJg1ui848.

With this value we now have all the elements necessary to import this app role assignment into the Terraform state.

Multiple assignments

In a situation where you have multiple AzureAD app role assignments for groups such as ECOM_SALES, ECOM_FINANCE and ECOM_LEGAL, you can use the following jq expression to list them all:

.value[] | select(.principalDisplayName | startswith("ECOM_"))
Enter fullscreen mode Exit fullscreen mode

Import existing app role assignments into the Terraform state

Having the app role assignment ID in a variable named ASSIGNMENT_ID and the AzureAD enterprise application for Snowflake having ID 1ab2c3de-f456-7890-fghi-j12345k67lm8, we can:

terraform import \
  azuread_app_role_assignment.example \
  1ab2c3de-f456-7890-fghi-j12345k67lm8/appRoleAssignment/$ASSIGNMENT_ID
Enter fullscreen mode Exit fullscreen mode

Conclusion

This article provided a quick solution for importing Azure AD app role assignments into Terraform, addressing the challenge of manual interventions in infrastructure management. Leveraging Microsoft's Graph API and Terraform, we demonstrated a streamlined process to list and import app role assignments.

Top comments (0)