2

I am trying to automate a build process by first getting the code from bitbucket as follows.

$output = "E:\FileName.xyz"
$url = 'https://bitbucket.org/WhatEver/WhatEverBranchName/get/master.zip'
$wc = New-Object -TypeName System.Net.WebClient
$wc.Headers.Add('Authorization','token oinksdilikncl--MyAccessToken--ioiwcnoisif89kfg9')
$wc.DownloadFile($url, $output)

When I execute this, The file i receive at FileName.xyz is a html file that redirects me to the loginpage of the bitbucket, essentially its asking for creds, even though I suppiled access token.

Where am I wrong? Are there other ways to do this say, Invoke-Webrequest? Or someone kindly direct me to a code sample please?

VivekDev
  • 20,868
  • 27
  • 132
  • 202

3 Answers3

2

I have absolutely zero experience in powershell, but I tried to do the similar task in node and here are my findings.

  1. First you create an "Oauth" in access management section of your bitbucket account setting. This gives you a "Key" and a "Secret".

  2. Now using these Key and Secret you ask Bitbucket for a token. In my case I made a http request to https://bitbucket.org/site/oauth2/access_token. In your case you should use an equivalent of CURL (Invoke-RestMethod maybe?). the CURL command is like this:

    $ curl -X POST -u "yourKeyHere:yourSecretHere" https://bitbucket.org/site/oauth2/access_token -d grant_type=client_credentials
    

    my http request was like this (using superagent in node) with my Content-Type set to application/x-www-form-urlencoded:

    request.post("https://yourKeyHere:yourSecretHere@bitbucket.org/site/oauth2/access_token").send('grant_type=client_credentials');
    
  3. Now that you have the token, your program or your command can clone a private repo with it. But the url to your repo should be like this (keep the bracket around token):

    https://x-token-auth:{tokenHere}@bitbucket.org/youRepoOwnerHere/RepoNameHere.git
    
  4. Now you have the whole codebase on your machine. But you want a single file rather than the whole repo which I refer you to this Retrieve a single file from a repository but remember to use above repo url with the token instead of a normal repo url.

Community
  • 1
  • 1
Vahid PG
  • 428
  • 6
  • 11
2

Actually, at least now (2 years after the original post), the things are more easy than that as it's enough to do a Basic auth. So as long as the script is private thous you have no problem having the creds written in it, the following should to the trick

Invoke-WebRequest -uri '<url>' -Headers @{ Authorization = 'Basic <auth_str_b64>' } -OutFile <dest_path>

where:
- url is something like https://bitbucket.org/<account>/<repo_name>/get/<branch_or_tag_or_whatever>.zip, get it from the Downloads page of the desired repository
- auth_str_b64 is the usual <username>:<password> pair base64 encoded

You can use the following to create/compute the encode string:

$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes('<username>:<password>'))

In order to avoid keeping the creds lying around in the script you could pass them as arguments or prompt them at runtime.

Lohmar ASHAR
  • 1,639
  • 14
  • 18
0

I've solved this problem like this:

# Instanciate the WebClient    
$wc = New-Object -TypeName System.Net.WebClient
# Add the base64 encoded credentials
$wc.Headers.Add('Authorization','Basic {0}' -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f '{USERNAME}','{TOKEN}'))))
# Download the file
$wc.DownloadFile( 'https://{BITBUCKET_URL}/projects/{PROJECT}/repos/{REPOSITORY}/raw/{FILE.EXT}?at=refs%2Fheads%2F{BRANCH}', 'C:\file.txt' )

I am assuming you are using a Personal Access Token. Oh, and it's much, much faster then Invoke-WebRequest or Invoke-RestMethod.

Mohl
  • 405
  • 2
  • 16