diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go index f4329d5730df..7720e27a9969 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go @@ -550,6 +550,7 @@ resource "azurerm_key_vault" "test" { secret_permissions = [ "Get", "Delete", + "List", "Purge", "Recover", "Set", diff --git a/azurerm/internal/services/keyvault/key_vault_secrets_data_source.go b/azurerm/internal/services/keyvault/key_vault_secrets_data_source.go new file mode 100644 index 000000000000..db8b35cea3fc --- /dev/null +++ b/azurerm/internal/services/keyvault/key_vault_secrets_data_source.go @@ -0,0 +1,101 @@ +package keyvault + +import ( + "fmt" + "net/url" + "strings" + "time" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/parse" + keyVaultValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceKeyVaultSecrets() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceKeyVaultSecretsRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "key_vault_id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: keyVaultValidate.VaultID, + }, + + "names": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + }, + } +} + +func dataSourceKeyVaultSecretsRead(d *pluginsdk.ResourceData, meta interface{}) error { + keyVaultsClient := meta.(*clients.Client).KeyVault + client := meta.(*clients.Client).KeyVault.ManagementClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + keyVaultId, err := parse.VaultID(d.Get("key_vault_id").(string)) + if err != nil { + return err + } + + keyVaultBaseUri, err := keyVaultsClient.BaseUriForKeyVault(ctx, *keyVaultId) + if err != nil { + return fmt.Errorf("fetching base vault url from id %q: %+v", *keyVaultId, err) + } + + secretList, err := client.GetSecretsComplete(ctx, *keyVaultBaseUri, utils.Int32(25)) + if err != nil { + return fmt.Errorf("Error making Read request on Azure KeyVault %q: %+v", *keyVaultId, err) + } + + d.SetId(keyVaultId.ID()) + + var names []string + + if secretList.Response().Value != nil { + for secretList.NotDone() { + for _, v := range *secretList.Response().Value { + name, err := parseNameFromSecretUrl(*v.ID) + if err != nil { + return err + } + names = append(names, *name) + err = secretList.NextWithContext(ctx) + if err != nil { + return fmt.Errorf("listing secrets on Azure KeyVault %q: %+v", *keyVaultId, err) + } + } + } + } + + d.Set("names", names) + d.Set("key_vault_id", keyVaultId.ID()) + + return nil +} + +func parseNameFromSecretUrl(input string) (*string, error) { + uri, err := url.Parse(input) + if err != nil { + return nil, err + } + // https://favoretti-keyvault.vault.azure.net/secrets/secret-name + segments := strings.Split(uri.Path, "/") + if len(segments) != 3 { + return nil, fmt.Errorf("expected a Path in the format `/secrets/secret-name` but got %q", uri.Path) + } + return &segments[2], nil +} diff --git a/azurerm/internal/services/keyvault/key_vault_secrets_data_source_test.go b/azurerm/internal/services/keyvault/key_vault_secrets_data_source_test.go new file mode 100644 index 000000000000..36611440ea8f --- /dev/null +++ b/azurerm/internal/services/keyvault/key_vault_secrets_data_source_test.go @@ -0,0 +1,45 @@ +package keyvault_test + +import ( + "fmt" + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" +) + +type KeyVaultSecretsDataSource struct { +} + +func TestAccDataSourceKeyVaultSecrets_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_key_vault_secrets", "test") + r := KeyVaultSecretsDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("names.#").HasValue("31"), + ), + }, + }) +} + +func (KeyVaultSecretsDataSource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_key_vault_secret" "test2" { + count = 30 + name = "secret-${count.index}" + value = "rick-and-morty" + key_vault_id = azurerm_key_vault.test.id +} + +data "azurerm_key_vault_secrets" "test" { + key_vault_id = azurerm_key_vault.test.id + + depends_on = [azurerm_key_vault_secret.test, azurerm_key_vault_secret.test2] +} +`, KeyVaultSecretResource{}.basic(data)) +} diff --git a/azurerm/internal/services/keyvault/registration.go b/azurerm/internal/services/keyvault/registration.go index 395e92fbb8c2..3d4dd88157e5 100644 --- a/azurerm/internal/services/keyvault/registration.go +++ b/azurerm/internal/services/keyvault/registration.go @@ -28,6 +28,7 @@ func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { "azurerm_key_vault_key": dataSourceKeyVaultKey(), "azurerm_key_vault_managed_hardware_security_module": dataSourceKeyVaultManagedHardwareSecurityModule(), "azurerm_key_vault_secret": dataSourceKeyVaultSecret(), + "azurerm_key_vault_secrets": dataSourceKeyVaultSecrets(), "azurerm_key_vault": dataSourceKeyVault(), } } diff --git a/website/docs/d/key_vault_secrets.html.markdown b/website/docs/d/key_vault_secrets.html.markdown new file mode 100644 index 000000000000..d66997c19add --- /dev/null +++ b/website/docs/d/key_vault_secrets.html.markdown @@ -0,0 +1,46 @@ +--- +subcategory: "Key Vault" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_key_vault_secrets" +description: |- + Gets a list of secret names from an existing Key Vault Secret. +--- + +# Data Source: azurerm_key_vault_secrets + +Use this data source to retrieve a list of secret names from an existing Key Vault Secret. + +## Example Usage + +```hcl +data "azurerm_key_vault_secrets" "example" { + key_vault_id = data.azurerm_key_vault.existing.id +} + +data "azurerm_key_vault_secret" "example" { + for_each = data.azurerm_key_vault_secrets.example.names + name = each.key +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `key_vault_id` - Specifies the ID of the Key Vault instance to fetch secret names from, available on the `azurerm_key_vault` Data Source / Resource. + +**NOTE:** The vault must be in the same subscription as the provider. If the vault is in another subscription, you must create an aliased provider for that subscription. + +## Attributes Reference + +The following attributes are exported: + +* `names` - List containing names of secrets that exist in this Key Vault. +* `key_vault_id` - The Key Vault ID. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Key Vault Secret.