Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backend/azurerm: exclusively using Microsoft Graph/MSAL and removing Azure Active Directory Graph/ADAL #31070

Merged
merged 1 commit into from Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 15 additions & 34 deletions internal/backend/remote-state/azure/arm_client.go
Expand Up @@ -7,18 +7,17 @@ import (
"os"
"time"

"github.com/manicminer/hamilton/environments"

"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"

"github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources"
armStorage "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-01-01/storage"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/hashicorp/go-azure-helpers/sender"
"github.com/hashicorp/terraform/internal/httpclient"
"github.com/hashicorp/terraform/version"
"github.com/manicminer/hamilton/environments"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
)

type ArmClient struct {
Expand Down Expand Up @@ -91,7 +90,7 @@ func buildArmClient(ctx context.Context, config BackendConfig) (*ArmClient, erro
SupportsClientSecretAuth: true,
SupportsManagedServiceIdentity: config.UseMsi,
SupportsOIDCAuth: config.UseOIDC,
UseMicrosoftGraph: config.UseMicrosoftGraph,
UseMicrosoftGraph: true,
}
armConfig, err := builder.Build()
if err != nil {
Expand All @@ -109,37 +108,19 @@ func buildArmClient(ctx context.Context, config BackendConfig) (*ArmClient, erro
}

sender := sender.BuildSender("backend/remote-state/azure")
var auth autorest.Authorizer
if builder.UseMicrosoftGraph {
log.Printf("[DEBUG] Obtaining an MSAL / Microsoft Graph token for Resource Manager..")
auth, err = armConfig.GetMSALToken(ctx, hamiltonEnv.ResourceManager, sender, oauthConfig, env.TokenAudience)
if err != nil {
return nil, err
}
} else {
log.Printf("[DEBUG] Obtaining an ADAL / Azure Active Directory Graph token for Resource Manager..")
auth, err = armConfig.GetADALToken(ctx, sender, oauthConfig, env.TokenAudience)
if err != nil {
return nil, err
}
log.Printf("[DEBUG] Obtaining an MSAL / Microsoft Graph token for Resource Manager..")
auth, err := armConfig.GetMSALToken(ctx, hamiltonEnv.ResourceManager, sender, oauthConfig, env.TokenAudience)
if err != nil {
return nil, err
}

if config.UseAzureADAuthentication {
if builder.UseMicrosoftGraph {
log.Printf("[DEBUG] Obtaining an MSAL / Microsoft Graph token for Storage..")
storageAuth, err := armConfig.GetMSALToken(ctx, hamiltonEnv.Storage, sender, oauthConfig, env.ResourceIdentifiers.Storage)
if err != nil {
return nil, err
}
client.azureAdStorageAuth = &storageAuth
} else {
log.Printf("[DEBUG] Obtaining an ADAL / Azure Active Directory Graph token for Storage..")
storageAuth, err := armConfig.GetADALToken(ctx, sender, oauthConfig, env.ResourceIdentifiers.Storage)
if err != nil {
return nil, err
}
client.azureAdStorageAuth = &storageAuth
log.Printf("[DEBUG] Obtaining an MSAL / Microsoft Graph token for Storage..")
storageAuth, err := armConfig.GetMSALToken(ctx, hamiltonEnv.Storage, sender, oauthConfig, env.ResourceIdentifiers.Storage)
if err != nil {
return nil, err
}
client.azureAdStorageAuth = &storageAuth
}

accountsClient := armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, armConfig.SubscriptionID)
Expand Down Expand Up @@ -252,7 +233,7 @@ func (c *ArmClient) configureClient(client *autorest.Client, auth autorest.Autho
}

func buildUserAgent() string {
userAgent := httpclient.UserAgentString()
userAgent := httpclient.TerraformUserAgent(version.Version)

// append the CloudShell version to the user agent if it exists
if azureAgent := os.Getenv("AZURE_HTTP_USER_AGENT"); azureAgent != "" {
Expand Down
9 changes: 0 additions & 9 deletions internal/backend/remote-state/azure/backend.go
Expand Up @@ -164,13 +164,6 @@ func New() backend.Backend {
Description: "Should Terraform use AzureAD Authentication to access the Blob?",
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_AZUREAD", false),
},
"use_microsoft_graph": {
Type: schema.TypeBool,
Optional: true,
Deprecated: "This field now defaults to `true` and will be removed in v1.3 of Terraform Core due to the deprecation of ADAL by Microsoft.",
Description: "Should Terraform obtain an MSAL auth token and use Microsoft Graph rather than Azure Active Directory?",
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_MSGRAPH", true),
},
},
}

Expand Down Expand Up @@ -213,7 +206,6 @@ type BackendConfig struct {
UseMsi bool
UseOIDC bool
UseAzureADAuthentication bool
UseMicrosoftGraph bool
}

func (b *Backend) configure(ctx context.Context) error {
Expand Down Expand Up @@ -248,7 +240,6 @@ func (b *Backend) configure(ctx context.Context) error {
UseMsi: data.Get("use_msi").(bool),
UseOIDC: data.Get("use_oidc").(bool),
UseAzureADAuthentication: data.Get("use_azuread_auth").(bool),
UseMicrosoftGraph: data.Get("use_microsoft_graph").(bool),
}

armClient, err := buildArmClient(context.TODO(), config)
Expand Down
173 changes: 5 additions & 168 deletions internal/backend/remote-state/azure/backend_test.go
Expand Up @@ -123,7 +123,7 @@ func TestAccBackendOIDCBasic(t *testing.T) {
backend.TestBackendStates(t, b)
}

func TestAccBackendADALAzureADAuthBasic(t *testing.T) {
func TestAccBackendAzureADAuthBasic(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestAccBackendADALAzureADAuthBasic(t *testing.T) {
backend.TestBackendStates(t, b)
}

func TestAccBackendADALManagedServiceIdentityBasic(t *testing.T) {
func TestAccBackendManagedServiceIdentityBasic(t *testing.T) {
testAccAzureBackendRunningInAzure(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
Expand Down Expand Up @@ -179,7 +179,7 @@ func TestAccBackendADALManagedServiceIdentityBasic(t *testing.T) {
backend.TestBackendStates(t, b)
}

func TestAccBackendADALServicePrincipalClientCertificateBasic(t *testing.T) {
func TestAccBackendServicePrincipalClientCertificateBasic(t *testing.T) {
testAccAzureBackend(t)

clientCertPassword := os.Getenv("ARM_CLIENT_CERTIFICATE_PASSWORD")
Expand Down Expand Up @@ -216,7 +216,7 @@ func TestAccBackendADALServicePrincipalClientCertificateBasic(t *testing.T) {
backend.TestBackendStates(t, b)
}

func TestAccBackendADALServicePrincipalClientSecretBasic(t *testing.T) {
func TestAccBackendServicePrincipalClientSecretBasic(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
Expand Down Expand Up @@ -245,7 +245,7 @@ func TestAccBackendADALServicePrincipalClientSecretBasic(t *testing.T) {
backend.TestBackendStates(t, b)
}

func TestAccBackendADALServicePrincipalClientSecretCustomEndpoint(t *testing.T) {
func TestAccBackendServicePrincipalClientSecretCustomEndpoint(t *testing.T) {
testAccAzureBackend(t)

// this is only applicable for Azure Stack.
Expand Down Expand Up @@ -281,169 +281,6 @@ func TestAccBackendADALServicePrincipalClientSecretCustomEndpoint(t *testing.T)
backend.TestBackendStates(t, b)
}

func TestAccBackendMSALAzureADAuthBasic(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useAzureADAuth = true
res.useMicrosoftGraph = true
armClient := buildTestClient(t, res)

ctx := context.TODO()
err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res)
if err != nil {
armClient.destroyTestResources(ctx, res)
t.Fatalf("Error creating Test Resources: %q", err)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"storage_account_name": res.storageAccountName,
"container_name": res.storageContainerName,
"key": res.storageKeyName,
"access_key": res.storageAccountAccessKey,
"environment": os.Getenv("ARM_ENVIRONMENT"),
"endpoint": os.Getenv("ARM_ENDPOINT"),
"use_azuread_auth": true,
})).(*Backend)

backend.TestBackendStates(t, b)
}

func TestAccBackendMSALManagedServiceIdentityBasic(t *testing.T) {
testAccAzureBackendRunningInAzure(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useMicrosoftGraph = true
armClient := buildTestClient(t, res)

ctx := context.TODO()
err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res)
if err != nil {
t.Fatalf("Error creating Test Resources: %q", err)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"storage_account_name": res.storageAccountName,
"container_name": res.storageContainerName,
"key": res.storageKeyName,
"resource_group_name": res.resourceGroup,
"use_msi": true,
"subscription_id": os.Getenv("ARM_SUBSCRIPTION_ID"),
"tenant_id": os.Getenv("ARM_TENANT_ID"),
"environment": os.Getenv("ARM_ENVIRONMENT"),
"endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend)

backend.TestBackendStates(t, b)
}

func TestAccBackendMSALServicePrincipalClientCertificateBasic(t *testing.T) {
testAccAzureBackend(t)

clientCertPassword := os.Getenv("ARM_CLIENT_CERTIFICATE_PASSWORD")
clientCertPath := os.Getenv("ARM_CLIENT_CERTIFICATE_PATH")
if clientCertPath == "" {
t.Skip("Skipping since `ARM_CLIENT_CERTIFICATE_PATH` is not specified!")
}

rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useMicrosoftGraph = true
armClient := buildTestClient(t, res)

ctx := context.TODO()
err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res)
if err != nil {
t.Fatalf("Error creating Test Resources: %q", err)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"storage_account_name": res.storageAccountName,
"container_name": res.storageContainerName,
"key": res.storageKeyName,
"resource_group_name": res.resourceGroup,
"subscription_id": os.Getenv("ARM_SUBSCRIPTION_ID"),
"tenant_id": os.Getenv("ARM_TENANT_ID"),
"client_id": os.Getenv("ARM_CLIENT_ID"),
"client_certificate_password": clientCertPassword,
"client_certificate_path": clientCertPath,
"environment": os.Getenv("ARM_ENVIRONMENT"),
"endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend)

backend.TestBackendStates(t, b)
}

func TestAccBackendMSALServicePrincipalClientSecretBasic(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useMicrosoftGraph = true
armClient := buildTestClient(t, res)

ctx := context.TODO()
err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res)
if err != nil {
t.Fatalf("Error creating Test Resources: %q", err)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"storage_account_name": res.storageAccountName,
"container_name": res.storageContainerName,
"key": res.storageKeyName,
"resource_group_name": res.resourceGroup,
"subscription_id": os.Getenv("ARM_SUBSCRIPTION_ID"),
"tenant_id": os.Getenv("ARM_TENANT_ID"),
"client_id": os.Getenv("ARM_CLIENT_ID"),
"client_secret": os.Getenv("ARM_CLIENT_SECRET"),
"environment": os.Getenv("ARM_ENVIRONMENT"),
"endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend)

backend.TestBackendStates(t, b)
}

func TestAccBackendMSALServicePrincipalClientSecretCustomEndpoint(t *testing.T) {
testAccAzureBackend(t)

// this is only applicable for Azure Stack.
endpoint := os.Getenv("ARM_ENDPOINT")
if endpoint == "" {
t.Skip("Skipping as ARM_ENDPOINT isn't configured")
}

rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useMicrosoftGraph = true
armClient := buildTestClient(t, res)

ctx := context.TODO()
err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res)
if err != nil {
t.Fatalf("Error creating Test Resources: %q", err)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"storage_account_name": res.storageAccountName,
"container_name": res.storageContainerName,
"key": res.storageKeyName,
"resource_group_name": res.resourceGroup,
"subscription_id": os.Getenv("ARM_SUBSCRIPTION_ID"),
"tenant_id": os.Getenv("ARM_TENANT_ID"),
"client_id": os.Getenv("ARM_CLIENT_ID"),
"client_secret": os.Getenv("ARM_CLIENT_SECRET"),
"environment": os.Getenv("ARM_ENVIRONMENT"),
"endpoint": endpoint,
})).(*Backend)

backend.TestBackendStates(t, b)
}

func TestAccBackendAccessKeyLocked(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
Expand Down
3 changes: 1 addition & 2 deletions internal/backend/remote-state/azure/client.go
Expand Up @@ -10,10 +10,9 @@ import (

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"

"github.com/hashicorp/terraform/internal/states/remote"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
)

const (
Expand Down
2 changes: 0 additions & 2 deletions internal/backend/remote-state/azure/helpers_test.go
Expand Up @@ -93,7 +93,6 @@ func buildTestClient(t *testing.T, res resourceNames) *ArmClient {
StorageAccountName: res.storageAccountName,
UseMsi: msiEnabled,
UseAzureADAuthentication: res.useAzureADAuth,
UseMicrosoftGraph: res.useMicrosoftGraph,
})
if err != nil {
t.Fatalf("Failed to build ArmClient: %+v", err)
Expand Down Expand Up @@ -137,7 +136,6 @@ type resourceNames struct {
storageKeyName string
storageAccountAccessKey string
useAzureADAuth bool
useMicrosoftGraph bool
}

func testResourceNames(rString string, keyName string) resourceNames {
Expand Down
2 changes: 1 addition & 1 deletion internal/httpclient/useragent.go
Expand Up @@ -13,7 +13,7 @@ import (
const userAgentFormat = "Terraform/%s"
const uaEnvVar = "TF_APPEND_USER_AGENT"

// Deprecated: Use UserAgent(version) instead
// Deprecated: Use TerraformUserAgent(version) instead
func UserAgentString() string {
ua := fmt.Sprintf(userAgentFormat, version.Version)

Expand Down