Skip to content

Commit

Permalink
feat: add support for OIDC bearer tokens to auth TFP against Octopus API
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhilton committed Nov 7, 2024
1 parent 6e97b3c commit 6a4d53c
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 26 deletions.
57 changes: 47 additions & 10 deletions octopusdeploy/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package octopusdeploy

import (
"fmt"
"net/url"

"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
Expand All @@ -10,19 +11,15 @@ import (

// Config holds Address and the APIKey of the Octopus Deploy server
type Config struct {
Address string
APIKey string
SpaceID string
Address string
APIKey string
AccessToken string
SpaceID string
}

// Client returns a new Octopus Deploy client
func (c *Config) Client() (*client.Client, diag.Diagnostics) {
apiURL, err := url.Parse(c.Address)
if err != nil {
return nil, diag.FromErr(err)
}

octopus, err := client.NewClient(nil, apiURL, c.APIKey, "")
octopus, err := getClientForDefaultSpace(c)
if err != nil {
return nil, diag.FromErr(err)
}
Expand All @@ -33,11 +30,51 @@ func (c *Config) Client() (*client.Client, diag.Diagnostics) {
return nil, diag.FromErr(err)
}

octopus, err = client.NewClient(nil, apiURL, c.APIKey, space.GetID())
octopus, err = getClientForSpace(c, space.GetID())
if err != nil {
return nil, diag.FromErr(err)
}
}

return octopus, nil
}

func getClientForDefaultSpace(c *Config) (*client.Client, error) {
return getClientForSpace(c, "")
}

func getClientForSpace(c *Config, spaceID string) (*client.Client, error) {
apiURL, err := url.Parse(c.Address)
if err != nil {
return nil, err
}

credential, err := getApiCredential(c)
if err != nil {
return nil, err
}

return client.NewClientWithCredentials(nil, apiURL, credential, spaceID, "TerraformProvider")
}

func getApiCredential(c *Config) (client.ICredential, error) {
if c.APIKey != "" {
credential, err := client.NewApiKey(c.APIKey)
if err != nil {
return nil, err
}

return credential, nil
}

if c.AccessToken != "" {
credential, err := client.NewAccessToken(c.AccessToken)
if err != nil {
return nil, err
}

return credential, nil
}

return nil, fmt.Errorf("either an APIKey or an AccessToken is required to connect to the Octopus Server instance")
}
13 changes: 10 additions & 3 deletions octopusdeploy/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ func Provider() *schema.Provider {
Type: schema.TypeString,
},
"api_key": {
DefaultFunc: schema.EnvDefaultFunc("OCTOPUS_APIKEY", nil),
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"OCTOPUS_APIKEY", "OCTOPUS_API_KEY"}, nil),
Description: "The API key to use with the Octopus REST API",
Optional: true,
Type: schema.TypeString,
},
"access_token": {
DefaultFunc: schema.EnvDefaultFunc("OCTOPUS_ACCESS_TOKEN", nil),
Description: "The OIDC Access Token to use with the Octopus REST API",
Optional: true,
Type: schema.TypeString,
},
"space_id": {
Description: "The space ID to target",
Optional: true,
Expand All @@ -94,8 +100,9 @@ func Provider() *schema.Provider {

func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
config := Config{
Address: d.Get("address").(string),
APIKey: d.Get("api_key").(string),
AccessToken: d.Get("access_token").(string),
Address: d.Get("address").(string),
APIKey: d.Get("api_key").(string),
}
if spaceID, ok := d.GetOk("space_id"); ok {
config.SpaceID = spaceID.(string)
Expand Down
65 changes: 55 additions & 10 deletions octopusdeploy_framework/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,17 @@ import (
)

type Config struct {
Address string
ApiKey string
SpaceID string
Client *client.Client
Address string
ApiKey string
AccessToken string
SpaceID string
Client *client.Client
}

func (c *Config) GetClient(ctx context.Context) error {
tflog.Debug(ctx, "GetClient")
apiURL, err := url.Parse(c.Address)
if err != nil {
return err
}

octopus, err := client.NewClient(nil, apiURL, c.ApiKey, "")
octopus, err := getClientForDefaultSpace(c, ctx)
if err != nil {
return err
}
Expand All @@ -36,7 +33,7 @@ func (c *Config) GetClient(ctx context.Context) error {
return err
}

octopus, err = client.NewClient(nil, apiURL, c.ApiKey, space.GetID())
octopus, err = getClientForSpace(c, ctx, space.GetID())
if err != nil {
return err
}
Expand All @@ -49,6 +46,54 @@ func (c *Config) GetClient(ctx context.Context) error {
return nil
}

func getClientForDefaultSpace(c *Config, ctx context.Context) (*client.Client, error) {
return getClientForSpace(c, ctx, "")
}

func getClientForSpace(c *Config, ctx context.Context, spaceID string) (*client.Client, error) {
apiURL, err := url.Parse(c.Address)
if err != nil {
return nil, err
}

credential, err := getApiCredential(c, ctx)
if err != nil {
return nil, err
}

return client.NewClientWithCredentials(nil, apiURL, credential, spaceID, "TerraformProvider")
}

func getApiCredential(c *Config, ctx context.Context) (client.ICredential, error) {
tflog.Debug(ctx, "GetClient: Trying the following auth methods in order of priority - APIKey, AccessToken")

if c.ApiKey != "" {
tflog.Debug(ctx, "GetClient: Attempting to authenticate with API Key")
credential, err := client.NewApiKey(c.ApiKey)
if err != nil {
return nil, err
}

return credential, nil
} else {
tflog.Debug(ctx, "GetClient: No API Key found")
}

if c.AccessToken != "" {
tflog.Debug(ctx, "GetClient: Attempting to authenticate with Access Token")
credential, err := client.NewAccessToken(c.AccessToken)
if err != nil {
return nil, err
}

return credential, nil
} else {
tflog.Debug(ctx, "GetClient: No Access Token found")
}

return nil, fmt.Errorf("either an APIKey or an AccessToken is required to connect to the Octopus Server instance")
}

func DataSourceConfiguration(req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) *Config {
if req.ProviderData == nil {
return nil
Expand Down
17 changes: 14 additions & 3 deletions octopusdeploy_framework/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import (
)

type octopusDeployFrameworkProvider struct {
Address types.String `tfsdk:"address"`
ApiKey types.String `tfsdk:"api_key"`
SpaceID types.String `tfsdk:"space_id"`
Address types.String `tfsdk:"address"`
ApiKey types.String `tfsdk:"api_key"`
AccessToken types.String `tfsdk:"access_token"`
SpaceID types.String `tfsdk:"space_id"`
}

var _ provider.Provider = (*octopusDeployFrameworkProvider)(nil)
Expand Down Expand Up @@ -45,6 +46,12 @@ func (p *octopusDeployFrameworkProvider) Configure(ctx context.Context, req prov
if config.ApiKey == "" {
config.ApiKey = os.Getenv("OCTOPUS_APIKEY")
}
if config.ApiKey == "" {
config.ApiKey = os.Getenv("OCTOPUS_API_KEY")
}
if config.AccessToken == "" {
config.AccessToken = os.Getenv("OCTOPUS_ACCESS_TOKEN")
}
config.Address = providerData.Address.ValueString()
if config.Address == "" {
config.Address = os.Getenv("OCTOPUS_URL")
Expand Down Expand Up @@ -118,6 +125,10 @@ func (p *octopusDeployFrameworkProvider) Schema(_ context.Context, req provider.
Optional: true,
Description: "The API key to use with the Octopus REST API",
},
"access_token": schema.StringAttribute{
Optional: true,
Description: "The OIDC Access Token to use with the Octopus REST API",
},
"space_id": schema.StringAttribute{
Optional: true,
Description: "The space ID to target",
Expand Down

0 comments on commit 6a4d53c

Please sign in to comment.