azure App registration using powershell does not create a service principal - azure

when we create an azure ad app registration from the azure portal the service principal is automatically created, and given a contributors role, how do we achieve the same using PowerShell ?
I tried running the following the command the app is created but no service principal is created, and there are no parameters for configuring a service principle
New-AzADApplication -DisplayName "NewApplication" -HomePage "http://www.microsoft.com" -IdentifierUris "http://NewApplication"
what i am looking for is to create the following using powershell, is this possible ?
AzureADAppregistration + ServicePrincipal
Create and get the client secret
Thanks

Try this:
#set your secret here.
$secretTextValue = "abcdefg1234567890"
$secret = ConvertTo-SecureString -String $secretTextValue -AsPlainText
$app = New-AzADApplication -DisplayName "NewApplication" -HomePage "http://www.microsoft.com" -IdentifierUris "http://NewApplication"
New-AzADAppCredential -ObjectId $app.ObjectId -Password $secret -EndDate (Get-Date).AddMonths(6)
#azure will assign contributor role of current subscription to this SP
New-AzADServicePrincipal -ApplicationId $app.ApplicationId
Result:

Related

Adding key vault access permissions while preserving existing ones

I have an Azure PowerShell task in my pipeline, in which I need to import a certificate to a key vault. Before doing that, I need to assign Import certificate permission to the current service principal. However, this service principal might already have existing certificate permissions (e.g. Get, List) from other tasks in this or other pipelines. If I use Set-AzKeyVaultAccessPolicy, it will remove these other permissions. Is there a way of preserving these permissions, and just adding some new ones?
$spId = (Get-AzContext).Account.Id;
Set-AzKeyVaultAccessPolicy -VaultName $kv -ServicePrincipalName $spId -PermissionsToCertificates Import
Import-AzKeyVaultCertificate -VaultName $kv …
There is no direct way to add the new permission, your option is to get the old permissions as a list, add the new permission to it, then set all the permissions again.
The sample works for me:
$spId = (Get-AzContext).Account.Id
$objectid = (Get-AzADServicePrincipal -ApplicationId $spId).Id
$kv = Get-AzKeyVault -ResourceGroupName <group-name> -VaultName joykeyvault
$cerpermission = ($kv.AccessPolicies | Where-Object {$_.ObjectId -eq $objectid}).PermissionsToCertificates
$cerpermission += "Import"
Set-AzKeyVaultAccessPolicy -VaultName joykeyvault -ObjectId $objectid -BypassObjectIdValidation -PermissionsToCertificates $cerpermission
Note: The parameters in the last line is important, if your service principal used in the devops service connection does not have the permission to list service principals in your AAD tenant, please use -ObjectId $objectid -BypassObjectIdValidation instead of -ServicePrincipalName $spId, otherwise you will get an error.

How to create Service Principal of Multi-tenant Application

I have created new Azure AAD Application with Multi-tenant enabled. But i Couldn't find App in another tenant ID. When i try to create a Service Principal of above App ID in another Tenant.It is failing with error "New-AzureRmADServicePrincipal : When using this permission, the backing application of the service principal being created must in the local tenant" . Has anyone experience such issue.
$StartDate = [DateTime]::UtcNow
$EndDate = [DateTime]::UtcNow.AddYears(3)
$secureString = convertto-securestring "XXXXXXXXX" -asplaintext -force
New-AzureRmADServicePrincipal -ApplicationId "XXXXXXXXXX" -Password $secureString -StartDate $StartDate -EndDate $EndDate
I fixed my question using following PS command
Connect-AzureAD -TenantId '<TargetTenant>'
New-AzureADServicePrincipal -AppId 'ThirdPartyAppID'
I couldn't reproduce this error. New-AzureRmADServicePrincipal -ApplicationId "XXXXXXXXXX" works fine for me to create the enterprise app in another tenant.
If you want to add the multi-tenant app into another tenant, there is another way. You can have a try with the admin consent.
I assume that your app is registered in tenant_x and want to add it into tenant_y.
You can redirect the user to the Microsoft identity platform admin consent endpoint.
GET https://login.microsoftonline.com/{tenant_y}/v2.0/adminconsent?
client_id={client id}
&state=12345
&redirect_uri={redirect_uri}
&scope=
https://graph.microsoft.com/calendars.read
https://graph.microsoft.com/mail.send
Access it in a broswer and log in with an admin account of tenant_y to do the admin consent. After that the app will be added into tenant_y.

