Skip to content

Commit

Permalink
Merge pull request #31070 from hashicorp/f/removing-adal-auth
Browse files Browse the repository at this point in the history
backend/azurerm: exclusively using Microsoft Graph/MSAL and removing Azure Active Directory Graph/ADAL
  • Loading branch information
manicminer committed Jul 12, 2022
2 parents 06baea9 + 05528e8 commit dc1f5bc
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 235 deletions.
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

0 comments on commit dc1f5bc

Please sign in to comment.