I want to get the health and other resource details of a particular Azure Account or Subscription using these API's
https://learn.microsoft.com/en-us/rest/api/resourcehealth/availabilitystatuses/listbysubscriptionid
When i do TryIt on the web page it works, but If i want to do it using say PostMan or programatically, how do i generate the Authorization key, I have seen docs to create Authorization Key using "App Registrations", but i dont have any WebApp here, All i want to do is get the details of a particular account or subscription using Azure provided API calls and using any AD user with proper roles for authentication.
This link provides some details but then i dont have a clientid here, since i dont have any webapp
https://msdn.microsoft.com/en-gb/library/azure/dn645543.aspx
Please let me know if anyone has tried doing this.
Thanks
You have to register an app in Azure AD.
This does not need to be an actual "Web app".
You are registering a service principal (you can think of it as a service account).
After registering the app (with type Web App/API), generate a Key for it.
Write down the Application Id (Client Id) and the key (Client Secret).
Then give the service principal access through the Access Control (IAM) section on the subscription/resource group/resource where you want to give the app access to.
You can then follow the instructions here to generate the access token: https://msdn.microsoft.com/en-gb/library/azure/dn645543.aspx.
Remember to use https://management.azure.com/ as the resource since you are calling the ARM API.
Related
We aim to collect data from the Azure Management APIs. These APIs provide information on the resources we have running in Azure, the consumed budget, etc (example). Following our design choices, we prefer to exclusively use Azure Data Factory to make the HTTP requests and store the data into our data lakes. This is fairly obvious, using the REST linked service. However, we struggle to correctly set up the OAuth2 authentication dance with this method.
Our first idea was to store the token and the refresh token within the Azure Key Vault. A series of HTTP requests within the pipeline would then test whether the token is still valid or otherwise use the refresh token to get a new token. The downside to this approach is that the token within the Azure Key Vault is never updated, when needed, and that the logic becomes more complex.
Alternatively, we were trying to set up the authorization through combination of a registered app and service principal to our Azure AD account. The REST linked service within Data Factory can be created with a service principal, which would then handle most of the information of the scope and consent. The service principal is also accompanied with a Azure app, which would hold the token etc. Unfortunately, we are unable to make this setup function correctly.
Questions we have:
Can we actually use a service principal / app to store our OAuth2 tokens? If so, will these be automatically refreshed within our app?
How do we assign the correct privileges / authorizations to our app that it can use this (external) API?
Is the additional logic with HTTP calls within Azure Data Factory pipeline needed to update the tokens or can these apps / service principals handle this?
Thank you for your time and help!
It is not a good idea to store the tokens in the keyvault, because they will expire.
In your case, two options for you to use.
Use service principal to auth
Use managed identity to auth(best practice)
Steps to use service principal to auth:
1.Register an application with Azure AD and create a service principal.
2.Get values for signing in and create a new application secret.
3.To call the Azure REST API e.g. Resources - List you mentioned, your service principal needs the RBAC role in your subscription.
Navigate to the Azure portal -> Subscription -> add your service principal as a Contributor/Owner role in the subscription like below.
4.In the linked service, configure it like below, fix them with the values got from step 2.
Don't forget to replace the {subscriptionId} in the Base URL.
https://management.azure.com/subscriptions/{subscriptionId}/resources?api-version=2020-06-01
5.Test the linked service with a copy activity, it works fine.
Steps to use managed identity to auth:
1.Make sure your data factory has enabled the MSI(managed identity), if you create it in the portal or powershell, MSI will be enabled automatically, don't worry about that.
2.Navigate to the Subsctiption in the portal, add the role to the MSI like step 3 in Steps to use service principal to auth, just search for your ADF name in the bar, the MSI is essentially a service principal with the same name of your ADF, which is managed by azure.
3.Then in the linked service, just change it like below.
At last, answer your questions.
Can we actually use a service principal / app to store our OAuth2 tokens? If so, will these be automatically refreshed within our app?
As I mentioned, it is not a good idea, just use the service principal/MSI to auth like the steps above.
How do we assign the correct privileges / authorizations to our app that it can use this (external) API?
To use the Azure REST API, just assign the RBAC roles like above, specify the correct AAD resource e.g. https://management.azure.com in this case.
Is the additional logic with HTTP calls within Azure Data Factory pipeline needed to update the tokens or can these apps / service principals handle this?
No need to do other steps, when you use the configuration above, essentially it will use the client credential flow to get the token in the background for you automatically, then use the token to call the API.
I am trying to find security best practice on App permissions in the context of azure resource management.
Currently, there is only one permission listed for management.azure.com and it is
management.azure.com/user_impersonation (preview). This delegated user impersonation can be a serious problem and it can led to account takeover by malicious app.
Think about a scenario where a user with global administrator role consent and authorize an access token to the app. App can use the token and do whatever it wants with the azure tenant.
Another scenario where a privileged user assigned contributor role to multiple subscriptions. Token authorized by this user can be misused by app to modify resources in any of the subscriptions.
Unlike graph (graph.microsoft.com) api where you can handpick the permission (user.read), resource management api has only one option - user_impersonation!
You may argue why would a privileged user authorize the action but people make mistakes. Our job is to stop or minimize such risk by design. So, what's the best way to allow app to manage resources in azure and minimize the security risk?
Thanks to #juunas for outline and tips. Thanks to #Gaurav for attempting to address my question. I was able to modify azure resources on a subscription without having to grant user_impersonation on management.azure.com api. Here are the steps-
1) Register an app (TestPermissions in my case)
2) Add API Permissions (optional). You don't need to add management.azure.com.
3) Go the Azure resource (subscription, resource group or management group level based on your requirement) and add IAM/RBAC role to the registered app. I assigned Contributor role to TestPermissions app at the subscription level.
4) Request a oauth2 access token following client credential grant flow. You can provide client_id and client_secret in the body of the POST request or you can provide it as Authorization Basic base64 encoded header (that's what I did). Save the access token for future use (until it expires).
Note: I could not add multiple audience (scope) at the same time. If you would like to get a token for graph api, you can request a separate token by changing the scope to http://graph.microsoft.com/.default
5) Use the access token captured in the previous step to interact with azure resource manager. You will need to add the jwt bearer token in the Authorization header (not shown here) on every request to https://management.azure.com. In this example, I am creating a new resource group named TestCreateRG003 to one of my Pay-as-you-go subscription.
6) Let's validate/verify that the resource is created or updated in Azure. Bingo, there they are! App can read/modify (based on RBAC) azure resources w/o having to grant impersonation permission.
It is true that by granting that permission you are allowing the app to act as you, with all the permissions that brings.
The main way I've seen used when limitations are desired is that you:
Register an app in your Azure AD
Grant the service principal the necessary roles (e.g. Reader on specific resources)
Set the tenant id, client id, client secret etc. in the app
This of course requires that the app itself supports this approach.
If it only allows usage through impersonation, then you'll need to either trust or not use it.
Let me see if I can answer this question.
When a user requests a token for management.azure.com, all is done at that time is that the user has permission to execute Azure ARM API. That doesn't mean that they can do everything that's possible with Azure ARM API.
The things that they can do is controlled by Azure Role Based Access Control (RBAC). So if a user is in the Reader role, the token got on behalf of the user can only read information about resources in their Azure Subscription. They will not be allowed to create, update or delete resources in their Azure Subscription.
What you will need to do is grant users appropriate RBAC role to minimize the risks of misuse.
I'm trying to call an Azure function from an API Management instance by using Managed Identity.
I have set a System Managed Identity to my APIM instance.
I have granted the Contributor role to this identity on the Azure Function App.
I have also change the App Service Authentication to AD.
Now I'm trying to call the function from an API.
I have two issues:
First One: when I use the authentication-managed-identity policy to get a token, I got an error when I use the audience https://myfunctionapp.azurewebsites.net. AD tells me that this app is not registered in the tenant
Second: If I retrieve a token for https://management.azure.com, I got a token but I received a 401 Unauthorized error from the Azure Function.
Maybe I'm just trying to get a token on the wrong audience, but unfortunately the audience of functions is not listed in the document (for service bus for example, there is a common URI to use, also for KeyVault, ...).
I think that I probably missed something in the picture...
Thanks.
You need to use the authentication-managed-identity policy to authenticate with a backend service using the managed identity of the API Management service.
https://learn.microsoft.com/en-us/azure/api-management/api-management-authentication-policies#ManagedIdentity
EDIT
1-In your APIM application on Azure AD,
grab the Application ID assigned for enterprise application.
2-Then go to Platform features in your Azure Function App, and click on Authentication / Authorization.
3-Select Azure Active Directory as the authentication provider, and the management mode "express".
4-Back to authentication-managed-identity policy, set the Application ID from step 1 as the resource.
you need to add the url in apim required resource. If you're planning to use delegated flow. To check if the issue is with the url registration you can use the AppId instead. This will at least tell you if the token can be retrieved.
All of the examples on the microsoft azure site having to do with a client application or a service principal having access to azure apis all show the graph apis as the example.
I got those to work, but what I need to do is access the azure service management apis.
If I take an auth token that works for the graph api and use it for the service management api, I get an "Authentication failed." error.
I have added the api permission for "azure service management" and the user_impersonation delegated permission type to my public client app, but the management apis still fail.
Am I going about this all wrong?
I get the idea that the service management apis are authenticated a different way since there's absolutely no mention of using them anywhere in any of the auth examples.
I suppose you are using the client application or a service principal to access azure resources. If so, you are using the client credential flow, but the user_impersonation of Azure Service Management API is a delegated permission, it will not take effect in this flow.
The permission is used to be consent by the user who login to the AD App e.g. in the auth code flow, when it has been consent by the user, the App will be able to represent the user to access the azure resources, note the permission is from the user, not the app. So if you want to use this flow, the user should have a role in the subscription or specific resources.
To access the azure resources with the client application or a service principal, you just need to add the service principal as an RBAC role in the Access control (IAM) of your subscription or specific resource, no need to add any API permission in Azure AD, see this link. Then the service principal will be able to access the azure resources.
When you getting the token to access the azure resources, e.g. call the REST APIs, the scope should be https://management.azure.com/.default, not the https://graph.microsoft.com/.default, you can just get the token for one resource in one time.
Is it possible to gain access to the Azure Management APIs through the client ID and secret for a web app?
I have a web app through which i want to be able to manage Azure. I want to do this using the credentials of the application itself so that the current user does not have to be an azure administrator.
I have given the web app the necessary role on my subscriptions and obtained the access token through the client credentials grant flow in AD but i still get an unauthorized.
This is probably because the azure management API has no permission set other than delegated - the access works fine if i use the authorization code grant flow for the logged in user, but thats not what i want.
So to reiterate, if, given a web app that has RBAC to a subscription and is able to obtain an access token from AD, is there any way, without an interactive user, that the web app is able to use the management API??
Yes, you can obtain a token from AAD for a service principal and use that to manage resources as long as that service principal has all the access you need.
Make sure the token you get has a resource/audience of "https://management.azure.com" and is for the tenantId that the subscription is associated with.
You can also see this article from Brady Gaster that explains how to use Azure AD applications to manage Azure Services from an external app : http://www.bradygaster.com/post/using-windows-azure-active-directory-to-authenticate-the-management-libraries
EDIT : Azure AD supports Service to Service calls using OAuth 2.0 client credentials: https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx
Hope this helps,
Julien