Skip to content

Commit

Permalink
Merge pull request #4122 from terraform-providers/f/storage-queue
Browse files Browse the repository at this point in the history
r/storage_queue: switching to use SharedKey for auth
  • Loading branch information
tombuildsstuff authored Aug 22, 2019
2 parents ae93d33 + 30e0f9b commit c77aeb0
Show file tree
Hide file tree
Showing 39 changed files with 221 additions and 29,601 deletions.
3 changes: 2 additions & 1 deletion azurerm/helpers/validate/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ func StorageShareDirectoryName(v interface{}, k string) (warnings []string, erro

// File share names can contain only lowercase letters, numbers, and hyphens,
// and must begin and end with a letter or a number.
if !regexp.MustCompile(`^[a-z0-9][a-z0-9-]+[a-z0-9]$`).MatchString(value) {
// however they can be nested (e.g. foo/bar)
if !regexp.MustCompile(`^[a-z0-9][a-z0-9-]+[a-z0-9]$`).MatchString(value) && !regexp.MustCompile(`^[a-z0-9]{1,}/[a-z0-9]{1,}$`).MatchString(value) {
errors = append(errors, fmt.Errorf("%s must contain only lowercase alphanumeric characters, numbers and hyphens. It must start and end with a letter and end only with a number or letter", k))
}

Expand Down
8 changes: 8 additions & 0 deletions azurerm/helpers/validate/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ func TestValidateStorageShareDirectoryName(t *testing.T) {
Input: "123--abc",
Expected: false,
},
{
Input: "hello/world",
Expected: true,
},
{
Input: "hello/",
Expected: false,
},
}

for _, v := range testCases {
Expand Down
67 changes: 67 additions & 0 deletions azurerm/internal/authorizers/authorizer_shared_key_lite_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package authorizers

import (
"net/http"
"testing"
)

Expand Down Expand Up @@ -34,3 +35,69 @@ func TestBuildCanonicalizedStringForSharedKeyLite(t *testing.T) {
}
}
}

func TestComputeSharedKey(t *testing.T) {
testData := []struct {
name string
accountName string
method string
url string
headers map[string]string
expected string
}{
{
name: "No Path",
accountName: "unlikely23exst2acct23wi",
method: "GET",
url: "https://unlikely23exst2acct23wi.queue.core.windows.net?comp=properties&restype=service",
headers: map[string]string{
"Content-Type": "application/xml; charset=utf-8",
"X-Ms-Date": "Wed, 21 Aug 2019 11:00:25 GMT",
"X-Ms-Version": "2018-11-09",
},
expected: `GET
application/xml; charset=utf-8
x-ms-date:Wed, 21 Aug 2019 11:00:25 GMT
x-ms-version:2018-11-09
/unlikely23exst2acct23wi?comp=properties`,
},
{
name: "With Path",
accountName: "unlikely23exst2accti1t0",
method: "GET",
url: "https://unlikely23exst2accti1t0.queue.core.windows.net/?comp=properties&restype=service",
headers: map[string]string{
"Content-Type": "application/xml; charset=utf-8",
"X-Ms-Date": "Wed, 21 Aug 2019 11:53:48 GMT",
"X-Ms-Version": "2018-11-09",
},
expected: `GET
application/xml; charset=utf-8
x-ms-date:Wed, 21 Aug 2019 11:53:48 GMT
x-ms-version:2018-11-09
/unlikely23exst2accti1t0/?comp=properties`,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Test %q", v.name)

headers := http.Header{}
for hn, hv := range v.headers {
headers.Add(hn, hv)
}

actual, err := computeSharedKeyLite(v.method, v.url, v.accountName, headers)
if err != nil {
t.Fatalf("Error computing shared key: %s", err)
}

if *actual != v.expected {
t.Fatalf("Expected %q but got %q", v.expected, *actual)
}
}
}
18 changes: 12 additions & 6 deletions azurerm/internal/services/storage/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
)

