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 }