backend/azurerm: support for using azuread authentication for blobs

This commit is contained in:
Matthew Frahry 2021-03-22 10:49:34 -07:00
parent 341479087c
commit 3722b1b613
3 changed files with 64 additions and 22 deletions

View File

@ -11,7 +11,7 @@ import (
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources"
armStorage "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/storage/mgmt/storage" 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"
"github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication" "github.com/hashicorp/go-azure-helpers/authentication"
@ -154,7 +154,7 @@ func (c ArmClient) getBlobClient(ctx context.Context) (*blobs.Client, error) {
accessKey := c.accessKey accessKey := c.accessKey
if accessKey == "" { if accessKey == "" {
log.Printf("[DEBUG] Building the Blob Client from an Access Token (using user credentials)") log.Printf("[DEBUG] Building the Blob Client from an Access Token (using user credentials)")
keys, err := c.storageAccountsClient.ListKeys(ctx, c.resourceGroupName, c.storageAccountName) keys, err := c.storageAccountsClient.ListKeys(ctx, c.resourceGroupName, c.storageAccountName, "")
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retrieving keys for Storage Account %q: %s", c.storageAccountName, err) return nil, fmt.Errorf("Error retrieving keys for Storage Account %q: %s", c.storageAccountName, err)
} }
@ -199,7 +199,7 @@ func (c ArmClient) getContainersClient(ctx context.Context) (*containers.Client,
accessKey := c.accessKey accessKey := c.accessKey
if accessKey == "" { if accessKey == "" {
log.Printf("[DEBUG] Building the Container Client from an Access Token (using user credentials)") log.Printf("[DEBUG] Building the Container Client from an Access Token (using user credentials)")
keys, err := c.storageAccountsClient.ListKeys(ctx, c.resourceGroupName, c.storageAccountName) keys, err := c.storageAccountsClient.ListKeys(ctx, c.resourceGroupName, c.storageAccountName, "")
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retrieving keys for Storage Account %q: %s", c.storageAccountName, err) return nil, fmt.Errorf("Error retrieving keys for Storage Account %q: %s", c.storageAccountName, err)
} }

View File

@ -123,6 +123,34 @@ func TestBackendSASTokenBasic(t *testing.T) {
backend.TestBackendStates(t, b) backend.TestBackendStates(t, b)
} }
func TestBackendAzureADAuthBasic(t *testing.T) {
testAccAzureBackend(t)
rs := acctest.RandString(4)
res := testResourceNames(rs, "testState")
res.useAzureADAuth = 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 TestBackendServicePrincipalClientCertificateBasic(t *testing.T) { func TestBackendServicePrincipalClientCertificateBasic(t *testing.T) {
testAccAzureBackend(t) testAccAzureBackend(t)

View File

@ -10,7 +10,7 @@ import (
"time" "time"
"github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources"
armStorage "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/storage/mgmt/storage" 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"
sasStorage "github.com/hashicorp/go-azure-helpers/storage" sasStorage "github.com/hashicorp/go-azure-helpers/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
@ -83,6 +83,7 @@ func buildTestClient(t *testing.T, res resourceNames) *ArmClient {
ResourceGroupName: res.resourceGroup, ResourceGroupName: res.resourceGroup,
StorageAccountName: res.storageAccountName, StorageAccountName: res.storageAccountName,
UseMsi: msiEnabled, UseMsi: msiEnabled,
UseAzureADAuthentication: res.useAzureADAuth,
}) })
if err != nil { if err != nil {
t.Fatalf("Failed to build ArmClient: %+v", err) t.Fatalf("Failed to build ArmClient: %+v", err)
@ -125,6 +126,7 @@ type resourceNames struct {
storageContainerName string storageContainerName string
storageKeyName string storageKeyName string
storageAccountAccessKey string storageAccountAccessKey string
useAzureADAuth bool
} }
func testResourceNames(rString string, keyName string) resourceNames { func testResourceNames(rString string, keyName string) resourceNames {
@ -134,6 +136,7 @@ func testResourceNames(rString string, keyName string) resourceNames {
storageAccountName: fmt.Sprintf("acctestsa%s", rString), storageAccountName: fmt.Sprintf("acctestsa%s", rString),
storageContainerName: "acctestcont", storageContainerName: "acctestcont",
storageKeyName: keyName, storageKeyName: keyName,
useAzureADAuth: false,
} }
} }
@ -145,13 +148,20 @@ func (c *ArmClient) buildTestResources(ctx context.Context, names *resourceNames
} }
log.Printf("Creating Storage Account %q in Resource Group %q", names.storageAccountName, names.resourceGroup) log.Printf("Creating Storage Account %q in Resource Group %q", names.storageAccountName, names.resourceGroup)
future, err := c.storageAccountsClient.Create(ctx, names.resourceGroup, names.storageAccountName, armStorage.AccountCreateParameters{ storageProps := armStorage.AccountCreateParameters{
Sku: &armStorage.Sku{ Sku: &armStorage.Sku{
Name: armStorage.StandardLRS, Name: armStorage.StandardLRS,
Tier: armStorage.Standard, Tier: armStorage.Standard,
}, },
Location: &names.location, Location: &names.location,
}) }
if names.useAzureADAuth {
allowSharedKeyAccess := false
storageProps.AccountPropertiesCreateParameters = &armStorage.AccountPropertiesCreateParameters{
AllowSharedKeyAccess: &allowSharedKeyAccess,
}
}
future, err := c.storageAccountsClient.Create(ctx, names.resourceGroup, names.storageAccountName, storageProps)
if err != nil { if err != nil {
return fmt.Errorf("failed to create test storage account: %s", err) return fmt.Errorf("failed to create test storage account: %s", err)
} }
@ -161,23 +171,27 @@ func (c *ArmClient) buildTestResources(ctx context.Context, names *resourceNames
return fmt.Errorf("failed waiting for the creation of storage account: %s", err) return fmt.Errorf("failed waiting for the creation of storage account: %s", err)
} }
log.Printf("fetching access key for storage account")
resp, err := c.storageAccountsClient.ListKeys(ctx, names.resourceGroup, names.storageAccountName)
if err != nil {
return fmt.Errorf("failed to list storage account keys %s:", err)
}
keys := *resp.Keys
accessKey := *keys[0].Value
names.storageAccountAccessKey = accessKey
storageAuth, err := autorest.NewSharedKeyAuthorizer(names.storageAccountName, accessKey, autorest.SharedKey)
if err != nil {
return fmt.Errorf("Error building Authorizer: %+v", err)
}
containersClient := containers.NewWithEnvironment(c.environment) containersClient := containers.NewWithEnvironment(c.environment)
containersClient.Client.Authorizer = storageAuth if names.useAzureADAuth {
containersClient.Client.Authorizer = *c.azureAdStorageAuth
} else {
log.Printf("fetching access key for storage account")
resp, err := c.storageAccountsClient.ListKeys(ctx, names.resourceGroup, names.storageAccountName, "")
if err != nil {
return fmt.Errorf("failed to list storage account keys %s:", err)
}
keys := *resp.Keys
accessKey := *keys[0].Value
names.storageAccountAccessKey = accessKey
storageAuth, err := autorest.NewSharedKeyAuthorizer(names.storageAccountName, accessKey, autorest.SharedKey)
if err != nil {
return fmt.Errorf("Error building Authorizer: %+v", err)
}
containersClient.Client.Authorizer = storageAuth
}
log.Printf("Creating Container %q in Storage Account %q (Resource Group %q)", names.storageContainerName, names.storageAccountName, names.resourceGroup) log.Printf("Creating Container %q in Storage Account %q (Resource Group %q)", names.storageContainerName, names.storageAccountName, names.resourceGroup)
_, err = containersClient.Create(ctx, names.storageAccountName, names.storageContainerName, containers.CreateInput{}) _, err = containersClient.Create(ctx, names.storageAccountName, names.storageContainerName, containers.CreateInput{})