diff --git a/internal/btpcli/client.go b/internal/btpcli/client.go index ffc244b7..647364c3 100644 --- a/internal/btpcli/client.go +++ b/internal/btpcli/client.go @@ -34,16 +34,16 @@ func NewV2ClientWithHttpClient(client *http.Client, serverURL *url.URL) *v2Clien } const ( - HeaderCorrelationID string = "X-CorrelationId" + HeaderCorrelationID string = "X-Correlationid" HeaderIDToken string = "X-Id-Token" - HeaderCLIFormat string = "X-CPCLI-Format" - HeaderCLIRefreshToken string = "X-CPCLI-RefreshToken" - HeaderCLIReplacementRefreshToken string = "X-CPCLI-ReplacementRefreshtoken" - HeaderCLISubdomain string = "X-CPCLI-Subdomain" - HeaderCLICustomIDP string = "X-CPCLI-CustomIdp" - HeaderCLIBackendStatus string = "X-CPCLI-Backend-Status" - HeaderCLIBackendMessage string = "X-CPCLI-Backend-Message" - HeaderCLIBackendMediaType string = "X-CPCLI-Backend-MediaType" + HeaderCLIFormat string = "X-Cpcli-Format" + HeaderCLIRefreshToken string = "X-Cpcli-Refreshtoken" + HeaderCLIReplacementRefreshToken string = "X-Cpcli-Replacementrefreshtoken" + HeaderCLISubdomain string = "X-Cpcli-Subdomain" + HeaderCLICustomIDP string = "X-Cpcli-Customidp" + HeaderCLIBackendStatus string = "X-Cpcli-Backend-Status" + HeaderCLIBackendMessage string = "X-Cpcli-Backend-Message" + HeaderCLIBackendMediaType string = "X-Cpcli-Backend-Mediatype" ) const cliTargetProtocolVersion string = "v2.38.0" diff --git a/internal/provider/provider.go b/internal/provider/provider.go index e058e268..f1e1a99c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -76,6 +76,8 @@ func (p *btpcliProvider) Metadata(_ context.Context, _ provider.MetadataRequest, } func (p *btpcliProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + const unableToCreateClient = "unableToCreateClient" + // Retrieve provider data from configuration var config providerData diags := req.Config.Get(ctx, &config) @@ -93,17 +95,30 @@ func (p *btpcliProvider) Configure(ctx context.Context, req provider.ConfigureRe u, err := url.Parse(selectedCLIServerURL) // TODO move to NewV2Client if err != nil { - resp.Diagnostics.AddError("Unable to create Client", fmt.Sprintf("%s", err)) + resp.Diagnostics.AddError(unableToCreateClient, fmt.Sprintf("%s", err)) return } client := btpcli.NewClientFacade(btpcli.NewV2ClientWithHttpClient(p.httpClient, u)) client.UserAgent = fmt.Sprintf("Terraform/%s terraform-provider-btp/%s", req.TerraformVersion, version.ProviderVersion) + // User may provide an idp to the provider + var idp string + if config.IdentityProvider.IsUnknown() { + resp.Diagnostics.AddWarning(unableToCreateClient, "Cannot use unknown value as identity provider") + return + } + + if config.IdentityProvider.IsNull() { + idp = os.Getenv("BTP_IDP") + } else { + idp = config.IdentityProvider.ValueString() + } + // User must provide a username to the provider var username string if config.Username.IsUnknown() { - resp.Diagnostics.AddWarning("Unable to create client", "Cannot use unknown value as client_certificate") + resp.Diagnostics.AddWarning(unableToCreateClient, "Cannot use unknown value as username") return } @@ -116,7 +131,7 @@ func (p *btpcliProvider) Configure(ctx context.Context, req provider.ConfigureRe // User must provide a password to the provider var password string if config.Password.IsUnknown() { - resp.Diagnostics.AddWarning("Unable to create client", "Cannot use unknown value as password") + resp.Diagnostics.AddWarning(unableToCreateClient, "Cannot use unknown value as password") return } @@ -127,12 +142,12 @@ func (p *btpcliProvider) Configure(ctx context.Context, req provider.ConfigureRe } if len(username) == 0 || len(password) == 0 { - resp.Diagnostics.AddError("Unable to create Client", "globalaccount, username and password must be given.") + resp.Diagnostics.AddError(unableToCreateClient, "globalaccount, username and password must be given.") return } - if _, err = client.Login(ctx, btpcli.NewLoginRequestWithCustomIDP(config.IdentityProvider.ValueString(), config.GlobalAccount.ValueString(), username, password)); err != nil { - resp.Diagnostics.AddError("Unable to create Client", fmt.Sprintf("%s", err)) + if _, err = client.Login(ctx, btpcli.NewLoginRequestWithCustomIDP(idp, config.GlobalAccount.ValueString(), username, password)); err != nil { + resp.Diagnostics.AddError(unableToCreateClient, fmt.Sprintf("%s", err)) return } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 05206c21..07933014 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/SAP/terraform-provider-btp/internal/btpcli" "github.com/SAP/terraform-provider-btp/internal/validation/uuidvalidator" "github.com/stretchr/testify/assert" @@ -39,6 +40,7 @@ provider "btp" { globalaccount = "terraformintcanary" username = "john.doe@int.test" password = "redacted" + idp = "" } `, cliServerURL) } @@ -62,11 +64,25 @@ func setupVCR(t *testing.T, cassetteName string) *recorder.Recorder { hookRedactIntegrationUserCredentials := func(i *cassette.Interaction) error { intUser := os.Getenv("BTP_USERNAME") intUserPwd := os.Getenv("BTP_PASSWORD") + intUserIdp := os.Getenv("BTP_IDP") firstName, lastName := getNameFromEmail(intUser) if strings.Contains(i.Request.URL, "/login/") { i.Request.Body = strings.ReplaceAll(i.Request.Body, intUserPwd, "redacted") + // TODO #277 the custom idp and issuer values should be redacted to some special value + // for now the custom idp is replaced by the empty string and the issuer by "accounts.sap.com" to keep + // existing fixtures working that were recorded without selecting a custom idp during login + i.Request.Body = strings.ReplaceAll(i.Request.Body, "\"customIdp\":\""+intUserIdp+"\"", "\"customIdp\":\"\"") + i.Response.Body = strings.ReplaceAll(i.Response.Body, "\"issuer\":\""+intUserIdp+"\"", "\"issuer\":\"accounts.sap.com\"") + i.Response.Body = strings.ReplaceAll(i.Response.Body, "\"issuer\":\""+intUserIdp+".accounts400.ondemand.com\"", "\"issuer\":\"accounts.sap.com\"") + } + + if _, exists := i.Request.Headers[btpcli.HeaderCLICustomIDP]; exists { + // TODO #277 the custom idp header value should be redacted to some special value + // for now the header is replaced by the empty string to keep existing fixtures working that were + // recorded without selecting a custom idp during login + i.Request.Headers.Set(btpcli.HeaderCLICustomIDP, "") } i.Request.Body = strings.ReplaceAll(i.Request.Body, intUser, "john.doe@int.test")