feat(#10): Support http-access-tokens for authentication

This commit is contained in:
xvlcwk
2024-02-07 23:26:35 +01:00
committed by chris
parent 8f9c46f7d7
commit 5c82693906
4 changed files with 47 additions and 32 deletions

View File

@@ -18,24 +18,31 @@ func Provider() *schema.Provider {
return &schema.Provider{ return &schema.Provider{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"server": { "server": {
Required: true, Optional: true,
Type: schema.TypeString, Type: schema.TypeString,
DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_SERVER", nil), DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_SERVER", nil),
Description: "The url of your bitbucket instance. For the docker compose instance this is http://localhost:7990", Description: "The url of your bitbucket instance. For the docker compose instance this is http://localhost:7990",
}, },
"username": { "username": {
Required: true, Optional: true,
Type: schema.TypeString, Type: schema.TypeString,
DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_USERNAME", nil), DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_USERNAME", nil),
Description: "The username for authentication. If you're using a personal access token use your normal username.", Description: "The username for authentication. If you're using a personal access token use your normal username.",
}, },
"password": { "password": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Optional: true,
Sensitive: true, Sensitive: true,
DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_PASSWORD", nil), DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_PASSWORD", nil),
Description: "the password for authentication. Personal access tokens are allowed, but http access token aren't yet", Description: "the password for authentication. Personal access tokens are allowed, but http access token aren't yet",
}, },
"token": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
DefaultFunc: schema.EnvDefaultFunc("BITBUCKET_TOKEN", nil),
Description: "Token as alternative to the Password. Only use for repository access tokens. Personal access tokens can use the normal basic authentication",
},
}, },
ConfigureContextFunc: providerConfigure, ConfigureContextFunc: providerConfigure,
DataSourcesMap: map[string]*schema.Resource{ DataSourcesMap: map[string]*schema.Resource{
@@ -91,6 +98,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
username := d.Get("username").(string) username := d.Get("username").(string)
password := d.Get("password").(string) password := d.Get("password").(string)
token := d.Get("token").(string)
configErrors := diag.Diagnostics{} configErrors := diag.Diagnostics{}
@@ -102,7 +110,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
Detail: "server is required and must be provided in the provider config or the BITBUCKET_SERVER environment variable", Detail: "server is required and must be provided in the provider config or the BITBUCKET_SERVER environment variable",
}) })
} }
if username == "" { if username == "" && token == "" {
configErrors = append(configErrors, configErrors = append(configErrors,
diag.Diagnostic{ diag.Diagnostic{
@@ -111,7 +119,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
Detail: "username is required and must be provided in the provider config or the BITBUCKET_USERNAME environment variable", Detail: "username is required and must be provided in the provider config or the BITBUCKET_USERNAME environment variable",
}) })
} }
if password == "" { if password == "" && token == "" {
configErrors = append(configErrors, configErrors = append(configErrors,
diag.Diagnostic{ diag.Diagnostic{
Severity: diag.Error, Severity: diag.Error,
@@ -128,6 +136,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
Server: serverSanitized, Server: serverSanitized,
Username: username, Username: username,
Password: password, Password: password,
Token: token,
HTTPClient: &http.Client{}, HTTPClient: &http.Client{},
} }

View File

@@ -34,6 +34,7 @@ type BitbucketServerProviderModel struct {
Server types.String `tfsdk:"server"` Server types.String `tfsdk:"server"`
Username types.String `tfsdk:"username"` Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"` Password types.String `tfsdk:"password"`
Token types.String `tfsdk:"token"`
} }
func (p *BitbucketServerProviderFramework) Resources(_ context.Context) []func() resource.Resource { func (p *BitbucketServerProviderFramework) Resources(_ context.Context) []func() resource.Resource {
@@ -71,6 +72,11 @@ func (p *BitbucketServerProviderFramework) Schema(_ context.Context, _ provider.
Description: "the password for authentication. Personal access tokens are allowed, but http access token aren't yet", Description: "the password for authentication. Personal access tokens are allowed, but http access token aren't yet",
Sensitive: true, Sensitive: true,
}, },
"token": schema.StringAttribute{
Optional: true,
Description: "Token as alternative to the Password. Only use for repository access tokens. Personal access tokens can use the normal basic authentication",
Sensitive: true,
},
}, },
} }
} }
@@ -101,11 +107,16 @@ func (p *BitbucketServerProviderFramework) Configure(ctx context.Context, req pr
) )
} }
token := os.Getenv("BITBUCKET_TOKEN")
if data.Token.ValueString() != "" {
token = data.Token.ValueString()
}
username := os.Getenv("BITBUCKET_USERNAME") username := os.Getenv("BITBUCKET_USERNAME")
if data.Username.ValueString() != "" { if data.Username.ValueString() != "" {
username = data.Username.ValueString() username = data.Username.ValueString()
} }
if username == "" { if username == "" && token == "" {
resp.Diagnostics.AddError( resp.Diagnostics.AddError(
"username is required", "username is required",
"username is required and must be provided in the provider config or the BITBUCKET_USERNAME environment variable", "username is required and must be provided in the provider config or the BITBUCKET_USERNAME environment variable",
@@ -116,7 +127,7 @@ func (p *BitbucketServerProviderFramework) Configure(ctx context.Context, req pr
if data.Password.ValueString() != "" { if data.Password.ValueString() != "" {
password = data.Password.ValueString() password = data.Password.ValueString()
} }
if password == "" { if password == "" && token == "" {
resp.Diagnostics.AddError( resp.Diagnostics.AddError(
"password is required", "password is required",
"password is required and must be provided in the provider config or the BITBUCKET_PASSWORD environment variable", "password is required and must be provided in the provider config or the BITBUCKET_PASSWORD environment variable",
@@ -127,6 +138,7 @@ func (p *BitbucketServerProviderFramework) Configure(ctx context.Context, req pr
Server: server, Server: server,
Username: username, Username: username,
Password: password, Password: password,
Token: token,
HTTPClient: &http.Client{}, HTTPClient: &http.Client{},
} }

View File

@@ -40,6 +40,7 @@ type BitbucketClient struct {
Server string Server string
Username string Username string
Password string Password string
Token string
HTTPClient *http.Client HTTPClient *http.Client
} }
@@ -60,7 +61,11 @@ func (c *BitbucketClient) Do(method, endpoint string, payload *bytes.Buffer, con
return nil, err return nil, err
} }
req.SetBasicAuth(c.Username, c.Password) if c.Password != "" {
req.SetBasicAuth(c.Username, c.Password)
} else {
req.Header.Add("Authorization", "Bearer "+c.Token)
}
req.Header.Add("X-Atlassian-Token", "no-check") req.Header.Add("X-Atlassian-Token", "no-check")
if payload != nil { if payload != nil {

View File

@@ -6,14 +6,12 @@ unlocks the power of terraform to manage your self-hosted Bitbucket Server insta
## Installation ## Installation
### Terraform 0.13+ ### Terraform 1.0+
The provider can be installed and managed automatically by Terraform. Sample `versions.tf` file : The provider can be installed and managed automatically by Terraform. Sample `versions.tf` file :
```hcl ```hcl
terraform { terraform {
required_version = ">= 0.13"
required_providers { required_providers {
bitbucketserver = { bitbucketserver = {
source = "xvlcwk-terraform/bitbucketserver" source = "xvlcwk-terraform/bitbucketserver"
@@ -22,26 +20,6 @@ terraform {
} }
``` ```
### Terraform 0.12
#### Install latest version
The following one-liner script will fetch the latest provider version and download it to your `~/.terraform.d/plugins` directory.
```bash
$ mkdir -p ~/.terraform.d/plugins && \
curl -Ls https://api.github.com/repos/xvlcwk-terraform/terraform-provider-bitbucketserver/releases/latest \
| jq -r ".assets[] | select(.browser_download_url | contains(\"$(uname -s | tr A-Z a-z)\")) | select(.browser_download_url | contains(\"amd64\")) | .browser_download_url" \
| xargs -n 1 curl -Lo ~/.terraform.d/plugins/terraform-provider-bitbucketserver.zip && \
pushd ~/.terraform.d/plugins/ && \
unzip ~/.terraform.d/plugins/terraform-provider-bitbucketserver.zip -d terraform-provider-bitbucketserver-tmp && \
mv terraform-provider-bitbucketserver-tmp/terraform-provider-bitbucketserver* . && \
chmod +x terraform-provider-bitbucketserver* && \
rm -rf terraform-provider-bitbucketserver-tmp && \
rm -rf terraform-provider-bitbucketserver.zip && \
popd
```
#### Install manually #### Install manually
If you don't want to use the one-liner above, you can download a binary for your system from the [release page](https://github.com/xvlcwk-terraform/terraform-provider-bitbucketserver/releases), If you don't want to use the one-liner above, you can download a binary for your system from the [release page](https://github.com/xvlcwk-terraform/terraform-provider-bitbucketserver/releases),
@@ -60,10 +38,20 @@ provider "bitbucketserver" {
} }
``` ```
Alternatively you can specify a http-access-token, but please be aware that those aren't able to create other access tokens and are overall limited in their scope.
```hcl
provider "bitbucketserver" {
server = "https://mybitbucket.example.com"
token = "BBDC-ODc4NTMyODU1MTI3OnSOs8sHd7EZneuWx2ZiYyF/Xmuj"
}
```
### Authentication ### Authentication
The `username` and `password` specified should be of a user with sufficient privileges to perform the operations you are after. The `username` and `password` specified should be of a user with sufficient privileges to perform the operations you are after.
Typically this is a user with `SYS_ADMIN` global permissions. Typically, this is a user with `SYS_ADMIN` global permissions.
### Environment Variables ### Environment Variables
@@ -72,6 +60,7 @@ You can also specify the provider configuration using the following env vars:
* `BITBUCKET_SERVER` * `BITBUCKET_SERVER`
* `BITBUCKER_USERNAME` * `BITBUCKER_USERNAME`
* `BITBUCKET_PASSWORD` * `BITBUCKET_PASSWORD`
* `BITBUCKET_TOKEN`
> Note: The hcl provider configuration takes precedence over the environment variables. > Note: The hcl provider configuration takes precedence over the environment variables.