I am using Azure API to create blob storage account.
For my old subscription it works, but after I created a new subscription, and tried to use it, the API fails with error:
The client 'xxx' with object id 'xxx' does not have authorization to perform action 'Microsoft.Storage/storageAccounts/write' over scope '/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxxx' or the scope is invalid. If access was recently granted, please refresh your credentials.
When I try to create it from the UI with that subscription it does work.
How can I solve the issue, so I will be able to use the API also with the new subscription?
Both subscriptions need to be in the same Azure AD directory. If they are not then you are out of luck (but you can move subscriptions between directories).
Click on your new subscription and go to Access Control. Look for your app registration and grant it the appropriate permission against your subscription.
You can also do this at the storage account level if you want to scope the app's permissions to only that resource.
Related
i'm new in Azure. And if the question is stupid don't punish me.
I made an App in Azure to get access to storage blob and key vault.
I used Azure AD tenant(with AD users) and user_impersonation scopes like https://storage.azure.com/user_impersonation and https://vault.azure.net/user_impersonation
All I need from that App is:
Upload file to Blob
Download file from Blob
Delete file from Blob
Generate SAS
Get value of secret from Key Vault.
In Azure AD tenant it works fine. I can request to login.microsoftonline.com enter credentials and get token to my back-end to do all this things listed above.But later customer desided to use custom UX(to hide Microsoft login page) and only one way to get this is to use B2C and local accounts.
I made a B2C tenant like here tutorial-create-tenant
Registered App like here tutorial-register-applications and add Api permissions to Azure Storage from APIs my organization uses tab
Created user-flows like here user-flows
All local users in one group with Owner policy
Using this request i got a token
https:/<domain_name>.b2clogin.com/<domain_name>.onmicrosoft.com/oauth2/v2.0/authorize?
p=B2C_1_signin&
client_id=<App_ID>&
nonce=defaultNonce&
redirect_uri=https%3A%2F%2Fjwt.ms%2F& // https://jwt.ms/
scope=https%3A%2F%2Fstorage.azure.com%2Fuser_impersonation& // https://storage.azure.com/user_impersonation
response_type=token&
prompt=login
In decoded token claim "aud" has id the same as Azure Storage API from APIs my organization uses tab when I register App, "scp" is "user_impersonation". But using this token i can't get access to storage using Postman (I use it as Bearer token)
For example GET request to https://.blob.core.windows.net/?comp=list must return json with list of containers(and in Azure AD it work) but with this token got an error
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:49873755-401e-0065-0dd0-386211000000
Time:2020-06-02T11:24:57.3079213Z</Message>
<AuthenticationErrorDetail>Signature validation failed. Signature key not found.</AuthenticationErrorDetail>
</Error>
May be I need to add additional Api access to Storage app some how?
What should I set up yet?
Or maybe there is a way to connect Ad B2C tenant to AD tenant?
Will appreciate any help.
Upd: as #juunas noiced I had differernt subscriptions for B2C tenant and Storage account. Now b2c and storage in one sub(i created new b2c, link subscription and move it inside b2c tenant, after that i made a storage account in moved subscription)
But the problem still exist.
I tried to change scope in request. On Api Permissions page in Azure Storage user_impersonation option you can see link like
https://*.dfs.core.windows.net/user_impersonation
when I used this link as a scope I've got an error
AADB2C90117: The scope
'https://*.dfs.core.windows.net/user_impersonation'
provided in the request is not supported.
After replacing of asterisk by name of storage account in link I've got the next message
AADB2C90205: This application does not have sufficient permissions
against this web resource to perform the operation.
It looks like I need to get additional permissions for App?
Does it make sense? Or trying to get access to particular storage account is wrong?
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.
Moved azure subscription from active directory AD1 to active directory AD2. Now tasks start failing as previous ARM endpoint (via Auto SPN) got created with old endpoint details. Hence tasks are not able to generate right access token.
Error Message
The access token is from the wrong issuer 'https://sts.windows.net/***/'. It must match the tenant 'https://sts.windows.net/<TenantIdNew>/' associated with this subscription.
Please use the authority (URL) 'https://login.windows.net/<TenantIdNew>' to get the token.
Note, if the subscription is transferred to another tenant there is no impact to the services, but information about new tenant could take time to propagate (up to an hour). If you just transferred your subscription and see this error message, please try back later. (CODE: 401)
Additional Questions
How do I find which tenant my VSTS is backing? Where can I find it?
How do I find which tenant my subscription is backed? Where can I find it?
Is it possible to re-use service endpoints created earlier (with AD1) after the move to AD2?
Is it possible to update the tenant Id (via REST API) in existing service endpoints after the move to AD2?
Will MSI based service endpoints be broken or will they be available after move to AD2?
There are the following possible solutions:
Change your backed active directory by AzureDevOps account from AD1 to AD2
Build trust relationship b/w active directory AD1 and AD2.
First, create SPN via script and then create a manual endpoint with details provided by the script.
Answers to additional Questions
How do I find which tenant my VSTS is backing? Where can I find it?
Go AzureDevOps account > Organization > Azure Active Directory
How do I find which tenant my subscription is backed? Where can I find it?
Go to Azure portal > Subscriptions > select your subscription > overview
Is it possible to re-use service endpoints created earlier (with AD1) after the move to AD2?
Yes.
First Let's understand what a service endpoint does internally.
Creates an app in AD.
Assign permission to it over the subscription.
Now let's go through our case,
You created a service connection with AD1, means AD app app1 is being created in active directory AD1 and assigned permission on subscription S
You moved subscription S to another active directory AD2, but AD app app1 still resides in previous active directory AD1.
To re-use existing service endpoint you have to update SPN Id, SPN key and tenant Id in the service endpoint.
In case of manual service connection, it's easy to update via UI but in case of auto SPN flow, you have to update the above mentioned fields via REST API.
Is it possible to update the tenant Id (via REST API) in existing service endpoints after the move to AD2?
Yes.
Get all endpoints
REQUEST TYPE - GET
https://<accountName>.visualstudio.com/<ProjectName>/_apis/distributedtask/serviceendpoints?api-version=3.2-preview.1
Get a specific endpoint
REQUEST TYPE - GET
https://<accountName>.visualstudio.com/<ProjectID>/_apis/distributedtask/serviceendpoints/<SERVICE_ENDPOINT_ID>?api-version=3.2-preview.1
Now update tenant Id in response and use it as a body in update endpoint REST API.
Update endpoint
REQUEST TYPE - PUT
https://<accountName>.visualstudio.com/<ProjectID>/_apis/distributedtask/serviceendpoints/<SERVICE_ENDPOINT_ID>?api-version=3.2-preview.1
Will MSI based service endpoints be broken or will they be available after move to AD2?
Yes, you only need to update the tenant Id in service connection.
We have lot of references in the web to fetch the all AAD users but i need to fetch all the users from an Azure subscription.
I have created an App in Azure active directory and added that App to the Subscription then used ClinetId and Client secret to create the AuthToken. Used the created auth token to hit the below REST API(an Azure resource management REST API)
https://management.azure.com/subscriptions/{my subscription id}/resourceGroups/{My resource group name}/providers/Microsoft.ApiManagement/service/{my Azure managment API Name}/users?api-version=2018-01-01
But this rest API is retrieving only one User, which is mine.
Here i want to retrieve all the users in a subscription.
Here is the MSDN url i used as reference.
Please can any one help me on this.
It is not because of the free sub.
Does your app have the permission to the Graph API (to read users)? If you try the same user via PS console and you get the same output then its not your code but permissions (Good read on PS https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ff730967(v=technet.10) ).
On the graph api here https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-graph-api-quickstart
You can find the answer for this question in below thread.
Removing the user from Azure subscription programtically(C#)
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.