Bitbucket Server (nee Stash) can hand out Personal Access Tokens (PAT) to be used in-place of user+password authentication.
When machine (rather than human) access to Stash is required, ideally it should be via short-lived credentials. This GitHub Action will take user+password credentials, and use them to generate a PAT. Your GitHub Actions workflow should then use the PAT whenever authenticating to Stash.
Wait. What? 🤔
Why would you use a PAT if you have a user+password already?
Ideally this GitHub Action is used in conjunction with Hashicorp Vault, which will automatically rotate the Stash user's password (e.g. using the AD secrets engine). This means during an execution of a (relatively long running) GitHub Actions workflow, the password could change from the value originally obtained from Vault.
Obtaining a PAT allows us to avoid this issue, since the PAT will not be rotated (or used again).
Not perfect
This isn't the perfect way to go about getting a PAT from Stash for GitHub Actions when Vault is in the mix. The ideal solution is to create a new Vault secrets engine that would connect to Stash directly and generate the PAT. This would simplify the implementation on the GitHub Actions side, since you could just use the Hashicorp Vault Action.
We have chosen not to create a new Vault secrets engine, as we could deliver this GitHub Action more quickly and simply (as opposed to creating, building, publishing and installing a Vault plugin).
- name: Get creds from Vault
id: vault
uses: hashicorp/[email protected]
with:
url: https://vault.example.org/
method: jwt
exportEnv: false
secrets: |
ad/creds/svc_github_stash username | username ;
ad/creds/svc_github_stash current_password | password
- name: Get PAT for Stash
id: stash
uses: reecetech/[email protected]
with:
base_url: https://stash.example.org/
username: ${{ steps.vault.outputs.username }}
password: ${{ steps.vault.outputs.password }}
- name: Clone repo from Stash
uses: example/git-clone
with:
url: https://stash.example.com/scm/example/repo.git
username: ${{ steps.vault.outputs.username }}
password: ${{ steps.stash.outputs.pat }}
INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
---|---|---|---|---|
base_url | string | true | Base URL of Bitbucket Server |
|
check_using_ldap_bind | string | false | "false" |
Check the password validity using an LDAP bind to avoid Bitbucket requiring a CAPTCHA after failed authentication attempts |
ldap_hosts | string | false | Comma separated list of LDAP hosts (only used if check_using_ldap_bind is true ) |
|
ldap_path | string | false | The path where the username will be found in the LDAP tree (only used if check_using_ldap_bind is true ) For example,if the user object is CN=username,OU=tech,OU=Accounts,DC=example,DC=org , then set ldap_path to:OU=tech,OU=Accounts,DC=example,DC=org |
|
ldap_port | string | false | "389" |
TCP port to connect to LDAP hosts (only used if check_using_ldap_bind is true ) |
max_attempts | string | false | "10" |
Number of times to attempt to generate a PAT |
mode | string | false | "create" |
Mode to run in - either create or revoke |
password | string | true | Password to connect to Bitbucket Server |
|
pat_id | string | false | The ID of the PAT to revoke (only used if mode is revoke ) |
|
pat_uri | string | false | "rest/access-tokens/1.0/users" |
The REST endpoint for PAT actions |
project_permissions | string | false | "write" |
Project permissions: read, write or admin |
repository_permissions | string | false | "write" |
Repository permissions: read, write or admin |
seconds_between_attempts | string | false | "30" |
Number of seconds to wait before retrying to generate a PAT |
username | string | true | Username to connect to Bitbucket Server |
|
valid_days | string | false | "1" |
Days the PAT will be valid |
OUTPUT | TYPE | DESCRIPTION |
---|---|---|
pat | string | PAT to connect to Bitbucket Server |
pat_encoded | string | PAT URL encoded |
pat_id | string | ID of the PAT (can be used to revoke) |
username | string | Username to connect to Bitbucket Server |
username_encoded | string | Username URL encoded |
Please raise a pull request, but note the testing tools below
pylint is used to lint the Python code
See: https://pylint.org/