connect to tfs with different user by using tfs api - powershell

I am trying to run a shellscript program to connect tfs by using tfsapi service.
Jenkins run on logged user but i want to connect tfs with different user (not with windows logged user)
How can i add credential to my powershell code? I use UseDefaultCredentials but need to use different user to connect tfs. how can i do that?
$tfsServerURL = "https://test.tfs.siemens.net/test"
$BuildDefinition = "test.rgs.project"
$URL = "$($tfsServerURL)"
#Get ID of Builddefinition
$buildDefinitionID = (Invoke-RestMethod -Uri ($URL + '/_apis/build/definitions?api-version=2.0&name=' + $BuildDefinition) -Method GET -UseDefaultCredentials).value.id

We can use this official Rest API: Definitions - List to get specific build definition with additional parameter name. And this API supports Oauth2 authentication. However, OAuth 2.0 is not supported on Azure DevOps Server. So we need to use PAT authentication with below least scope: vso.build.
Therefore, if you want to connect tfs with different user using this API, please provide their corresponding PAT, and then below script should work as expected.
$tfsServerURL = "https://test.tfs.siemens.net/test"
$BuildDefinition = "test.rgs.project"
$URL = "$($tfsServerURL)"
$connectionToken="PAT here"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$AzureDevOpsAuthenicationHeader = #{authorization = "Basic $base64AuthInfo"}
#Get ID of Builddefinition
$buildDefinitionID = (Invoke-RestMethod -Uri ($URL + '/_apis/build/definitions?api-version=5.0&name=' + $BuildDefinition) -Method GET -Headers $AzureDevOpsAuthenicationHeader).value[0].id
Write-host $buildDefinitionID

Related

How to access Azure storage account Via Azure windows Virtual Machine Through Managed Identity

I am Trying to Access Azure Storage Account Via Azure Windows VM.
I followed This Microsoft Document Link: https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-datalake
I followed almost All steps That Mentioned In the above Document Link& JWT Access Token also Generated Successfully But My Commands For Uploading/Downloading Files are Throwing Errors.
Error: InvalidAuthenticationInfoAuthentication information is not given in the correct format
Please Correct me if i Used any wrong Commands For Download/Upload Files Via Virtual Machines Through Managed Identity
Commands Used For Generating JSW Token:
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://adlsrg.blob.core.windows.net/' -Method GET -Headers #{Metadata="true"}
$content = $response.Content | ConvertFrom-Json
$AccessToken = $content.access_token
To access storage accounts, you need to generate access token for https://storage.azure.com resource.
I tried to reproduce the same in my environment and got below results:
I created one VM and enabled system-assigned managed identity like below:
Assign Storage Blob Data Contributor role to VM under your storage account as below:
Go to Azure Portal -> Storage accounts -> Your account -> Access Control (IAM) -> Add role assignment
Now connect to VM and run below PowerShell commands to get access token:
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://storage.azure.com' -Method GET -Headers #{Metadata="true"}
$content = $response.Content | ConvertFrom-Json
$AccessToken = $content.access_token
Response:
To upload file to storage account, you can use below script:
$file = "C:\Users\sri\Desktop\hello.txt" #File path
$name = (Get-Item $file).Name
$url="https://sristorageacc5.blob.core.windows.net/sri/$($name)"
$RequestHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$RequestHeader.Add("Authorization", "Bearer $AccessToken")
$RequestHeader.Add("x-ms-version", "2019-02-02")
$RequestHeader.Add("x-ms-blob-type", "BlockBlob")
$result = Invoke-WebRequest -Uri $url -Method Put -Headers $RequestHeader -InFile $file
Response:
When I checked the same in Portal, file uploaded to container successfully like below:

I want to use a System.AccessToken to a rest api call to deploy one release

