Search code examples
azure-devopsazure-devops-rest-apiazure-devops-server-2019

Getting 401 Unauthorized trying to Create or Update Wiki page using Powershell script


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.


Solution

  • 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!