DEV Community

Cover image for Create service connection using Devops CLI
Arindam Mitra
Arindam Mitra

Posted on • Updated on

Create service connection using Devops CLI

Greetings to my fellow Technology Advocates and Specialists.

In this Session, I will demonstrate How to Create Service Connection Using DevOps CLI.

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

NAME OF THE AZURE COMMUNITY TYPE OF SPEAKER SESSION
Festive Tech Calendar 2022 Virtual
LIVE RECORDED SESSIONS:-
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 CASES:-
Create DevOps Service Connection, Prompting PAT (Personal Access Token)
Create DevOps Service Connection, Without Prompting PAT (Personal Access Token)
AUTOMATION OBJECTIVE:-
Create Service Principal.
Query the Application ID of the Service Principal.
Store the Service Principal Application ID and Secret in Key Vault.
Assign the Service Principal, "Contributor" RBAC (Role Based Access Control) on Subscription Level.
Set Service Principal Secret as an Environmental Variable for creating Azure DevOps Service Connection.
Set PAT (Personal Access Token) as an environment variable for DevOps Login.
Create Azure DevOps Service Connection.
Grant Access to all Pipelines to the Newly Created Azure DevOps Service Connection.
Verify Service Connection.
REQUIREMENTS:-
  1. Azure Subscription.
  2. Azure DevOps Organisation and Project.
  3. Full Access PAT (Personal Access Token).
  4. The Identity executing the script has required privilege to a) Create Service Principal in Azure Active Directory, b) Assign RBAC, and c) Create Secret in Key vault.
CODE REPOSITORY:-

GitHub logo arindam0310018 / 15-Nov-2022-DevOpsCLI__Create-Service-Connection

CREATE SERVICE CONNECTION USING DEVOPS CLI

CREATE SERVICE CONNECTION USING DEVOPS CLI

Greetings to my fellow Technology Advocates and Specialists.

In this Session, I will demonstrate How to Create Service Connection Using DevOps CLI.

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

NAME OF THE AZURE COMMUNITY TYPE OF SPEAKER SESSION
Festive Tech Calendar 2022 Virtual
LIVE RECORDED SESSION:-
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
IMAGE ALT TEXT HERE
USE CASES:-
Create DevOps Service Connection, Prompting PAT (Personal Access Token)
Create DevOps Service Connection, Without Prompting PAT (Personal Access Token)
AUTOMATION OBJECTIVE:-
Create Service Principal.
Query the Application ID of the Service Principal.
Store the Service Principal Application ID and Secret in Key Vault.
Assign the Service Principal, "Contributor" RBAC (Role Based Access Control) on Subscription Level.
Set Service Principal Secret as an
…
BELOW FOLLOWS THE CODE SNIPPET:-
USE CASE #1:-
CREATE AZURE DEVOPS SERVICE CONNECTION WITH PAT AS USER INPUT (Create-DevOps-Service-Connection-Prompt-PAT.ps1):-
##############
# VARIABLES:-
############## 
$spiname = "AM-Test-SPI-100"
$rbac = "Contributor"
$devopsOrg = "https://dev.azure.com/arindammitra0251/"
$devopsPrj = "AMCLOUD"
$subsID = "210e66cb-55cf-424e-8daa-6cad804ab604"
$subsName = "AM-PROD-VS"
$tenantID = "20516b3d-42af-4bd4-b2e6-e6b4051af72a"
$kv = "ampockv"

##############
# CORE SCRIPT:-
############## 

# Create Service Principal and Store Secret in a variable:-
$spipasswd = az ad sp create-for-rbac -n $spiname --query "password" -o tsv

# Query the Application ID of the Service Principal and Store it in a variable:-
$spiID = az ad sp list --display-name $spiname --query [].appId -o tsv

# Store the Service Principal Application ID and Secret in Key Vault:-
az keyvault secret set --name $spiname-id --vault-name $kv --value $spiID
az keyvault secret set --name $spiname-passwd --vault-name $kv --value $spipasswd

# Assign the Service Principal, "Contributor" RBAC on Subscription Level:-
az role assignment create --assignee "$spiID" --role "$rbac" --scope "/subscriptions/$subsID"

#Set Service Principal Secret as an Environment Variable for creating Azure DevOps Service Connection:-
$env:AZURE_DEVOPS_EXT_AZURE_RM_SERVICE_PRINCIPAL_KEY=$spipasswd

# Perform DevOps Login. It will Prompt for PAT:-
az devops login

# Set Default DevOps Organisation and Project:-
az devops configure --defaults organization=$devopsOrg project=$devopsPrj

