Skip to content

Commit c536ca7

Browse files
Merge pull request #44 from AlexanderSehr/users/alsehr/oidc
feat: Replacing usage of Service Principal service connection with OIDC-based solution
2 parents ed93813 + 4c918ad commit c536ca7

22 files changed

+120
-42
lines changed

.azuredevops/azureImageBuilder/.templates/pipeline.jobs.yml

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ jobs:
4444
4545
# Set agent up
4646
Set-EnvironmentOnAgent -PSModules $Modules
47-
# [Sanitization] task(s)
48-
#-----------------------
4947
- task: AzureCLI@2
5048
name: Remove_ImageTemplates_Task
5149
displayName: 'Remove previous Image Template resources'
@@ -55,11 +53,11 @@ jobs:
5553
scriptType: pscore
5654
scriptLocation: inlineScript
5755
inlineScript: |
58-
# Log into Az-PowerShell context
59-
. $profile # Load PS-Profile configuration
60-
$SecuredPassword = ConvertTo-SecureString -AsPlainText -String $env:servicePrincipalKey
61-
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:servicePrincipalId, $SecuredPassword
62-
$null = Connect-AzAccount -ServicePrincipal -TenantId $env:tenantId -Credential $Credential
56+
# Load PS-Profile configuration
57+
. $profile
58+
59+
# Login to Azure-Powershell context
60+
$null = Connect-AzAccount -ApplicationId $env:servicePrincipalId -Tenant $env:tenantId -FederatedToken $env:idToken
6361
6462
Write-Verbose "Load function" -Verbose
6563
. (Join-Path '$(System.DefaultWorkingDirectory)' '$(orchestrationFunctionsPath)' 'image' 'Remove-ImageTemplate.ps1')
@@ -81,11 +79,11 @@ jobs:
8179
scriptType: pscore
8280
scriptLocation: inlineScript
8381
inlineScript: |
84-
# Log into Az-PowerShell context
85-
. $profile # Load PS-Profile configuration
86-
$SecuredPassword = ConvertTo-SecureString -AsPlainText -String $env:servicePrincipalKey
87-
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:servicePrincipalId, $SecuredPassword
88-
$null = Connect-AzAccount -ServicePrincipal -TenantId $env:tenantId -Credential $Credential
82+
# Load PS-Profile configuration
83+
. $profile
84+
85+
# Login to Azure-Powershell context
86+
$null = Connect-AzAccount -ApplicationId $env:servicePrincipalId -Tenant $env:tenantId -FederatedToken $env:idToken
8987
9088
Write-Verbose "Load function" -Verbose
9189
. (Join-Path '$(System.DefaultWorkingDirectory)' '$(orchestrationFunctionsPath)' 'image' 'Remove-DeploymentScript.ps1')
@@ -107,11 +105,11 @@ jobs:
107105
scriptType: pscore
108106
scriptLocation: inlineScript
109107
inlineScript: |
110-
# Log into Az-PowerShell context
111-
. $profile # Load PS-Profile configuration
112-
$SecuredPassword = ConvertTo-SecureString -AsPlainText -String $env:servicePrincipalKey
113-
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:servicePrincipalId, $SecuredPassword
114-
$null = Connect-AzAccount -ServicePrincipal -TenantId $env:tenantId -Credential $Credential
108+
# Load PS-Profile configuration
109+
. $profile
110+
111+
# Login to Azure-Powershell context
112+
$null = Connect-AzAccount -ApplicationId $env:servicePrincipalId -Tenant $env:tenantId -FederatedToken $env:idToken
115113
116114
Write-Verbose "Load function" -Verbose
117115
. (Join-Path '$(System.DefaultWorkingDirectory)' '$(orchestrationFunctionsPath)' 'image' 'Remove-ResourcesInStagingRg.ps1')
@@ -174,11 +172,11 @@ jobs:
174172
scriptType: pscore
175173
scriptLocation: inlineScript
176174
inlineScript: |
177-
# Log into Az-PowerShell context
178-
. $profile # Load PS-Profile configuration
179-
$SecuredPassword = ConvertTo-SecureString -AsPlainText -String $env:servicePrincipalKey
180-
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:servicePrincipalId, $SecuredPassword
181-
$null = Connect-AzAccount -ServicePrincipal -TenantId $env:tenantId -Credential $Credential
175+
# Load PS-Profile configuration
176+
. $profile
177+
178+
# Login to Azure-Powershell context
179+
$null = Connect-AzAccount -ApplicationId $env:servicePrincipalId -Tenant $env:tenantId -FederatedToken $env:idToken
182180
183181
# Load used functions
184182
. (Join-Path '$(System.DefaultWorkingDirectory)' '$(sharedOrchestrationFunctionsPath)' 'deployment' 'New-TemplateDeployment.ps1')

