In Azure DevOps Services where can one configure "Administer Permissions" access of a user to some Environment? - azure-devops

When I am trying to change the access of Project Administrators from Reader to Administrator I get
Access Denied: e...4 needs the following permission(s) on the resource Environments/f...6/7 to perform this action: Administer Permissions
Where e...4 corresponds to the id of my user in Azure DevOps Services.
(I am a Project Administrator)
Who can grant these Administer Permissions rights? Is it some kind of Organization Administrator? Where its screen? Documentation? Rest API?
I could not find anything.

If the UI interface is improperly operated, even PCA (Project Collection Administrators) or Organization Owner will also be trapped in the UI interface here (the PCA/ORG Owner may also lose all operating permissions on Env in the UI interface of Env's permission settings.). But REST API can get rid of this situation.
There is a REST API document about this, but there doesn't have a specific document for this.
Roleassignments - Set Role Assignments
You can use f12 to capture the detailed request(UI also based on the above REST API).
I write a python demo to achieve your requirement.
import requests
import json
url = "https://dev.azure.com/<Organization Name>/_apis/securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/<Project ID>_<Env ID>?api-version=5.0-preview.1"
payload = json.dumps([
{
"userId": "<User ID>",
"roleName": "Administrator"
}
])
headers = {
'Authorization': 'Basic <Your Personal Access Token>',
'Content-Type': 'application/json'
}
response = requests.request("PUT", url, headers=headers, data=payload)
print(response.text)
Use List Projects REST API to get the project id.
Use List Users REST API to get the user ID.
Get the Env ID from the Env page url.

Related

Add User as owner of Azure AD Group through REST API

Is it possible to add the owner to the Azure AD group from any REST API?
I think I should have one service principal and I have to generate an access token to do that.
I tried to generate access token and used below query to add owner via Postman.
https://graph.microsoft.com/v1.0/groups/groupid/owners/$ref
But I am facing 403 Forbidden error like below:
{ "error": { "code": "Authorization_RequestDenied", "message":
"Insufficient privileges to complete the operation.", "innerError": {
"date": "2022-06-29T05:42:38", "request-id":
"ebd01257-b890-4b3d-8c22-a1b34738e5a6", "client-request-id":
"ebd01257-b890-4b3d-8c22-a1b34738e5a6" } }
I have granted API permissions like below:
What else permissions are needed? Is there any other way instead of Postman?
You can make use of Microsoft Graph Explorer instead of Postman that doesn't require you to generate access token separately.
You can call the same query by granting below permissions based on your account type:
I tried to reproduce the same in my environment and added the owner to the Azure AD group like below:
After running the above query, owner added successfully like below:
To confirm the above, check the portal whether the owner is added or not like below:
Reference:
Add owners - Microsoft Graph v1.0 | Microsoft Docs

Azure DevOps REST API Error: You are not authorized to create a subscription

Following this documentation I try to make a user following a work item but I receive the following error:
{
"$id": "1",
"innerException": null,
"message": "You are not authorized to create a subscription.",
"typeName": "System.UnauthorizedAccessException, mscorlib",
"typeKey": "UnauthorizedAccessException",
"errorCode": 0,
"eventId": 0
}
The user which tries to create the subscription is an Admin of the project. Both users have access level Basic on organization level. The request uses Basic Auth with PAT with Full Access privileges. The same request succеeds in a different (test) organization but I don't see where is the difference between.
If your users want to set up Global notification, you need to make sure they are members of the Project Collection Administrators group of the organization.
I tested it in the UI, if the user is a project admin but not a member of the PCA group, then he has no permission to perform the operation.
Thanks for providing detail on your user role & licensing, those are usually the first two things to check in cases like these.
Since you're a Project Administrator and have at least a Basic license, I'd recommend checking two things:
If you're using the same PAT when issuing both calls between organizations, make sure that you've chosen "All accessible organizations" when configuring your PAT:
Within your project, head to Project Settings > Service Connections > Security, verify that the user you're attempting to create a service connection with has access. If they don't, add them to the Endpoint Administrators group.

Azure isMemberOf api gives "Insufficient privileges to complete the operation." error when trying to access from Azure Virtual Machine

So my requirement is for the application running on Azure Machine to check if a particular Azure user logged in belongs to an assigned Azure group.
I have enabled Managed Service Identity for the said virtual machine.
MSI
I get the token for the VM by making a call to the metadata service running locally using the following command for the graph resource on the VM:
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fgraph.windows.net' -H Metadata:true
Once I get the token I make a POST request to the graph API of isMemberOf with that newly acquired token:
curl -i -H "Authorization: Bearer <token-value>" -H "Content-Type: application/json" --data '{"groupId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","memberId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}' https://graph.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/isMemberOf?api-version=1.6
I get the following response
{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}
I have assigned the resource group the VM belongs to with IAM as a owner to the resource
Am I missing something that I should have it configured or I am doing something wrong here?
So I dug around a little bit and found that Microsoft prefers us developers using Microsoft Graph rather than the Azure AD Graph
Microsoft Graph vs Azure AD Graph
I found a similar call in Microsoft Graph API to get member of information User list member of call
This call requires the following scope:
Directory.Read.All
Directory.ReadWrite.All
And these are the steps I followed:
Application would need to fetch the token for making the Microsoft graph API call.
POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
HEADER
Content-type: application/x-www-form-urlencoded
BODY:
client_id=&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=&grant_type=client_credentials
RESPONSE:
{
"token_type": "Bearer",
"expires_in": 3600,
"ext_expires_in": 0,
"access_token": "<token-value>"
}
Client secret is generated at app registration time.
Application would make the call to microsoft graph API to fetch
POST https://graph.microsoft.com/v1.0/users/{user-object-id}/checkMemberGroups
HEADERS: Authorization: Bearer {token-value}
Content-Type: application/json
BODY:
{
"groupIds":["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"]
}
RESPONSE:
200 OK - if user belongs to the group
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(Edm.String)",
"value": [
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
]
}
404 Not found - if user does not exist
{
"error": {
"code": "Request_ResourceNotFound",
"message": "Resource 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' does not exist or one of its queried reference-property objects are not present.",
"innerError": {
"request-id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"date": "2018-05-23T02:54:47"
}
}
}
This would help application identify if the Azure user belongs to the assigned group or not.
You are calling Azure AD Graph API, not ARM API.
The IAM blade only gives access rights for the ARM API.
You'll need to assign the necessary rights to the service principal kinda manually.
I actually wrote an article on this a while back: Calling your APIs with Azure AD Managed Service Identity using application permissions.
You will need:
Your MSI service principal object id (you can see how to find this in my article)
The target service principal object id (in this case Azure AD Graph API)
Id of the app permission you want to assign (you can use e.g. https://graphexplorer.azurewebsites.net to find these, they are under appRoles on the service principal)
Once you have these, then you can run this PowerShell cmdlet (using the AAD v2 cmdlets):
Connect-AzureAD
New-AzureADServiceAppRoleAssignment -ObjectId msi-sp-id -Id app-permission-id -PrincipalId msi-sp-id -ResourceId aad-graph-sp-id
Then everything should work.

How to authenticate to Azure Active Directory without user interaction?

I wish to obtain an access token without user interaction in order to automate REST API calls to Azure services (Compute, Network, etc.). In the documentation, several authentication scenarios are listed. The one that fits my use-case the most is "Daemon or Server Application to Web API".
I followed the instructions to request an access token : first I registered an App in my Azure Active Directory. Then I created a key (client_secret parameter) associated to the application ID (client_id parameter). I also obtained the App ID URI (resource parameter). I used all these parameters to create a POST request to the /token endpoint of my Azure AD. However I get the following error message:
{
"code":"InvalidAuthenticationTokenAudience",
"message":"The access token has been obtained from wrong audience or resource 'https://solutionsmosaixsoft.onmicrosoft.com/<APP_ID_URI>'. It should exactly match (including forward slash) with one of the allowed audiences 'https://management.core.windows.net/','https://management.azure.com/'."
}
What am I doing wrong? Am I setting the resource parameter to the wrong value?
The resource parameter tells your application where to get token(identifier of the resource for which the access token is being requested). If you want to get a token to call Azure Service Management API , you could set the resource as https://management.core.windows.net/ .
Edit:
If the APIs you want to call are Microsoft provided APIs , the resource is known ,for example :
Azure Service Management API:https://management.core.windows.net/
Microsoft Graph API :https://graph.microsoft.com/
If you want to call the API apps which your created , you can either use the Client ID or the App ID URI of the resource WebAPI (Find them in the configure tab of the Azure AD application in the Azure Management portal).
You could refer to below link for code samples :
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-code-samples
You need to make a POST request to the token endpoint.
The resource parameter must be the resource URI for the API that you want to access, not yours.
Azure AD Graph API: https://graph.windows.net/
Microsoft Graph API: https://graph.microsoft.com/

TFS REST API: How to "Make requests on behalf of others"?

I want my VSTS extension (installed on-prem TFS2015.3) to be able to do specific requests on behalf of a admin/service account ("Make requests on behalf of others")
Background: I manipulate (WorkItem) Process Template, specifically the GLOBALWORKFLOW (only on team-project level) in my extensions typescript, but the user of the extension in Web Access is NOT a project-admin so he is not allowed to use the function updateWorkItemTypeDefinition() - Non-Project-Admins get "Access denied" even if I gave that custom group every permission available ("Edit project-level-information" permissions for project-level GLOBALWORKFLOWs? Still didn't work for custom groups, only for Project Admin Accounts).
It seems I'm forced to impersonate a project admin /service account which is allowed to change the global workflow in the project
How do I impersonate in extension typescript code on-prem TFS and REST (1. not .NET and 2. without changing to basic auth, saw that solution already somewhere else - but I'm very sure I cannot request that change in my organization)
Thanks for your help
You can impersonate user through vsts-node-api.
There are many function to impersonate user, such as Basic, NTLM, PWA (VSTS) etc..., you can check these function here.
import * as vm from 'vso-node-api';
// your collection url
var collectionUrl = "XXX";
let authHandler = vm.getNtlmHandler("[user name]","[password]","[workstation optional]","[domain optional]");
var connect = new vm.WebApi(collectionUrl, authHandler);
There is the sample that you could refer to.