# Create DevOps Service Connection:-
az devops service-endpoint azurerm create --azure-rm-service-principal-id $spiID --azure-rm-subscription-id $subsID --azure-rm-subscription-name $subsName --azure-rm-tenant-id $tenantID --name $spiname --org $devopsOrg --project $devopsPrj

# Grant Access to all Pipelines to the Newly Created DevOps Service Connection:-
$srvEndpointID = az devops service-endpoint list --query "[?name=='$spiname'].id" -o tsv
az devops service-endpoint update --id $srvEndpointID --enable-for-all

Enter fullscreen mode Exit fullscreen mode
USE CASE #2:-
CREATE AZURE DEVOPS SERVICE CONNECTION WITH PAT AS ENVIRONMENT VARIABLE (Create-DevOps-Service-Connection-Without-Prompting-PAT.ps1):-
##############
# VARIABLES:-
############## 
$spiname = "AM-Test-SPI-200"
$rbac = "Contributor"
$pat = "<Provide your own PAT>"
$devopsOrg = "https://dev.azure.com/arindammitra0251/"
$devopsPrj = "AMCLOUD"
$subsID = "210e66cb-55cf-424e-8daa-6cad804ab604"
$subsName = "AM-PROD-VS"
$tenantID = "20516b3d-42af-4bd4-b2e6-e6b4051af72a"
$kv = "ampockv"

##############
# CORE SCRIPT:-
############## 

# Create Service Principal and Store Secret in a variable:-
$spipasswd = az ad sp create-for-rbac -n $spiname --query "password" -o tsv

# Query the Application ID of the Service Principal and Store it in a variable:-
$spiID = az ad sp list --display-name $spiname --query [].appId -o tsv

# Store the Service Principal Application ID and Secret in Key Vault:-
az keyvault secret set --name $spiname-id --vault-name $kv --value $spiID
az keyvault secret set --name $spiname-passwd --vault-name $kv --value $spipasswd

# Assign the Service Principal, "Contributor" RBAC on Subscription Level:-
az role assignment create --assignee "$spiID" --role "$rbac" --scope "/subscriptions/$subsID"

#Set Service Principal Secret as an Environment Variable for creating Azure DevOps Service Connection:-
$env:AZURE_DEVOPS_EXT_AZURE_RM_SERVICE_PRINCIPAL_KEY=$spipasswd

# Set PAT as an environment variable for DevOps Login:-
$env:AZURE_DEVOPS_EXT_PAT = $pat

# Set Default DevOps Organisation and Project:-
az devops configure --defaults organization=$devopsOrg project=$devopsPrj

# Create DevOps Service Connection:-
az devops service-endpoint azurerm create --azure-rm-service-principal-id $spiID --azure-rm-subscription-id $subsID --azure-rm-subscription-name $subsName --azure-rm-tenant-id $tenantID --name $spiname --org $devopsOrg --project $devopsPrj

# Grant Access to all Pipelines to the Newly Created DevOps Service Connection:-
$srvEndpointID = az devops service-endpoint list --query "[?name=='$spiname'].id" -o tsv
az devops service-endpoint update --id $srvEndpointID --enable-for-all

Enter fullscreen mode Exit fullscreen mode
DIFFERENCE BETWEEN BOTH USE CASES:-
In Use Case 1, PAT is prompted as User Input during script execution.
In Use Case 2, PAT is set as Environment variable so that it is not prompted as User Input during script execution.

Now, let me explain the script, part by part for better understanding.

VARIABLES:-

USE CASE 1:-

##############
# VARIABLES:-
############## 
$spiname = "AM-Test-SPI-100"
$rbac = "Contributor"
$devopsOrg = "https://dev.azure.com/arindammitra0251/"
$devopsPrj = "AMCLOUD"
$subsID = "210e66cb-55cf-424e-8daa-6cad804ab604"
$subsName = "AM-PROD-VS"
$tenantID = "20516b3d-42af-4bd4-b2e6-e6b4051af72a"
$kv = "ampockv"

Enter fullscreen mode Exit fullscreen mode

USE CASE 2:-

##############
# VARIABLES:-
############## 
$spiname = "AM-Test-SPI-200"
$rbac = "Contributor"
$pat = "<Provide your own PAT>"
$devopsOrg = "https://dev.azure.com/arindammitra0251/"
$devopsPrj = "AMCLOUD"
$subsID = "210e66cb-55cf-424e-8daa-6cad804ab604"
$subsName = "AM-PROD-VS"
$tenantID = "20516b3d-42af-4bd4-b2e6-e6b4051af72a"
$kv = "ampockv"

Enter fullscreen mode Exit fullscreen mode
NOTE:-
Please change the values of the variables accordingly.
The entire script is build using Variables. No Values are Hardcoded. Changing the values of the variables should help you execute the script seamlessly.
CORE SCRIPT:-

Create Service Principal and Store Secret in a variable:-

