Deploying azure automation account cert - azure

I generated a pfx blob using this script :
$appId = Read-Host "Enter application ID of service principal"
$adApp = (Get-AzureRmADApplication -ApplicationId $appId)[0]
$spnId = (Get-AzureRmADServicePrincipal -ServicePrincipalName $adApp.IdentifierUris[0])[0].Id.Guid
$endDate = (Get-Date).AddYears(1)
$certSelfSigned = New-SelfSignedCertificateEx -Subject "CN=$spnId" -StoreLocation CurrentUser -NotAfter $endDate -Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
$publicKey = [System.Convert]::ToBase64String($certSelfSigned.GetRawCertData())
New-AzureRmADSpCredential -ServicePrincipalObjectId $spnId -CertValue $publicKey -EndDate $certSelfSigned.GetExpirationDateString()
# TEST: Login-AzureRmAccount -ServicePrincipal -CertificateThumbprint $certSelfSigned.Thumbprint -ApplicationId $appId -TenantId <guid>
$storeLocation = [Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
$storeName = [Security.Cryptography.X509Certificates.StoreName]::My
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store #($storeName, $storeLocation)
$store.Open([Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly)
$findType = [System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint
$cert = $store.Certificates.Find($findType, $certSelfSigned.Thumbprint, $false)
$pfxBlob = [System.Convert]::ToBase64String($cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12))
$store.Close()
"THUMBPRINT: $($certSelfSigned.Thumbprint)"
"PFX BLOB: `n$pfxBlob"
I copied the pfx blob and made a .pfx file and in azure portal when I create a new certificate for an automation account and upload the file I created before it gives me internal server error.
What is the correct format of .pfx file and what is the password that I will be using to set and how will I use a thumbprint?

Related

PowerShell Export Pfx from Azure Key Vault using Az.KeyVault

I am creating a certificate inside Azure Key Vault and then attempting to export it with private key as a PFX.
# Create new Certificate in Key Vault
$policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" -SubjectName "CN=contoso" -IssuerName "Self" -ValidityInMonths 12 -ReuseKeyOnRenewal -KeySize 4096 -KeyType 'RSA-HSM';
Add-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName -CertificatePolicy $policy;
# From https://learn.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultcertificate?view=azps-5.8.0
# Export new Key Vault Certificate as PFX
$securePassword = "fBoFXYD%dg^Q" | ConvertTo-SecureString -AsPlainText -Force; # This is a throwaway password
$certificate = Get-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName;
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $certificate.Name -AsPlainText;
$secretByte = [Convert]::FromBase64String($secret)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $securePassword);
[System.IO.File]::WriteAllBytes("C:\Repos\Certificate.pfx", $pfxFileByte)
Get-PnPAzureCertificate -Path "C:\Repos\Certificate.pfx" -Password $securePassword
However, the PFX file is not valid
Error with Get-PnPAzureCertificate
Error with Certificate Import
Any ideas? Using Import-AzKeyVaultCertificate is not an option because there's a bug with it in environments that have policies that forces key lengths
Also, might be worth mentioning that I am using PowerShell 7
According to my test, we need to change keytype as RSA when we create cert policy.
For example
$VaultName=""
$ADServicePrincipalCertificateName=""
$policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" `
-SubjectName "CN=contoso.com" -IssuerName "Self" `
-ValidityInMonths 12 -ReuseKeyOnRenewal `
-KeySize 4096 -KeyType 'RSA';
Add-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName -CertificatePolicy $policy;
Start-Sleep -Seconds 30
# From https://learn.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultcertificate?view=azps-5.8.0
# Export new Key Vault Certificate as PFX
$securePassword = "fBoFXYD%dg^Q" | ConvertTo-SecureString -AsPlainText -Force; # This is a throwaway password
$certificate = Get-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName;
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $certificate.Name -AsPlainText;
$secretByte = [Convert]::FromBase64String($secret)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $securePassword);
[System.IO.File]::WriteAllBytes("E:\Certificate.pfx", $pfxFileByte)
Get-PnPAzureCertificate -Path "E:\Certificate.pfx" -Password $securePassword

Can't Connect to Exchange Online with a private certificate at Poweshell

