From f8ec14dd919cd973978fe28d502f3b5c8c900942 Mon Sep 17 00:00:00 2001 From: dkershaw Date: Fri, 6 Dec 2024 20:18:13 +0000 Subject: [PATCH 1/5] First draft MSI as a FIC sample --- .../msi-as-a-fic-secretless/README.md | 16 +++ .../msi-as-a-fic-secretless/bicepconfig.json | 9 ++ .../msi-as-a-fic-secretless/main.bicep | 103 ++++++++++++++++++ .../msi-as-a-fic-secretless/main.bicepparam | 6 + 4 files changed, 134 insertions(+) create mode 100644 quickstart-templates/msi-as-a-fic-secretless/README.md create mode 100644 quickstart-templates/msi-as-a-fic-secretless/bicepconfig.json create mode 100644 quickstart-templates/msi-as-a-fic-secretless/main.bicep create mode 100644 quickstart-templates/msi-as-a-fic-secretless/main.bicepparam diff --git a/quickstart-templates/msi-as-a-fic-secretless/README.md b/quickstart-templates/msi-as-a-fic-secretless/README.md new file mode 100644 index 0000000..1fa1172 --- /dev/null +++ b/quickstart-templates/msi-as-a-fic-secretless/README.md @@ -0,0 +1,16 @@ +# Configure an application to trust a managed identity and go secret-less + +## Details + +[Public doc](https://learn.microsoft.com/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity?tabs=microsoft-entra-admin-center) + +### Prerequisites + +TBD + +* [Bicep tools for authoring and deployment](https://learn.microsoft.com/graph/templates/quickstart-install-bicep-tools). The minimum required Bicep version is v0.30.3. +* Have a **Microsoft Entra role** that assigns you permissions to create applications. [Users have this permission by default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#compare-member-and-guest-default-permissions). However, [admins can turn off this default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#restrict-member-users-default-permissions) in which case you need to be assigned at least the [Application Developer](https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#application-developer) role. + +### Deploy the Bicep template + +TBD diff --git a/quickstart-templates/msi-as-a-fic-secretless/bicepconfig.json b/quickstart-templates/msi-as-a-fic-secretless/bicepconfig.json new file mode 100644 index 0000000..d38f239 --- /dev/null +++ b/quickstart-templates/msi-as-a-fic-secretless/bicepconfig.json @@ -0,0 +1,9 @@ +{ + "experimentalFeaturesEnabled": { + "extensibility": true + }, + // specify an alias for the version of the v1.0 dynamic types package you want to use + "extensions": { + "microsoftGraphV1": "br:mcr.microsoft.com/bicep/extensions/microsoftgraph/v1.0:0.1.8-preview" + } +} \ No newline at end of file diff --git a/quickstart-templates/msi-as-a-fic-secretless/main.bicep b/quickstart-templates/msi-as-a-fic-secretless/main.bicep new file mode 100644 index 0000000..0cc85a2 --- /dev/null +++ b/quickstart-templates/msi-as-a-fic-secretless/main.bicep @@ -0,0 +1,103 @@ +extension microsoftGraphV1 + +// TEMPLATE DESCRIPTION +// Creates a secret-less client application, using a user-assigned managed identity +// as the credential (configured as part of the application's federated identity credential). +// The script optionally + +@description('Specifies the name of cloud environment to run this deployment in.') +@allowed(['publicCloud','usGov','china','usNat','usSec']) +param cloudEnvironment string + +// NOTE: Microsoft Graph Bicep file deployment is only supported in Public Cloud +@description('Audience uris for public and national clouds') +param audiences object = { + publicCloud: { + uri: 'api://AzureADTokenExchange' + } + usGov: { + uri: 'api://AzureADTokenExchangeUSGov' + } + usNat: { + uri: 'api://AzureADTokenExchangeUSNat' + } + usSec: { + uri: 'api://AzureADTokenExchangeUSSec' + } + china: { + uri: 'api://AzureADTokenExchangeChina' + } +} + +@description('Specifies the resource group location.') +param location string = resourceGroup().location + +@description('Specifies the user-assigned managed identity to use as an application credential via federated identity credentials') +param myWorkloadManagedIdentity string + +@description('Specified the application display name') +param applicationDisplayName string + +@description('Specifies the applications unique name identifier') +param applicationName string + +@description('Specifies the Microsoft Graph delegated scopes to be granted to the created application. If not specified no delegated scopes will be granted.') +param oauth2GraphScopes string? + +// login endpoint and tenant ID and issuer +var loginEndpoint = environment().authentication.loginEndpoint +var tenantId = tenant().tenantId +var issuer = '${loginEndpoint}${tenantId}/v2.0' + +// create a user assigned managed identity scoped to a resource group +resource myManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: myWorkloadManagedIdentity + location: location +} + +// Create a (client) application registration with a federated identity credential (FIC) +// The FIC is configured with the managed identity as the subject +// NOTE: app is configured with required properties only. Add the properties your app needs +resource myApp 'Microsoft.Graph/applications@v1.0' = { + displayName: applicationDisplayName + uniqueName: applicationName + + resource myMsiFic 'federatedIdentityCredentials@v1.0' = { + name: '${myApp.uniqueName}/msiAsFic' + description: 'Trust the workload\'s user-assigned MI as a credential for the app' + audiences: [ + audiences[cloudEnvironment].uri + ] + issuer: issuer + subject: myManagedIdentity.properties.principalId + } +} + +// Create a service principal for the application +resource mySp 'Microsoft.Graph/servicePrincipals@v1.0' = { + appId: myApp.appId +} + +// NOTE: This section (to grant Microsoft Graph permissions) requires an elevated role +// Grant the application the User.Read permission to Microsoft Graph +// First find the Microsoft Graph service principal +// Finally assign delegated scopes to the app (if values supplied) + +// 1. find Graph based on well-known appId +resource msGraphSP 'Microsoft.Graph/servicePrincipals@v1.0' existing = { + appId: '00000003-0000-0000-c000-000000000000' +} + +// 2. Grant the client app access to Microsoft Graph using the Oauth2 scope +// which delegates the app to act as the sign-in user, constrained by the Oauth2 scope +// This step only happens if the oauth2GraphScope is specified. +resource oauth2Grant 'Microsoft.Graph/oauth2PermissionGrants@v1.0' = if(oauth2GraphScopes != null) { + clientId: mySp.id + consentType: 'AllPrincipals' // granted for all users in the tenant + resourceId: msGraphSP.id + scope: oauth2GraphScopes +} + +output clientAppId string = myApp.id +output clientSPId string = mySp.id +output grantedScopes string = ((oauth2GraphScopes != null) ? 'Scopes granted:${oauth2GraphScopes}' : 'Scopes not granted') diff --git a/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam b/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam new file mode 100644 index 0000000..811cd5f --- /dev/null +++ b/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam @@ -0,0 +1,6 @@ +using './main.bicep' + +param myWorkloadManagedIdentity = '[MANAGED-IDENTITY-NAME]' +param applicationDisplayName = '[APPLICATION-DISPLAY-NAME]' +param applicationName = '[APPLICATION-UNIQUE-NAME]' +param cloudEnvironment = 'publicCloud' From 7dcfa97cf171cc7d690e0e88d3941bfc8ab4b1bd Mon Sep 17 00:00:00 2001 From: dkershaw Date: Wed, 18 Dec 2024 22:10:28 +0000 Subject: [PATCH 2/5] Added README, a PS1 file and updated Bicep file --- .../msi-as-a-fic-secretless/README.md | 79 ++++++++++++++-- .../msi-as-a-fic-secretless/main.bicep | 91 ++++++++++++++----- .../msi-as-a-fic-secretless/main.bicepparam | 2 + .../secretless-graph-request.ps1 | 36 ++++++++ 4 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 diff --git a/quickstart-templates/msi-as-a-fic-secretless/README.md b/quickstart-templates/msi-as-a-fic-secretless/README.md index 1fa1172..e7af6bb 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/README.md +++ b/quickstart-templates/msi-as-a-fic-secretless/README.md @@ -1,16 +1,83 @@ -# Configure an application to trust a managed identity and go secret-less +# Configure a secret-less application to call Microsoft Graph + +This template demonstrates how to create a secret-less client application, using a user-assigned managed identity +as the credential (configured as part of the application's federated identity credential). +It also creates other resources, that enable you to test using the application to call Microsoft Graph, all without +any application secret or certificate. + +Further details are available on [using a user-assigned managed identity as a federated identity credential to enable your apps +to go secret-less][msi-as-fic]. ## Details -[Public doc](https://learn.microsoft.com/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity?tabs=microsoft-entra-admin-center) +This template sample deploys the following resources: + +1. A user-assigned managed identity +2. An application registration with a federated identity credential (configured to use the user-assigned managed identity) +3. A service principal created from the application +4. \[Optional\] App role assignments to the service principal (to access Microsoft Graph) - requires additional permissions +5. \[Optional\] An Azure Automation Account and runbook to validate the newly created application can call Microsoft Graph without using a secret ### Prerequisites -TBD +* A valid **Azure subscription**: If you don't own an Azure subscription, [create a free account](https://azure.microsoft.com/free/) before you begin. +* An **Azure resource group** that you own under a valid Azure subscription. +[Bicep tools for authoring and deployment](https://learn.microsoft.com/graph/templates/quickstart-install-bicep-tools). The minimum required Bicep version is v0.30.3. +* Have the requisite **Microsoft Entra roles** to deploy this template: -* [Bicep tools for authoring and deployment](https://learn.microsoft.com/graph/templates/quickstart-install-bicep-tools). The minimum required Bicep version is v0.30.3. -* Have a **Microsoft Entra role** that assigns you permissions to create applications. [Users have this permission by default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#compare-member-and-guest-default-permissions). However, [admins can turn off this default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#restrict-member-users-default-permissions) in which case you need to be assigned at least the [Application Developer](https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#application-developer) role. + * Permissions to create applications. [Users have this permission by default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#compare-member-and-guest-default-permissions). However, [admins can turn off this default](https://learn.microsoft.com/entra/fundamentals/users-default-permissions#restrict-member-users-default-permissions) in which case you need to be assigned at least the [Application Developer](https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#application-developer) role. + * \[Optional\] Permissions to grant Microsoft Graph app roles to the application. This requires the [Privileged Role Administrator][priv-role-admin] ### Deploy the Bicep template -TBD +#### Deploy all resources in the template and go on to end-to-end test + +By default, the Bicep template will deploy the five resources listed earlier (managed identity, application, service principal, app role grants to Microsoft Graph, and an automation account and runbook), which will enable end-to-end testing. The default app roles granted to the application are Group.Read.All and Application.Read.All. This requires the signed-in user to have the elevated [Privileged Role Administrator][priv-role-admin] role. + +##### Az CLI + +```sh +az deployment group create --resource-group --template-file main.bicep +``` + +##### Az Powershell + +```powershell +New-AzResourceGroupDeployment -ResourceGroupName -TemplateFile .\main.bicep +``` + +#### Deploy app and FIC resources only and forego end-to-end test + +If you just want to create the managed identity, application and service principal - and **forego any end-to-end testing within the Azure Automation account**, then set the `graphRoles` parameter to an empty array - i.e. [] in CLI or @() in PowerShell. + +##### Az CLI + +```sh +az deployment group create --resource-group --template-file main.bicep --parameters graphRoles=[] +``` + +##### Az Powershell + +```powershell +New-AzResourceGroupDeployment -ResourceGroupName -TemplateFile .\main.bicep -graphRoles @() +``` + +### Test calling Microsoft Graph with a secretless application + +>**NOTE**: This testing **assumes** that you have deployed all resources described in the template, as the test relies on using Azure Automation. + +Now that the template is deployed, the application can acquire a token for the managed identity and use that token as a credential assertion to acquire an access token to resources like Microsoft Graph. However, in order to acquire a token for the managed identity, the app **must** be running in an Azure Cloud Service like a VM, App Services or Azure Automation. + +1. Sign in to the [Azure Automation Accounts page][auto-accounts] in the Azure Portal. You should see a new Automation Account that was created as part of +the Bicep template deployment. +2. Click on that account, and on the next page click on **Manage a runbook**. This should take you to a page that contains the runbook deployed by the Bicep template. Click on the runbook. +3. On the runbook page, click on **Edit** and select **Edit in portal**. This brings up a page with an empty edit pane. +4. In this sample's GitHub folder find the **secretless-graph-request.ps1** PowerShell script and copy its contents into the empty edit pane in the portal. Click Save. Click on **Test pane** to run and test the PowerShell script +5. The script acquires a token for the managed identity and then uses it (as a federated token) to sign in to Azure PS as the app. Finally, Azure PS, running as the app, is used to call Microsoft Graph to get the tenant's Entra groups. + +If successful, you should see that the script, running as the app, successfully calls Microsoft Graph, responding with the collection of groups in the tenant. And all without requiring the application to have a secret of a certificate. + +[msi-as-fic]:https://learn.microsoft.com/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity?tabs=microsoft-entra-admin-center +[priv-role-admin]:https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#privileged-role-administrator +[az-portal]:https://portal.azure.com +[auto-accounts]:https://portal.azure.com/#view/HubsExtension/BrowseResource/resourceType/Microsoft.Automation%2FAutomationAccounts \ No newline at end of file diff --git a/quickstart-templates/msi-as-a-fic-secretless/main.bicep b/quickstart-templates/msi-as-a-fic-secretless/main.bicep index 0cc85a2..899ef60 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/main.bicep +++ b/quickstart-templates/msi-as-a-fic-secretless/main.bicep @@ -6,25 +6,24 @@ extension microsoftGraphV1 // The script optionally @description('Specifies the name of cloud environment to run this deployment in.') -@allowed(['publicCloud','usGov','china','usNat','usSec']) -param cloudEnvironment string +param cloudEnvironment string = environment().name // NOTE: Microsoft Graph Bicep file deployment is only supported in Public Cloud @description('Audience uris for public and national clouds') param audiences object = { - publicCloud: { + AzureCloud: { uri: 'api://AzureADTokenExchange' } - usGov: { + AzureUSGovernment: { uri: 'api://AzureADTokenExchangeUSGov' } - usNat: { + USNat: { uri: 'api://AzureADTokenExchangeUSNat' } - usSec: { + USSec: { uri: 'api://AzureADTokenExchangeUSSec' } - china: { + AzureChinaCloud: { uri: 'api://AzureADTokenExchangeChina' } } @@ -32,17 +31,20 @@ param audiences object = { @description('Specifies the resource group location.') param location string = resourceGroup().location -@description('Specifies the user-assigned managed identity to use as an application credential via federated identity credentials') -param myWorkloadManagedIdentity string +@description('Specifies the user-assigned managed identity name to use as an application credential via federated identity credentials') +param myWorkloadManagedIdentity string = 'myMSI-2024-12-18' @description('Specified the application display name') -param applicationDisplayName string +param applicationDisplayName string = 'myApp-2024-12-18' @description('Specifies the applications unique name identifier') -param applicationName string +param applicationName string = 'myApp-2024-12-18' -@description('Specifies the Microsoft Graph delegated scopes to be granted to the created application. If not specified no delegated scopes will be granted.') -param oauth2GraphScopes string? +@description('Specifies the Microsoft Graph app roles to be granted to the created application. If set to empty array [], app roles will NOT be granted and no Azure Automation accounts will be created.') +param graphRoles array = ['Group.Read.All','Application.Read.All'] + +@description('Specifies an Azure Automation Account name for a runbook where a PS script can be run. Only created is graphRoles is not an empty array []') +param automationAccountName string = 'myAutomationAccount-2024-12-18' // login endpoint and tenant ID and issuer var loginEndpoint = environment().authentication.loginEndpoint @@ -74,14 +76,14 @@ resource myApp 'Microsoft.Graph/applications@v1.0' = { } // Create a service principal for the application -resource mySp 'Microsoft.Graph/servicePrincipals@v1.0' = { +resource mySP 'Microsoft.Graph/servicePrincipals@v1.0' = { appId: myApp.appId } // NOTE: This section (to grant Microsoft Graph permissions) requires an elevated role -// Grant the application the User.Read permission to Microsoft Graph +// Grant the application only permission to Microsoft Graph // First find the Microsoft Graph service principal -// Finally assign delegated scopes to the app (if values supplied) +// Finally assign app roles to the app (if graphRoles is not an empty array) // 1. find Graph based on well-known appId resource msGraphSP 'Microsoft.Graph/servicePrincipals@v1.0' existing = { @@ -91,13 +93,54 @@ resource msGraphSP 'Microsoft.Graph/servicePrincipals@v1.0' existing = { // 2. Grant the client app access to Microsoft Graph using the Oauth2 scope // which delegates the app to act as the sign-in user, constrained by the Oauth2 scope // This step only happens if the oauth2GraphScope is specified. -resource oauth2Grant 'Microsoft.Graph/oauth2PermissionGrants@v1.0' = if(oauth2GraphScopes != null) { - clientId: mySp.id - consentType: 'AllPrincipals' // granted for all users in the tenant - resourceId: msGraphSP.id - scope: oauth2GraphScopes + +// would use a for loop but that appears to be busted for some reason +var graphAppRoles = msGraphSP.appRoles + +// Assign multiple app role assignments to MS Graph for the app/SP. +// This gives the app/SP the necessary permissions to deploy this Bicep file (in app-only mode) +resource appRoleAssignments 'Microsoft.Graph/appRoleAssignedTo@v1.0' = [for (role, i) in graphRoles: { + appRoleId: filter(graphAppRoles, graphAppRoles => graphAppRoles.value == role)[0].id + principalId: mySP.id // Client SP being granted permission to access the resource (API) + resourceId: msGraphSP.id // Resource here is Microsoft Graph + } +] + +// Create an automation account and runbook to validate created application +// can call Microsoft Graph without using a secret +resource automationAccount 'Microsoft.Automation/automationAccounts@2023-11-01' = if(graphRoles != []) { + name: automationAccountName + identity: { + type:'UserAssigned' + userAssignedIdentities: { + '${resourceGroup().id}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${myWorkloadManagedIdentity}':{} + } + } + location: location + properties: { + sku: { + name: 'Basic' + } + } + resource myRunbook 'runbooks@2023-11-01' = { + name: 'msi-as-fic-test-runbook' + location: location + properties: { + description: 'Runbook for msi-as-fic testing using Az PowerShell' + runbookType: 'PowerShell72' + logProgress: false + logVerbose: false + } + } } -output clientAppId string = myApp.id -output clientSPId string = mySp.id -output grantedScopes string = ((oauth2GraphScopes != null) ? 'Scopes granted:${oauth2GraphScopes}' : 'Scopes not granted') +// outputs +output clientAppId string = myApp.appId +output ficIssuerAudience string = audiences[cloudEnvironment].uri +output issuerURI string = issuer +output tenantId string = tenantId +output assignments array = [ for (role,i) in graphRoles: { + appRoleIDName: appRoleAssignments[i].appRoleId +}] +output miPrincipalId string = myManagedIdentity.properties.principalId +output miClientId string = myManagedIdentity.properties.clientId diff --git a/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam b/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam index 811cd5f..6c3352b 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam +++ b/quickstart-templates/msi-as-a-fic-secretless/main.bicepparam @@ -4,3 +4,5 @@ param myWorkloadManagedIdentity = '[MANAGED-IDENTITY-NAME]' param applicationDisplayName = '[APPLICATION-DISPLAY-NAME]' param applicationName = '[APPLICATION-UNIQUE-NAME]' param cloudEnvironment = 'publicCloud' +param graphRoles = ['Group.Read.All'] + diff --git a/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 b/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 new file mode 100644 index 0000000..d1bf9fa --- /dev/null +++ b/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 @@ -0,0 +1,36 @@ +####################################################################### +<# +Perform a 2-legged flow to acquire an access token with a managed +identity as the credential and then use it to call Microsoft Graph. + +PRE-REQUISITES: +1. An app registered with a user-assigned managed identity as a + federated identity credential (FIC). +2. There's a service principal for the app. +3. The service principal is is granted access to Microsoft Graph. + +SCRIPT STEPS +1. Acquire a token for a user-assigned managed identity +2. Run PS as an app, using the token from step 1 as the credential +3. Call Microsoft Graph +#> +####################################################################### + +param +( + [Parameter(Mandatory=$true)] + $managedIdentityPrincipalId, + $applicationClientId, + $tenantId +) + +# Step 1: Acquire token for the managed identity +Connect-AzAccount -Identity -AccountId $managedIdentityPrincipalId +$token = Get-AzAccessToken -ResourceUrl "api://AzureADTokenExchange" + + +# Step 2: Sign in to Azure PowerShell (as the app with the FIC configuration) +Connect-AzAccount -ApplicationId $applicationClientId -FederatedToken $token.Token -Tenant $tenantId + +# Step 3: Get all Entra groups in the tenant (assumes app has Group.Read.All permission) +Invoke-AzRestMethod -Method GET -Uri https://graph.microsoft.com/v1.0/groups From 0c31b9ec52b21384a988a68939191c2342b7ef61 Mon Sep 17 00:00:00 2001 From: dkershaw Date: Thu, 19 Dec 2024 16:34:44 +0000 Subject: [PATCH 3/5] Minor changes to the readme --- quickstart-templates/msi-as-a-fic-secretless/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/quickstart-templates/msi-as-a-fic-secretless/README.md b/quickstart-templates/msi-as-a-fic-secretless/README.md index e7af6bb..a38d51b 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/README.md +++ b/quickstart-templates/msi-as-a-fic-secretless/README.md @@ -5,8 +5,10 @@ as the credential (configured as part of the application's federated identity cr It also creates other resources, that enable you to test using the application to call Microsoft Graph, all without any application secret or certificate. -Further details are available on [using a user-assigned managed identity as a federated identity credential to enable your apps -to go secret-less][msi-as-fic]. +Testing involves using an Azure Automation account runbook, which uses PowerShell cmdlets to acquire an access token for the secret-less application, which is then used to call Microsoft Graph. + +Further details on using a user-assigned managed identity as a federated identity credential to enable your apps +to go secret-less, including how it works and sample code to acquire access tokens using various client libraries can be found in the [public documentation][msi-as-fic]. ## Details @@ -66,7 +68,7 @@ New-AzResourceGroupDeployment -ResourceGroupName -TemplateFile >**NOTE**: This testing **assumes** that you have deployed all resources described in the template, as the test relies on using Azure Automation. -Now that the template is deployed, the application can acquire a token for the managed identity and use that token as a credential assertion to acquire an access token to resources like Microsoft Graph. However, in order to acquire a token for the managed identity, the app **must** be running in an Azure Cloud Service like a VM, App Services or Azure Automation. +Now that the template is deployed, the application can acquire a token for the managed identity and use that token as a credential assertion to acquire an access token to resources like Microsoft Graph. However, in order to acquire a token for the managed identity, the managed identity **must** be assigned in an Azure Cloud Service like a VM, App Services or in our case an Azure Automation account. 1. Sign in to the [Azure Automation Accounts page][auto-accounts] in the Azure Portal. You should see a new Automation Account that was created as part of the Bicep template deployment. From 4e3d7b632563c6f0c825f79620550bcbe93a9466 Mon Sep 17 00:00:00 2001 From: dkershaw Date: Fri, 20 Dec 2024 17:22:47 +0000 Subject: [PATCH 4/5] Update to allow for running in different clouds --- .../msi-as-a-fic-secretless/secretless-graph-request.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 b/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 index d1bf9fa..f68d140 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 +++ b/quickstart-templates/msi-as-a-fic-secretless/secretless-graph-request.ps1 @@ -22,11 +22,12 @@ param $managedIdentityPrincipalId, $applicationClientId, $tenantId + $ficIssuerAudience ) # Step 1: Acquire token for the managed identity Connect-AzAccount -Identity -AccountId $managedIdentityPrincipalId -$token = Get-AzAccessToken -ResourceUrl "api://AzureADTokenExchange" +$token = Get-AzAccessToken -ResourceUrl $ficIssuerAudience # Step 2: Sign in to Azure PowerShell (as the app with the FIC configuration) From 5a87b95b02af1271215d5b0293287b7dbf5c3678 Mon Sep 17 00:00:00 2001 From: dkershaw Date: Fri, 20 Dec 2024 17:29:07 +0000 Subject: [PATCH 5/5] Minor update to the README --- quickstart-templates/msi-as-a-fic-secretless/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart-templates/msi-as-a-fic-secretless/README.md b/quickstart-templates/msi-as-a-fic-secretless/README.md index a38d51b..d3d64a0 100644 --- a/quickstart-templates/msi-as-a-fic-secretless/README.md +++ b/quickstart-templates/msi-as-a-fic-secretless/README.md @@ -74,7 +74,7 @@ Now that the template is deployed, the application can acquire a token for the m the Bicep template deployment. 2. Click on that account, and on the next page click on **Manage a runbook**. This should take you to a page that contains the runbook deployed by the Bicep template. Click on the runbook. 3. On the runbook page, click on **Edit** and select **Edit in portal**. This brings up a page with an empty edit pane. -4. In this sample's GitHub folder find the **secretless-graph-request.ps1** PowerShell script and copy its contents into the empty edit pane in the portal. Click Save. Click on **Test pane** to run and test the PowerShell script +4. In this sample's GitHub folder find the **secretless-graph-request.ps1** PowerShell script and copy its contents into the empty edit pane in the portal. Click Save. Click on **Test pane** to run and test the PowerShell script. NOTE: the PowerShell script requires the input of four parameters that you can get from the output of the Bicep template deployment. 5. The script acquires a token for the managed identity and then uses it (as a federated token) to sign in to Azure PS as the app. Finally, Azure PS, running as the app, is used to call Microsoft Graph to get the tenant's Entra groups. If successful, you should see that the script, running as the app, successfully calls Microsoft Graph, responding with the collection of groups in the tenant. And all without requiring the application to have a secret of a certificate.