-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New resource azurerm_managed_disk_sas_token to manage disk exports (#…
…15558) Co-authored-by: Harshavardhan Musanalli <Harshavardhan Musanalli>
- Loading branch information
Showing
4 changed files
with
324 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package compute | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-11-01/compute" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/clients" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" | ||
) | ||
|
||
func resourceManagedDiskSasToken() *pluginsdk.Resource { | ||
|
||
return &pluginsdk.Resource{ | ||
Create: resourceManagedDiskSasTokenCreate, | ||
Read: resourceManagedDiskSasTokenRead, | ||
Delete: resourceManagedDiskSasTokenDelete, | ||
|
||
Timeouts: &pluginsdk.ResourceTimeout{ | ||
Create: pluginsdk.DefaultTimeout(30 * time.Minute), | ||
Read: pluginsdk.DefaultTimeout(5 * time.Minute), | ||
Delete: pluginsdk.DefaultTimeout(30 * time.Minute), | ||
}, | ||
|
||
Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { | ||
_, err := parse.ManagedDiskID(id) | ||
return err | ||
}), | ||
|
||
Schema: map[string]*pluginsdk.Schema{ | ||
"managed_disk_id": { | ||
Type: pluginsdk.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validate.ManagedDiskID, | ||
}, | ||
|
||
// unable to provide upper value of 4294967295 as it's not comptabile with 32-bit (overflow errors) | ||
"duration_in_seconds": { | ||
Type: pluginsdk.TypeInt, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.IntAtLeast(30), | ||
}, | ||
|
||
"access_level": { | ||
Type: pluginsdk.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
string(compute.AccessLevelRead), | ||
string(compute.AccessLevelWrite), | ||
}, false), | ||
}, | ||
|
||
"sas_url": { | ||
Type: pluginsdk.TypeString, | ||
Computed: true, | ||
Sensitive: true, | ||
}, | ||
}, | ||
} | ||
|
||
} | ||
|
||
func resourceManagedDiskSasTokenCreate(d *pluginsdk.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Compute.DisksClient | ||
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
log.Printf("[INFO] preparing arguments for AzureRM Disk Export.") | ||
durationInSeconds := int32(d.Get("duration_in_seconds").(int)) | ||
access := compute.AccessLevel(d.Get("access_level").(string)) | ||
|
||
diskId, err := parse.ManagedDiskID(d.Get("managed_disk_id").(string)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
grantAccessData := compute.GrantAccessData{ | ||
Access: access, | ||
DurationInSeconds: &durationInSeconds, | ||
} | ||
|
||
resp, err := client.Get(ctx, diskId.ResourceGroup, diskId.DiskName) | ||
if err != nil { | ||
return fmt.Errorf("error retrieving Disk %s: %+v", *diskId, err) | ||
} | ||
|
||
// checking whether disk export SAS URL is active already before creating. If yes, we raise an error | ||
if resp.DiskState == "ActiveSAS" { | ||
return fmt.Errorf("active SAS Token for Disk Export already exists, cannot create another one %s: %+v", *diskId, err) | ||
} | ||
|
||
future, err := client.GrantAccess(ctx, diskId.ResourceGroup, diskId.DiskName, grantAccessData) | ||
if err != nil { | ||
return fmt.Errorf("granting access to %s: %+v", *diskId, err) | ||
} | ||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("waiting for access to be granted to %s: %+v", *diskId, err) | ||
} | ||
read, err := future.Result(*client) | ||
if err != nil { | ||
return fmt.Errorf("retrieving SAS Token for Disk Access %s: %+v", *diskId, err) | ||
} | ||
if read.AccessSAS == nil { | ||
return fmt.Errorf("retrieving SAS Token for Disk Access %s: SAS was nil", *diskId) | ||
} | ||
|
||
d.SetId(diskId.ID()) | ||
sasToken := *read.AccessSAS | ||
d.Set("sas_url", sasToken) | ||
|
||
return resourceManagedDiskSasTokenRead(d, meta) | ||
|
||
} | ||
|
||
func resourceManagedDiskSasTokenRead(d *pluginsdk.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Compute.DisksClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
diskId, err := parse.ManagedDiskID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resp, err := client.Get(ctx, diskId.ResourceGroup, diskId.DiskName) | ||
if err != nil { | ||
// checking whether disk export SAS URL is active post creation. If no, we raise an error | ||
if resp.DiskState != "ActiveSAS" { | ||
log.Printf("[INFO] Disk SAS token %q does not exist - removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("making Read request on Azure Disk Export for SAS Token %s (resource group %s): %s", diskId.DiskName, diskId.ResourceGroup, err) | ||
} | ||
|
||
d.SetId(diskId.ID()) | ||
|
||
return nil | ||
} | ||
|
||
func resourceManagedDiskSasTokenDelete(d *pluginsdk.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Compute.DisksClient | ||
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
id, err := parse.ManagedDiskID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
future, err := client.RevokeAccess(ctx, id.ResourceGroup, id.DiskName) | ||
if err != nil { | ||
return fmt.Errorf("revoking access to %s: %+v", *id, err) | ||
} | ||
|
||
if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("waiting for revocation of access to %s: %+v", *id, err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package compute_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/clients" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" | ||
"github.com/hashicorp/terraform-provider-azurerm/utils" | ||
) | ||
|
||
type ManagedDiskSASTokenResource struct{} | ||
|
||
func TestAccManagedDiskSASToken_basic(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "azurerm_managed_disk_sas_token", "test") | ||
r := ManagedDiskSASTokenResource{} | ||
|
||
data.ResourceTest(t, r, []acceptance.TestStep{ | ||
{ | ||
Config: r.basic(data), | ||
Check: acceptance.ComposeTestCheckFunc( | ||
check.That(data.ResourceName).ExistsInAzure(r), | ||
), | ||
}, | ||
}) | ||
} | ||
|
||
func (t ManagedDiskSASTokenResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { | ||
id, err := parse.ManagedDiskID(state.ID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resp, err := clients.Compute.DisksClient.Get(ctx, id.ResourceGroup, id.DiskName) | ||
if err != nil { | ||
return nil, fmt.Errorf("retrieving Compute Disk Export status %q", id.String()) | ||
} | ||
|
||
if resp.DiskState != "ActiveSAS" { | ||
return nil, fmt.Errorf("Disk SAS token %s (resource group %s): %s", id.DiskName, id.ResourceGroup, err) | ||
} | ||
|
||
return utils.Bool(resp.ID != nil), nil | ||
} | ||
|
||
func (r ManagedDiskSASTokenResource) basic(data acceptance.TestData) string { | ||
return fmt.Sprintf(` | ||
provider "azurerm" { | ||
features {} | ||
} | ||
resource "azurerm_resource_group" "test" { | ||
name = "acctestRG-revokedisk-%d" | ||
location = "%s" | ||
} | ||
resource "azurerm_managed_disk" "test" { | ||
name = "acctestsads%s" | ||
location = azurerm_resource_group.test.location | ||
resource_group_name = azurerm_resource_group.test.name | ||
storage_account_type = "Standard_LRS" | ||
create_option = "Empty" | ||
disk_size_gb = "1" | ||
} | ||
resource "azurerm_managed_disk_sas_token" "test" { | ||
managed_disk_id = azurerm_managed_disk.test.id | ||
duration_in_seconds = 300 | ||
access_level = "Read" | ||
} | ||
`, data.RandomInteger, data.Locations.Primary, data.RandomString) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
subcategory: "Compute" | ||
layout: "azurerm" | ||
page_title: "Azure Resource Manager: azurerm_managed_disk_sas_token" | ||
description: |- | ||
Manages a Disk SAS Token. | ||
--- | ||
|
||
# azurerm_managed_disk_sas_token | ||
|
||
Manages a Disk SAS Token. | ||
|
||
Use this resource to obtain a Shared Access Signature (SAS Token) for an existing Managed Disk. | ||
|
||
Shared access signatures allow fine-grained, ephemeral access control to various aspects of Managed Disk similar to blob/storage account container. | ||
|
||
With the help of this resource, data from the disk can be copied from managed disk to a storage blob or to some other system without the need of azcopy. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "azurerm_resource_group" "test" { | ||
name = "testrg" | ||
location = "West Europe" | ||
} | ||
resource "azurerm_managed_disk" "test" { | ||
name = "tst-disk-export" | ||
location = azurerm_resource_group.test.location | ||
resource_group_name = azurerm_resource_group.test.name | ||
storage_account_type = "Standard_LRS" | ||
create_option = "Empty" | ||
disk_size_gb = "1" | ||
} | ||
resource "azurerm_managed_disk_sas_token" "test" { | ||
managed_disk_id = azurerm_managed_disk.test.id | ||
duration_in_seconds = 300 | ||
access_level = "Read" | ||
} | ||
``` | ||
|
||
## Arguments Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `managed_disk_id` - (Required) The ID of an existing Managed Disk which should be exported. Changing this forces a new resource to be created. | ||
|
||
* `duration_in_seconds` - (Required) The duration for which the export should be allowed. Should be between 30 & 4294967295 seconds. | ||
|
||
* `access_level` - (Required) The level of access required on the disk. Supported are Read, Write. | ||
|
||
Refer to the [SAS creation reference from Azure](https://docs.microsoft.com/en-us/rest/api/compute/disks/grant-access) | ||
for additional details on the fields above. | ||
|
||
## Attributes Reference | ||
|
||
In addition to the Arguments listed above - the following Attributes are exported: | ||
|
||
* `id` - The ID of the Disk Export resource. | ||
|
||
* `sas_url` - The computed Shared Access Signature (SAS) of the Managed Disk. | ||
|
||
## Timeouts | ||
|
||
The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: | ||
|
||
* `create` - (Defaults to 30 minutes) Used when creating the Disk. | ||
* `read` - (Defaults to 5 minutes) Used when retrieving the Disk. | ||
* `delete` - (Defaults to 30 minutes) Used when deleting the Disk. | ||
|
||
## Import | ||
|
||
Disk SAS Token can be imported using the `resource id`, e.g. | ||
|
||
```shell | ||
terraform import azurerm_managed_disk_sas_token.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/microsoft.compute/disks/manageddisk1 | ||
``` |