0

I am trying to create a new page in my Wiki from a Build pipeline with the generated release notes. I receive this error in response : Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.

I have looked at every resource I found on the subject and everything looks good to me.

Here is my powershell script :

# Get content of the generated release notes file
$content = [IO.File]::ReadAllText("$(build.artifactstagingdirectory)/release-notes-$(Build.BuildNumber).md")
$data = @{content=$content;} | ConvertTo-Json;

$params = @{uri = '$(WikiPath)';
  Method = 'PUT';
  Headers = @{Authorization = "Bearer $(System.AccessToken)" };
  ContentType = "application/json";
  Body = $data;
}

Write-Host "PUT $(WikiPath)"

$response = Invoke-WebRequest @params

Write-Host $response

The value of WikiPath variable is set to :
https://<server-ip>/PersonalProjects/Personal-KM/_apis/wiki/wikis/Personal-KM.wiki/pages?path=%2FRelease%20notes%2F$(Build.BuildNumber)&api-version=5.0

The uri comes from the official API documentation. I would like to create sub-pages of the page Release notes which does exist. I tried to create a root page without success (?path=$(Build.BuildNumber)&api-version=5.0).

Note that I also tried without .wiki at the end of the wiki identifier.

Here is the output of the build step :

##[command]"C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'C:\DevOpsAgent\_work\_temp\ebf68890-3544-4a8d-a415-4309983b1381.ps1'"
PUT https://<server-ip>/PersonalProjects/Personal-KM/_apis/wiki/wikis/Personal-KM.wiki/pages?path=%2FRelease%20notes%2F1.0.0.7&api-version=5.0
Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.
At C:\DevOpsAgent\_work\_temp\ebf68890-3544-4a8d-a415-4309983b1381.ps1:26 char:13
+ $response = Invoke-WebRequest @params
+             ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc 
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

##[error]PowerShell exited with code '1'.

Key point 1 : I have checked Allow scripts to access the OAuth Token in Agent Job :

Scripts token

Key point 2 : I have given the permissions 'Contribute' to the Build service account :

Build service permissions

Can you see anything wrong with my script or configuration ?

Edit 1 based on the comment from @MarioDietner :
I have tried to use a PAT instead of $(System.AccessToken), I get the same error (I am member of Project Collection Administrators and my PAT has Full access scope).
I also tried executing the script from my local computer (variables replaced) :

enter image description here

Edit 2 I tried to run the script from Azure Pipelines on our production server and it worked on the first try. I don't know what is wrong with our local Azure DevOps but I will focus the investigation on the identities and not on the Powershell script.

KevinM
  • 144
  • 3
  • 13
  • can you try replace the System.AccessToken with your PAT and run the pipeline to see if this is actually working? Or even run it from your local pc...? – Mario Dietner Apr 02 '20 at 16:17
  • @MarioDietner Thank you for the suggestion. Unfortunately I still get the same error. I have updated my question with the details. – KevinM Apr 02 '20 at 16:54

1 Answers1

0

please update your script and use an encoded token with format:

$PAT = "username@domain.com:PAT"
$encodedPat = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($PAT))

$params = @{uri = '$(WikiPath)';
  Method = 'PUT';
  Headers = @{Authorization = "Basic $encodedPat" };
  ContentType = "application/json";
  Body = $data;
}

I followed this guideline for the powershell and encoding part, but added username to the PAT to get it working from SOAP UI. Try first with your user and later adopt to use System.AccessToken. Hope it helps!

Mario Dietner
  • 566
  • 2
  • 9
  • While my initial script worked on the first try on our production server, I accept your answer since it made me try different configuration on different environments. Note that both my initial script using `Bearer $(System.AccessToken)` and your proposition using `Basic $encodedPat` are working. Thank you – KevinM Apr 03 '20 at 10:26