github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/internal/backend/remote-state/azure/backend.go (about)

     1  package azure
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/iaas-resource-provision/iaas-rpc/internal/backend"
     8  	"github.com/iaas-resource-provision/iaas-rpc/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  			// Feature Flags
   139  			"use_azuread_auth": {
   140  				Type:        schema.TypeBool,
   141  				Optional:    true,
   142  				Description: "Should Terraform use AzureAD Authentication to access the Blob?",
   143  				DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AZUREAD", false),
   144  			},
   145  		},
   146  	}
   147  
   148  	result := &Backend{Backend: s}
   149  	result.Backend.ConfigureFunc = result.configure
   150  	return result
   151  }
   152  
   153  type Backend struct {
   154  	*schema.Backend
   155  
   156  	// The fields below are set from configure
   157  	armClient     *ArmClient
   158  	containerName string
   159  	keyName       string
   160  	accountName   string
   161  	snapshot      bool
   162  }
   163  
   164  type BackendConfig struct {
   165  	// Required
   166  	StorageAccountName string
   167  
   168  	// Optional
   169  	AccessKey                     string
   170  	ClientID                      string
   171  	ClientCertificatePassword     string
   172  	ClientCertificatePath         string
   173  	ClientSecret                  string
   174  	CustomResourceManagerEndpoint string
   175  	MetadataHost                  string
   176  	Environment                   string
   177  	MsiEndpoint                   string
   178  	ResourceGroupName             string
   179  	SasToken                      string
   180  	SubscriptionID                string
   181  	TenantID                      string
   182  	UseMsi                        bool
   183  	UseAzureADAuthentication      bool
   184  }
   185  
   186  func (b *Backend) configure(ctx context.Context) error {
   187  	if b.containerName != "" {
   188  		return nil
   189  	}
   190  
   191  	// Grab the resource data
   192  	data := schema.FromContextBackendConfig(ctx)
   193  	b.containerName = data.Get("container_name").(string)
   194  	b.accountName = data.Get("storage_account_name").(string)
   195  	b.keyName = data.Get("key").(string)
   196  	b.snapshot = data.Get("snapshot").(bool)
   197  
   198  	config := BackendConfig{
   199  		AccessKey:                     data.Get("access_key").(string),
   200  		ClientID:                      data.Get("client_id").(string),
   201  		ClientCertificatePassword:     data.Get("client_certificate_password").(string),
   202  		ClientCertificatePath:         data.Get("client_certificate_path").(string),
   203  		ClientSecret:                  data.Get("client_secret").(string),
   204  		CustomResourceManagerEndpoint: data.Get("endpoint").(string),
   205  		MetadataHost:                  data.Get("metadata_host").(string),
   206  		Environment:                   data.Get("environment").(string),
   207  		MsiEndpoint:                   data.Get("msi_endpoint").(string),
   208  		ResourceGroupName:             data.Get("resource_group_name").(string),
   209  		SasToken:                      data.Get("sas_token").(string),
   210  		StorageAccountName:            data.Get("storage_account_name").(string),
   211  		SubscriptionID:                data.Get("subscription_id").(string),
   212  		TenantID:                      data.Get("tenant_id").(string),
   213  		UseMsi:                        data.Get("use_msi").(bool),
   214  		UseAzureADAuthentication:      data.Get("use_azuread_auth").(bool),
   215  	}
   216  
   217  	armClient, err := buildArmClient(context.TODO(), config)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	thingsNeededToLookupAccessKeySpecified := config.AccessKey == "" && config.SasToken == "" && config.ResourceGroupName == ""
   223  	if thingsNeededToLookupAccessKeySpecified && !config.UseAzureADAuthentication {
   224  		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")
   225  	}
   226  
   227  	b.armClient = armClient
   228  	return nil
   229  }