Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,11 @@ func azureBlobStorageDataSchema() *schema.Resource {
},
Description: ` Workload Identity Details used to authenticate API requests to Azure.`,
},
"private_network_service": {
Type: schema.TypeString,
Optional: true,
Description: `Service Directory Service used as the endpoint for transfers from a customer-managed VPC. Format: projects/{projectId}/locations/{location}/namespaces/{namespace}/services/{service}`,
},
},
}
}
Expand Down Expand Up @@ -1782,6 +1787,7 @@ func expandAzureBlobStorageData(azureBlobStorageDatas []interface{}) *storagetra
AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})),
CredentialsSecret: azureBlobStorageData["credentials_secret"].(string),
FederatedIdentityConfig: expandAzureFederatedIdentifyConfig(azureBlobStorageData["federated_identity_config"].([]interface{})),
PrivateNetworkService: azureBlobStorageData["private_network_service"].(string),
}
}

Expand All @@ -1793,6 +1799,7 @@ func flattenAzureBlobStorageData(azureBlobStorageData *storagetransfer.AzureBlob
"azure_credentials": flattenAzureCredentials(d),
"federated_identity_config": flattenAzureFederatedIdentifyConfig(d),
"credentials_secret": azureBlobStorageData.CredentialsSecret,
"private_network_service": azureBlobStorageData.PrivateNetworkService,
}

return []map[string]interface{}{data}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ fields:
- api_field: 'transferSpec.azureBlobStorageDataSource.federatedIdentityConfig.clientId'
- api_field: 'transferSpec.azureBlobStorageDataSource.federatedIdentityConfig.tenantId'
- api_field: 'transferSpec.azureBlobStorageDataSource.path'
- api_field: 'transferSpec.azureBlobStorageDataSource.privateNetworkService'
- api_field: 'transferSpec.azureBlobStorageDataSource.storageAccount'
- api_field: 'transferSpec.awsS3CompatibleDataSource.bucketName'
- api_field: 'transferSpec.awsS3CompatibleDataSource.path'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,61 @@ func TestAccStorageTransferJob_awsS3CompatibleDataSource(t *testing.T) {
})
}

func TestAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(t *testing.T) {
t.Parallel()

project := envvar.GetTestProjectFromEnv()
testDataSinkName := acctest.RandString(t, 10)
suffix := acctest.RandString(t, 10)
namespaceId := "tf-test-sts-azure-" + suffix
serviceIdA := "tf-test-sts-azure-svc-a-" + suffix
serviceIdB := "tf-test-sts-azure-svc-b-" + suffix
location := "us-central1"
expectedPNSA := fmt.Sprintf("projects/%s/locations/%s/namespaces/%s/services/%s", project, location, namespaceId, serviceIdA)
expectedPNSB := fmt.Sprintf("projects/%s/locations/%s/namespaces/%s/services/%s", project, location, namespaceId, serviceIdB)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccStorageTransferJobDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, testDataSinkName, namespaceId, serviceIdA, serviceIdB, location, "a"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
"google_storage_transfer_job.transfer_job",
"transfer_spec.0.azure_blob_storage_data_source.0.private_network_service",
expectedPNSA,
),
),
},
{
ResourceName: "google_storage_transfer_job.transfer_job",
ImportState: true,
ImportStateVerify: true,
// azure_credentials is input-only on the API and not returned on Read.
ImportStateVerifyIgnore: []string{"transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials"},
},
{
Config: testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, testDataSinkName, namespaceId, serviceIdA, serviceIdB, location, "b"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
"google_storage_transfer_job.transfer_job",
"transfer_spec.0.azure_blob_storage_data_source.0.private_network_service",
expectedPNSB,
),
),
},
{
ResourceName: "google_storage_transfer_job.transfer_job",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials"},
},
},
})
}

func TestAccStorageTransferJob_transferManifest(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -3035,6 +3090,85 @@ resource "google_storage_transfer_job" "transfer_job" {
`, project, dataSourceBucketName, dataSinkBucketName, transferJobDescription, manifestObjectName)
}

func testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, dataSinkBucketName, namespaceId, serviceIdA, serviceIdB, location, which string) string {
pnsRef := "google_service_directory_service.sts_azure_a.id"
if which == "b" {
pnsRef = "google_service_directory_service.sts_azure_b.id"
}
return fmt.Sprintf(`
data "google_storage_transfer_project_service_account" "default" {
project = "%[1]s"
}

resource "google_storage_bucket" "data_sink" {
name = "%[2]s"
project = "%[1]s"
location = "US"
force_destroy = true
}

resource "google_storage_bucket_iam_member" "data_sink" {
bucket = google_storage_bucket.data_sink.name
role = "roles/storage.admin"
member = "serviceAccount:${data.google_storage_transfer_project_service_account.default.email}"
}

resource "google_service_directory_namespace" "sts_azure" {
project = "%[1]s"
namespace_id = "%[3]s"
location = "%[6]s"
}

resource "google_service_directory_service" "sts_azure_a" {
service_id = "%[4]s"
namespace = google_service_directory_namespace.sts_azure.id
}

resource "google_service_directory_service" "sts_azure_b" {
service_id = "%[5]s"
namespace = google_service_directory_namespace.sts_azure.id
}

resource "google_storage_transfer_job" "transfer_job" {
description = "Azure source with private network service"
project = "%[1]s"

transfer_spec {
azure_blob_storage_data_source {
storage_account = "examplestorageaccount"
container = "example-container"
path = "foo/bar/"
azure_credentials {
sas_token = "fakesastoken"
}
private_network_service = %[7]s
}
gcs_data_sink {
bucket_name = google_storage_bucket.data_sink.name
path = "foo/bar/"
}
}

schedule {
schedule_start_date {
year = 2024
month = 1
day = 1
}
schedule_end_date {
year = 2024
month = 1
day = 1
}
}

depends_on = [
google_storage_bucket_iam_member.data_sink,
]
}
`, project, dataSinkBucketName, namespaceId, serviceIdA, serviceIdB, location, pnsRef)
}

func testAccStorageTransferJob_withoutTransferManifest(project, dataSourceBucketName, dataSinkBucketName, transferJobDescription string) string {
return fmt.Sprintf(`
data "google_storage_transfer_project_service_account" "default" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ The `aws_access_key` block supports:

* `federated_identity_config` - (Optional) Federated identity config of a user registered Azure application. Structure [documented below](#nested_federated_identity_config).

* `private_network_service` - (Optional) Service Directory Service to be used as the endpoint for transfers from a customer-managed VPC. Format: `projects/{projectId}/locations/{location}/namespaces/{namespace}/services/{service}`.

The `azure_credentials` block supports:

* `sas_token` - (Required) Azure shared access signature. See [Grant limited access to Azure Storage resources using shared access signatures (SAS)](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview).
Expand Down
Loading