Updates
If you want to do this with GUI options continue reading this post.
CLI version
If you want to automate the deployment via script, please check the CLI version repo

To create Azure Service Connection for ARM with certificate you need to include PEM certificate with Bag attributes.
Issue
When you create RSA key pair BAG attributes are omitted, as BAG attributes are typically only included if the key pair was of type PKCS#12
Solution
include BAG attributes when creating the PEM file for Azure Devops Service Connection
Why should you use certificate credential over password credential? (From Azure Secure DevOps Kit)
Rationale: Password/shared secret credentials can be easily shared and hence can be easily compromised. Certificate credentials offer better security.
Description Azure Active Directory applications, which used in pipeline, must use certificate based authentication.
Error messages you may counter with adding SPN with cert
You encounter this if you have not uploaded the correct Public Key for the App registration _[Reason - The key was not found., Thumbprint of key used by client

Failed to obtain the Json Web Token(JWT) using service principal client ID. Exception message: Cannot find the requested object.
Failed to obtain the Json Web Token(JWT) using service principal client ID. Exception message: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
GUI setup
Correct type certificate
I’ve created an previous example which creates the correct type certificate, but you could do similar version with following commands (change the subj to match something you use)
- I didn’t found handy command to include the BAG attributes without first going through ”pkcs12” pass-trough, as it appends the BAG attributes for the file.
openssl genrsa -out private1.pem 2048
openssl req -new -x509 -key private1.pem -out public1.pem -days 720 -subj "/C=FI/CN=spnforaad.localdom/OU=IT Department/"
openssl pkcs12 -inkey private1.pem -in public1.pem -export -out pack.pfx -passout "pass:mypass"
openssl pkcs12 -in pack.pfx -passin "pass:mypass" -out "PemWithBagAttributes.pem" -nodes
Upload the public key to Azure AD
You can follow previous guide I’ve written here. If you used openssl commands above, use the public key ”public1.pem” in upload dialog for Azure AD app

jsa2/aadClientCredWithCert: Azure AD Client Credentials with Certificate code examples (github.com)
It’s recommended to test the token retrieval locally before proceeding to next phase


Create service connection (GUI)
Before doing the service connection you need to assign the SPN to appropriate subscription and role.


Paste contents of ” PemWithBagAttributes.pem” to certificate selection

Create service connection (AZ CLI with powershell)
az devops login --org https://dev.azure.com/yourOrganization az devops service-endpoint azurerm create ` --azure-rm-service-principal-certificate-path C:\git\aadClientCredWithCert\PemWithBagAttributes.pem ` --azure-rm-tenant-id "46d2c4e6-a732-4fb4-b9f8-374af03f3f58" ` --azure-rm-subscription-id "MYGUIDID" ` --azure-rm-service-principal-id "010ef950-c02b-47d8-87a1-cbc6de2145b9" ` --name "CertConnection" ` --azure-rm-subscription-name "MySub" ` --project "MyProject"
Alternative options
Create an Azure Resource Manager service connection using automated security
- This option unfortunately uses the password credential option by default
Managed identity
- The SPN can also be Managed Identity, but last time I checked it required the agent to be on a VM.

Connect to Microsoft Azure – Azure Pipelines | Microsoft Docs
It’s a comprehensive post to learn why certificate-based authentication is better while creating a new Azure service connection. Thank you!
TykkääTykkää
Thx for your feedback!
TykkääTykkää
Thank you so much, you really saved my day.
Would you mind sharing where did you find the information that states such private-key format is required?
TykkääTykkää
Sorry for reply delay and thx!. I think I was able to piece together the solution by following some disparate threads on ms tech forum, and stackOverflow, unless there was any clear guidance… to be honest I don’t remember, and if there was something clear I always try to credit op
TykkääTykkää
Thank you for your detailed explanation especially on points like using certificate credential over password credentials & using legit public key.
TykkääTykkää
Thx for the feedback Sir!
TykkääTykkää
Thank you for the post, you are a life-saver!
Just want to point out that with Azure DevOps service (as of 2021-12-02), the only thing required to in the ”certificate” field appears to be the ”Bag Attributes” headers:
Bag Attributes
—–BEGIN CERTIFICATE—–
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
…
AAAAAAAAAAAAAAAAAAAAAAAA
—–END CERTIFICATE—–
Bag Attributes
—–BEGIN PRIVATE KEY—–
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
…
AAAAAAAAAAAAAAAAAAAAAAAA
—–END PRIVATE KEY—–
TykkääTykkää
Upon further inspection… it turns out that the ”Bag attributes” headers are not necessary as long as the private key is in PKCS#8 format (instead of PKCS#1 in our case). You can tell them apart by the header and footer:
PKCS#8 (GOOD)
—–BEGIN PRIVATE KEY—–
…
—–END PRIVATE KEY—–
PKCS#1 (NOT GOOD for Azure DevOps service connection)
—–BEGIN RSA PRIVATE KEY—–
…
—–END RSA PRIVATE KEY—–
TykkääTykkää
Thx for the insight- What do you mean, by not good? Unnecessary I might understand, vs using PKCS8. I shall test this, and update the blog at some point if it turns out to be correct. Nonetheless from security perspective there is no difference, just different attributes for a workflow which delivers the keys to service connection
TykkääTykkää
Hi Joosua,
By ”not good”, I meant that when using the PKCS#1 encoded private key (instead of the same private key encoded in PKCS#8), the ”Edit service connection” dialog in Azure DevOps would give the following error message on ”Verify”:
Failed to obtain the Json Web Token(JWT) using service principal client ID. Exception message: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
(I think we can all agree it’s not the best error message…)
TykkääTykkää
Thx for the insights! And glad to have helped
TykkääTykkää