I'm trying to create powershell script with the next flow.
Login to Azure Active Directory via Application.
Create Private Certificate.
Upload Certificate to Azure AD Application Certificates.
Connect to ExchangeOnline.
For this I created the next sсript according to the steps:
1st Step:
$clientId = 'xxx'
$tenantId = 'xxx'
$clientSecret = 'xxx'
$org = 'xxx.onmicrosoft.com'
$clientSecret = ConvertTo-SecureString $clientSecret -AsPlainText -Force
$credObject = New-Object System.Management.Automation.PSCredential ($clientId, $clientSecret)
Connect-AzAccount -Credential $credObject -Tenant $tenantId -ServicePrincipal
2nd and 3d Step:
$cert = New-SelfSignedCertificate -DnsName $org -NotAfter (Get-Date).AddYears(1) -KeySpec KeyExchange
$binCert = $cert.GetRawCertData()
$credValue = [System.Convert]::ToBase64String($binCert)
$validFrom = [datetime]::Parse($cert.GetEffectiveDateString())
$validTo = [datetime]::Parse($pfx.GetExpirationDateString())
$validTo = $validTo.AddDays(-1);
New-AzADAppCredential -ApplicationId $clientId -CertValue $credValue -StartDate $validFrom -EndDate $validTo
And up to now all is going fine. I can see this certificate at certificates list of Application.
But when I'm going to connect to MS Exchange Online with this command:
Connect-ExchangeOnline -Certificate $cert -AppID $clientId -Organization $org
i getting the next issue:
{
"error":"invalid_client",
"error_description":"xxx: Client assertion contains an invalid signature. [Reason - The key used is expired., Thumbprint of key used by client: 'xxx', Found key 'Start=03/11/2021 14:59:26, End=03/11/2022 13:09:26', Please visit the Azure Portal, Graph Explorer or directly use MS Graph to see configured keys for app Id 'xxx'. Review the documentation at https://learn.microsoft.com/en-us/graph/deployments to determine the corresponding service endpoint and https://learn.microsoft.com/en-us/graph/api/application-get?view=graph-rest-1.0&tabs=http to build a query request URL, such as 'https://graph.microsoft.com/beta/applications/xxx']\r\nTrace ID: xxxx\r\nCorrelation ID: xxx\r\nTimestamp: 2021-03-11 13:15:28Z",
"error_codes":[
700027
],
"timestamp":"2021-03-11 13:15:28Z",
"trace_id":"xxx",
"correlation_id":"xxx",
"error_uri":"https://login.microsoftonline.com/error?code=700027"
}
But this newly created certificate could not expire. I'll be glad to see any idea. Stacked with this for few days.
EDIT:
Also i admitted that if i uploading newly created certificate with UI but not with this command:
New-AzADAppCredential -ApplicationId $clientId -CertValue $credValue -StartDate $validFrom -EndDate $validTo
Then i can to exchange online with newly created certificate
The issue lies on $validTo = $validTo.AddDays(-1);. As a result, $validTo is earlier than $cert.NotAfter.
Please modify the script like this:
$cert = New-SelfSignedCertificate -DnsName $org -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(1) -KeySpec KeyExchange
$binCert = $cert.GetRawCertData()
$credValue = [System.Convert]::ToBase64String($binCert)
New-AzADAppCredential -ApplicationId $clientId -CertValue $credValue -StartDate $cert.NotBefore -EndDate $cert.NotAfter

New-AzADAppCredential Generate Client Secret

Is there a way to generate a password client secret using the New-AzADAppCredential cmdlet? I don't want to supply the password to the cmdlet and would much rather use the generate one much like the Azure Portal.
I am afraid you can't, when using New-AzADAppCredential to create client secret, the -Password is needed.
The workaround is to use the New-AzureADApplicationPasswordCredential command in AzureAD module.
New-AzureADApplicationPasswordCredential -ObjectId "<object-id>"
Not natively, but you can create a very similar client secret using the same tools that generate them in the portal.
It's not as elegant as having the solution baked into the cmdlet, but it works very well.
$bytes = New-Object Byte[] 32
$rand = ([System.Security.Cryptography.RandomNumberGenerator]::Create()).GetBytes($bytes)
$ClientSecret = [System.Convert]::ToBase64String($bytes) | ConvertTo-SecureString -AsPlainText -Force
$endDate = [System.DateTime]::Now.AddYears(1)
New-AzADAppCredential -ObjectId "<object-id>" -Password $ClientSecret -startDate $(get-date) -EndDate $endDate
This is possible now.
$Sub = "Your Sub Here"
Set-AzContext -SubscriptionName $Sub
$app = New-AzADApplication -DisplayName 'MyTestApp'
$secretStartDate = Get-Date
$secretEndDate = $secretStartDate.AddYears(1)
$webApiSecret = New-AzADAppCredential -StartDate $secretStartDate -EndDate $secretEndDate -ApplicationId $app.AppId
Write-Output $webApiSecret
Output:

Azure Authentication With Certificate Setup

