github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/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  
   146  			"oidc_request_url": {
   147  				Type:        schema.TypeString,
   148  				Optional:    true,
   149  				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_URL", "ACTIONS_ID_TOKEN_REQUEST_URL"}, ""),
   150  				Description: "The URL for the OIDC provider from which to request an ID token",
   151  			},
   152  
   153  			"oidc_request_token": {
   154  				Type:        schema.TypeString,
   155  				Optional:    true,
   156  				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ARM_OIDC_REQUEST_TOKEN", "ACTIONS_ID_TOKEN_REQUEST_TOKEN"}, ""),
   157  				Description: "The bearer token for the request to the OIDC provider",
   158  			},
   159  
   160  			// Feature Flags
   161  			"use_azuread_auth": {
   162  				Type:        schema.TypeBool,
   163  				Optional:    true,
   164  				Description: "Should Terraform use AzureAD Authentication to access the Blob?",
   165  				DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AZUREAD", false),
   166  			},
   167  		},
   168  	}
   169  
   170  	result := &Backend{Backend: s}
   171  	result.Backend.ConfigureFunc = result.configure
   172  	return result
   173  }
   174  
   175  type Backend struct {
   176  	*schema.Backend
   177  
   178  	// The fields below are set from configure
   179  	armClient     *ArmClient
   180  	containerName string
   181  	keyName       string
   182  	accountName   string
   183  	snapshot      bool
   184  }
   185  
   186  type BackendConfig struct {
   187  	// Required
   188  	StorageAccountName string
   189  
   190  	// Optional
   191  	AccessKey                     string
   192  	ClientID                      string
   193  	ClientCertificatePassword     string
   194  	ClientCertificatePath         string
   195  	ClientSecret                  string
   196  	CustomResourceManagerEndpoint string
   197  	MetadataHost                  string
   198  	Environment                   string
   199  	MsiEndpoint                   string
   200  	OIDCRequestURL                string
   201  	OIDCRequestToken              string
   202  	ResourceGroupName             string
   203  	SasToken                      string
   204  	SubscriptionID                string
   205  	TenantID                      string
   206  	UseMsi                        bool
   207  	UseOIDC                       bool
   208  	UseAzureADAuthentication      bool
   209  }
   210  
   211  func (b *Backend) configure(ctx context.Context) error {
   212  	if b.containerName != "" {
   213  		return nil
   214  	}
   215  
   216  	// Grab the resource data
   217  	data := schema.FromContextBackendConfig(ctx)
   218  	b.containerName = data.Get("container_name").(string)
   219  	b.accountName = data.Get("storage_account_name").(string)
   220  	b.keyName = data.Get("key").(string)
   221  	b.snapshot = data.Get("snapshot").(bool)
   222  
   223  	config := BackendConfig{
   224  		AccessKey:                     data.Get("access_key").(string),
   225  		ClientID:                      data.Get("client_id").(string),
   226  		ClientCertificatePassword:     data.Get("client_certificate_password").(string),
   227  		ClientCertificatePath:         data.Get("client_certificate_path").(string),
   228  		ClientSecret:                  data.Get("client_secret").(string),
   229  		CustomResourceManagerEndpoint: data.Get("endpoint").(string),
   230  		MetadataHost:                  data.Get("metadata_host").(string),
   231  		Environment:                   data.Get("environment").(string),
   232  		MsiEndpoint:                   data.Get("msi_endpoint").(string),
   233  		OIDCRequestURL:                data.Get("oidc_request_url").(string),
   234  		OIDCRequestToken:              data.Get("oidc_request_token").(string),
   235  		ResourceGroupName:             data.Get("resource_group_name").(string),
   236  		SasToken:                      data.Get("sas_token").(string),
   237  		StorageAccountName:            data.Get("storage_account_name").(string),
   238  		SubscriptionID:                data.Get("subscription_id").(string),
   239  		TenantID:                      data.Get("tenant_id").(string),
   240  		UseMsi:                        data.Get("use_msi").(bool),
   241  		UseOIDC:                       data.Get("use_oidc").(bool),
   242  		UseAzureADAuthentication:      data.Get("use_azuread_auth").(bool),
   243  	}
   244  
   245  	armClient, err := buildArmClient(context.TODO(), config)
   246  	if err != nil {
   247  		return err
   248  	}
   249  
   250  	thingsNeededToLookupAccessKeySpecified := config.AccessKey == "" && config.SasToken == "" && config.ResourceGroupName == ""
   251  	if thingsNeededToLookupAccessKeySpecified && !config.UseAzureADAuthentication {
   252  		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")
   253  	}
   254  
   255  	b.armClient = armClient
   256  	return nil
   257  }