What is Azure Service Principal? - azure

My requirement is simple. I want to login to Azure through my shell script in non-interactive mode, but "az login -u username -p password" command gives the following error:
Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS70002: Error validating credentials. : SAML token is invalid. : The element with ID 'xxxxxx' was either unsigned or the signature was invalid.
Some site told me to create a service principal. Now my question is, what is a service principal, and how do I create a service principal so that I can execute my commands (for creating different resources like app gateway) from my shell script?

Please refer to this official document.
An Azure service principal is a security identity used by user-created
apps, services, and automation tools to access specific Azure
resources. Think of it as a 'user identity' (login and password or
certificate) with a specific role, and tightly controlled permissions
to access your resources. It only needs to be able to do specific
things, unlike a general user identity. It improves security if you
only grant it the minimum permissions level needed to perform its
management tasks.
If you want to create a new service principal(sp) with Azure CLi 2.0. You could login with your Azure AD user. Then execute following command.
az ad sp create-for-rbac --name {appId} --password "{strong password}"
The result like below:
{
"appId": "a487e0c1-82af-47d9-9a0b-af184eb87646d",
"displayName": "MyDemoWebApp",
"name": "http://MyDemoWebApp",
"password": {strong password},
"tenant": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
appId is your login user, password is login password.
After the sp is created, you also need give it Contributor role, then you could manage your Azure resource.
az role assignment create --assignee <objectID> --role Contributor
Now, you could login in non interctive mode with following command.
az login --service-principal -u <appid> --password {password-or-path-to-cert} --tenant {tenant}

Service principal just work as an impersonation for user in Azure AD. Refer - https://sanganakauthority.blogspot.com/2019/04/how-to-create-service-principal-or-app.html
Using this you can perform any type of management task against Azure using REST APIs. This way you avoid need of providing credentials in pop up and hence help to automate things in Azure using REST APIs.

Here your go: Use portal to create an Azure Active Directory application and service principal that can access resources.
When you have an application that needs to access or modify resources, you must set up an Azure Active Directory (AD) application and assign the required permissions to it. This approach is preferable to running the app under your own credentials because:
You can assign permissions to the app identity that are different than your own permissions. Typically, these permissions are restricted to exactly what the app needs to do.
You do not have to change the app's credentials if your responsibilities change.
You can use a certificate to automate authentication when executing an unattended script.

Related

Azure AD App Registration secret manipulation

I'm working with an app registration that has a secret defined. Via PowerShell I am able to get the credential, but not the secret value. Function used is Get-AzADAppCredential This is expected behavior, no issue here.
To renew the secret I run two functions Remove-AzADAppCredential and New-AzADAppCredential.
I run these PowerShell cmdlets via a DevOps pipeline and use a service connection with permissions in Azure portal.
I noticed that, when we create a service connection from DevOps to Azure, the service principal gets the role Cloud application administrator automatically assigned.
This role includes the permission "microsoft.directory/applications/credentials/update".
So the above (remove + new) should work, but it does not...
DevOps returns an error:
Az.MSGraph.internal\Remove-AzADApplicationPassword : Insufficient privileges to complete the operation.
Az.MSGraph.internal\Add-AzADApplicationPassword : Insufficient privileges to complete the operation.
PS. Using Az.Resources version 5.4.0 when working with the PowerShell functions.
Anyone got any idea what I'm missing?
Thanks.
Insufficient privileges to complete the operation.
The error comes when the user doesn't have sufficient privileges in AAD and doesn't have Write permission for the selected Azure Subscription.
Note: If you have Cloud application administrator privileges of the user, this role grants the ability to manage application credentials. Users assigned this role can add credentials to an application and use those credentials to impersonate the application’s identity. If the application’s identity has been granted access to a resource, such as the ability to create or update User or other objects, then a user assigned to this role could perform those actions while impersonating the application.
Make sure to check once if you have Global Administrator Access. If you have the access you can able to Modify the secret.
Users who are assigned to the Global administrator role can read and modify every administrative setting in your Azure AD organization.
The permission issue may happen due to
The user has only guest permission in the directory
The user is not authorized to the add applications in the directory
Refer here for detailed information
To be able to update a secret on an app registration, through DevOps, using a service principal, with minimal permissions, first make the service connection owner on that random app registration.
Next, add the Application.ReadWrite.OwnedBy application API permission on the app registration that's linked to the enterprise application. Not on the app registration where the service principal was made owner.
Than renewing the secret works fine.
It remains a question though why the role Cloud application administrator isn't sufficient because microsoft.directory/applications/credentials/update is included in that role, and that should also be enough.

How to grant permission scope to an Azure App in Powershell?

I am updating a Powershell script to replace use of Azure CLI calls with PowerShell commands. The Powershell script creates a number of App Registrations in an Azure tenant, adds permissions to them, and then grants access to those permissions.
I am finding it difficult to replace the CLI calls granting access. Typically these calls grant a service principal access with a scope or scopes, e.g.
az ad app permission grant --id $app.appId --api 00000003-0000-0000-c000-000000000000 --scope "offline_access openid"
I see no way to do this with the Cmdlets in the Azure Resources Module, and have not been to find a direct equivalent in the Azure Graph API. The nearest thing I have found in the Graph API is an endpoint for granting an App Role Assignment (https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignedto?view=graph-rest-1.0&tabs=powershell) but that addresses a different problem, assigning roles rather than scopes.
I'm pretty new to Azure development, but I've been knocking my head off this one for a few days now, so any advice would be appreciated!
Edit: Adding an example of a permission I'd like to be able to grant where Admin Consent is not required.
We have tested this in our local environment it is working fine. Below statements are based on our analysis.
You can use the below PowerShell cmdlet to add a permission to the app registration.
Add-AzADAppPermission -ObjectId "<objectID>" -ApiId "00000003-0000-0000-c000-000000000000" -PermissionId "<PermissionId>" -Type "<role(ApplicationPermissions),Scope(DelagatedPermissions)"
Here is the sample Output screenshot for reference:
As per the Current documentation, User needs to grant consent via Azure Portal if the permission requires admin consent because Azure PowerShell doesn't support it yet.
Note :
Application permissions under the appRoles property correspond to Role in -Type. Delegated permissions under the oauth2Permissions property correspond to Scope in -Type.

Call Databricks API from DevOps Pipeline using Service principal

I want to be able to call Databricks API from DevOps pipeline. I can do this usint personal access token for my account, however I want to make API calls user independent so I wanted to use Service principal (App registration). I followed this tutorial https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/service-prin-aad-token to create access token for the service principal, however I have 2 issues:
such generated token expires in 1 hour - is there any elegant was to automatically refresh it?
even when calling the ADB API using this token I get 403 unauthorized - is there anything else I should do? The app registration has Contributor role for the ADB service.
EDIT: Added API Permission for the AzureDatabricks in App registration and Granted admin consent, however still no luck.
So I found 3 possible solutions at the end.
Generate access token for service principal, generate management service token for service principal and use both of these to access Databricks API - reference
Use access token and management token to generate Databricks Personal access token for the service principal using Databricks Token API, then you can use it for Databricks CLI - reference
Authenticate to Databricks via CLI using AAD token (reference and Databricks CLI help):
az login --service-principal -u <app-id> -p <app-password> --tenant <tenant-id>
token_response=$(az account get-access-token --resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d)
export DATABRICKS_AAD_TOKEN=$(jq .accessToken -r <<< "$token_response")
databricks configure --host https://<adb-url> --aad-token
such generated token expires in 1 hour - is there any elegant was to
automatically refresh it?
No, client credentials flow doesn't support refresh token. You can try to get a new token, please refer to this issue.
even when calling the ADB API using this token I get 403 unauthorized - is there anything else I should do? The app
registration has User role for the ADB service.
Make sure your service principal have a Contributor role assigned.
There are two kinds of resource in different situations.
API access for service principals that are Azure Databricks workspace users and admins
resource=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d
API access for service principals that are not workspace users
resource=https://management.core.windows.net/

Azure login for tenant failing for Az app/principal with No subscription found message

I have an azure account called account1 where I create an App/Principal that is across tenants visibility. I then give it some API permissions. I have another azure account account2 where I need to access resources using this app. I complete the admin consent flow for account2 by going to the following url
https://login.microsoftonline.com/<account2 domain>/adminconsent?client_id=cid1
The flow finishes and I get the tenant id back as say tid2. When I try to login from command prompt with app creds to access account2, I get an error
(it was working before and suddenly stopped working)
az login --service-principal --username cid1 --password "pwd" --tenant tid2
Error:
No subscriptions found for cid1.
EDIT: In the chat we found the issue had something to do with the terminal app used on Mac. After using the native terminal, the login was successful and the other terminal app worked as well.
You need to assign RBAC roles to the service principal in account 2.
You can do that through the Access Control (IAM) tab of the subscription by adding the necessary role to the app.
This would happen if you created a service principal and granted it access permissions to specific azure resources within a susbcription, in which case your sp will not have access to whole susbcription. I had same issue as you were facing until I tried flag "--allow-no-subscriptions". Following worked fine for me from within a container to read and update a certificate from/to azure key vault, where I granted sp read,list and import permissions.
az login --allow-no-subscriptions --service-principal --username cid1 --password "pwd" --tenant tid2

Azure KeyVault Managed Storage Account

I am trying to implement KeyVault managed Storage Account in Azure to rotate storage keys using KeyVault. I did follow the documentation, which uses both "ServicePrincipalID" and "UserPrincipalID", but in my case i am provisioning my resources and implementing all the steps involved using my service principal (as we deploy using VSTS with service principal) and using "ServicePrincipalID" as ObjectID in place of "UserPrincipalID" (as there is no user intervention during provisioning and post-provisioning process). I did give my service principal "Owner" role and all required permissions for keyvault to access storage. But when i do "Add-AzureKeyVaultManagedStorageAccount" i get the below error which says "KeyVault is unable to perform the action on behalf of the caller". So i am not sure what access i am still missing, even after making my principal as Owner. Please find my screenshots below for more details. Would be glad to hear any suggestions to cross this hurdle.
Error
KeyVault details
Thanks
Chaitanya Alladi.
i get the below error which says "KeyVault is unable to perform the action on behalf of the caller". So i am not sure what access i am still missing, even after making my principal as Owner.
Unfortunly, we can't do that with service principle now.
AAD doesn't support get OBO(OnBehalfOf) token for service principle caller tokens.
We need to use the user credentials instead of Service Principal credentials. There are some operations that are only possible on behalf of the user and not Service Principal when it comes to storage account keys as of now.

Resources