.azuredevops/azureImageBuilder/variables.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ variables:
2020
poolName_dev: '' # Use this for self-hosted agents
2121
poolName_prd: '' # Use this for self-hosted agents
2222

23-
serviceConnection_sbx: '<PrivateConnection>'
24-
serviceConnection_dev: '<PrivateConnection>'
25-
serviceConnection_prd: '<PrivateConnection>'
23+
serviceConnection_sbx: '<ServiceConnectionName>'
24+
serviceConnection_dev: '<ServiceConnectionName>'
25+
serviceConnection_prd: '<ServiceConnectionName>'
2626
#endregion
2727

2828
#region specific

.azuredevops/managedDevOpsPool/.templates/pipeline.jobs.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ jobs:
4646
scriptType: pscore
4747
scriptLocation: inlineScript
4848
inlineScript: |
49-
# Log into Az-PowerShell context
50-
. $profile # Load PS-Profile configuration
51-
$SecuredPassword = ConvertTo-SecureString -AsPlainText -String $env:servicePrincipalKey
52-
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:servicePrincipalId, $SecuredPassword
53-
$null = Connect-AzAccount -ServicePrincipal -TenantId $env:tenantId -Credential $Credential
49+
# Load PS-Profile configuration
50+
. $profile
51+
52+
# Login to Azure-Powershell context
53+
$null = Connect-AzAccount -ApplicationId $env:servicePrincipalId -Tenant $env:tenantId -FederatedToken $env:idToken
5454
5555
# Load used functions
5656
. (Join-Path '$(System.DefaultWorkingDirectory)' '$(sharedOrchestrationFunctionsPath)' 'deployment' 'New-TemplateDeployment.ps1')

.azuredevops/managedDevOpsPool/variables.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ variables:
2020
poolName_dev: '' # Use this for self-hosted agents
2121
poolName_prd: '' # Use this for self-hosted agents
2222

23-
serviceConnection_sbx: '<PrivateConnection>'
24-
serviceConnection_dev: '<PrivateConnection>'
25-
serviceConnection_prd: '<PrivateConnection>'
23+
serviceConnection_sbx: '<ServiceConnectionName>'
24+
serviceConnection_dev: '<ServiceConnectionName>'
25+
serviceConnection_prd: '<ServiceConnectionName>'
2626
#endregion
2727

2828
#region specific

constructs/managedDevOpsPool/templates/pool.deploy.bicep

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,11 @@ param poolMaximumConcurrency int = 1
5252
param poolSize string = 'Standard_B1ms'
5353

5454
@description('Optional. The managed identity definition for the Managed DevOps Pool.')
55-
import { managedIdentitiesType } from 'br/public:avm/res/dev-ops-infrastructure/pool:0.1.1'
56-
param poolManagedIdentities managedIdentitiesType
57-
58-
// import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.1.0'
59-
// param poolManagedIdentities managedIdentityOnlyUserAssignedType?
55+
import { managedIdentityOnlyUserAssignedType } from 'br/public:avm/utl/types/avm-common-types:0.3.0'
56+
param poolManagedIdentities managedIdentityOnlyUserAssignedType?
6057

