Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Data Sources: azurerm_key_vault & azurerm_key_vault_secret #1202

Merged
merged 10 commits into from
May 10, 2018
210 changes: 210 additions & 0 deletions azurerm/data_source_key_vault.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package azurerm

import (
"fmt"

"github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault"
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmKeyVault() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmKeyVaultRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateKeyVaultName,
},

"resource_group_name": resourceGroupNameForDataSourceSchema(),

"location": locationForDataSourceSchema(),

"sku": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},

"vault_uri": {
Type: schema.TypeString,
Computed: true,
},

"tenant_id": {
Type: schema.TypeString,
Computed: true,
},

"access_policy": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"tenant_id": {
Type: schema.TypeString,
Computed: true,
},
"object_id": {
Type: schema.TypeString,
Computed: true,
},
"application_id": {
Type: schema.TypeString,
Computed: true,
},
"certificate_permissions": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"key_permissions": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"secret_permissions": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},

"enabled_for_deployment": {
Type: schema.TypeBool,
Computed: true,
},

"enabled_for_disk_encryption": {
Type: schema.TypeBool,
Computed: true,
},

"enabled_for_template_deployment": {
Type: schema.TypeBool,
Computed: true,
},

"tags": tagsForDataSourceSchema(),
},
}
}

func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).keyVaultClient
ctx := meta.(*ArmClient).StopContext

name := d.Get("name").(string)
resourceGroup := d.Get("resource_group_name").(string)

resp, err := client.Get(ctx, resourceGroup, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("KeyVault %q (Resource Group %q) does not exist", name, resourceGroup)
}
return fmt.Errorf("Error making Read request on KeyVault %q: %+v", name, err)
}

d.SetId(*resp.ID)

d.Set("name", resp.Name)
d.Set("resource_group_name", resourceGroup)
if location := resp.Location; location != nil {
d.Set("location", azureRMNormalizeLocation(*location))
}

if props := resp.Properties; props != nil {
d.Set("tenant_id", props.TenantID.String())
d.Set("enabled_for_deployment", props.EnabledForDeployment)
d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption)
d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment)
if err := d.Set("sku", flattenKeyVaultDataSourceSku(props.Sku)); err != nil {
return fmt.Errorf("Error flattening `sku` for KeyVault %q: %+v", resp.Name, err)
}
if err := d.Set("access_policy", flattenKeyVaultDataSourceAccessPolicies(props.AccessPolicies)); err != nil {
return fmt.Errorf("Error flattening `access_policy` for KeyVault %q: %+v", resp.Name, err)
}
d.Set("vault_uri", props.VaultURI)
}

flattenAndSetTags(d, resp.Tags)

return nil
}

func flattenKeyVaultDataSourceSku(sku *keyvault.Sku) []interface{} {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, is there a reason sku is a list/block instead of a string value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also possible to set some additional fields here, but we don't expose them

result := map[string]interface{}{
"name": string(sku.Name),
}

return []interface{}{result}
}

func flattenKeyVaultDataSourceAccessPolicies(policies *[]keyvault.AccessPolicyEntry) []interface{} {
result := make([]interface{}, 0, len(*policies))

if policies == nil {
return result
}

for _, policy := range *policies {
policyRaw := make(map[string]interface{})

keyPermissionsRaw := make([]interface{}, 0)
secretPermissionsRaw := make([]interface{}, 0)
certificatePermissionsRaw := make([]interface{}, 0)

if permissions := policy.Permissions; permissions != nil {
if keys := permissions.Keys; keys != nil {
for _, keyPermission := range *keys {
keyPermissionsRaw = append(keyPermissionsRaw, string(keyPermission))
}
}
if secrets := permissions.Secrets; secrets != nil {
for _, secretPermission := range *secrets {
secretPermissionsRaw = append(secretPermissionsRaw, string(secretPermission))
}
}

if certificates := permissions.Certificates; certificates != nil {
for _, certificatePermission := range *certificates {
certificatePermissionsRaw = append(certificatePermissionsRaw, string(certificatePermission))
}
}
}

policyRaw["tenant_id"] = policy.TenantID.String()
if policy.ObjectID != nil {
policyRaw["object_id"] = *policy.ObjectID
}
if policy.ApplicationID != nil {
policyRaw["application_id"] = policy.ApplicationID.String()
}
policyRaw["key_permissions"] = keyPermissionsRaw
policyRaw["secret_permissions"] = secretPermissionsRaw
policyRaw["certificate_permissions"] = certificatePermissionsRaw

result = append(result, policyRaw)
}

return result
}
80 changes: 80 additions & 0 deletions azurerm/data_source_key_vault_secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package azurerm

import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmKeyVaultSecret() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmKeyVaultSecretRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"vault_uri": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"value": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},

"content_type": {
Type: schema.TypeString,
Computed: true,
},

"version": {
Type: schema.TypeString,
Computed: true,
},

"tags": tagsForDataSourceSchema(),
},
}
}

func dataSourceArmKeyVaultSecretRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).keyVaultManagementClient
ctx := meta.(*ArmClient).StopContext

name := d.Get("name").(string)
vaultUri := d.Get("vault_uri").(string)

// we always want to get the latest version
resp, err := client.GetSecret(ctx, vaultUri, name, "")
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("KeyVault Secret %q (KeyVault URI %q) does not exist", name, vaultUri)
}
return fmt.Errorf("Error making Read request on Azure KeyVault Secret %s: %+v", name, err)
}

// the version may have changed, so parse the updated id
respID, err := parseKeyVaultChildID(*resp.ID)
if err != nil {
return err
}

d.SetId(*resp.ID)

d.Set("name", respID.Name)
d.Set("vault_uri", respID.KeyVaultBaseUrl)
d.Set("value", resp.Value)
d.Set("version", respID.Version)
d.Set("content_type", resp.ContentType)

flattenAndSetTags(d, resp.Tags)
return nil
}
78 changes: 78 additions & 0 deletions azurerm/data_source_key_vault_secret_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package azurerm

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataSourceAzureRMKeyVaultSecret_basic(t *testing.T) {
dataSourceName := "data.azurerm_key_vault_secret.test"

rString := acctest.RandString(8)
location := testLocation()
config := testAccDataSourceKeyVaultSecret_basic(rString, location)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "value", "rick-and-morty"),
resource.TestCheckResourceAttr(dataSourceName, "tags.%", "0"),
),
},
},
})
}

func TestAccDataSourceAzureRMKeyVaultSecret_complete(t *testing.T) {
dataSourceName := "data.azurerm_key_vault_secret.test"

rString := acctest.RandString(8)
location := testLocation()
config := testAccDataSourceKeyVaultSecret_complete(rString, location)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "value", "<rick><morty /></rick>"),
resource.TestCheckResourceAttr(dataSourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(dataSourceName, "tags.hello", "world"),
),
},
},
})
}

func testAccDataSourceKeyVaultSecret_basic(rString string, location string) string {
resource := testAccAzureRMKeyVaultSecret_basic(rString, location)
return fmt.Sprintf(`
%s

data "azurerm_key_vault_secret" "test" {
name = "${azurerm_key_vault_secret.test.name}"
vault_uri = "${azurerm_key_vault_secret.test.vault_uri}"
}
`, resource)
}

func testAccDataSourceKeyVaultSecret_complete(rString string, location string) string {
resource := testAccAzureRMKeyVaultSecret_complete(rString, location)
return fmt.Sprintf(`
%s

data "azurerm_key_vault_secret" "test" {
name = "${azurerm_key_vault_secret.test.name}"
vault_uri = "${azurerm_key_vault_secret.test.vault_uri}"
}
`, resource)
}
Loading