AzureDevOps - Failed to fetch access token after moving subscription to different AD - azure

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.

Related

Get All subscriptions per tenant in azure

I want to have a Logic App that gets per tenant all its subscriptions.
I understand that there is a rest API for that purpose:
GET https://management.azure.com/subscriptions?api-version=2020-01-01
as mentioned in the Subscriptions - List documentation.
Two questions:
Where do I specify here for which tenant I want to get the list of subscriptions?
I understand that I need a token in order to get this data, but how do I get this token and from where exactly?
As it states in the documentation you linked to, the API call uses the Azure Active Directory OAuth2 Flow. This means it will get the subscriptions from the logged in user's tenant.
However, there's a Logic App connector to connect to Azure Resource Manager. And that connector has an action called List subscriptions.
When you add it, you create a service connection to Azure by logging in, which can be used for subsequent requests.
This sample implementation does the trick: it gets the subscriptions and returns them from the Logic App.

Azure API doesn't work for one subscription

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.

Using service principals / apps for OAuth2 authentication within Azure Data Factory

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.

devops: materialize Azure AD Security group

I'm trying to add an Azure AD security group (without mail/upn) to a Devops Permission with the rest api.
Is this possible?
In this page https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/users/create?view=azure-devops-rest-6.0#add-an-aad-user-by-oid I see the following
The body of the request must be a derived type of GraphUserCreationContext:
GraphUserMailAddressCreationContext - Create a new user using the mail address as a reference to an existing user from an external AD or AAD backed provider.
GraphUserOriginIdCreationContext - Create a new user using the OriginID as a reference to an existing user from an externalAD or AAD backed provider.
GraphUserPrincipalNameCreationContext - Create a new user using the principal name as a reference to an existing user from an external AD or AAD backed provider.
The groups are created as universal security groups on our onprem AD, and synced to Azure AD.
I don't have a mailadress nor a UPN; but I can't find more info on what exactly OriginID is.
Edit; OriginID seems to work for a user, but not for a group.
To add an Azure AD group to Azure DevOps, you need to use the REST API Groups - Create.
POST https://vssps.dev.azure.com/{organization}/_apis/graph/groups?api-version=6.0-preview.1
Click this link for an example. The originId in the request body is the Object id of your Azure AD group.
The REST API link your provide in the question is to create a user, not a group.
I ended up connecting with the Azure commandlets to get my ObjectID, as #jane-ma-msft suggested.

Retrieving all the users in an Azure subscription

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#)

Resources