From e2722969bc049de77e77d4cdc8ea11a294652221 Mon Sep 17 00:00:00 2001 From: David Debeau Date: Thu, 29 Aug 2024 07:37:27 -0500 Subject: [PATCH 1/7] Move provider validation logic to ValidateConfig method --- internal/provider/provider.go | 72 ++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7b025ae..313da92 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -54,6 +54,52 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ return } + quayURL := os.Getenv("QUAY_URL") + quayToken := os.Getenv("QUAY_TOKEN") + + if !config.Url.IsNull() { + quayURL = config.Url.ValueString() + } + + if !config.Token.IsNull() { + quayToken = config.Token.ValueString() + } + + ctx = tflog.SetField(ctx, "quay_url", quayURL) + ctx = tflog.SetField(ctx, "quay_token", quayToken) + ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "quay_token") + + tflog.Debug(ctx, "Creating Quay client") + + configuration := &quay_api.Configuration{ + DefaultHeader: make(map[string]string), + UserAgent: "OpenAPI-Generator/1.0.0/go", + Debug: false, + Servers: quay_api.ServerConfigurations{ + { + URL: quayURL, + Description: "No description provided", + }, + }, + OperationServers: map[string]quay_api.ServerConfigurations{}, + } + configuration.AddDefaultHeader("Authorization", "Bearer "+quayToken) + client := quay_api.NewAPIClient(configuration) + + resp.DataSourceData = client + resp.ResourceData = client + + tflog.Info(ctx, "Configured Quay client", map[string]any{"success": true}) +} + +func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.ValidateConfigRequest, resp *provider.ValidateConfigResponse) { + var config quayProviderModel + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + if config.Url.IsUnknown() { resp.Diagnostics.AddAttributeError( path.Root("url"), @@ -116,32 +162,6 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ if resp.Diagnostics.HasError() { return } - - ctx = tflog.SetField(ctx, "quay_url", quayURL) - ctx = tflog.SetField(ctx, "quay_token", quayToken) - ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "quay_token") - - tflog.Debug(ctx, "Creating Quay client") - - configuration := &quay_api.Configuration{ - DefaultHeader: make(map[string]string), - UserAgent: "OpenAPI-Generator/1.0.0/go", - Debug: false, - Servers: quay_api.ServerConfigurations{ - { - URL: quayURL, - Description: "No description provided", - }, - }, - OperationServers: map[string]quay_api.ServerConfigurations{}, - } - configuration.AddDefaultHeader("Authorization", "Bearer "+quayToken) - client := quay_api.NewAPIClient(configuration) - - resp.DataSourceData = client - resp.ResourceData = client - - tflog.Info(ctx, "Configured Quay client", map[string]any{"success": true}) } func (p *quayProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) { From 988ae9ee8b6bf1a5d2abac63619649fc639279df Mon Sep 17 00:00:00 2001 From: David Debeau Date: Fri, 30 Aug 2024 08:18:04 -0500 Subject: [PATCH 2/7] Update provider validation for client credentials and add tests --- internal/provider/provider.go | 100 ++++++++++++++----- internal/provider/provider_test.go | 150 +++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 23 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 313da92..bf53c75 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -26,8 +26,10 @@ func New() func() provider.Provider { type quayProvider struct{} type quayProviderModel struct { - Url types.String `tfsdk:"url"` - Token types.String `tfsdk:"token"` + Url types.String `tfsdk:"url"` + Token types.String `tfsdk:"token"` + ClientID types.String `tfsdk:"client_id"` + ClientSecret types.String `tfsdk:"client_secret"` } func (p *quayProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { @@ -41,6 +43,15 @@ func (p *quayProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp Optional: true, Sensitive: true, }, + "client_id": schema.StringAttribute{ + Description: "Client ID. Used for generating a JWT OAuth2 access token with client credentials.", + Optional: true, + }, + "client_secret": schema.StringAttribute{ + Description: "Client secret. Used for generating a JWT OAuth2 access token with client credentials.", + Optional: true, + Sensitive: true, + }, }} } @@ -100,21 +111,11 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if config.Url.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("url"), - "Unknown Quay URL", - "The provider cannot create the Quay client as the URL value is unknown. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the QUAY_URL environment variable", - ) - } - - if config.Token.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("token"), - "Unknown Quay token", - "The provider cannot create the Quay client as the token value is unknown. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the QUAY_TOKEN environment variable", + if config.Url.IsUnknown() || config.Token.IsUnknown() || config.ClientID.IsUnknown() || config.ClientSecret.IsUnknown() { + resp.Diagnostics.AddError( + "Unknown configuration values", + "The provider cannot create the Quay client if any configuration values are unknown. "+ + "Either target apply the source of the unknown value(s) first, set the value(s) statically in the configuration, or set the appropriate environment variable(s).", ) } @@ -124,6 +125,8 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate quayURL := os.Getenv("QUAY_URL") quayToken := os.Getenv("QUAY_TOKEN") + clientID := os.Getenv("QUAY_CLIENT_ID") + clientSecret := os.Getenv("QUAY_CLIENT_SECRET") if !config.Url.IsNull() { quayURL = config.Url.ValueString() @@ -133,15 +136,38 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate quayToken = config.Token.ValueString() } + if !config.ClientID.IsNull() { + clientID = config.ClientID.ValueString() + } + + if !config.ClientSecret.IsNull() { + clientSecret = config.ClientSecret.ValueString() + } + + if (quayToken != "" && clientID != "") || (quayToken != "" && clientSecret != "") { + resp.Diagnostics.AddError( + "Cannot specify token and client credentials", + "Token cannot be specified when a client ID or client secret are also specified. You must pick one authentication method.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + if quayURL == "" { resp.Diagnostics.AddAttributeError( path.Root("url"), "Missing Quay URL", "The provider cannot create the Quay client as there is a missing or empty value for the Quay URL. "+ - "Set the URL in the configuration or use the QUAY_URL environment variable. ", + "Set the URL in the configuration or use the QUAY_URL environment variable.", ) } + if resp.Diagnostics.HasError() { + return + } + if !isValidURL(quayURL) { resp.Diagnostics.AddAttributeError( path.Root("url"), @@ -150,12 +176,40 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate ) } - if quayToken == "" { + if resp.Diagnostics.HasError() { + return + } + + if quayToken == "" && (clientID == "" && clientSecret == "") { + resp.Diagnostics.AddError( + "Missing Quay token and client credentials", + "The provider cannot create the Quay client as both the Quay token and client credentials are missing or empty.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + + if clientID != "" && clientSecret == "" { + resp.Diagnostics.AddAttributeError( + path.Root("client_secret"), + "Missing client secret", + "The provider cannot create the Quay client as there is a missing value or empty value for the client secret."+ + "Set the client secret in the configuration or use the QUAY_CLIENT_SECRET environment variable.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + + if clientID == "" && clientSecret != "" { resp.Diagnostics.AddAttributeError( - path.Root("token"), - "Missing Quay token", - "The provider cannot create the Quay client as there is a missing or empty value for the Quay token. "+ - "Set the token in the configuration or use the QUAY_TOKEN environment variable. ", + path.Root("client_id"), + "Missing client ID", + "The provider cannot create the Quay client as there is a missing value or empty value for the client ID."+ + "Set the client ID in the configuration or use the QUAY_CLIENT_ID environment variable.", ) } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 4fc1ea7..dd8a003 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -1,8 +1,12 @@ package provider import ( + "regexp" + "testing" + "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) const ( @@ -16,3 +20,149 @@ var ( "quay": providerserver.NewProtocol6WithError(New()()), } ) + +func TestAccProviderValidationWithoutENV(t *testing.T) { + // unset QUAY_* environment variables + t.Setenv("QUAY_URL", "") + t.Setenv("QUAY_TOKEN", "") + t.Setenv("QUAY_CLIENT_ID", "") + t.Setenv("QUAY_CLIENT_SECRET", "") + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{ + "random": { + Source: "hashicorp/random", + VersionConstraint: "~> 3.6", + }, + }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Unknown config values + { + PlanOnly: true, + Config: ` +resource "random_string" "this" { + length = 8 +} + +provider "quay" { + url = "https://quay-${random_string.this}.example.com" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Unknown configuration values"), + }, + // Token and client credentials + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" + token = "asdf" + client_id = "quay" + client_secret = "asdf" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Cannot specify token and client credentials"), + }, + // No config values + { + PlanOnly: true, + Config: ` +provider "quay" {} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing Quay URL"), + }, + // Invalid URL + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "quay.example.com" + token = "asdf" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Quay URL is not a valid URL"), + }, + // Missing Quay token and client credentials + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing Quay token and client credentials"), + }, + // Missing client secret + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" + client_id = "quay" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing client secret"), + }, + // Missing client ID + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" + client_secret = "asdf" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing client ID"), + }, + }, + }) +} + +func TestAccProviderValidationWithEnv(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // No config values + { + PlanOnly: true, + Config: ` +provider "quay" {} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Error reading Quay org"), + }, + }, + }) +} From 323dc0ddbbdcb5290467eee0195dda8808c1a1d9 Mon Sep 17 00:00:00 2001 From: David Debeau Date: Wed, 4 Sep 2024 13:14:26 -0500 Subject: [PATCH 3/7] Use OAuth2 password grant instead of client credentials --- go.mod | 23 ---- go.sum | 60 ----------- internal/provider/provider.go | 163 +++++++++++++++++++++-------- internal/provider/provider_test.go | 67 +++++++++--- 4 files changed, 170 insertions(+), 143 deletions(-) diff --git a/go.mod b/go.mod index e774705..bdd3f33 100644 --- a/go.mod +++ b/go.mod @@ -14,23 +14,13 @@ require ( ) require ( - github.com/BurntSushi/toml v1.2.1 // indirect - github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - github.com/armon/go-radix v1.0.0 // indirect - github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/cli v1.1.6 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -46,36 +36,25 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect github.com/hashicorp/terraform-json v0.22.1 // indirect - github.com/hashicorp/terraform-plugin-docs v0.19.4 // indirect github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/huandu/xstrings v1.3.3 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.0.0 // indirect - github.com/posener/complete v1.2.3 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/shopspring/decimal v1.3.1 // indirect - github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.1 // indirect - github.com/yuin/goldmark-meta v1.1.0 // indirect github.com/zclconf/go-cty v1.15.0 // indirect - go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect golang.org/x/crypto v0.26.0 // indirect - golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sync v0.8.0 // indirect @@ -86,6 +65,4 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.0 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index eb03bce..37706b8 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,5 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= -github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= @@ -19,12 +9,6 @@ github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= @@ -59,11 +43,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8= -github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -76,7 +55,6 @@ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUK github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= @@ -98,8 +76,6 @@ github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVW github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= -github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c= -github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= github.com/hashicorp/terraform-plugin-framework v1.11.0 h1:M7+9zBArexHFXDx/pKTxjE6n/2UCXY6b8FIq9ZYhwfE= github.com/hashicorp/terraform-plugin-framework v1.11.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= @@ -118,11 +94,6 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= @@ -145,9 +116,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= @@ -156,7 +124,6 @@ github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= @@ -165,25 +132,14 @@ github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -197,23 +153,14 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= -github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= -go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -221,7 +168,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -240,19 +186,16 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -279,8 +222,5 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/provider/provider.go b/internal/provider/provider.go index bf53c75..91316d4 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -26,10 +26,12 @@ func New() func() provider.Provider { type quayProvider struct{} type quayProviderModel struct { - Url types.String `tfsdk:"url"` - Token types.String `tfsdk:"token"` - ClientID types.String `tfsdk:"client_id"` - ClientSecret types.String `tfsdk:"client_secret"` + Url types.String `tfsdk:"url"` + Token types.String `tfsdk:"token"` + OAuth2Username types.String `tfsdk:"oauth2_username"` + OAuth2Password types.String `tfsdk:"oauth2_password"` + OAuth2ClientID types.String `tfsdk:"oauth2_client_id"` + OAuth2TokenURL types.String `tfsdk:"oauth2_token_url"` } func (p *quayProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { @@ -43,15 +45,23 @@ func (p *quayProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp Optional: true, Sensitive: true, }, - "client_id": schema.StringAttribute{ - Description: "Client ID. Used for generating a JWT OAuth2 access token with client credentials.", + "oauth2_username": schema.StringAttribute{ + Description: "OAuth2 username. Used for generating a JWT OAuth2 access token with password grant.", Optional: true, }, - "client_secret": schema.StringAttribute{ - Description: "Client secret. Used for generating a JWT OAuth2 access token with client credentials.", + "oauth2_password": schema.StringAttribute{ + Description: "OAuth2 password. Used for generating a JWT OAuth2 access token with password grant.", Optional: true, Sensitive: true, }, + "oauth2_client_id": schema.StringAttribute{ + Description: "OAuth2 client ID. Used for generating a JWT OAuth2 access token with password grant.", + Optional: true, + }, + "oauth2_token_url": schema.StringAttribute{ + Description: "OAuth2 token endpoint URL. Used for generating a JWT OAuth2 access token with password grant.", + Optional: true, + }, }} } @@ -65,20 +75,45 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ return } - quayURL := os.Getenv("QUAY_URL") - quayToken := os.Getenv("QUAY_TOKEN") + url := os.Getenv("QUAY_URL") + token := os.Getenv("QUAY_TOKEN") + oauth2Username := os.Getenv("QUAY_OAUTH2_USERNAME") + oauth2Password := os.Getenv("QUAY_OAUTH2_PASSWORD") + oauth2ClientID := os.Getenv("QUAY_OAUTH2_CLIENT_ID") + oauth2TokenURL := os.Getenv("QUAY_OAUTH2_TOKEN_URL") if !config.Url.IsNull() { - quayURL = config.Url.ValueString() + url = config.Url.ValueString() } if !config.Token.IsNull() { - quayToken = config.Token.ValueString() + token = config.Token.ValueString() + } + + if !config.OAuth2Username.IsNull() { + oauth2Username = config.OAuth2Username.ValueString() + } + + if !config.OAuth2Password.IsNull() { + oauth2Password = config.OAuth2Password.ValueString() } - ctx = tflog.SetField(ctx, "quay_url", quayURL) - ctx = tflog.SetField(ctx, "quay_token", quayToken) - ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "quay_token") + if !config.OAuth2ClientID.IsNull() { + oauth2ClientID = config.OAuth2ClientID.ValueString() + } + + if !config.OAuth2TokenURL.IsNull() { + oauth2TokenURL = config.OAuth2TokenURL.ValueString() + } + + ctx = tflog.SetField(ctx, "url", url) + ctx = tflog.SetField(ctx, "token", token) + ctx = tflog.SetField(ctx, "oauth2_username", oauth2Username) + ctx = tflog.SetField(ctx, "oauth2_password", oauth2Password) + ctx = tflog.SetField(ctx, "oauth2_client_id", oauth2ClientID) + ctx = tflog.SetField(ctx, "oauth2_token_url", oauth2TokenURL) + ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "token") + ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "oauth2_password") tflog.Debug(ctx, "Creating Quay client") @@ -88,13 +123,13 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ Debug: false, Servers: quay_api.ServerConfigurations{ { - URL: quayURL, + URL: url, Description: "No description provided", }, }, OperationServers: map[string]quay_api.ServerConfigurations{}, } - configuration.AddDefaultHeader("Authorization", "Bearer "+quayToken) + configuration.AddDefaultHeader("Authorization", "Bearer "+token) client := quay_api.NewAPIClient(configuration) resp.DataSourceData = client @@ -111,7 +146,8 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if config.Url.IsUnknown() || config.Token.IsUnknown() || config.ClientID.IsUnknown() || config.ClientSecret.IsUnknown() { + if config.Url.IsUnknown() || config.Token.IsUnknown() || config.OAuth2Username.IsUnknown() || config.OAuth2Password.IsUnknown() || + config.OAuth2ClientID.IsUnknown() || config.OAuth2TokenURL.IsUnknown() { resp.Diagnostics.AddError( "Unknown configuration values", "The provider cannot create the Quay client if any configuration values are unknown. "+ @@ -123,31 +159,40 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - quayURL := os.Getenv("QUAY_URL") - quayToken := os.Getenv("QUAY_TOKEN") - clientID := os.Getenv("QUAY_CLIENT_ID") - clientSecret := os.Getenv("QUAY_CLIENT_SECRET") + url := os.Getenv("QUAY_URL") + token := os.Getenv("QUAY_TOKEN") + oauth2Username := os.Getenv("QUAY_OAUTH2_USERNAME") + oauth2Password := os.Getenv("QUAY_OAUTH2_PASSWORD") + oauth2ClientID := os.Getenv("QUAY_OAUTH2_CLIENT_ID") + oauth2TokenURL := os.Getenv("QUAY_OAUTH2_TOKEN_URL") if !config.Url.IsNull() { - quayURL = config.Url.ValueString() + url = config.Url.ValueString() } if !config.Token.IsNull() { - quayToken = config.Token.ValueString() + token = config.Token.ValueString() } - if !config.ClientID.IsNull() { - clientID = config.ClientID.ValueString() + if !config.OAuth2Username.IsNull() { + oauth2Username = config.OAuth2Username.ValueString() } - if !config.ClientSecret.IsNull() { - clientSecret = config.ClientSecret.ValueString() + if !config.OAuth2Password.IsNull() { + oauth2Password = config.OAuth2Password.ValueString() } - if (quayToken != "" && clientID != "") || (quayToken != "" && clientSecret != "") { + if !config.OAuth2ClientID.IsNull() { + oauth2ClientID = config.OAuth2ClientID.ValueString() + } + + if !config.OAuth2TokenURL.IsNull() { + oauth2TokenURL = config.OAuth2TokenURL.ValueString() + } + if token != "" && (oauth2Username != "" || oauth2Password != "" || oauth2ClientID != "" || oauth2TokenURL != "") { resp.Diagnostics.AddError( - "Cannot specify token and client credentials", - "Token cannot be specified when a client ID or client secret are also specified. You must pick one authentication method.", + "Cannot specify token and OAuth2 credentials", + "Token cannot be specified when OAuth2 credentials are also specified. You must pick one authentication method.", ) } @@ -155,7 +200,7 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if quayURL == "" { + if url == "" { resp.Diagnostics.AddAttributeError( path.Root("url"), "Missing Quay URL", @@ -168,7 +213,7 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if !isValidURL(quayURL) { + if !isValidURL(url) { resp.Diagnostics.AddAttributeError( path.Root("url"), "Quay URL is not a valid URL", @@ -180,10 +225,36 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if quayToken == "" && (clientID == "" && clientSecret == "") { + if token == "" && oauth2Username == "" && oauth2Password == "" && oauth2ClientID == "" && oauth2TokenURL == "" { resp.Diagnostics.AddError( - "Missing Quay token and client credentials", - "The provider cannot create the Quay client as both the Quay token and client credentials are missing or empty.", + "Missing Quay token and OAuth2 credentials", + "The provider cannot create the Quay client as both the Quay token and OAuth2 credentials are missing or empty.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + + if token == "" && oauth2Username == "" { + resp.Diagnostics.AddAttributeError( + path.Root("oauth2_username"), + "Missing OAuth2 username", + "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 username."+ + "Set the OAuth2 username in the configuration or use the QUAY_OAUTH2_USERNAME environment variable.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + + if token == "" && oauth2Password == "" { + resp.Diagnostics.AddAttributeError( + path.Root("oauth2_password"), + "Missing OAuth2 password", + "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 password."+ + "Set the OAuth2 password in the configuration or use the QUAY_OAUTH2_PASSWORD environment variable.", ) } @@ -191,12 +262,12 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if clientID != "" && clientSecret == "" { + if token == "" && oauth2ClientID == "" { resp.Diagnostics.AddAttributeError( - path.Root("client_secret"), - "Missing client secret", - "The provider cannot create the Quay client as there is a missing value or empty value for the client secret."+ - "Set the client secret in the configuration or use the QUAY_CLIENT_SECRET environment variable.", + path.Root("oauth2_client_id"), + "Missing OAuth2 client ID", + "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 client ID."+ + "Set the OAuth2 client ID in the configuration or use the QUAY_OAUTH2_CLIENT_ID environment variable.", ) } @@ -204,12 +275,12 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate return } - if clientID == "" && clientSecret != "" { + if token == "" && oauth2TokenURL == "" { resp.Diagnostics.AddAttributeError( - path.Root("client_id"), - "Missing client ID", - "The provider cannot create the Quay client as there is a missing value or empty value for the client ID."+ - "Set the client ID in the configuration or use the QUAY_CLIENT_ID environment variable.", + path.Root("oauth2_token_url"), + "Missing OAuth2 token URL", + "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 token URL."+ + "Set the OAuth2 token URL in the configuration or use the QUAY_OAUTH2_TOKEN_URL environment variable.", ) } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index dd8a003..1d944c4 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -25,8 +25,10 @@ func TestAccProviderValidationWithoutENV(t *testing.T) { // unset QUAY_* environment variables t.Setenv("QUAY_URL", "") t.Setenv("QUAY_TOKEN", "") - t.Setenv("QUAY_CLIENT_ID", "") - t.Setenv("QUAY_CLIENT_SECRET", "") + t.Setenv("QUAY_OAUTH2_USERNAME", "") + t.Setenv("QUAY_OAUTH2_PASSWORD", "") + t.Setenv("QUAY_OAUTH2_CLIENT_ID", "") + t.Setenv("QUAY_OAUTH2_TOKEN_URL", "") resource.Test(t, resource.TestCase{ ExternalProviders: map[string]resource.ExternalProvider{ @@ -55,22 +57,21 @@ data "quay_organization" "provider_test" { `, ExpectError: regexp.MustCompile(".*Error: Unknown configuration values"), }, - // Token and client credentials + // Token and OAuth2 credentials { PlanOnly: true, Config: ` provider "quay" { url = "https://quay.example.com" token = "asdf" - client_id = "quay" - client_secret = "asdf" + oauth2_client_id = "quay" } data "quay_organization" "provider_test" { name = "provider_test" } `, - ExpectError: regexp.MustCompile(".*Error: Cannot specify token and client credentials"), + ExpectError: regexp.MustCompile(".*Error: Cannot specify token and OAuth2 credentials"), }, // No config values { @@ -99,7 +100,7 @@ data "quay_organization" "provider_test" { `, ExpectError: regexp.MustCompile(".*Error: Quay URL is not a valid URL"), }, - // Missing Quay token and client credentials + // Missing Quay token and OAuth2 credentials { PlanOnly: true, Config: ` @@ -111,37 +112,75 @@ data "quay_organization" "provider_test" { name = "provider_test" } `, - ExpectError: regexp.MustCompile(".*Error: Missing Quay token and client credentials"), + ExpectError: regexp.MustCompile(".*Error: Missing Quay token and OAuth2 credentials"), }, - // Missing client secret + // Missing OAuth2 username { PlanOnly: true, Config: ` provider "quay" { url = "https://quay.example.com" - client_id = "quay" + oauth2_password = "test" + oauth2_client_id = "quay" + oauth2_token_url = "https://auth.example.com/token" } data "quay_organization" "provider_test" { name = "provider_test" } `, - ExpectError: regexp.MustCompile(".*Error: Missing client secret"), + ExpectError: regexp.MustCompile(".*Error: Missing OAuth2 username"), }, - // Missing client ID + // Missing OAuth2 password { PlanOnly: true, Config: ` provider "quay" { url = "https://quay.example.com" - client_secret = "asdf" + oauth2_username = "test" + oauth2_client_id = "quay" + oauth2_token_url = "https://auth.example.com/token" } data "quay_organization" "provider_test" { name = "provider_test" } `, - ExpectError: regexp.MustCompile(".*Error: Missing client ID"), + ExpectError: regexp.MustCompile(".*Error: Missing OAuth2 password"), + }, + // Missing OAuth2 client ID + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" + oauth2_username = "test" + oauth2_password = "test" + oauth2_token_url = "https://auth.example.com/token" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing OAuth2 client ID"), + }, + // Missing OAuth2 token URL + { + PlanOnly: true, + Config: ` +provider "quay" { + url = "https://quay.example.com" + oauth2_username = "test" + oauth2_password = "test" + oauth2_client_id = "quay" +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Missing OAuth2 token URL"), }, }, }) From 065f3063e2d9952576f551d8be219db29e2bdeb8 Mon Sep 17 00:00:00 2001 From: David Debeau Date: Wed, 4 Sep 2024 16:46:39 -0500 Subject: [PATCH 4/7] Add code for retrieving an OAuth2 access token --- go.mod | 1 + go.sum | 4 ++++ internal/provider/provider.go | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/go.mod b/go.mod index bdd3f33..aa50f43 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.10.0 + golang.org/x/oauth2 v0.23.0 ) require ( diff --git a/go.sum b/go.sum index 37706b8..d1e0272 100644 --- a/go.sum +++ b/go.sum @@ -170,6 +170,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 91316d4..420a59e 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "golang.org/x/oauth2" "github.com/enthought/terraform-provider-quay/quay_api" ) @@ -129,6 +130,25 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ }, OperationServers: map[string]quay_api.ServerConfigurations{}, } + + if token == "" { + oauth2Config := &oauth2.Config{ + ClientID: oauth2ClientID, + Endpoint: oauth2.Endpoint{ + TokenURL: oauth2TokenURL, + }, + } + + oauth2Token, err := oauth2Config.PasswordCredentialsToken(ctx, oauth2Username, oauth2Password) + if err != nil { + resp.Diagnostics.AddError("Error retrieving OAuth2 access token", + "Error retrieving OAuth2 access token: "+err.Error()) + return + } + + token = oauth2Token.AccessToken + } + configuration.AddDefaultHeader("Authorization", "Bearer "+token) client := quay_api.NewAPIClient(configuration) From a482fc40f46cc53eca9930a43fdfbbee2e0987f3 Mon Sep 17 00:00:00 2001 From: David Debeau Date: Thu, 5 Sep 2024 09:49:15 -0500 Subject: [PATCH 5/7] Don't check if there is an error before returning --- internal/provider/provider.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 420a59e..c00d37e 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -173,9 +173,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client if any configuration values are unknown. "+ "Either target apply the source of the unknown value(s) first, set the value(s) statically in the configuration, or set the appropriate environment variable(s).", ) - } - - if resp.Diagnostics.HasError() { return } @@ -214,9 +211,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "Cannot specify token and OAuth2 credentials", "Token cannot be specified when OAuth2 credentials are also specified. You must pick one authentication method.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -227,9 +221,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client as there is a missing or empty value for the Quay URL. "+ "Set the URL in the configuration or use the QUAY_URL environment variable.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -239,9 +230,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "Quay URL is not a valid URL", "The provider cannot create the Quay client as the URL provided is not valid.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -250,9 +238,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "Missing Quay token and OAuth2 credentials", "The provider cannot create the Quay client as both the Quay token and OAuth2 credentials are missing or empty.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -263,9 +248,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 username."+ "Set the OAuth2 username in the configuration or use the QUAY_OAUTH2_USERNAME environment variable.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -276,9 +258,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 password."+ "Set the OAuth2 password in the configuration or use the QUAY_OAUTH2_PASSWORD environment variable.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -289,9 +268,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 client ID."+ "Set the OAuth2 client ID in the configuration or use the QUAY_OAUTH2_CLIENT_ID environment variable.", ) - } - - if resp.Diagnostics.HasError() { return } @@ -302,9 +278,6 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate "The provider cannot create the Quay client as there is a missing value or empty value for the OAuth2 token URL."+ "Set the OAuth2 token URL in the configuration or use the QUAY_OAUTH2_TOKEN_URL environment variable.", ) - } - - if resp.Diagnostics.HasError() { return } } From a197f1d4c600633f2705b7c21c9b9ca47b17697a Mon Sep 17 00:00:00 2001 From: David Debeau Date: Thu, 5 Sep 2024 13:20:24 -0500 Subject: [PATCH 6/7] Remove exportloopref linter since it's no longer relevant in Go 1.22 --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index af1e14a..1890a55 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,7 +15,6 @@ linters: enable: - durationcheck - errcheck - - exportloopref - forcetypeassert - godot - gofmt From 03ca9d84473ece9faa81dbc57e8006c85e43454d Mon Sep 17 00:00:00 2001 From: David Debeau Date: Thu, 5 Sep 2024 13:56:37 -0500 Subject: [PATCH 7/7] Update documentation --- docs/index.md | 8 +++++ go.mod | 23 ++++++++++++++ go.sum | 60 +++++++++++++++++++++++++++++++++++ internal/provider/provider.go | 22 +++++++------ templates/index.md.tmpl | 4 +++ 5 files changed, 108 insertions(+), 9 deletions(-) diff --git a/docs/index.md b/docs/index.md index 8ba932b..220c3e4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,6 +14,10 @@ an `OAuth 2 Access Token`. Since there is no mechanism in Quay for creating appl is recommended to create a separate organization and application for Terraform. Be sure to create the `OAuth 2 Access Token` using a service account since the token will be tied to that account. +An alternative method of authentication is to use JWT OAuth2 access tokens that are generated by an external Identity +Provider (Quay must be configured to trust this Identity Provider). Only password grant is supported at this time. +Specify the `oauth2_*` set of variables to enable this feature. + ## Example Usage ```terraform @@ -27,6 +31,10 @@ provider "quay" { ### Optional +- `oauth2_client_id` (String) OAuth2 client ID. Used for generating a JWT OAuth2 access token with password grant. May also be provided via the QUAY_OAUTH2_CLIENT_ID environment variable. +- `oauth2_password` (String, Sensitive) OAuth2 password. Used for generating a JWT OAuth2 access token with password grant. May also be provided via the QUAY_OAUTH2_PASSWORD environment variable. +- `oauth2_token_url` (String) OAuth2 token endpoint URL. Used for generating a JWT OAuth2 access token with password grant. May also be provided via the QUAY_OAUTH2_TOKEN_URL environment variable. +- `oauth2_username` (String) OAuth2 username. Used for generating a JWT OAuth2 access token with password grant. May also be provided via the QUAY_OAUTH2_USERNAME environment variable. - `token` (String, Sensitive) Quay token. May also be provided via the QUAY_TOKEN environment variable. - `url` (String) Quay URL. May also be provided via the QUAY_URL environment variable. Example: https://quay.example.com diff --git a/go.mod b/go.mod index aa50f43..55236ce 100644 --- a/go.mod +++ b/go.mod @@ -15,13 +15,23 @@ require ( ) require ( + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/cli v1.1.6 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -37,25 +47,36 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect github.com/hashicorp/terraform-json v0.22.1 // indirect + github.com/hashicorp/terraform-plugin-docs v0.19.4 // indirect github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.0.0 // indirect + github.com/posener/complete v1.2.3 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yuin/goldmark v1.7.1 // indirect + github.com/yuin/goldmark-meta v1.1.0 // indirect github.com/zclconf/go-cty v1.15.0 // indirect + go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sync v0.8.0 // indirect @@ -66,4 +87,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.0 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d1e0272..b47f40f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,15 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= +github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= @@ -9,6 +19,12 @@ github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= @@ -43,6 +59,11 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8= +github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -55,6 +76,7 @@ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUK github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= @@ -76,6 +98,8 @@ github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVW github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= +github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c= +github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= github.com/hashicorp/terraform-plugin-framework v1.11.0 h1:M7+9zBArexHFXDx/pKTxjE6n/2UCXY6b8FIq9ZYhwfE= github.com/hashicorp/terraform-plugin-framework v1.11.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= @@ -94,6 +118,11 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= @@ -116,6 +145,9 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= @@ -124,6 +156,7 @@ github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= @@ -132,14 +165,25 @@ github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -153,14 +197,23 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= +github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= +github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= +go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -168,6 +221,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= @@ -190,16 +244,19 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -226,5 +283,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/provider/provider.go b/internal/provider/provider.go index c00d37e..0705ca7 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -47,21 +47,25 @@ func (p *quayProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp Sensitive: true, }, "oauth2_username": schema.StringAttribute{ - Description: "OAuth2 username. Used for generating a JWT OAuth2 access token with password grant.", - Optional: true, + Description: "OAuth2 username. Used for generating a JWT OAuth2 access token with password grant. " + + "May also be provided via the QUAY_OAUTH2_USERNAME environment variable.", + Optional: true, }, "oauth2_password": schema.StringAttribute{ - Description: "OAuth2 password. Used for generating a JWT OAuth2 access token with password grant.", - Optional: true, - Sensitive: true, + Description: "OAuth2 password. Used for generating a JWT OAuth2 access token with password grant. " + + "May also be provided via the QUAY_OAUTH2_PASSWORD environment variable.", + Optional: true, + Sensitive: true, }, "oauth2_client_id": schema.StringAttribute{ - Description: "OAuth2 client ID. Used for generating a JWT OAuth2 access token with password grant.", - Optional: true, + Description: "OAuth2 client ID. Used for generating a JWT OAuth2 access token with password grant. " + + "May also be provided via the QUAY_OAUTH2_CLIENT_ID environment variable.", + Optional: true, }, "oauth2_token_url": schema.StringAttribute{ - Description: "OAuth2 token endpoint URL. Used for generating a JWT OAuth2 access token with password grant.", - Optional: true, + Description: "OAuth2 token endpoint URL. Used for generating a JWT OAuth2 access token with password grant. " + + "May also be provided via the QUAY_OAUTH2_TOKEN_URL environment variable.", + Optional: true, }, }} } diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index c26af47..1fef708 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -14,6 +14,10 @@ an `OAuth 2 Access Token`. Since there is no mechanism in Quay for creating appl is recommended to create a separate organization and application for Terraform. Be sure to create the `OAuth 2 Access Token` using a service account since the token will be tied to that account. +An alternative method of authentication is to use JWT OAuth2 access tokens that are generated by an external Identity +Provider (Quay must be configured to trust this Identity Provider). Only password grant is supported at this time. +Specify the `oauth2_*` set of variables to enable this feature. + ## Example Usage {{ tffile "examples/provider/provider.tf" }}