In Azure Pipeline Releases, I have one task "Azure PowerShell".
This script will do a deployment of another release. In my code, I use a System.AutenticantionToken: "$AzureDevOpsToken = $env:SYSTEM_ACCESSTOKEN" and my headers for a call rest API is:
$basicAuthValue = "Bearer $AzureDevOpsToken"
$headers = #{
Authorization = $basicAuthValue
}
When I ran this code :
$deploymentBody = #{
status = "inProgress"
} | ConvertTo-Json
$urlDeployment = "https://vsrm.dev.azure.com/$Organization/$ProjectName/_apis/Release/releases/$ReleaseId/environments/$EnvironmentId`?api-version=5.1-preview.6"
$deployment = Invoke-WebRequest -Uri $urlDeployment -Method Patch -ContentType "application/json" -Headers $header -UseBasicParsing -Body $deploymentBody
I received an error:
2022-06-01T14:53:15.4901741Z {"$id":"1","customProperties":{"Descriptor":null,"IdentityDisplayName":null,"Token":null,"RequestedPermissions":0,"NamespaceId":"00000000-0000-0000-0000-000000000000"},"innerException":null,"message":"VS402904: Access denied: User e3b793c5-a512-44b7-a704-878e8adb62e9 does not have manage deployments permission. Contact your release manager.","typeName":"Microsoft.VisualStudio.Services.Security.AccessCheckException, Microsoft.VisualStudio.Services.WebApi","typeKey":"AccessCheckException","errorCode":0,"eventId":3000}
This happened when I use a System.AccessToken.
But when I use a Personal Access Token it goes well. But I don't want to use it because I need to put the password in plain sight in the pipeline. So I want to use a System.AccessToken.
In my pipeline, on the agent pool, I have this check: "Allow scripts to access the OAuth token"
Can you help me?
You do not have to use the password plaintext for the personal access token. You can set a variable lets call it PAT on your pipeline with the value as a secret and then inject this variable on your powershell script.
$connectionToken="$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
Then you have to use as a header
-Headers #{authorization = "Basic $base64AuthInfo"}
VS402904: Access denied: User e3b793c5-a512-44b7-a704-878e8adb62e9 does not have manage deployments permission.
Based on the error message, it means that the service account has no access to manage the deployment.
The variable: $(system.accesstoken) will create a token based on the permissions of the service account: {Project Name} Build Service ({Org Name}).
Refer to this doc: Scoped build identities
To solve this issue, you need to navigate to Piplines -> Release -> Security and grant the Manage Deployments permission to the service account: {Project Name} Build Service ({Org Name}).
For example:

Check Groupmembership or jobtitle of Logged On User withouth calling azuread (Get-AzureADUserMembership)

I am building a script with a colleague. This script will show a popup.
We want this popup only to be shown to a certain group of users (teachers and not students). So we want to check group membership of a user. Since this script will be installed on the computer locally and we would not like to install azuread cmdlets on all our computers and also not pass azure ad credentials to the script.
So we where wondering if their is azure-ad info about group membership stored on the computers locally. And also if we can acces it via powershell? (if we could get jobtitle of user that would also be helpfull)
Other ideas are also welcome.
The information related user that you are looking for less likely to be stored locally.
So to meet your requirement, you will have to have some means to communicate with the Azure AD. Your requirement was not to make use of any additional libraries and by using PowerShell.
Graph API can come handy.
To prevent user intervention, you can use App only Graph permission for the App.
You can refer this article to know more App registration, client secret & Application permission :
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
https://learn.microsoft.com/en-us/graph/notifications-integration-app-registration
You consume the graph endpoint from PowerShell and acquire the necessary details of the logged user from the Azure AD without a necessity of external libraries.
#Acquiring the graph token
$web="https://login.microsoftonline.com/<TENANT ID>/oauth2/v2.0/token"
$body = "client_id=<CLIENT ID>&scope=https://graph.microsoft.com/.default&client_secret=<CLIENTSECRET>&grant_type=client_credentials"
$response = Invoke-WebRequest $web -Body $body -Method Post
$token = ($response | ConvertFrom-Json).access_token
#Getting the logged username that will be used in the graph api
$upn = $env:USERNAME + "#" + $env:USERDNSDOMAIN
#building the authorization header
$header = #{"Authorization" = " Bearer $token"}
#gettting the user details
$content = Invoke-WebRequest "https://graph.microsoft.com/v1.0/users/$upn" -Headers $header -Method Get
$details = $content.Content | ConvertFrom-Json
#getting the group membership
$content = Invoke-WebRequest "https://graph.microsoft.com/v1.0/users/$upn/memberof" -Headers $header -Method Get
$groupdetails = ($content.Content | ConvertFrom-Json).value

