DEV Community

Cover image for Create service principal and store secret in key vault using Az Devops
Arindam Mitra
Arindam Mitra

Posted on • Updated on

Create service principal and store secret in key vault using Az Devops

Greetings to my fellow Technology Advocates and Specialists.

In this Session, I will demonstrate how to Create Service Principal and Store Secret in Key Vault Using Azure DevOps.

I had the Privilege to talk on this topic in THREE Azure Communities:-

NAME OF THE AZURE COMMUNITY TYPE OF SPEAKER SESSION
Microsoft Azure Bern User Group In Person
Journey to the Cloud 9.0 Virtual
Festive Tech Calendar 2022 Virtual
IN-PERSON SESSION:-
I presented this Demo as a part of AZURE DEVOPS: TAKEAWAYS BEST PRACTISES AND LIVE DEMOS In-Person Speaker Session in MICROSOFT AZURE BERN USER GROUP Forum/Platform.
Event Meetup Announcement:-
Image description
Moment Captured with Founders of MICROSOFT AZURE BERN USER GROUP "STEFAN JOHNER", "STEFAN ROTH", "PAUL AFFENTRANGER" and Co-organizer "DAMIEN BOWDEN":-
Image description
VIRTUAL 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 Create Service Principal.
Cloud Engineer CANNOT ELEVATE rights using PIM (Privileged Identity Management) to Create Service Principal.
AUTOMATION OBJECTIVE:-
Validate If the Service Principal Exists. If Yes, 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 Create the Service Principal, Generate Secret and Store it in the Key Vault.
IMPORTANT NOTE:-

The YAML Pipeline is tested on WINDOWS BUILD AGENT Only!!!

REQUIREMENTS:-
  1. Azure Subscription.
  2. Azure DevOps Organisation and Project.
  3. Service Principal with Required RBAC ( Contributor) applied on Subscription or Resource Group(s).
  4. Azure Resource Manager Service Connection in Azure DevOps.
CODE REPOSITORY:-

GitHub logo arindam0310018 / 16-Aug-2022-DevOps__Create-SPI-Generate-Secret-Store-In-KV

CREATE SERVICE PRINCIPAL AND STORE SECRET IN KEY VAULT USING AZ DEVOPS

CREATE SERVICE PRINCIPAL AND STORE SECRET IN KEY VAULT USING AZ DEVOPS

Greetings to my fellow Technology Advocates and Specialists.

In this Session, I will demonstrate how to Create Service Principal and Store Secret in Key Vault Using Azure DevOps.

I had the Privilege to talk on this topic in THREE Azure Communities:-

NAME OF THE AZURE COMMUNITY TYPE OF SPEAKER SESSION
Microsoft Azure Bern User Group In Person
Journey to the Cloud 9.0 Virtual
Festive Tech Calendar 2022 Virtual
IN-PERSON SESSION:-
I presented this Demo as a part of AZURE DEVOPS: TAKEAWAYS BEST PRACTISES AND LIVE DEMOS In-Person Speaker Session in MICROSOFT AZURE BERN USER GROUP Forum/Platform.
Event Meetup Announcement:-
Image description
Moment Captured with Founders of MICROSOFT AZURE BERN USER GROUP "STEFAN JOHNER", "STEFAN ROTH", "PAUL AFFENTRANGER" and Co-organizer "DAMIEN BOWDEN":-
Image description
VIRTUAL SESSION:-
LIVE DEMO was Recorded as part of my Presentation in JOURNEY TO THE CLOUD 9.0 Forum/Platform
Duration
HOW DOES MY CODE PLACEHOLDER LOOKS LIKE:-
Image description
PIPELINE CODE SNIPPET:-
AZURE DEVOPS YAML PIPELINE (azure-pipelines-spi-validate-create-store-in-KV-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: CREATE_SERVICE_PRINCIPAL 
  jobs:
  - job: CREATE_SERVICE_PRINCIPAL 
    displayName: CREATE SERVICE PRINCIPAL
    steps:
    - task: AzureCLI@2
      displayName: VALIDATE AND CREATE SPI
      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 -ne "${{ 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 }}") {
                        $spipasswd = az ad sp create-for-rbac -n ${{ parameters.SPINAME }} --query "password" -o tsv
                        az keyvault secret set --name ${{ parameters.SPINAME }} --vault-name ${{ parameters.KVNAME }} --value $spipasswd
                        echo "##################################################################"
                        echo "Service Principal ${{ parameters.SPINAME }} created successfully and the Secret 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 }} EXISTS and hence Cannot Proceed with Deployment!!!"
          echo "##################################################################"
          exit 1
              }

Enter fullscreen mode Exit fullscreen mode

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:

Enter fullscreen mode Exit fullscreen mode
PART #2:-
BELOW FOLLOWS PIPELINE VARIABLES CODE SNIPPET:-
######################
#DECLARE VARIABLES:-
######################
variables:
  ServiceConnection: amcloud-cicd-service-connection
  BuildAgent: windows-latest

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.
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 -ne "${{ 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 }}") {
                        $spipasswd = az ad sp create-for-rbac -n ${{ parameters.SPINAME }} --query "password" -o tsv
                        az keyvault secret set --name ${{ parameters.SPINAME }} --vault-name ${{ parameters.KVNAME }} --value $spipasswd
                        echo "##################################################################"
                        echo "Service Principal ${{ parameters.SPINAME }} created successfully and the Secret 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 }} EXISTS and hence Cannot Proceed with Deployment!!!"
          echo "##################################################################"
          exit 1
              }

Enter fullscreen mode Exit fullscreen mode

NOW ITS TIME TO TEST !!!...

TEST CASES:-
TEST CASE #1: SERVICE PRINCIPAL NAME DOES NOT EXISTS, RESOURCE GROUP AND KEY VAULT EXISTS:-
DESIRED OUTPUT: PIPELINE EXECUTED SUCCESSFULLY. SERVICE PRINCIPAL GOT CREATED. SECRET WAS GENERATED AND STORED IN KEY VAULT.
PIPELINE RUNTIME VARIABLES VALUE:-
Image description
PIPELINE EXECUTED SUCCESSFULLY:-
Image description
SERVICE PRINCIPAL CREATED + SECRET GENERATED:-
Image description
SECRET STORED IN KEY VAULT:-
Image description
TEST CASE #2: SERVICE PRINCIPAL, RESOURCE GROUP AND KEY VAULT EXISTS:-
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE SERVICE PRINCIPAL ALREADY EXISTS.
PIPELINE FAILED:-
Image description
Image description
TEST CASE #3: KEYVAULT EXISTS BUT SERVICE PRINCIPAL AND RESOURCE GROUP DOES NOT EXISTS:-
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE RESOURCE GROUP DOES NOT EXISTS.
PIPELINE FAILED:-
Image description
Image description
TEST CASE #4: RESOURCE GROUP EXISTS BUT SERVICE PRINCIPAL AND KEY VAULT DOES NOT EXISTS:-
DESIRED OUTPUT: PIPELINE FAILS STATING THAT THE KEY VAULT DOES NOT EXISTS.
PIPELINE FAILED:-
Image description
Image description

Hope You Enjoyed the Session!!!

Stay Safe | Keep Learning | Spread Knowledge

Top comments (0)