// Copyright (c) The OpenTofu Authors // SPDX-License-Identifier: MPL-2.0 // Copyright (c) 2023 HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package auth import ( "context" "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/opentofu/opentofu/internal/httpclient" "github.com/opentofu/opentofu/internal/tfdiags" ) type ClientSecretCredentialAuthConfig struct { ClientID string ClientIDFilePath string ClientSecret string ClientSecretFilePath string } type clientSecretCredentialAuth struct{} var _ AuthMethod = &clientSecretCredentialAuth{} func (cred *clientSecretCredentialAuth) Name() string { return "Client Secret Auth" } func (cred *clientSecretCredentialAuth) Construct(ctx context.Context, config *Config) (azcore.TokenCredential, error) { client := httpclient.New(ctx) clientId, err := consolidateClientId(config) if err != nil { // This should never happen; this is checked in the Validate function return nil, err } clientSecret, err := consolidateClientSecret(config) if err != nil { // This should never happen; this is checked in the Validate function return nil, err } return azidentity.NewClientSecretCredential( config.StorageAddresses.TenantID, clientId, clientSecret, &azidentity.ClientSecretCredentialOptions{ ClientOptions: clientOptions(client, config.CloudConfig), }, ) } func (cred *clientSecretCredentialAuth) Validate(_ context.Context, config *Config) tfdiags.Diagnostics { var diags tfdiags.Diagnostics if config.StorageAddresses.TenantID == "" { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid Azure Client Secret Auth", "Tenant ID is missing.", )) } _, err := consolidateClientId(config) if err != nil { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid Azure Client Secret Auth", fmt.Sprintf("The Client ID is misconfigured: %s.", tfdiags.FormatError(err)), )) } _, err = consolidateClientSecret(config) if err != nil { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid Azure Client Secret Auth", fmt.Sprintf("The Client Secret is misconfigured: %s.", tfdiags.FormatError(err)), )) } return diags } func (cred *clientSecretCredentialAuth) AugmentConfig(_ context.Context, config *Config) error { return checkNamesForAccessKeyCredentials(config.StorageAddresses) } func consolidateClientId(config *Config) (string, error) { return consolidateFileAndValue(config.ClientID, config.ClientIDFilePath, "client ID", false) } func consolidateClientSecret(config *Config) (string, error) { return consolidateFileAndValue(config.ClientSecret, config.ClientSecretFilePath, "client secret", false) }