New-AzADAppCredential Generate Client Secret - azure

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:

Related

PowerShell - How do I bulk upload Certificates to an Azure App Registration Certificate store?

As you can see from the code below I can upload on certificate at a time, but the problem is it wipes out all of the existing certificates when doing so.
$Tenant_ID = '00000000-0000-0000-0000-000000000000'
$Subscription_ID = '00000000-0000-0000-0000-000000000000'
$Azure_PassWord = (Get-StoredCredential -Target 'Domain' -Type Generic -AsCredentialObject).Password
$UserName = "$($env:USERNAME)#Google.com"
$EncryptedPassword = ConvertTo-SecureString $Azure_PassWord -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PsCredential($UserName,$EncryptedPassword)
$AzureConnection = (Connect-AzAccount -Credential $Credential -Tenant $Tenant_ID -Subscription $Subscription_ID -WarningAction 'Ignore').context
$AzureContext = (Set-AzContext -SubscriptionName $Subscription_ID -DefaultProfile $AzureConnection)
$Application_ID = '00000000-0000-0000-0000-000000000000'
$PFX_FileName = "Azure_Dev_V2"
$Cert_Password = "123456"
$Cert_Password = ConvertTo-SecureString -String $Cert_Password -Force -AsPlainText
$CurrentDate = Get-Date
$EndDate = $CurrentDate.AddYears(10)
$certificatePath = "C:\FilePath\Certificates\Certs\$($PFX_FileName).pfx" # OR Get-ChildItem -Path cert:\localmachine\my\$($Certificate_Thumbprint)
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2($certificatePath, $Cert_Password)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
$Azure_App_Registration = Get-AzADApplication -ApplicationId $Application_ID -DefaultProfile $AzureContext
New-AzADAppCredential -ApplicationObject $Azure_App_Registration -CertValue $keyValue -EndDate $EndDate -StartDate $CurrentDate
Connect-AzAccount -Subscription $Subscription_ID -ApplicationId $Azure_App_Registration.AppId -Tenant $Tenant_ID -CertificateThumbprint $cert.Thumbprint | Out-Null
Get-AzADAppCredential -ApplicationId $Azure_App_Registration.AppId | Where-Object {$_.DisplayName -match "CN=Azure_Dev_V2"}
In the Azure portal multiple certificates can be uploaded manually, and they will not delete the existing certificates.
EDIT: If bulk upload is not possible then how would I go about making sure the existing certificates that are in the Azure AD App Registration cert store do not get deleted ?
Thanks in Advance.

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

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

Authenticated with "Login-AzureRmAccount -ServicePrincipal" but no subscription is set?

I've successfully created a self-signed certificate with application & service principle using the New-AzureRmADApplication and New-AzureRmADServicePrincipal cmdlets.
I can execute the login using this command after retrieving the certificate:
Login-AzureRmAccount -ServicePrincipal -CertificateThumbprint $cert.Thumbprint -TenantId $tenantID -ApplicationId $applicationID
However, the SubscriptionId/SubscriptionName attributes of this authentication display as blank:
Environment : AzureCloud
Account : ********************
TenantId : ********************
SubscriptionId :
SubscriptionName :
CurrentStorageAccount :
Subsquently, this command works!
$secret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $keyName
What is confusing to me is that I am able to retrieve a AzureKeyVaultSecret in my DEV subscription, but I do not understand how this cmdlet knows which of my subscriptions to use??? I intend to create the same vault in my PROD subscription, but first need to understand how this ServicePrincipal/Certificate authentication knows which subscription to pull from and/or how to manipulate it?
I can say that when I created the App/ServicePrincipal, I logged in specifying the "DEV" subscription like so:
$subscriptionName = "DEV"
$user = "user#company.com"
$password = "*****"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($user, $securePassword)
Login-AzureRmAccount -Credential $credential -SubscriptionName $subscriptionName

Resources