Authenticate Azure Pipelines Powershell task against Azure DevOps Rest API

Requirements
My requirement is that for my Azure devops release pipeline I want to tag a specific commit with an annotated tag which contains the build number and the date (which is auto-set on an annotated tag).
Proposed solution
My solution to this is to use a the Azure Powershell pipeline task, the one shown here:
The task (ignore what's in the script box right now) will use the Azure Subscription that I have set in order to authenticate towards the Azure DevOps REST API. I have successfully been able to perform the task I want using a personal access token (PAT) but this is not stable long-term for a whole team and I want to use our Azure Subscription.
The problem
My problem is that I'm not sure how to use the authentication of the Azure Subscription correctly. I seem to get some data using Get-AzureRmContext (see current code below) and then I found a GitHub issue which seems to do sort of the same thing. The code gets some kind of OAuth token but using the code below, Azure still returns to me that I need to sign in, so I assume it's not the correct token. I don't understand how things hatch into each other.
Note that my subscription should have all the permissions it needs to do what I want.
Code so far:
Function Get-AccessToken($tenantId) {
$cache = [Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache]::DefaultShared
$cacheItem = $cache.ReadItems() | Where-Object { $_.TenantId -eq $tenantId } | Select-Object -First 1
return $cacheItem.AccessToken
}
$context = Get-AzureRmContext
$uri = "https://dev.azure.com/<my_org>/<my_area>/_apis/git/repositories/<project_sha>/annotatedtags?api-version=5.0-preview.1"
$token = Get-AccessToken $context.tenantID
$body = #"
{
"taggedObject": {
"objectId": "$(BUILD.SOURCEVERSION)"
},
"name": "D-$(Build.BuildNumber)",
"message": "dummy"
}
"#
$header = #{"Authorization" = "Bearer" + $token}
Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body $body -Headers $header
Any help is greatly appreciated!
There is the example for the build tasks: Use a PowerShell script to customize your build pipeline
You have to enable access to token (option Allow Scripts to Access OAuth Token)
Then use it in your script. Script from the example:
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$($env:SYSTEM_DEFINITIONID)?api-version=5.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"

How can I get the last test run id from TFS to my powershell script

I would like to use the very last TestRunId in case of create a report via powershell which sends the infos to Slack. I use Team Services REST API to get the test results. It works fine but only with specific Run ID. Here is a link where you can find good examples: enter link description here
I'm stuck at finding a way to get the last test result ID which I would use in my GET request to the TFS REST API:
Invoke-RestMethod -Uri "https://{instance}/DefaultCollection/{project}/_apis/test/runs/{run}/results?api-version={version}[&detailsToInclude={string}&$skip={int}&$top={int}]"
So I find {run} as the last Test Run ID with no luck.
Anyone have an idea? I cant find any query language which can be use in this situation in a powershell script.
You could retrieve the list of test runs, the sort descending the result on ID, since the most recent test run has the greatest ID. Then get the first item of the result. All of this shown below in powershell:
$username = "doesnotmatter"
$token = "PUTYOURTOKEN_HERE"
$instance = "PUTYOURACCOUNTHERE.visualstudio.com"
$teamProjectName = "PUTHEREYOUR_TEAM_PROJECT_NAME"
#create auth header to use for REST calls
$accessToken = ("{0}:{1}" -f $username,$token)
$accessToken = [System.Text.Encoding]::UTF8.GetBytes($accessToken)
$accessToken = [System.Convert]::ToBase64String($accessToken)
$headers = #{Authorization=("Basic {0}" -f $accessToken)}
$testRuns = Invoke-RestMethod -Uri "https://$instance/defaultcollection/$(teamProjectName)/_apis/test/runs/?api-version=3.0-preview" -Headers $headers -Method Get
$testRunsIdSorted = $testRuns.value | sort-object id -Descending
$mostRecentTestRun = Invoke-RestMethod -Uri "https://$instance/defaultcollection/$(teamProjectName)/_apis/test/runs/$($testRunsIdSorted[0].id)?api-version=3.0-preview" -Headers $headers -Method Get
$mostRecentTestRun is now the most recent test run.
Note that the script does no error checking at all.
Note that for authentication the script is using a Personal Access Token that needs to have the Test management (read) scope at least.