How to get thumbprint of the cert associated with a service principal in AzureAD when the sp is created independently without App and Cred

I have a service principal that I've creating using below powershell.
$sp3 = New-AzureRmADServicePrincipal `
-DisplayName "<service-principal-name>" `
-CertValue $certValue3 `
-EndDate ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($cert3.Certificate.GetExpirationDateString(), [System.TimeZoneInfo]::Local.Id, 'GMT Standard Time'))
where certValue3 is Base64String RawCertData. This service principal works fine and I am able to get a token when using the cert.
Once service principal is created in Azure AD, how do I see thumbprint of the certificate associated with the service principal using Powershell?
I've tried this, but I get Forbidden when I try to execute Get-AzureADApplicationKeyCredential
I also checked the manifest in Azure Portal under the service principal that gets created under Azure Active Directory → App Registrations → <service-principal-name> → Manifest, but the keyCredentials node is empty
"keyCredentials": [],
Please note that when I create an application using New-AzureRmADApplication followed by credential New-AzureRmADAppCredential and then New-AzureRmADServicePrincipal, then I see the keyCredentials with customKeyIdentifier set to the certificate thumbprint. Sample script below -
$adapp = New-AzureRmADApplication -DisplayName "<application-name>" `
-HomePage "<home-page-url>" `
-IdentifierUris "<identifier-url>" `
-CertValue $certValue `
-StartDate ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($cert.Certificate.GetEffectiveDateString(), [System.TimeZoneInfo]::Local.Id, 'GMT Standard Time')) `
-EndDate ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($cert.Certificate.GetExpirationDateString(), [System.TimeZoneInfo]::Local.Id, 'GMT Standard Time'))
New-AzureRmADAppCredential -ApplicationId $adapp.ApplicationId -CertValue $certValue2
$sp2 = New-AzureRmADServicePrincipal -ApplicationId $adapp.ApplicationId -DisplayName "<application-name>"
How to get thumbprint of the certificate associated with a service principal in Azure AD using powershell when the service principal is created independently without AzureRmADApplication and AzureRmADAppCredential?
According to my test, we can use the following Azure AD Graph API to get the key credentials of the sp. The customKeyIdentifier in KeyCredential is the thumbprint of the certificate
GET https://graph.windows.net/<your teanant id>/servicePrincipals/<your sp object id>/keyCredentials?api-version=1.6
For example
Create sp and get thumbprint
$tenantId ="<tenant id>"
#use the goabl admin account to login
Connect-AzureRmAccount -Tenant $tenantId
$certificateObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificateObject.Import("E:\Cert\examplecert.pfx","Password0123!", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet)
Write-Host "the thumbrint of cert"
$certificateObject.Thumbprint
$keyValue = [System.Convert]::ToBase64String($certificateObject.GetRawCertData())
$sp =New-AzureRmADServicePrincipal -DisplayName "jimtestsample" -CertValue $keyValue -EndDate $endDate
$context=Get-AzureRmContext
$token=$context.TokenCache.ReadItems() |Where-Object { ($_.TenantId -eq $tenantId) -and ($_.Resource -eq "https://graph.windows.net/") }
$accesstoken=$token.AccessToken
$url = "https://graph.windows.net/$tenantId/servicePrincipals/"+$sp.Id+"/keyCredentials?api-version=1.6"
$keyCreds = Invoke-RestMethod -Uri $url -Method Get -Headers #{"Authorization" = "Bearer $accesstoken"}
Write-Host "--------------------------------------------"
$keyCreds.value | Select-Object customKeyIdentifier
I test your command, it should work. When using New-AzADServicePrincipal to create the service principal, it will create an AD App(i.e. App Registration) for you automatically, and the certificate will also appear in the Certificates & secrets of your AD App.
In my sample, I use the new Az module, for the old AzureRm module which you used, it should also work(Not completely sure, I recommend you to use the new Az module, because the AzureRm module has been deprecated and will not be updated). And make sure you are looking into the correct AD App in the portal, because the DisplayName of the AD App could be repeated.
$cert=New-SelfSignedCertificate -Subject "CN=TodoListDaemonWithCert" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature
$bin = $cert.RawData
$base64Value = [System.Convert]::ToBase64String($bin)
New-AzADServicePrincipal -DisplayName joy134 -CertValue $base64Value
Check in the portal:
Then you can use this way you have tried, to fix the Forbidden error, your account should at least be the Owner of the AD App, or if your account has an admin role in the tenant e.g. Application administrator, Groups administrator, it will also work.
$CustomKeyIdentifier = (Get-AzureADApplicationKeyCredential -ObjectId "<object-id>").CustomKeyIdentifier
$Thumbprint = [System.Convert]::ToBase64String($CustomKeyIdentifier)
Besides, you should note the different command combinations will lead to different results, see this link. So when you test it, I recommend you to use different values of the parameters.

