Greetings to my fellow Technology Advocates and Specialists.
In this Session, I will demonstrate How to Reset Service Principal Secret and Store in Key Vault Using Azure DevOps.
I had the Privilege to talk on this topic in TWO Azure Communities:-
NAME OF THE AZURE COMMUNITY | TYPE OF SPEAKER SESSION |
---|---|
Journey to the Cloud 9.0 | Virtual |
Festive Tech Calendar 2022 | Virtual |
LIVE RECORDED SESSION:- |
---|
LIVE DEMO was Recorded as part of my Presentation in JOURNEY TO THE CLOUD 9.0 Forum/Platform |
Duration of My Demo = 55 Mins 42 Secs |
LIVE DEMO was Recorded as part of my Presentation in FESTIVE TECH CALENDAR 2022 Forum/Platform |
Duration of My Demo = 1 Hour 05 Mins 08 Secs |
USE CASE:- |
---|
Cloud Engineer DOES NOT have access to Azure Active Directory (AAD) to Reset Service Principal Secret. |
Cloud Engineer CANNOT ELEVATE rights using PIM (Privileged Identity Management) to Reset Service Principal Secret. |
AUTOMATION OBJECTIVE:- |
---|
Validate If the Service Principal Exists. If No, Pipeline will FAIL. |
Validate If Resource Group Containing Key Vault Exists. If No Resource Group Found, Pipeline will FAIL. |
Validate If Key Vault Exists inside the Specified Resource Group. If No Key Vault Found, Pipeline will FAIL. |
If All of the above validation is SUCCESSFUL, Pipeline will then Reset the Service Principal Secret and Store it in the Key Vault. |
IMPORTANT NOTE:- |
---|
The YAML Pipeline is tested on WINDOWS BUILD AGENT Only!!!
REQUIREMENTS:- |
---|
- Azure Subscription.
- Azure DevOps Organisation and Project.
- Service Principal either assigned Global Administrator Privileged Identity Management (PIM) Azure AD Role or Required Microsoft Graph API Rights (Directory.ReadWrite.All: Read and Write Directory Data).
- Service Principal with Required RBAC ( Contributor) applied on Subscription or Resource Group(s).
- Azure Resource Manager Service Connection in Azure DevOps.
CODE REPOSITORY:- | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
NAME OF THE AZURE COMMUNITY | TYPE OF SPEAKER SESSION |
---|---|
Journey to the Cloud 9.0 | Virtual |
Festive Tech Calendar 2022 | Virtual |
USE CASE:- |
---|
Cloud Engineer DOES NOT have access to Azure Active Directory (AAD) to Reset Service Principal Secret. |
Cloud Engineer CANNOT ELEVATE rights |
HOW DOES MY CODE PLACEHOLDER LOOKS LIKE:- |
---|
![]() |
PIPELINE CODE SNIPPET:- |
---|
AZURE DEVOPS YAML PIPELINE (azure-pipelines-spi-reset-secret-v1.0.yml):- |
---|
trigger:
none
######################
#DECLARE PARAMETERS:-
######################
parameters:
- name: SubscriptionID
displayName: Subscription ID Details Follow Below:-
type: string
default: 210e66cb-55cf-424e-8daa-6cad804ab604
values:
- 210e66cb-55cf-424e-8daa-6cad804ab604
- name: RGNAME
displayName: Please Provide the Resource Group Name:-
type: object
default:
- name: KVNAME
displayName: Please Provide the Keyvault Name:-
type: object
default:
- name: SPINAME
displayName: Please Provide the Service Principal Name:-
type: object
default:
######################
#DECLARE VARIABLES:-
######################
variables:
ServiceConnection: amcloud-cicd-service-connection
BuildAgent: windows-latest
#########################
# Declare Build Agents:-
#########################
pool:
vmImage: $(BuildAgent)
###################
# Declare Stages:-
###################
stages:
- stage: RESET_SECRET_SERVICE_PRINCIPAL
jobs:
- job: RESET_SECRET_SERVICE_PRINCIPAL
displayName: RESET SECRET SERVICE PRINCIPAL
steps:
- task: AzureCLI@2
displayName: Reset SPI Secret
inputs:
azureSubscription: $(ServiceConnection)
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
az --version
az account set --subscription ${{ parameters.SubscriptionID }}
az account show
$i = az ad sp list --display-name ${{ parameters.SPINAME }} --query [].appDisplayName -o tsv
if ($i -eq "${{ parameters.SPINAME }}") {
$j = az group exists -n ${{ parameters.RGNAME }}
if ($j -eq "true") {
$k = az keyvault list --resource-group ${{ parameters.RGNAME }} --query [].name -o tsv
if ($k -eq "${{ parameters.KVNAME }}") {
$spiappid = az ad sp list --display-name ${{ parameters.SPINAME }} --query [].appId -o tsv
$spireset = az ad sp credential reset --id $spiappid --query "password" -o tsv
az keyvault secret set --name ${{ parameters.SPINAME }} --vault-name ${{ parameters.KVNAME }} --value $spireset
echo "##################################################################"
echo "The Reset of Service Principal ${{ parameters.SPINAME }} secret was successful. The New Secret was then Stored inside Key Vault ${{ parameters.KVNAME }} in the Resource Group ${{ parameters.RGNAME }}!!!"
echo "##################################################################"
}
else {
echo "####################################################################################################"
echo "Key Vault ${{ parameters.KVNAME }} DOES NOT EXISTS in Resource Group ${{ parameters.RGNAME }}!!!"
echo "####################################################################################################"
exit 1
}
}
else {
echo "##################################################################"
echo "Resource Group ${{ parameters.RGNAME }} DOES NOT EXISTS!!!"
echo "##################################################################"
exit 1
}
}
else {
echo "####################################################################################################################"
echo "Service Principal ${{ parameters.SPINAME }} DOES NOT EXISTS and hence Cannot Proceed with the Reset of Secret!!!"
echo "####################################################################################################################"
exit 1
}
Now, let me explain each part of YAML Pipeline for better understanding.
PART #1:- |
---|
BELOW FOLLOWS PIPELINE RUNTIME VARIABLES CODE SNIPPET:- |
---|
######################
#DECLARE PARAMETERS:-
######################
parameters:
- name: SubscriptionID
displayName: Subscription ID Details Follow Below:-
type: string
default: 210e66cb-55cf-424e-8daa-6cad804ab604
values:
- 210e66cb-55cf-424e-8daa-6cad804ab604
- name: RGNAME
displayName: Please Provide the Resource Group Name:-
type: object
default:
- name: KVNAME
displayName: Please Provide the Keyvault Name:-
type: object
default:
- name: SPINAME
displayName: Please Provide the Service Principal Name:-
type: object
default:
PART #2:- |
---|
BELOW FOLLOWS PIPELINE VARIABLES CODE SNIPPET:- |
---|
######################
#DECLARE VARIABLES:-
######################
variables:
ServiceConnection: amcloud-cicd-service-connection
BuildAgent: windows-latest
NOTE:- |
---|
Please change the values of the variables accordingly. |
The entire YAML pipeline is build using Runtime Parameters and Variables. No Values are Hardcoded. |
PART #3:- |
---|
BELOW FOLLOWS THE CONDITIONS AND LOGIC DEFINED IN THE PIPELINE (AS MENTIONED ABOVE IN THE "AUTOMATION OBJECTIVE"):- |
---|
inlineScript: |
az --version
az account set --subscription ${{ parameters.SubscriptionID }}
az account show
$i = az ad sp list --display-name ${{ parameters.SPINAME }} --query [].appDisplayName -o tsv
if ($i -eq "${{ parameters.SPINAME }}") {
$j = az group exists -n ${{ parameters.RGNAME }}
if ($j -eq "true") {
$k = az keyvault list --resource-group ${{ parameters.RGNAME }} --query [].name -o tsv
if ($k -eq "${{ parameters.KVNAME }}") {
$spiappid = az ad sp list --display-name ${{ parameters.SPINAME }} --query [].appId -o tsv
$spireset = az ad sp credential reset --id $spiappid --query "password" -o tsv
az keyvault secret set --name ${{ parameters.SPINAME }} --vault-name ${{ parameters.KVNAME }} --value $spireset
echo "##################################################################"
echo "The Reset of Service Principal ${{ parameters.SPINAME }} secret was successful. The New Secret was then Stored inside Key Vault ${{ parameters.KVNAME }} in the Resource Group ${{ parameters.RGNAME }}!!!"
echo "##################################################################"
}
else {
echo "####################################################################################################"
echo "Key Vault ${{ parameters.KVNAME }} DOES NOT EXISTS in Resource Group ${{ parameters.RGNAME }}!!!"
echo "####################################################################################################"
exit 1
}
}
else {
echo "##################################################################"
echo "Resource Group ${{ parameters.RGNAME }} DOES NOT EXISTS!!!"
echo "##################################################################"
exit 1
}
}
else {
echo "####################################################################################################################"
echo "Service Principal ${{ parameters.SPINAME }} DOES NOT EXISTS and hence Cannot Proceed with the Reset of Secret!!!"
echo "####################################################################################################################"
exit 1
}
NOW ITS TIME TO TEST !!!...
TEST CASES:- |
---|
TEST CASE #1: SERVICE PRINCIPAL NAME EXISTS, RESOURCE GROUP AND KEY VAULT EXISTS:- |
---|
DESIRED OUTPUT: PIPELINE EXECUTED SUCCESSFULLY. SERVICE PRINCIPAL SECRET GOT RESET AND STORED IN KEY VAULT. |
SERVICE PRINCIPAL IN PLACE:- |
PIPELINE RUNTIME VARIABLES VALUE:- |
PIPELINE EXECUTED SUCCESSFULLY:- |
![]() |
![]() |
SERVICE PRINCIPAL RESET SECRET STORED IN KEY VAULT:- |
TEST CASE #2: SERVICE PRINCIPAL DOES NOT EXISTS, RESOURCE GROUP AND KEY VAULT EXISTS:- |
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE SERVICE PRINCIPAL DOES NOT EXISTS. |
PIPELINE FAILED:- |
![]() |
![]() |
TEST CASE #3: SERVICE PRINCIPAL AND KEYVAULT EXISTS BUT RESOURCE GROUP DOES NOT EXISTS:- |
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE RESOURCE GROUP DOES NOT EXISTS. |
PIPELINE FAILED:- |
![]() |
![]() |
TEST CASE #4: SERVICE PRINCIPAL AND RESOURCE GROUP EXISTS BUT KEY VAULT DOES NOT EXISTS:- |
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE KEY VAULT DOES NOT EXISTS. |
PIPELINE FAILED:- |
![]() |
![]() |
IMPORTANT OBSERVATION:- |
---|
The Service Principal Reset Secret Entry Does Not appear in Azure Portal though available in Key Vault. |
SECRET DETAILS IN KEY VAULT AFTER RESET:- |
SECRET DETAILS IN AZURE PORTAL APP REGISTRATION GUI AFTER RESET:- |
Hope You Enjoyed the Session!!!
Stay Safe | Keep Learning | Spread Knowledge
Top comments (0)