6158
@description('Optional. Defines how the machine will be handled once it executed a job.')
62-
import { agentProfileType } from 'br/public:avm/res/dev-ops-infrastructure/pool:0.1.1'
59+
import { agentProfileType } from 'br/public:avm/res/dev-ops-infrastructure/pool:0.2.0'
6360
param poolAgentProfile agentProfileType = {
6461
kind: 'Stateless'
6562
}
@@ -169,7 +166,7 @@ module vnetPermission 'br/public:avm/ptn/authorization/resource-role-assignment:
169166
}
170167
}
171168

172-
module pool 'br/public:avm/res/dev-ops-infrastructure/pool:0.1.1' = {
169+
module pool 'br/public:avm/res/dev-ops-infrastructure/pool:0.3.0' = {
173170
name: '${uniqueString(deployment().name, resourceLocation)}-pool'
174171
scope: rg
175172
params: {

docs/wiki/Creating images with the Azure Image Builder.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ This sections gives you an overview on how to use the Azure Image Builder (AIB)
1818
## Prerequisites
1919

2020
The deployments described in the following sections assume certain prerequisites to be in place prior to deployment.
21-
22-
- The deployment principal (e.g., the Service Principal tied to the deploying Service Connection) must have at least `Contributor` & `User Access Administrator` permissions on the target subscription to be able to deploy both resources and assign permissions to created user-assigned identities
21+
- The deployment principal (i.e., the principal tied to the deploying Service Connection) **must** be setup for OIDC. This is required so that all AzureCLI tasks that also run _pwsh_ commands can log into the Azure PowerShell context too. For instructions on this matter, please refer to [this guide](./OIDC).
22+
- The deployment principal must have at least `Contributor` & `Role Based Access Control Administrator` permissions on the target subscription to be able to deploy both resources and assign permissions to created user-assigned identities
2323
- IF you have a policy in place that prevents Storage Accounts from being deployed without a Firewall, you have to create an exemption for the Image Template / Staging Resource Group you can configure for the Image Template Resource (parameter `imageTemplateResourceGroupName`). The rationale is that the Azure-Image-Builder service uses this resource group to deploy both temporal resources used during the image build (e.g., a Virtual Machine), as well as a Storage Account to store temporal files & a 'packerlogs/customization.log' file in (which contains the logs of the image build). This Storage Account has no firewall configured, has a random name, and cannot be configured at deploy time.
2424

2525
## Elements

docs/wiki/OIDC.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
This section gives you an overview of how to set up a managed identity and use it for an OIDC-based service connection in Azure DevOPs
2+
3+
### _Navigation_
4+
- [Create Service Connection (Part 1)](#create-service-connection-part-1)
5+
- [Create managed identity](#create-managed-identity)
6+
- [Create federated credential](#create-federated-credential)
7+
- [Create Service Connection (Part 2)](#create-service-connection-part-2)
8+
9+
# Create Service Connection (Part 1)
10+
11+
1. To start the setup, navigate to the 'Service connections' of your 'Project Settings' and select 'New service connection'
12+
13+
<img src="./media/oidc/serviceConnection-init.png" alt="Init service connection" height="300">
14+
15+
1. Next, select 'Azure Resource Manager' as the service connection type and click on 'Next'
16+
17+
<img src="./media/oidc/serviceConnection-type.png" alt="Select service connection type" height="300">
18+
19+
1. When asked which type of authentication you'd like to use, select 'Workload Identity Federation (manual)'
20+
21+
<img src="./media/oidc/serviceConnection-authentication.png" alt="Select service connection authentication" height="350">
22+
23+
1. Finally, give the to-be service connection a name, and select 'Next' one last time (for now)
24+
25+
<img src="./media/oidc/serviceConnection-name.png" alt="Select service connection name" height="450">
26+
27+
1. In this following view, take not of the 'Issuer' & 'Subject identifier' values. You'll need those to create the federated credential
28+
29+
<img src="./media/oidc/serviceConnection-issuer.png" alt="Select service connection issuer info" height="350">
30+
31+
# Create managed identity
32+
33+
With the service connection prepared, we can now move on the the Managed Identity in Azure
34+
35+
1. To start, navigate to the Managed Identity overview and select '+ Create'
36+
37+
<img src="./media/oidc/managedIdentityCreate.png" alt="Init MSI creation" height="200">
38+
39+
1. Next, provide the required information like the resource group, name & location and initialize the creation by selecting the 'Review + create', followed by another click on the 'Create' button
40+
41+
<img src="./media/oidc/managedIdentityDetails.png" alt="MSI details" height="450">
42+
43+
1. Once the resource is created, navigate to it so that we can start creating the federated credential. Also, take note of the 'Client ID' in the resource's overview which we will need again to finish up the Service Connection creation later.
44+
45+
<img src="./media/oidc/managedIdentityId.png" alt="MSI details" height="300">
46+
47+
# Create federated credential
48+
49+
1. On the managed identity resource, select 'Federated credentials' in the resource blade, followed by '+ Add Credential'
50+
51+
<img src="./media/oidc/credentialInit.png" alt="Init credential" height="350">
52+
53+
1. Now, for the
54+
- 'Federated credential scenario', select '**Other** Configure an identity managed by an external OpenID Connect Provider to access Azure resources as this application'
55+
- 'Issuer Url' provide the 'Issuer' value from the last step in the preceding Service Connection creation
56+
- 'Subject identifier' provide the 'Subject identifier' value from the last step in the preceding Service Connection creation
57+
- Name, a name of your choice
58+
59+
<img src="./media/oidc/credentialDetails.png" alt="Credential details" height="500">
60+
61+
1. Finally, finish the creation of the Federated Credential by selecting 'Add'
62+
63+
# Create Service Connection (Part 2)
64+
65+
Now, with the federated credential ready, we can return to the creation of the Service Connection to wrap it up. To do so,
66+
67+
1. Provide all required details in the Service connection's form, including
68+
- Subscription ID: Must be the Subscription ID of the Subscription containing the created Managed Identity
69+
- Subscription Name: The name of the Subscription
70+
- Service Principal Id: The client ID of the created Managed Identity, taken from its overview page. **Note:** This refers to the Client ID, not the Object / Principal ID
71+
- Tenant ID: The ID of the Tenant containing the created Managed Identity
72+
73+
<img src="./media/oidc/serviceConnection-finish.png" alt="Service Connection finish" height="700">
74+
75+
1. Finally, select 'Verify and save' and you should be good to go to use the Service Connection in your pipelines.
76+
77+
> **NOTE:** Don't forget to grant your Managed Identity the permissions it needs to perform its tasks (e.g., create resources)

docs/wiki/Self-hosted Managed DevOps Pool.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This sections gives you an overview on how to use the Managed DevOps Pool pipeli
66

77
- [Overview](#overview)
88
- [Advantages](#Advantages)
9+
- [Prerequisites](#prerequisites)
910
- [Elements](#elements)
1011
- [File structure & flow](#file-structure--flow)
1112
- [Process](#process)
@@ -27,6 +28,11 @@ This sections gives you an overview on how to use the Managed DevOps Pool pipeli
2728
- As the Managed DevOps Pool can be configured to e.g. scale in to 0 and spin up a new VM only if a job is scheduled
2829
- As a single agent is installed on a new instance. Hence virtual machines can be deployed using a SKU with less compute power
2930

31+
## Prerequisites
32+
33+
The deployments described in the following sections assume certain prerequisites to be in place prior to deployment.
34+
- The deployment principal (i.e., the principal tied to the deploying Service Connection) **must** be setup for OIDC. This is required so that all AzureCLI tasks that also run _pwsh_ commands can log into the Azure PowerShell context too. For instructions on this matter, please refer to [this guide](./OIDC).
35+
3036
## Elements
3137

3238
<img src="./media/pool/managedPoolSetup.png" alt="Managed DevOps Pool infrastructure" height="200">
55.3 KB
Loading
40 KB
Loading

0 commit comments

Comments
 (0)