Authenticate to Azure Keyvault using Certificate and get secret

I am looking for an example of using a certificate to authenticate to the keyvault, and then get a secret -- all in PowerShell (already have operational C#).
Have an app in AD for accessing Keyvault.
First, make sure your AD App(service principal) has the correct permission in your keyvault -> Access policies, in your case, it should be Get and List secret permissions.
Then get values for signing in and try the command as below.
Connect-AzAccount -CertificateThumbprint "<certificate Thumbprint>" -ApplicationId "<AD App applicationid(clientid)>" -Tenant "<tenant id>" -ServicePrincipal
Get-AzKeyVaultSecret -VaultName "<keyvault name>" -Name "<secret name>" -Version "<secret version>" | ConvertTo-Json

Azure Runbook can't modify Azure AD application

I'm trying to execute this in an Azure Automation runbook
$app = Get-AzureADApplication -ObjectId $ApplicationId
$appRole = New-Object Microsoft.Open.AzureAD.Model.AppRole
$appRole.AllowedMemberTypes = New-Object System.Collections.Generic.List[string]
$appRole.AllowedMemberTypes.Add("User");
$appRole.DisplayName = $TenantName + " Users"
$appRole.Id = New-Guid
$appRole.IsEnabled = $true
$appRole.Description = "Users of the tenant"
$appRole.Value = $TenantName
$app.AppRoles.Add($appRole)
Set-AzureADApplication -ObjectId $ApplicationId -AppRoles $app.AppRoles
Reading the application works fine, when I print the app variable I can see it's the correct application. Executing the script from my own machine also gives no errors. Yet executing it via the runbook gives me:
Set-AzureADApplication : Error occurred while executing SetApplication
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
HttpResponseStatus: Completed
By now I have given the automation application registration in Azure AD all rights of the Active Directory API. I have also clicked "Grant Permissions". I know it's the correct app registration because the script also invites an external user, when I gave the correct rights on the "Graph Api" that started to work.
I tried out your exact script in a run book and to make it work, I had to add code to "Login as the service principal" just before your PowerShell script. You can see more details here:
Using Azure Run As Account in Azure Automation
On the permissions front, I only gave 1 application permission (i.e. "Read and write all applications") and then clicked "Grant Permissions" as it did need Admin consent. Steps were done by a user with "Global administrator" directory role in my Azure AD.
Here is my final working PowerShell script (copied from edit runbook):
# Get Azure Run As Connection Name
$connectionName = "AzureRunAsConnection"
# Get the Service Principal connection details for the Connection name
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
# Logging in to Azure AD with Service Principal
"Logging in to Azure AD..."
Connect-AzureAD -TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
$ApplicationId = "redacted-xxxx-xxxx-xxxx-xxxxxxxe3"
$TenantName = "RohitTenant"
$app = Get-AzureADApplication -ObjectId $ApplicationId
$appRole = New-Object Microsoft.Open.AzureAD.Model.AppRole
$appRole.AllowedMemberTypes = New-Object System.Collections.Generic.List[string]
$appRole.AllowedMemberTypes.Add("User");
$appRole.DisplayName = $TenantName + " Users"
$appRole.Id = New-Guid
$appRole.IsEnabled = $true
$appRole.Description = "Users of the tenant"
$appRole.Value = $TenantName
$app.AppRoles.Add($appRole)
Set-AzureADApplication -ObjectId $ApplicationId -AppRoles $app.AppRoles
Here are screenshots from some other important steps that I followed, which you may or may not have done already.
Create Azure Run As account while creating automation account
Make sure account settings for your automation account has the run as accounts now.
Find the App Registration created for Run as Account and give it permission to read and write all Azure AD applications.

Resources