8

I am trying to automate the creation of release notes in Azure DevOps release pipelines by creating a new page in the Azure DevOps wiki using it's Rest API.

The issue I'm having is that I'm using a PowerShell script task to post to the Rest API and I'd like to avoid using a Personal Access Token (PAT) and use OAuth instead. The PAT expires and I don't want all of the releases to suddenly fail when the PAT expires. By running the PowerShell script using OAuth under the context of the build agent, I can avoid this expiration issue. I have the "Allow scripts to access the OAuth token" checked in the Agent Job for the release where the PowerShell script task is.

To keep things simple, I'm running the following inline PowerShell script to test creating a new wiki page using OAuth ("Bearer $env:SYSTEM_ACCESSTOKEN"):

$uri = "https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?api-version=5.0&path=/Release%20Notes/Customers%20API/Release-299%20[Build:%2020191010.1]";

try {
    $response = Invoke-RestMethod `
    -Method PUT $uri `
    -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} `
    -ContentType "application/json" `
    -Body $json
} catch {
    Write-Host "Message: " $_.Exception.Message;
    Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__ ;
    Write-Host "StatusDescription: " $_.Exception.Response.StatusDescription;
}

If I perform the HTTP PUT to the URL above using Postman and a Personal Access Token, the new wiki page is successfully created. However, if I run the above PowerShell script within the context of a release in Azure DevOps, I get an HTTP 400 "Bad Request" response. I find this odd since a similar PowerShell script task can query the wiki's Rest API for the existence of pages without error.

Is it not possible to create a new Wiki page using a Bearer token (OAuth) via the wiki's Rest API or am I doing something wrong?

riQQ
  • 9,878
  • 7
  • 49
  • 66
PoorInRichfield
  • 1,436
  • 2
  • 19
  • 29

1 Answers1

9

Is it not possible to create a new Wiki page using a Bearer token (OAuth) via the wiki's Rest API?

Of course yes, it is possible. Any rest api that you can execute with PAT token locally, are all can be run programmatically with System.AccessToken in Powershell task.

For the error you are facing, in fact, if you just Write-Host $response, the error message would make you clearer:

Invoke-RestMethod : {"$id":"1","innerException":null,"message":"The wiki page operation failed with message : User does not have write permissions for this  wiki.","typeName":"Microsoft.TeamFoundation.Wiki.Server.WikiPageOperationFailedException, 
Microsoft.TeamFoundation.Wiki.Server","typeKey":"WikiPageOperationFailedException","errorCode":0,"eventId":3000}

Indeed, this is the root error cause you need focus on.

When you run Rest api with powershell task in Azure Devops pipeline, at this point, the request user account of this api is {Projectname} Build service({Orgname}). In other words, the user which is requesting to add the wiki page during the build is {Projectname} Build service({Orgname}), which is a build service account that permission scope is only in pipeline.

Also, since the Wiki is hosted in Repository, to resolve this issue, you must add this Project Build service(Org name) account into your Repository Permission group, and ensure its Contribute permission as Allow. Thus this build service account can have enough permission to add wiki page:

enter image description here

(Public is my project name, ForMerlin is my org name)


To let you more clear get that why you receive 400 Bad request error instead of this non-permission error after you print out $_.Exception.Message;$_.Exception.Response.StatusCode.value__ ; $_.Exception.Response.StatusDescription;, I reproduced this issue then check our backend IIS log.

When executing this api, in fact, the server is calling Microsoft.TeamFoundation.Wiki.Web.Controllers.WikiPagesController.CreateOrUpdatePage to pack "request body" which will send to the next operation method used. (Note: this "request body" does not equal with the normal one we used in rest API. Here I means the completed one which is the server needed). In its parameters, there include one which can represent user: callerName.

As I mentioned previously, the user account which is calling this API request is the build service account, and its permission scope does not meet the server requirement. So, this "request body" that server needed is invalid. Then you received 400 code with the command $_.Exception.Response.StatusCode.value__.

Mengdi Liang
  • 17,577
  • 2
  • 28
  • 35
  • Thank you for the detailed response! The *Project Build Service* account is part of the Git repositories users in our Azure DevOps project. However, The only permissions the account has set are *Create Tag* and *Read*. I'm assuming it'll need other permissions in order to write to the Wiki. Do you know which other permissions must be set to *Allow*? Unfortunately, your screen capture doesn't show which permissions are granted to that account. – PoorInRichfield Oct 14 '19 at 14:16
  • Hah, forgive my carelessness:-) Missing this key configuration. To achieve create wiki page with Project Build Service account, please at least ensure the permissions of **Contribute** are set to **Allow**. Since the wiki is hosted in Repository, create wiki page means do doing contribution onto Repository. – Mengdi Liang Oct 14 '19 at 14:26
  • Setting the Project Build Service account to have Contribute set to Allow seems to have worked! I accepted your answer, but please edit the answer to reflect this important step. Thanks again for your time in helping me resolve this! – PoorInRichfield Oct 14 '19 at 14:50
  • @PoorInRichfield Got it! My pleasure to help you solve the issue. Will update this key info into answer! Thanks for your notify. – Mengdi Liang Oct 14 '19 at 14:55
  • Hi @MerlinLiang-MSFT, we also get this error, but all the rights are granted. {"$id":"1","innerException":null,"message":"The wiki page operation failed with message : User does not have write permissions for this wiki.","typeName":"Microsoft.TeamFoundation.Wiki.Server.WikiPageOperationFailedException, Microsoft.TeamFoundation.Wiki.Server","typeKey":"WikiPageOperationFailedException","errorCode":0,"eventId":3000}. I can see that User Build SErvbice (org) has contrubute allow rights. Any idea how to check what user is unning the pipeline?... What else could cause this error? – DolceVita Aug 03 '21 at 07:11
  • 1
    @DolceVita As I don't know the relevant details about your organization settings, you could try adding **Project Collection Build Service (org name)** and granting it contribute allow role. This is the collection level service account, I guess your organization may using this level account instead of the project level one. You can go your **organization settings** page -> **settings** to check if the option **Limit job authorization scope to current project for non-release pipelines** is enabled or not. – Mengdi Liang Aug 24 '21 at 03:16
  • @DolceVita This is the key option that determines whether your org is using the collection level service account or the project level service account. – Mengdi Liang Aug 24 '21 at 03:16