I'm trying to set up Azure Key Vault so I can access with a certificate from my PHP application. I'm trying to follow the steps at https://azurecto.com/azure-keyvault-authenticating-with-certificates-and-reading-secrets/, which says you have to create an AD application, but i'm getting error messages. This is what I tried.
A. I already have a self-signed .pfx file on my Windows machine.
B. Because I already have a .pfx file, i change up his steps a bit. I import the .pfx file into the console with
$cert = Get-PfxCertificate -FilePath "C:\azurecrt.pfx"
C. Then it says to create some variables
$vaultName = 'Picklistsca1'
$dnsName = 'picklistsfakeurl.ca'
$dummyUrl = "http://$dnsName/"
D. Then it says call New-AzureRmADApplication. This is where I get into trouble.
$app = New-AzureRmADApplication
-DisplayName $dummyUrl
-HomePage $dummyUrl
-IdentifierUris $dummyUrl
-CertValue $cert
-StartDate '2018-04-07 6:40:23 PM'
-EndDate '2019-04-07 6:40:23 PM'
I get the error message "New-AzureRmADApplication : Cannot convert a primitive value to the expected type 'Edm.Binary'. See the inner exception for more details."
I think this is because the $cert has to be in base64 format, but everything I've tried to convert it to base64 fails. For example I've tried
$bytes = [System.IO.File]::ReadAllBytes("C:\azurecrt.pfx")
$b64 = [System.Convert]::ToBase64String($bytes)
Then replace $cert with $b64 in New-AzureRmADApplication. That gives me the error "New-AzureRmADApplication : Invalid certificate: Key value is invalid certificate"
Any advice would be greatly appreciated. Thanks
I'm trying to set up Azure Key Vault so I can access with a certificate from my PHP application
You could get the answer and demo code from this tutorial.
As juunas mentioned that you need a .cer file.
Following is the snippet from the tutorial
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificate.Import('c:\location\certificate.cer') # need a .cer file.
$startDate = $certificate.GetEffectiveDateString()
$endDate = $certificate.GetExpirationDateString()
$credValue = [System.Convert]::ToBase64String($certificate.GetRawCertData())
$azureADApplication = New-AzureRmADApplication -DisplayName "{application name}" -HomePage "{application page}" -IdentifierUris "{application page}" -KeyValue $credValue -KeyType "AsymmetricX509Cert" -KeyUsage "Verify" -StartDate $startDate -EndDate $endDate
Update:
I have updated the code as following. I have tested it on my side.
$credValue = [System.Convert]::ToBase64String($certificate.GetRawCertData())
$azureADApplication = New-AzureRmADApplication -DisplayName "{application name}" -HomePage "{application page}" -IdentifierUris "{application page}" -CertValue $credValue -StartDate $startDate -EndDate $endDate
$azureADApplication.ApplicationId
$principal= New-AzureRmADServicePrincipal -ApplicationId $azureADApplication.ApplicationId

When are my Azure application registration/service principal credentials going to expire?

So that our Azure Web Apps can access Azure Key Vault, we use certificates and application registrations with service principals.
After generating a certificate, we use the following Azure PowerShell to create an application registration and service principal and then give the service principal access to the Azure Key Vault. The Web App then loads this certificate and uses it to authenticate with Azure Key Vault. It all works fine.
$subscriptionId = Read-Host -Prompt 'SubscriptionId'
Select-AzureRmSubscription -SubscriptionId $subscriptionId
$resourceGroupName = Read-Host -Prompt 'Resource group name'
$vaultName = Read-Host -Prompt 'Vault name'
$certificateName = Read-Host -Prompt 'Certificate name'
$applicationName = Read-Host -Prompt 'Application name'
$certificatePath = Join-Path (Get-Location) "$certificateName.cer"
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificate.Import($certificatePath)
$rawCertData = [System.Convert]::ToBase64String($certificate.GetRawCertData())
$now = [System.DateTime]::UtcNow
$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://$applicationName" -IdentifierUris "https://$applicationName" -CertValue $rawCertData -StartDate $now -EndDate $now.AddYears(1)
$servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $application.ApplicationId
Set-AzureRmKeyVaultAccessPolicy -ResourceGroupName $resourceGroupName -VaultName $vaultName -ServicePrincipalName "https://$applicationName" -PermissionsToSecrets get
The problem is this line:
$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://$applicationName" -IdentifierUris "https://$applicationName" -CertValue $rawCertData -StartDate $now -EndDate $now.AddYears(1)
It sets the StartDate and EndDate to the current date and the current date plus 1 year. In hindsight I think it should have been the certificate start and end date:
$application = New-AzureRmADApplication -DisplayName $applicationName -HomePage "https://$applicationName" -IdentifierUris "https://$applicationName" -CertValue $rawCertData -StartDate` $certificate.NotBefore -EndDate $certificate.NotAfter
My question is - what will happen after $now.AddYears(1)? The certificate was created with a 3 year expiry but the application registration/service principal was created with an earlier EndDate - but what does that mean?
From the docs, it's the effective end date for the credential so I would assume the credential would stop working at that time.
https://learn.microsoft.com/en-us/powershell/module/azurerm.resources/new-azurermadapplication?view=azurermps-5.1.1
You can use New-AzureRmADAppCredential to roll the secret before that time.
https://learn.microsoft.com/en-us/powershell/module/azurerm.resources/new-azurermadappcredential?view=azurermps-5.1.1

Resources