Greetings to my fellow Technology Advocates and Specialists.
In this Session, I will demonstrate How to Automate Azure Container Registry (ACR) Service Connection using Devops.
#
TOPICS
1.
Install Azure Devops CLI Extension in the Build Agent.
2.
Validate Azure Devops CLI Extension Installation by running the Help option in the Build Agent.
3.
Download Key Vault Secrets.
4.
Create Azure Container Registry Service Connection.
5.
Grant Access Permission to Azure Container Registry Service Connection for all Pipelines.
The YAML Pipeline is tested on WINDOWS BUILD AGENT Only!!!
Azure Subscription.
Azure DevOps Organisation and Project.
Full Access PAT (Personal Access Token).
Service Principal with Required RBAC ( Contributor) applied on Subscription or Resource Group(s).
Azure Resource Manager Service Connection in Azure DevOps.
Azure Container Registry with "Admin" User Enabled.
Key Vault with 3 Secrets stored - 1) Azure Container Registry password, 2) Azure DevOps Project ID, and 3) Azure Devops Personal Access Token (PAT).
CODE REPOSITORY:-
Setup ACR Service Connection using Devops
Setup ACR Service Connection using Devops
Greetings to my fellow Technology Advocates and Specialists.
In this Session, I will demonstrate How to Automate Azure Container Registry (ACR) Service Connection using Devops.
#
TOPICS
1.
Install Azure Devops CLI Extension in the Build Agent.
2.
Validate Azure Devops CLI Extension Installation by running the Help option in the Build Agent.
3.
Download Key Vault Secrets.
4.
Create Azure Container Registry Service Connection.
5.
Grant Access Permission to Azure Container Registry Service Connection for all Pipelines.
The YAML Pipeline is tested on WINDOWS BUILD AGENT Only!!!
Azure Subscription.
Azure DevOps Organisation and Project.
Full Access PAT (Personal Access Token).
Service Principal with Required RBAC ( Contributor) applied on Subscription or Resource Group(s).
Azure Resource Manager Service Connection in Azure DevOps.
Azure Container Registry with "Admin" User Enabled.
Key Vault with 3 Secrets stored - 1) Azure Container…
LIST OF AZURE RESOURCES DEPLOYED AND CONFIGURED FOR THIS AUTOMATION:-
Azure Container Registry with "Admin" user enabled
Key Vault with 3 Secrets stored - 1) Azure Container Registry password, 2) Azure DevOps Project ID, and 3) Azure Devops Personal Access Token (PAT).
HOW DOES MY CODE PLACEHOLDER LOOKS LIKE:-
AZURE DEVOPS YAML PIPELINE (azure-pipelines-acr-service-connection-v1.0.yml):-
trigger:
none
######################
# Declare Parameters:-
######################
parameters:
- name: DevOpsOrganisation
type: string
default: https://dev.azure.com/ArindamMitra0251
values:
- https://dev.azure.com/ArindamMitra0251
- name: DevOpsProjName
type: string
default: AMCLOUD
values:
- AMCLOUD
- name: KVNAME
displayName: Please Provide the Keyvault Name:-
type: object
default: ampockv
- name: ACRName
type: object
default: ampocapplacr
- name: ACRSrvConnectionName
type: object
default: AM-ACR-Srv-Connection
#######################
# Declare Variables:-
#######################
variables:
ServiceConnection: 'amcloud-cicd-service-connection'
BuildAgent: 'windows-latest'
emailID: "mail2arindam2003@yahoo.com"
######################
# Declare Build Agent:-
######################
pool:
vmImage: '$(BuildAgent)'
###################
# Declare Stages:-
###################
stages:
- stage: Az_DevOps_ACR_Service_Connection
jobs:
- job: Setup_ACR_Service_Connection
displayName: Setup ACR Service Connection
steps:
########################################################
# Install Az DevOps CLI Extension in the Build Agent:-
#######################################################
- task: AzureCLI@1
displayName: Install Devops CLI Extension
inputs:
azureSubscription: '$(ServiceConnection)'
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
az extension add --name azure-devops
az extension show --name azure-devops --output table
###############################################################
# Help Option of Az DevOps CLI Extension in the Build Agent:-
###############################################################
- task: PowerShell@2
displayName: Help Option of Az Devops CLI
inputs:
targetType: 'inline'
script: |
az devops -h
################################
# Download Keyvault Secrets:-
################################
- task: AzureKeyVault@2
displayName: Fetch all Secrets from Keyvault
inputs:
azureSubscription: '$(ServiceConnection)'
KeyVaultName: '${{ parameters.KVNAME }}'
SecretsFilter: '*'
RunAsPreJob: false
############################################################
# Create ACR Service Connection in Azure DevOps Project:-
############################################################
- task: PowerShell@2
displayName: Create ACR Service Connection
inputs:
targetType: 'inline'
script: |
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$(PAT)"))
$header = @{
'Authorization' = 'Basic ' + $B64Pat
'Content-Type' = 'application/json'
}
$body = '{
"data": {},
"name": "${{ parameters.ACRSrvConnectionName }}",
"type": "dockerregistry",
"authorization": {
"parameters": {
"username": "${{ parameters.ACRName }}",
"password": "$(ACRPasswd)",
"email": "$(emailID)",
"registry": "https://${{ parameters.ACRName }}.azurecr.io"
},
"scheme": "UsernamePassword"
},
"isShared": false,
"isReady": true,
"serviceEndpointProjectReferences": [
{
"projectReference": {
"id": "$(AMCLOUD-DevOps-Prj-ID)",
"name": "${{ parameters.DevOpsProjName }}"
},
"name": "${{ parameters.ACRSrvConnectionName }}"
}
]
}'
$srvEndpointID = Invoke-RestMethod -Method Post -Uri ${{ parameters.DevOpsOrganisation }}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4 -Headers $header -Body $body | Select -ExpandProperty id
echo "#####################################################################################"
echo "ACR Service Connection ${{ parameters.ACRSrvConnectionName }} created successfully."
echo "#####################################################################################"
$patchbody = '{
"allPipelines": {
"authorized": true,
"authorizedBy": null,
"authorizedOn": null
},
"pipelines": null,
"resource": {
"id": "$srvEndpointID",
"type": "endpoint"
}
}'
Invoke-RestMethod -Method PATCH -Uri ${{ parameters.DevOpsOrganisation }}/${{ parameters.DevOpsProjName }}/_apis/pipelines/pipelinepermissions/endpoint/"$srvEndpointID"?api-version=7.0-preview.1 -Headers $header -Body $patchbody
echo "###############################################################################################################"
echo "ACR Service Connection ${{ parameters.ACRSrvConnectionName }} was granted access permission to all Pipelines."
echo "###############################################################################################################"
Enter fullscreen mode
Exit fullscreen mode
Now, let me explain each part of YAML Pipeline for better understanding.
BELOW FOLLOWS PIPELINE RUNTIME VARIABLES CODE SNIPPET:-
######################
# Declare Parameters:-
######################
parameters:
- name: DevOpsOrganisation
type: string
default: https://dev.azure.com/ArindamMitra0251
values:
- https://dev.azure.com/ArindamMitra0251
- name: DevOpsProjName
type: string
default: AMCLOUD
values:
- AMCLOUD
- name: KVNAME
displayName: Please Provide the Keyvault Name:-
type: object
default: ampockv
- name: ACRName
type: object
default: ampocapplacr
- name: ACRSrvConnectionName
type: object
default: AM-ACR-Srv-Connection
Enter fullscreen mode
Exit fullscreen mode
THIS IS HOW IT LOOKS:-
BELOW FOLLOWS PIPELINE VARIABLES CODE SNIPPET:-
#######################
# Declare Variables:-
#######################
variables:
ServiceConnection: 'amcloud-cicd-service-connection'
BuildAgent: 'windows-latest'
emailID: "mail2arindam2003@yahoo.com"
Enter fullscreen mode
Exit fullscreen mode
NOTE:-
Please change the values of the variables accordingly.
The entire YAML pipeline is build using Runtime Parameters and Variables. No Values are Hardcoded.
This is a Single Stage Pipeline - Az_DevOps_ACR_Service_Connection (with 4 Pipeline Tasks):-
###################
# Declare Stages:-
###################
stages:
- stage: Az_DevOps_ACR_Service_Connection
jobs:
- job: Setup_ACR_Service_Connection
displayName: Setup ACR Service Connection
steps:
Enter fullscreen mode
Exit fullscreen mode
PIPELINE TASK #1:-:-
Install Az DevOps CLI Extension in the Build Agent.
########################################################
# Install Az DevOps CLI Extension in the Build Agent:-
#######################################################
- task: AzureCLI@1
displayName: Install Devops CLI Extension
inputs:
azureSubscription: '$(ServiceConnection)'
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
az extension add --name azure-devops
az extension show --name azure-devops --output table
Enter fullscreen mode
Exit fullscreen mode
PIPELINE TASK #2:-:-
Validate installation of Az DevOps CLI Extension in the Build Agent by running the Help option.
###############################################################
# Help Option of Az DevOps CLI Extension in the Build Agent:-
###############################################################
- task: PowerShell@2
displayName: Help Option of Az Devops CLI
inputs:
targetType: 'inline'
script: |
az devops -h
Enter fullscreen mode
Exit fullscreen mode
PIPELINE TASK #3:-:-
Download all secrets from Keyvault.
################################
# Download Keyvault Secrets:-
################################
- task: AzureKeyVault@2
displayName: Fetch all Secrets from Keyvault
inputs:
azureSubscription: '$(ServiceConnection)'
KeyVaultName: '${{ parameters.KVNAME }}'
SecretsFilter: '*'
RunAsPreJob: false
Enter fullscreen mode
Exit fullscreen mode
PIPELINE TASK #4:-:-
Create ACR Service Connection in Azure DevOps Project.
Grant the newly created ACR Service Connection in Azure DevOps Project access permission to all Pipelines.
############################################################
# Create ACR Service Connection in Azure DevOps Project:-
############################################################
- task: PowerShell@2
displayName: Create ACR Service Connection
inputs:
targetType: 'inline'
script: |
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$(PAT)"))
$header = @{
'Authorization' = 'Basic ' + $B64Pat
'Content-Type' = 'application/json'
}
$body = '{
"data": {},
"name": "${{ parameters.ACRSrvConnectionName }}",
"type": "dockerregistry",
"authorization": {
"parameters": {
"username": "${{ parameters.ACRName }}",
"password": "$(ACRPasswd)",
"email": "$(emailID)",
"registry": "https://${{ parameters.ACRName }}.azurecr.io"
},
"scheme": "UsernamePassword"
},
"isShared": false,
"isReady": true,
"serviceEndpointProjectReferences": [
{
"projectReference": {
"id": "$(AMCLOUD-DevOps-Prj-ID)",
"name": "${{ parameters.DevOpsProjName }}"
},
"name": "${{ parameters.ACRSrvConnectionName }}"
}
]
}'
$srvEndpointID = Invoke-RestMethod -Method Post -Uri ${{ parameters.DevOpsOrganisation }}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4 -Headers $header -Body $body | Select -ExpandProperty id
echo "#####################################################################################"
echo "ACR Service Connection ${{ parameters.ACRSrvConnectionName }} created successfully."
echo "#####################################################################################"
$patchbody = '{
"allPipelines": {
"authorized": true,
"authorizedBy": null,
"authorizedOn": null
},
"pipelines": null,
"resource": {
"id": "$srvEndpointID",
"type": "endpoint"
}
}'
Invoke-RestMethod -Method PATCH -Uri ${{ parameters.DevOpsOrganisation }}/${{ parameters.DevOpsProjName }}/_apis/pipelines/pipelinepermissions/endpoint/"$srvEndpointID"?api-version=7.0-preview.1 -Headers $header -Body $patchbody
echo "###############################################################################################################"
echo "ACR Service Connection ${{ parameters.ACRSrvConnectionName }} was granted access permission to all Pipelines."
echo "###############################################################################################################"
Enter fullscreen mode
Exit fullscreen mode
NOTE:-
Passing PAT as Pipeline Runtime variable or Fetching it from Key Vault and use it as Environmental variables will not work and it will throw below error.
Refer the Github Issue: 24108
Sample format of the JSON Config file is used to prepare the "$body" variable section. It can be found here
NOW ITS TIME TO TEST!!!
TEST CASES:-
1. Pipeline executed successfully.
2. ACR Service connection created successfully in the Devops project.
Hope You Enjoyed the Session!!!
Stay Safe | Keep Learning | Spread Knowledge
Top comments (0)