$spipasswd = az ad sp create-for-rbac -n $spiname --query "password" -o tsv
Enter fullscreen mode Exit fullscreen mode

Query the Application ID of the Service Principal and Store it in a variable:-

$spiID = az ad sp list --display-name $spiname --query [].appId -o tsv
Enter fullscreen mode Exit fullscreen mode

Store the Service Principal Application ID and Secret in Key Vault:-

az keyvault secret set --name $spiname-id --vault-name $kv --value $spiID
az keyvault secret set --name $spiname-passwd --vault-name $kv --value $spipasswd
Enter fullscreen mode Exit fullscreen mode

Assign the Service Principal, "Contributor" RBAC on Subscription Level:-

az role assignment create --assignee "$spiID" --role "$rbac" --scope "/subscriptions/$subsID"
Enter fullscreen mode Exit fullscreen mode

Set Service Principal Secret as an Environment Variable for creating Azure DevOps Service Connection:-

$env:AZURE_DEVOPS_EXT_AZURE_RM_SERVICE_PRINCIPAL_KEY=$spipasswd
Enter fullscreen mode Exit fullscreen mode

Perform DevOps Login. It will Prompt for PAT Token:-

az devops login
Enter fullscreen mode Exit fullscreen mode

OR

Set PAT as an environment variable for DevOps Login:-

$env:AZURE_DEVOPS_EXT_PAT = $pat
Enter fullscreen mode Exit fullscreen mode

Set Default DevOps Organisation and Project:-

az devops configure --defaults organization=$devopsOrg project=$devopsPrj
Enter fullscreen mode Exit fullscreen mode

Create DevOps Service Connection:-

az devops service-endpoint azurerm create --azure-rm-service-principal-id $spiID --azure-rm-subscription-id $subsID --azure-rm-subscription-name $subsName --azure-rm-tenant-id $tenantID --name $spiname --org $devopsOrg --project $devopsPrj
Enter fullscreen mode Exit fullscreen mode

Grant Access to all Pipelines to the Newly Created DevOps Service Connection:-

$srvEndpointID = az devops service-endpoint list --query "[?name=='$spiname'].id" -o tsv
az devops service-endpoint update --id $srvEndpointID --enable-for-all
Enter fullscreen mode Exit fullscreen mode

NOW ITS TIME TO TEST

TEST CASES:-
TEST CASE FOR USE CASE #1: PAT AS USER INPUT:-
Service Principal has been created. Application ID and Secret has been Stored in Key Vault. "Contributor" RBAC has been assigned to the newly created Service Principal on Subscription Level.
As Observed, the script is now waiting for User Input PAT.
Image description
After providing the correct PAT, script executed successfully.
Image description
Image description
Service Principal (with secret) created successfully.
Image description
Application ID and Secret of Service Principal has been stored in Key Vault.
Image description
"Contributor" RBAC has been assigned to the newly created Service Principal on Subscription Level.
Image description
Azure DevOps Service Connection has been created successfully with the newly created Service Principal.
Image description
Azure DevOps Service Connection Verification is successful.
Image description
TEST CASE FOR USE CASE #2: PAT AS ENVIRONMENT VARIABLE:-
Service Principal has been created. Application ID and Secret has been Stored in Key Vault. "Contributor" RBAC has been assigned to the newly created Service Principal on Subscription Level.
As Observed, No PAT is prompted during script execution.
Image description
Image description
Image description
Service Principal (with secret) created successfully.
Image description
Application ID and Secret of Service Principal has been stored in Key Vault.
Image description
"Contributor" RBAC has been assigned to the newly created Service Principal on Subscription Level.
Image description
Azure DevOps Service Connection has been created successfully with the newly created Service Principal.
Image description
Azure DevOps Service Connection Verification is successful.
Image description

Hope You Enjoyed the Session!!!

Stay Safe | Keep Learning | Spread Knowledge

Top comments (2)

Collapse
 
cbergmeister profile image
Chris Bergmeister

I wrote a similar script in the past but found when running the script in one go, I needed about 20 second of sleep after creation of service principle to ensure it was fully created behind the scenes because otherwise the creation of the service connection sometimes failed.

Collapse
 
arindam0310018 profile image
Arindam Mitra • Edited

Hi @cbergmeister, I did not experience any such behavior while I was testing it. I normally do a rigorous testing before producing it in my Github.

But the Idea is not bad. Putting your Script in Sleep for few seconds can always reduce the chances of failure of your script. Proactive measure to make it less error prone.

The Initial idea was to automate it with Az DevOps , but somehow could not make it work .
All the things which I tried to make it work are mentioned in my Github.
I then raised an Github Issue, Still waiting for Microsoft to provide a solution.

Cheers, Arindam