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 }