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

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:

Related

connect to tfs with different user by using tfs api

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

Azure Devops - Azure powershell task find release/deployment directory

I'm running Azure devops where i have a pipeline and a release (running on a self hosted agent), and the release is set to send up to an azure app service. The deployment works fine, the only issue is that i'd also like to be able to (based on some of my release variables) edit the web.config of the site AFTER it has already been deployed to the azure website.
I'm using the Azure Powershell task ( https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-powershell?view=azure-devops ) ,and i can't find anywhere in the release variables ( https://learn.microsoft.com/en-us/azure/devops/pipelines/release/variables?view=azure-devops&tabs=batch ) that shows the directory of where the site exists. Looking through Kudu, it's pretty basic, like d:\home\site\wwwroot\ , but using that doesn't work at all.
Is this post config that i'm looking for not really possible, or should i be approaching it a different way?
I think you can use powershell task to call Kudu api to get the deployed web.config and edit it using Magic Chunks task or File Transform task in your release pipeline. Then using Kudu api to upload the changed web.config to azure website again.
1, Below script shows how to get web.config from azure website.
$srcResGroupName = "Test"
$srcWebAppName = "tstest12"
$outwebconfig="$(System.DefaultWorkingDirectory)\tempfolder\web.config"
# Get publishing profile for SOURCE application
$srcWebApp = Get-AzWebApp -Name $srcWebAppName -ResourceGroupName $srcResGroupName
[xml]$publishingProfile = Get-AzWebAppPublishingProfile -WebApp $srcWebApp
# Create Base64 authorization header
$username = $publishingProfile.publishData.publishProfile[0].userName
$password = $publishingProfile.publishData.publishProfile[0].userPWD
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$apiBaseUrl = "https://$($srcWebApp.Name).scm.azurewebsites.net/api/vfs/site/wwwroot/web.config"
# Download the web.config file to $outwebconfig
Invoke-RestMethod -Uri "$apiBaseUrl" `
-Headers #{UserAgent="powershell/1.0"; `
Authorization=("Basic {0}" -f $base64AuthInfo)} `
-Method GET `
-OutFile $outwebconfig
Above script will download the web.config from the azure website and save it to $(System.DefaultWorkingDirectory)\tempfolder\web.config, where you can edit it with transform task later.
Above scripts get the username and password with scripts, you can also get them in the publish profile by going to the Overview blade on your App Service, clicking ...More at the top of the blade, and then clicking Get publish profile
2, Then you can add a config transform task to change your web.config according.
3, Last add a powershell task to upload the changed web.config to azure website
$srcResGroupName = "Test"
$srcWebAppName = "tstest12"
$webconfig="$(System.DefaultWorkingDirectory)\tempfolder\web.config"
# Get publishing profile for SOURCE application
$srcWebApp = Get-AzWebApp -Name $srcWebAppName -ResourceGroupName $srcResGroupName
[xml]$publishingProfile = Get-AzWebAppPublishingProfile -WebApp $srcWebApp
# Create Base64 authorization header
$username = $publishingProfile.publishData.publishProfile[0].userName
$password = $publishingProfile.publishData.publishProfile[0].userPWD
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$apiUrl = "https://$($srcWebApp.Name).scm.azurewebsites.net/api/vfs/site/wwwroot/web.config";
Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -UserAgent $userAgent -Method PUT -InFile $webconfig -ContentType "application/xml";
For more usage of Kudu api you can check here.

Powershell Google Sheets API with service account, how do I set scopes?

I have a Google Sheet I want to fill using Google Cloud service account. So I've created the account, shared the sheet with it. I activate it with:
gcloud auth activate-service-account --key-file=XXX.json
and I put this in my powershell code:
$cred = gcloud auth print-access-token
$result = Invoke-RestMethod -Headers #{Authorization = "Bearer $cred"} -Uri
$requestUri -Method Post -ContentType "application/json" -Body $data
but I keep getting this error:
#{code=403; message=Request had insufficient authentication scopes.; status=PERMISSION_DENIED}
so my question is, where and how do I set scopes for service account?

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

VSTS build running locally - error: "Microsoft Internet Explorer. Enhanced Security Configuration"

I'm running Windows 10 and making a script to handle/start VSTS builds.
Sample call (overriding properties for testing):
$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI = "https://mytenancy.visualstudio.com/"
$env:SYSTEM_TEAMPROJECTID = "Project1"
$env:SYSTEM_DEFINITIONID = 5
#$env:SYSTEM_ACCESSTOKEN = "mytoken" - uncomment when running locally
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$($env:SYSTEM_DEFINITIONID)?api-version=2.0"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 100)"
"Authenticated"
This script works fine on the server, but if I uncomment the $env:SYSTEM_ACCESSTOKEN and run locally, I get the following error:
Microsoft Internet Explorer\u0026#39;s Enhanced Security Configuration
is currently enabled on your environment. This enhanced level of
security prevents our web integration experiences from displaying or
performing correctly. To continue with your operation please disable
this configuration or contact your administrator.
I'm running Windows 10.
I've tried many things, including:
Turning off as much security as possible in Internet Options.
Fresh Token
Converting the token to a secure string
Converting to a Base64 string as detailed in the answer to this post
How can I authenticate locally?
EDIT (following accepted answer)
The accepted answer solved the problem. I think the two key points here were:
The correct encoding in conversion to Base64
Changing authentication from Bearer to Basic when running in this way (locally).
Final code:
$user = "[username]"
$accessToken="[token]"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$accessToken)))
$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI = "https://mytenancy.visualstudio.com/"
$env:SYSTEM_TEAMPROJECTID = "Project1"
$checkBuildUrl = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$($env:SYSTEM_TEAMPROJECTID)/_apis/build/builds/$($requestedBuildId)?api-version=2.0"
$buildStatus = Invoke-RestMethod -Uri $checkBuildUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Create a new access token and refer to this code to call the REST API through PowerShell:
$user = "[anything]"
$accessToken="[access token]"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$accessToken)))
...
Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $bodyJson
Regarding enhanced security, there is a similar issue:
Enhanced Security Error while Visual Studio Team Services Rest API