mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-22 11:17:35 -05:00
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
// 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"
|
|
"os"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
|
"github.com/opentofu/opentofu/internal/httpclient"
|
|
"github.com/opentofu/opentofu/internal/tfdiags"
|
|
)
|
|
|
|
type MSIAuthConfig struct {
|
|
UseMsi bool
|
|
Endpoint string
|
|
}
|
|
|
|
type managedIdentityAuth struct{}
|
|
|
|
var _ AuthMethod = &managedIdentityAuth{}
|
|
|
|
func (cred *managedIdentityAuth) Name() string {
|
|
return "Managed Service Identity Auth"
|
|
}
|
|
|
|
// msiTokenCredentialWrapper wraps the ManagedIdentityCredential with a bit of logic
|
|
// to manage the MSI_ENDPOINT environment variable. See the reconcileMSIEndpoint documentation
|
|
// for details.
|
|
type msiTokenCredentialWrapper struct {
|
|
cred *azidentity.ManagedIdentityCredential
|
|
|
|
Endpoint string
|
|
}
|
|
|
|
func (cred *managedIdentityAuth) Construct(ctx context.Context, config *Config) (azcore.TokenCredential, error) {
|
|
client := httpclient.New(ctx)
|
|
c, err := azidentity.NewManagedIdentityCredential(
|
|
&azidentity.ManagedIdentityCredentialOptions{
|
|
ClientOptions: clientOptions(client, config.CloudConfig),
|
|
},
|
|
)
|
|
endpoint := reconcileMSIEndpoint(config.Endpoint)
|
|
if endpoint != "" {
|
|
return &msiTokenCredentialWrapper{
|
|
cred: c,
|
|
Endpoint: endpoint,
|
|
}, err
|
|
}
|
|
return c, err
|
|
}
|
|
|
|
const MSI_ENDPOINT string = "MSI_ENDPOINT"
|
|
|
|
func (credWrapper *msiTokenCredentialWrapper) GetToken(ctx context.Context, options policy.TokenRequestOptions) (token azcore.AccessToken, err error) {
|
|
os.Setenv(MSI_ENDPOINT, credWrapper.Endpoint)
|
|
token, err = credWrapper.cred.GetToken(ctx, options)
|
|
os.Unsetenv(MSI_ENDPOINT)
|
|
return
|
|
}
|
|
|
|
// reconcileMSIEndpoint helps to set MSI_ENDPOINT, if it has not already set.
|
|
// This is a bit of a hack, but we do this to ensure backwards compatibility.
|
|
// The microsoft-authentication-library-for-go uses the MSI_ENDPOINT environment variable
|
|
// to automatically set the endpoint, in the case OpenTofu is running in
|
|
// Cloud Shell or AzureML. There isn't another way to get the endpoint information
|
|
// to the library...
|
|
func reconcileMSIEndpoint(msiEndpointFromConfig string) string {
|
|
_, ok := os.LookupEnv(MSI_ENDPOINT)
|
|
if ok {
|
|
return ""
|
|
}
|
|
return msiEndpointFromConfig
|
|
}
|
|
|
|
func (cred *managedIdentityAuth) Validate(_ context.Context, config *Config) tfdiags.Diagnostics {
|
|
var diags tfdiags.Diagnostics
|
|
if !config.MSIAuthConfig.UseMsi {
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
tfdiags.Error,
|
|
"Invalid Azure Managed Service Identity Auth",
|
|
"The Managed Service Identity (MSI) needs to have \"use_msi\" (or ARM_USE_MSI) set to true in order to be used.",
|
|
))
|
|
}
|
|
return diags
|
|
}
|
|
|
|
func (cred *managedIdentityAuth) AugmentConfig(_ context.Context, config *Config) error {
|
|
return checkNamesForAccessKeyCredentials(config.StorageAddresses)
|
|
}
|