github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/backend/remote-state/azure/backend.go (about)

     1  package azure
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform/internal/backend"
     8  	"github.com/hashicorp/terraform/internal/legacy/helper/schema"
     9  )
    10  
    11  // New creates a new backend for Azure remote state.
    12  func New() backend.Backend {
    13  	s := &schema.Backend{
    14  		Schema: map[string]*schema.Schema{
    15  			"storage_account_name": {
    16  				Type:        schema.TypeString,
    17  				Required:    true,
    18  				Description: "The name of the storage account.",
    19  			},
    20  
    21  			"container_name": {
    22  				Type:        schema.TypeString,
    23  				Required:    true,
    24  				Description: "The container name.",
    25  			},
    26  
    27  			"key": {
    28  				Type:        schema.TypeString,
    29  				Required:    true,
    30  				Description: "The blob key.",
    31  			},
    32  
    33  			"metadata_host": {
    34  				Type:        schema.TypeString,
    35  				Required:    true,
    36  				DefaultFunc: schema.EnvDefaultFunc("ARM_METADATA_HOST", ""),
    37  				Description: "The Metadata URL which will be used to obtain the Cloud Environment.",
    38  			},
    39  
    40  			"environment": {
    41  				Type:        schema.TypeString,
    42  				Optional:    true,
    43  				Description: "The Azure cloud environment.",
    44  				DefaultFunc: schema.EnvDefaultFunc("ARM_ENVIRONMENT", "public"),
    45  			},
    46  
    47  			"access_key": {
    48  				Type:        schema.TypeString,
    49  				Optional:    true,
    50  				Description: "The access key.",
    51  				DefaultFunc: schema.EnvDefaultFunc("ARM_ACCESS_KEY", ""),
    52  			},
    53  
    54  			"sas_token": {
    55  				Type:        schema.TypeString,
    56  				Optional:    true,
    57  				Description: "A SAS Token used to interact with the Blob Storage Account.",
    58  				DefaultFunc: schema.EnvDefaultFunc("ARM_SAS_TOKEN", ""),
    59  			},
    60  
    61  			"snapshot": {
    62  				Type:        schema.TypeBool,
    63  				Optional:    true,
    64  				Description: "Enable/Disable automatic blob snapshotting",
    65  				DefaultFunc: schema.EnvDefaultFunc("ARM_SNAPSHOT", false),
    66  			},
    67  
    68  			"resource_group_name": {
    69  				Type:        schema.TypeString,
    70  				Optional:    true,
    71  				Description: "The resource group name.",
    72  			},
    73  
    74  			"client_id": {
    75  				Type:        schema.TypeString,
    76  				Optional:    true,
    77  				Description: "The Client ID.",
    78  				DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_ID", ""),
    79  			},
    80  
    81  			"endpoint": {
    82  				Type:        schema.TypeString,
    83  				Optional:    true,
    84  				Description: "A custom Endpoint used to access the Azure Resource Manager API's.",
    85  				DefaultFunc: schema.EnvDefaultFunc("ARM_ENDPOINT", ""),
    86  			},
    87  
    88  			"subscription_id": {
    89  				Type:        schema.TypeString,
    90  				Optional:    true,
    91  				Description: "The Subscription ID.",
    92  				DefaultFunc: schema.EnvDefaultFunc("ARM_SUBSCRIPTION_ID", ""),
    93  			},
    94  
    95  			"tenant_id": {
    96  				Type:        schema.TypeString,
    97  				Optional:    true,
    98  				Description: "The Tenant ID.",
    99  				DefaultFunc: schema.EnvDefaultFunc("ARM_TENANT_ID", ""),
   100  			},
   101  
   102  			// Service Principal (Client Certificate) specific
   103  			"client_certificate_password": {
   104  				Type:        schema.TypeString,
   105  				Optional:    true,
   106  				Description: "The password associated with the Client Certificate specified in `client_certificate_path`",
   107  				DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PASSWORD", ""),
   108  			},
   109  			"client_certificate_path": {
   110  				Type:        schema.TypeString,
   111  				Optional:    true,
   112  				Description: "The path to the PFX file used as the Client Certificate when authenticating as a Service Principal",
   113  				DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PATH", ""),
   114  			},
   115  
   116  			// Service Principal (Client Secret) specific
   117  			"client_secret": {
   118  				Type:        schema.TypeString,
   119  				Optional:    true,
   120  				Description: "The Client Secret.",
   121  				DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_SECRET", ""),
   122  			},
   123  
   124  			// Managed Service Identity specific
   125  			"use_msi": {
   126  				Type:        schema.TypeBool,
   127  				Optional:    true,
   128  				Description: "Should Managed Service Identity be used?",
   129  				DefaultFunc: schema.EnvDefaultFunc("ARM_USE_MSI", false),
   130  			},
   131  			"msi_endpoint": {
   132  				Type:        schema.TypeString,
   133  				Optional:    true,
   134  				Description: "The Managed Service Identity Endpoint.",
   135  				DefaultFunc: schema.EnvDefaultFunc("ARM_MSI_ENDPOINT", ""),
   136  			},
   137  
   138  			// OIDC auth specific fields
   139  			"use_oidc": {
   140  				Type:        schema.TypeBool,
   141  				Optional:    true,
   142  				DefaultFunc: schema.EnvDefaultFunc("ARM_USE_OIDC", false),
   143  				Description: "Allow OIDC to be used for authentication",
   144  			},
   145  			"oidc_token": {
   146  				Type:        schema.TypeString,
   147  				Optional:    true,
   148  				DefaultFunc: schema.EnvDefaultFunc("ARM_OIDC_TOKEN", ""),
   149  				Description: "A generic JWT token that can be used for OIDC authentication. Should not be used in conjunction with `oidc_request_token`.",
   150  			},
   151  			"oidc_token_file_path": {
   152  				Type:        schema.TypeString,
   153  				Optional:    true,
   154  				DefaultFunc: schema.EnvDefaultFunc("ARM_OIDC_TOKEN_FILE_PATH", ""),
   155  				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`.",
   156  			},
   157  			"oidc_request_url": {
   158  				Type:        schema.TypeString,
   159  				Optional:    true,
   160  				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_URL", "ACTIONS_ID_TOKEN_REQUEST_URL"}, ""),
   161  				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.",
   162  			},
   163  			"oidc_request_token": {
   164  				Type:        schema.TypeString,
   165  				Optional:    true,
   166  				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_TOKEN", "ACTIONS_ID_TOKEN_REQUEST_TOKEN"}, ""),
   167  				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.",
   168  			},
   169  
   170  			// Feature Flags
   171  			"use_azuread_auth": {
   172  				Type:        schema.TypeBool,
   173  				Optional:    true,
   174  				Description: "Should Terraform use AzureAD Authentication to access the Blob?",
   175  				DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AZUREAD", false),
   176  			},
   177  		},
   178  	}
   179  
   180  	result := &Backend{Backend: s}
   181  	result.Backend.ConfigureFunc = result.configure
   182  	return result
   183  }
   184  
   185  type Backend struct {
   186  	*schema.Backend
   187  
   188  	// The fields below are set from configure
   189  	armClient     *ArmClient
   190  	containerName string
   191  	keyName       string
   192  	accountName   string
   193  	snapshot      bool
   194  }
   195  
   196  type BackendConfig struct {
   197  	// Required
   198  	StorageAccountName string
   199  
   200  	// Optional
   201  	AccessKey                     string
   202  	ClientID                      string
   203  	ClientCertificatePassword     string
   204  	ClientCertificatePath         string
   205  	ClientSecret                  string
   206  	CustomResourceManagerEndpoint string
   207  	MetadataHost                  string
   208  	Environment                   string
   209  	MsiEndpoint                   string
   210  	OIDCToken                     string
   211  	OIDCTokenFilePath             string
   212  	OIDCRequestURL                string
   213  	OIDCRequestToken              string
   214  	ResourceGroupName             string
   215  	SasToken                      string
   216  	SubscriptionID                string
   217  	TenantID                      string
   218  	UseMsi                        bool
   219  	UseOIDC                       bool
   220  	UseAzureADAuthentication      bool
   221  }
   222  
   223  func (b *Backend) configure(ctx context.Context) error {
   224  	if b.containerName != "" {
   225  		return nil
   226  	}
   227  
   228  	// Grab the resource data
   229  	data := schema.FromContextBackendConfig(ctx)
   230  	b.containerName = data.Get("container_name").(string)
   231  	b.accountName = data.Get("storage_account_name").(string)
   232  	b.keyName = data.Get("key").(string)
   233  	b.snapshot = data.Get("snapshot").(bool)
   234  
   235  	config := BackendConfig{
   236  		AccessKey:                     data.Get("access_key").(string),
   237  		ClientID:                      data.Get("client_id").(string),
   238  		ClientCertificatePassword:     data.Get("client_certificate_password").(string),
   239  		ClientCertificatePath:         data.Get("client_certificate_path").(string),
   240  		ClientSecret:                  data.Get("client_secret").(string),
   241  		CustomResourceManagerEndpoint: data.Get("endpoint").(string),
   242  		MetadataHost:                  data.Get("metadata_host").(string),
   243  		Environment:                   data.Get("environment").(string),
   244  		MsiEndpoint:                   data.Get("msi_endpoint").(string),
   245  		OIDCToken:                     data.Get("oidc_token").(string),
   246  		OIDCTokenFilePath:             data.Get("oidc_token_file_path").(string),
   247  		OIDCRequestURL:                data.Get("oidc_request_url").(string),
   248  		OIDCRequestToken:              data.Get("oidc_request_token").(string),
   249  		ResourceGroupName:             data.Get("resource_group_name").(string),
   250  		SasToken:                      data.Get("sas_token").(string),
   251  		StorageAccountName:            data.Get("storage_account_name").(string),
   252  		SubscriptionID:                data.Get("subscription_id").(string),
   253  		TenantID:                      data.Get("tenant_id").(string),
   254  		UseMsi:                        data.Get("use_msi").(bool),
   255  		UseOIDC:                       data.Get("use_oidc").(bool),
   256  		UseAzureADAuthentication:      data.Get("use_azuread_auth").(bool),
   257  	}
   258  
   259  	armClient, err := buildArmClient(context.TODO(), config)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	thingsNeededToLookupAccessKeySpecified := config.AccessKey == "" && config.SasToken == "" && config.ResourceGroupName == ""
   265  	if thingsNeededToLookupAccessKeySpecified && !config.UseAzureADAuthentication {
   266  		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")
   267  	}
   268  
   269  	b.armClient = armClient
   270  	return nil
   271  }