mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
275 lines
9.4 KiB
Go
275 lines
9.4 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package azure
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/placeholderplaceholderplaceholder/opentf/internal/backend"
|
|
"github.com/placeholderplaceholderplaceholder/opentf/internal/legacy/helper/schema"
|
|
)
|
|
|
|
// New creates a new backend for Azure remote state.
|
|
func New() backend.Backend {
|
|
s := &schema.Backend{
|
|
Schema: map[string]*schema.Schema{
|
|
"storage_account_name": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "The name of the storage account.",
|
|
},
|
|
|
|
"container_name": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "The container name.",
|
|
},
|
|
|
|
"key": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "The blob key.",
|
|
},
|
|
|
|
"metadata_host": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_METADATA_HOST", ""),
|
|
Description: "The Metadata URL which will be used to obtain the Cloud Environment.",
|
|
},
|
|
|
|
"environment": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Azure cloud environment.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_ENVIRONMENT", "public"),
|
|
},
|
|
|
|
"access_key": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The access key.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_ACCESS_KEY", ""),
|
|
},
|
|
|
|
"sas_token": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "A SAS Token used to interact with the Blob Storage Account.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_SAS_TOKEN", ""),
|
|
},
|
|
|
|
"snapshot": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
Description: "Enable/Disable automatic blob snapshotting",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_SNAPSHOT", false),
|
|
},
|
|
|
|
"resource_group_name": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The resource group name.",
|
|
},
|
|
|
|
"client_id": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Client ID.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_ID", ""),
|
|
},
|
|
|
|
"endpoint": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "A custom Endpoint used to access the Azure Resource Manager API's.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_ENDPOINT", ""),
|
|
},
|
|
|
|
"subscription_id": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Subscription ID.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_SUBSCRIPTION_ID", ""),
|
|
},
|
|
|
|
"tenant_id": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Tenant ID.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_TENANT_ID", ""),
|
|
},
|
|
|
|
// Service Principal (Client Certificate) specific
|
|
"client_certificate_password": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The password associated with the Client Certificate specified in `client_certificate_path`",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PASSWORD", ""),
|
|
},
|
|
"client_certificate_path": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The path to the PFX file used as the Client Certificate when authenticating as a Service Principal",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PATH", ""),
|
|
},
|
|
|
|
// Service Principal (Client Secret) specific
|
|
"client_secret": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Client Secret.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_SECRET", ""),
|
|
},
|
|
|
|
// Managed Service Identity specific
|
|
"use_msi": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
Description: "Should Managed Service Identity be used?",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_MSI", false),
|
|
},
|
|
"msi_endpoint": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Description: "The Managed Service Identity Endpoint.",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_MSI_ENDPOINT", ""),
|
|
},
|
|
|
|
// OIDC auth specific fields
|
|
"use_oidc": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_OIDC", false),
|
|
Description: "Allow OIDC to be used for authentication",
|
|
},
|
|
"oidc_token": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_OIDC_TOKEN", ""),
|
|
Description: "A generic JWT token that can be used for OIDC authentication. Should not be used in conjunction with `oidc_request_token`.",
|
|
},
|
|
"oidc_token_file_path": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_OIDC_TOKEN_FILE_PATH", ""),
|
|
Description: "Path to file containing a generic JWT token that can be used for OIDC authentication. Should not be used in conjunction with `oidc_request_token`.",
|
|
},
|
|
"oidc_request_url": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_URL", "ACTIONS_ID_TOKEN_REQUEST_URL"}, ""),
|
|
Description: "The URL of the OIDC provider from which to request an ID token. Needs to be used in conjunction with `oidc_request_token`. This is meant to be used for Github Actions.",
|
|
},
|
|
"oidc_request_token": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_TOKEN", "ACTIONS_ID_TOKEN_REQUEST_TOKEN"}, ""),
|
|
Description: "The bearer token to use for the request to the OIDC providers `oidc_request_url` URL to fetch an ID token. Needs to be used in conjunction with `oidc_request_url`. This is meant to be used for Github Actions.",
|
|
},
|
|
|
|
// Feature Flags
|
|
"use_azuread_auth": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
Description: "Should OpenTF use AzureAD Authentication to access the Blob?",
|
|
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AZUREAD", false),
|
|
},
|
|
},
|
|
}
|
|
|
|
result := &Backend{Backend: s}
|
|
result.Backend.ConfigureFunc = result.configure
|
|
return result
|
|
}
|
|
|
|
type Backend struct {
|
|
*schema.Backend
|
|
|
|
// The fields below are set from configure
|
|
armClient *ArmClient
|
|
containerName string
|
|
keyName string
|
|
accountName string
|
|
snapshot bool
|
|
}
|
|
|
|
type BackendConfig struct {
|
|
// Required
|
|
StorageAccountName string
|
|
|
|
// Optional
|
|
AccessKey string
|
|
ClientID string
|
|
ClientCertificatePassword string
|
|
ClientCertificatePath string
|
|
ClientSecret string
|
|
CustomResourceManagerEndpoint string
|
|
MetadataHost string
|
|
Environment string
|
|
MsiEndpoint string
|
|
OIDCToken string
|
|
OIDCTokenFilePath string
|
|
OIDCRequestURL string
|
|
OIDCRequestToken string
|
|
ResourceGroupName string
|
|
SasToken string
|
|
SubscriptionID string
|
|
TenantID string
|
|
UseMsi bool
|
|
UseOIDC bool
|
|
UseAzureADAuthentication bool
|
|
}
|
|
|
|
func (b *Backend) configure(ctx context.Context) error {
|
|
if b.containerName != "" {
|
|
return nil
|
|
}
|
|
|
|
// Grab the resource data
|
|
data := schema.FromContextBackendConfig(ctx)
|
|
b.containerName = data.Get("container_name").(string)
|
|
b.accountName = data.Get("storage_account_name").(string)
|
|
b.keyName = data.Get("key").(string)
|
|
b.snapshot = data.Get("snapshot").(bool)
|
|
|
|
config := BackendConfig{
|
|
AccessKey: data.Get("access_key").(string),
|
|
ClientID: data.Get("client_id").(string),
|
|
ClientCertificatePassword: data.Get("client_certificate_password").(string),
|
|
ClientCertificatePath: data.Get("client_certificate_path").(string),
|
|
ClientSecret: data.Get("client_secret").(string),
|
|
CustomResourceManagerEndpoint: data.Get("endpoint").(string),
|
|
MetadataHost: data.Get("metadata_host").(string),
|
|
Environment: data.Get("environment").(string),
|
|
MsiEndpoint: data.Get("msi_endpoint").(string),
|
|
OIDCToken: data.Get("oidc_token").(string),
|
|
OIDCTokenFilePath: data.Get("oidc_token_file_path").(string),
|
|
OIDCRequestURL: data.Get("oidc_request_url").(string),
|
|
OIDCRequestToken: data.Get("oidc_request_token").(string),
|
|
ResourceGroupName: data.Get("resource_group_name").(string),
|
|
SasToken: data.Get("sas_token").(string),
|
|
StorageAccountName: data.Get("storage_account_name").(string),
|
|
SubscriptionID: data.Get("subscription_id").(string),
|
|
TenantID: data.Get("tenant_id").(string),
|
|
UseMsi: data.Get("use_msi").(bool),
|
|
UseOIDC: data.Get("use_oidc").(bool),
|
|
UseAzureADAuthentication: data.Get("use_azuread_auth").(bool),
|
|
}
|
|
|
|
armClient, err := buildArmClient(context.TODO(), config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
thingsNeededToLookupAccessKeySpecified := config.AccessKey == "" && config.SasToken == "" && config.ResourceGroupName == ""
|
|
if thingsNeededToLookupAccessKeySpecified && !config.UseAzureADAuthentication {
|
|
return fmt.Errorf("Either an Access Key / SAS Token or the Resource Group for the Storage Account must be specified - or Azure AD Authentication must be enabled")
|
|
}
|
|
|
|
b.armClient = armClient
|
|
return nil
|
|
}
|