To create a service principal using certificates, the following steps should be executed:
- Create a self-signed certificate or purchase a certificate: A self-signed certificate is used to create this example end-to-end application. For real-life deployments, a valid certificate should be purchased from a certificate authority.
To create a self-signed certificate, the following command can be executed. The self-signed certificate is exportable and stored in a personal folder on the local machine. It also has an expiry date:
$currentDate = Get-Date
$expiryDate = $currentDate.AddYears(1)
$finalDate = $expiryDate.AddYears(1)
$servicePrincipalName = "https://automation.book.com"
$automationCertificate = New-SelfSignedCertificate -DnsName $servicePrincipalName -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $finalDate -CertStoreLocation "Cert:\LocalMachine\My"
- Export the newly created certificate: The new certificate must be exported to the filesystem so that later, it can be uploaded to other destinations, such as Azure AD, to create a service principal.
The commands used to export the certificate to the local filesystem are shown next. Please note that this certificate has both public and private keys, and so while it is exported, it must be protected using a password, and the password must be a secure string:
$securepfxpwd = ConvertTo-SecureString -String 'password' -AsPlainText -Force # Password for the private key PFX certificate
$cert1 = Get-Item -Path Cert:\LocalMachine\My\$($automationCertificate.Thumbprint)
Export-PfxCertificate -Password $securepfxpwd -FilePath "C:\book\azureautomation.pfx" -Cert $cert1
The Get-Item cmdlet reads the certificate from the certificate store and stores it in the $cert1 variable. The Export-PfxCertificate actually exports the certificate in the certificate store to the filesystem. In this case, it is in the C:\book folder.
- Read the content from the newly generated PFX file: An object of X509Certificate is created to hold the certificate in memory, and the data is converted to a Base64 string using the System.Convert function:
$newCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate -ArgumentList "C:\book\azureautomation.pfx", $securepfxpwd
$newcertdata = [System.Convert]::ToBase64String($newCert.GetRawCertData())
Create an instance of the PSADKeyCredential class and fill in the values of its data structure. This data structure is then used when creating the service principal. This class is available in the Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory namespace. A new Guid is also generated to assign it to the keyid property of this object. The Base64-encoded cert value is assigned to the CertValue property, and both the start date and the end date are assigned as well. When the service principal is created using this object, it will configure it according to the values provided here:
$keyid = [Guid]::NewGuid()
$keyCredential = New-Object -TypeName Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory.PSADKeyCredential
$keyCredential.StartDate = [datetime]::Now
$keyCredential.KeyId = $keyid
$keyCredential.CertValue = $newcertdata
$keyCredential.EndDate = [datetime]::Now.AddYears(1)
- Create the service application and service principal in Azure: We have already executed these commands once when creating the service principal with a password. This time, the key difference is that instead of a password, the keyCredential property is used. Finally, a service principal is created with owner rights.
We will be using this same principal to connect to Azure from the Azure Automation account. It is important that the application ID, tenant ID, subscription ID, and certificate thumbprint values are stored in a temporary location so that they can be used to configure subsequent resources:
$adAppName = http://automationcertcred2
$adApp =New-AzureRmADApplication -DisplayName $adAppName -HomePage $adAppName -IdentifierUris $adAppName -KeyCredentials $keyCredential -Verbose
New-AzureRmADServicePrincipal -ApplicationId $adApp.ApplicationId.Guid -Role owner