type Client struct {
QueuesClient queues.Client
// this is currently unexported since we only use it to look up the account key
// we could export/use this in the future - but there's no point it being public
// until that time
Expand All @@ -31,16 +30,11 @@ type Client struct {
// NOTE: this temporarily diverges from the other clients until we move this client in here
// once we have this, can take an Options like everything else
func BuildClient(accountsClient storage.AccountsClient, options *common.ClientOptions) *Client {
queuesClient := queues.New()
options.ConfigureClient(&queuesClient.Client, options.StorageAuthorizer)

// TODO: switch Storage Containers to using the storage.BlobContainersClient
// (which should fix #2977) when the storage clients have been moved in here
return &Client{
accountsClient: accountsClient,
environment: options.Environment,

QueuesClient: queuesClient,
}
}

Expand Down Expand Up @@ -122,6 +116,18 @@ func (client Client) FileSharesClient(ctx context.Context, resourceGroup, accoun
return &directoriesClient, nil
}

func (client Client) QueuesClient(ctx context.Context, resourceGroup, accountName string) (*queues.Client, error) {
accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName)
if err != nil {
return nil, fmt.Errorf("Error retrieving Account Key: %s", err)
}

storageAuth := authorizers.NewSharedKeyLiteAuthorizer(accountName, *accountKey)
queuesClient := queues.NewWithEnvironment(client.environment)
queuesClient.Client.Authorizer = storageAuth
return &queuesClient, nil
}

func (client Client) TableEntityClient(ctx context.Context, resourceGroup, accountName string) (*entities.Client, error) {
accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName)
if err != nil {
Expand Down
16 changes: 13 additions & 3 deletions azurerm/resource_arm_storage_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,10 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e
}

if val, ok := d.GetOk("queue_properties"); ok {
queueClient := meta.(*ArmClient).storage.QueuesClient
queueClient, err := meta.(*ArmClient).storage.QueuesClient(ctx, resourceGroupName, storageAccountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

queueProperties, err := expandQueueProperties(val.([]interface{}))
if err != nil {
Expand Down Expand Up @@ -926,7 +929,10 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e
}

if d.HasChange("queue_properties") {
queueClient := meta.(*ArmClient).storage.QueuesClient
queueClient, err := meta.(*ArmClient).storage.QueuesClient(ctx, resourceGroupName, storageAccountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

queueProperties, err := expandQueueProperties(d.Get("queue_properties").([]interface{}))
if err != nil {
Expand Down Expand Up @@ -1072,7 +1078,11 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err
}
}

queueClient := meta.(*ArmClient).storage.QueuesClient
queueClient, err := meta.(*ArmClient).storage.QueuesClient(ctx, resGroup, name)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

queueProps, err := queueClient.GetServiceProperties(ctx, name)
if err != nil {
if queueProps.Response.Response != nil && !utils.ResponseWasNotFound(queueProps.Response) {
Expand Down
6 changes: 3 additions & 3 deletions azurerm/resource_arm_storage_blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ resource "azurerm_storage_blob" "source" {
storage_account_name = "${azurerm_storage_account.test.name}"
storage_container_name = "${azurerm_storage_container.test.name}"
type = "block"
source_uri = "http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-desktop-amd64.iso"
source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso"
content_type = "application/x-iso9660-image"
}
Expand Down Expand Up @@ -789,7 +789,7 @@ resource "azurerm_storage_blob" "test" {
storage_account_name = "${azurerm_storage_account.test.name}"
storage_container_name = "${azurerm_storage_container.test.name}"
type = "block"
source_uri = "http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-desktop-amd64.iso"
source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso"
content_type = "application/x-iso9660-image"
}
`, template)
Expand All @@ -806,7 +806,7 @@ resource "azurerm_storage_blob" "source" {
storage_account_name = "${azurerm_storage_account.test.name}"
storage_container_name = "${azurerm_storage_container.test.name}"
type = "block"
source_uri = "http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-desktop-amd64.iso"
source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso"
content_type = "application/x-iso9660-image"
}
Expand Down
44 changes: 40 additions & 4 deletions azurerm/resource_arm_storage_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func validateArmStorageQueueName(v interface{}, k string) (warnings []string, er
}

func resourceArmStorageQueueCreate(d *schema.ResourceData, meta interface{}) error {
queueClient := meta.(*ArmClient).storage.QueuesClient
storageClient := meta.(*ArmClient).storage
ctx := meta.(*ArmClient).StopContext

queueName := d.Get("name").(string)
Expand All @@ -86,6 +86,19 @@ func resourceArmStorageQueueCreate(d *schema.ResourceData, meta interface{}) err
metaDataRaw := d.Get("metadata").(map[string]interface{})
metaData := storage.ExpandMetaData(metaDataRaw)

resourceGroup, err := storageClient.FindResourceGroup(ctx, accountName)
if err != nil {
return fmt.Errorf("Error locating Resource Group for Storage Queue %q (Account %s): %s", queueName, accountName, err)
}
if resourceGroup == nil {
return fmt.Errorf("Unable to locate Resource Group for Storage Queue %q (Account %s)", queueName, accountName)
}

queueClient, err := storageClient.QueuesClient(ctx, *resourceGroup, accountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

resourceID := queueClient.GetResourceID(accountName, queueName)
if requireResourcesToBeImported {
existing, err := queueClient.GetMetaData(ctx, accountName, queueName)
Expand Down Expand Up @@ -121,7 +134,20 @@ func resourceArmStorageQueueUpdate(d *schema.ResourceData, meta interface{}) err
metaDataRaw := d.Get("metadata").(map[string]interface{})
metaData := storage.ExpandMetaData(metaDataRaw)

if _, err := storageClient.QueuesClient.SetMetaData(ctx, id.AccountName, id.QueueName, metaData); err != nil {
resourceGroup, err := storageClient.FindResourceGroup(ctx, id.AccountName)
if err != nil {
return fmt.Errorf("Error locating Resource Group for Storage Queue %q (Account %s): %s", id.QueueName, id.AccountName, err)
}
if resourceGroup == nil {
return fmt.Errorf("Unable to locate Resource Group for Storage Queue %q (Account %s)", id.QueueName, id.AccountName)
}

queuesClient, err := storageClient.QueuesClient(ctx, *resourceGroup, id.AccountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

if _, err := queuesClient.SetMetaData(ctx, id.AccountName, id.QueueName, metaData); err != nil {
return fmt.Errorf("Error setting MetaData for Queue %q (Storage Account %q): %s", id.QueueName, id.AccountName, err)
}

Expand All @@ -147,7 +173,12 @@ func resourceArmStorageQueueRead(d *schema.ResourceData, meta interface{}) error
return nil
}

metaData, err := storageClient.QueuesClient.GetMetaData(ctx, id.AccountName, id.QueueName)
queuesClient, err := storageClient.QueuesClient(ctx, *resourceGroup, id.AccountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

metaData, err := queuesClient.GetMetaData(ctx, id.AccountName, id.QueueName)
if err != nil {
if utils.ResponseWasNotFound(metaData.Response) {
log.Printf("[INFO] Storage Queue %q no longer exists, removing from state...", id.QueueName)
Expand Down Expand Up @@ -188,7 +219,12 @@ func resourceArmStorageQueueDelete(d *schema.ResourceData, meta interface{}) err
return nil
}

if _, err := storageClient.QueuesClient.Delete(ctx, id.AccountName, id.QueueName); err != nil {
queuesClient, err := storageClient.QueuesClient(ctx, *resourceGroup, id.AccountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

if _, err := queuesClient.Delete(ctx, id.AccountName, id.QueueName); err != nil {
return fmt.Errorf("Error deleting Storage Queue %q: %s", id.QueueName, err)
}

Expand Down
32 changes: 30 additions & 2 deletions azurerm/resource_arm_storage_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,21 @@ func testCheckAzureRMStorageQueueExists(resourceName string) resource.TestCheckF
name := rs.Primary.Attributes["name"]
accountName := rs.Primary.Attributes["storage_account_name"]

queueClient := testAccProvider.Meta().(*ArmClient).storage.QueuesClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext
storageClient := testAccProvider.Meta().(*ArmClient).storage

resourceGroup, err := storageClient.FindResourceGroup(ctx, accountName)
if err != nil {
return fmt.Errorf("Error locating Resource Group for Storage Queue %q (Account %s): %s", name, accountName, err)
}
if resourceGroup == nil {
return fmt.Errorf("Unable to locate Resource Group for Storage Queue %q (Account %s) - assuming removed", name, accountName)
}

queueClient, err := storageClient.QueuesClient(ctx, *resourceGroup, accountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

metaData, err := queueClient.GetMetaData(ctx, accountName, name)
if err != nil {
Expand All @@ -181,8 +194,23 @@ func testCheckAzureRMStorageQueueDestroy(s *terraform.State) error {
name := rs.Primary.Attributes["name"]
accountName := rs.Primary.Attributes["storage_account_name"]

queueClient := testAccProvider.Meta().(*ArmClient).storage.QueuesClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext
storageClient := testAccProvider.Meta().(*ArmClient).storage

resourceGroup, err := storageClient.FindResourceGroup(ctx, accountName)
if err != nil {
return fmt.Errorf("Error locating Resource Group for Storage Queue %q (Account %s): %s", name, accountName, err)
}

// expected if this has been deleted
if resourceGroup == nil {
return nil
}

queueClient, err := storageClient.QueuesClient(ctx, *resourceGroup, accountName)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
}

metaData, err := queueClient.GetMetaData(ctx, accountName, name)
if err != nil {
Expand Down
30 changes: 30 additions & 0 deletions azurerm/resource_arm_storage_share_directory.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package azurerm

import (
"context"
"fmt"
"log"
"strconv"
"time"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
Expand Down Expand Up @@ -89,6 +93,21 @@ func resourceArmStorageShareDirectoryCreate(d *schema.ResourceData, meta interfa
return fmt.Errorf("Error creating Directory %q (File Share %q / Account %q): %+v", directoryName, shareName, accountName, err)
}

// Storage Share Directories are eventually consistent
log.Printf("[DEBUG] Waiting for Directory %q (File Share %q / Account %q) to become available", directoryName, shareName, accountName)
stateConf := &resource.StateChangeConf{
Pending: []string{"404"},
Target: []string{"200"},
Refresh: storageShareDirectoryRefreshFunc(ctx, client, accountName, shareName, directoryName),
Timeout: 5 * time.Minute,
MinTimeout: 10 * time.Second,
ContinuousTargetOccurence: 5,
}

if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for Directory %q (File Share %q / Account %q) to become available: %s", directoryName, shareName, accountName, err)
}

resourceID := client.GetResourceID(accountName, shareName, directoryName)
d.SetId(resourceID)

Expand Down Expand Up @@ -199,3 +218,14 @@ func resourceArmStorageShareDirectoryDelete(d *schema.ResourceData, meta interfa

return nil
}

func storageShareDirectoryRefreshFunc(ctx context.Context, client *directories.Client, accountName, shareName, directoryName string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
res, err := client.Get(ctx, accountName, shareName, directoryName)
if err != nil {
return nil, strconv.Itoa(res.StatusCode), fmt.Errorf("Error retrieving Directory %q (File Share %q / Account %q): %s", directoryName, shareName, accountName, err)
}

return res, strconv.Itoa(res.StatusCode), nil
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/satori/go.uuid v1.2.0
github.com/satori/uuid v0.0.0-20160927100844-b061729afc07
github.com/terraform-providers/terraform-provider-azuread v0.4.1-0.20190610202312-5a179146b9f9
github.com/tombuildsstuff/giovanni v0.3.0
github.com/tombuildsstuff/giovanni v0.3.2
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net v0.0.0-20190502183928-7f726cade0ab
gopkg.in/yaml.v2 v2.2.2
Expand Down
Loading

0 comments on commit c77aeb0

Please sign in to comment.