-
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 Data Source:
azurerm_key_vault_encrypted_value
``` $ TF_ACC=1 go test -v ./internal/services/keyvault -run=TestAccEncryptedValueDataSource_ === RUN TestAccEncryptedValueDataSource_encryptAndDecrypt === PAUSE TestAccEncryptedValueDataSource_encryptAndDecrypt === CONT TestAccEncryptedValueDataSource_encryptAndDecrypt --- PASS: TestAccEncryptedValueDataSource_encryptAndDecrypt (274.42s) PASS ok github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault 276.443s ``` This commit supersedes #8895 by converting this into a Data Source rather than a Resource which handles the bi-directional conversion of encrypted/decrypted values as necessary.
- Loading branch information
1 parent
7110726
commit 24377d9
Showing
5 changed files
with
301 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
128 changes: 128 additions & 0 deletions
128
internal/services/keyvault/encrypted_value_data_source.go
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,128 @@ | ||
package keyvault | ||
|
||
import ( | ||
"context" | ||
"crypto/sha1" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/parse" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" | ||
"github.com/hashicorp/terraform-provider-azurerm/utils" | ||
) | ||
|
||
var _ sdk.DataSource = EncryptedValueDataSource{} | ||
|
||
type EncryptedValueDataSource struct{} | ||
|
||
type EncryptedValueDataSourceModel struct { | ||
KeyVaultKeyId string `tfschema:"key_vault_key_id"` | ||
Algorithm string `tfschema:"algorithm"` | ||
EncryptedData string `tfschema:"encrypted_data"` | ||
PlainTextValue string `tfschema:"plain_text_value"` | ||
} | ||
|
||
func (EncryptedValueDataSource) Arguments() map[string]*schema.Schema { | ||
return map[string]*schema.Schema{ | ||
"key_vault_key_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validate.NestedItemId, | ||
}, | ||
"algorithm": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
string(keyvault.RSA15), | ||
string(keyvault.RSAOAEP), | ||
string(keyvault.RSAOAEP256), | ||
}, false), | ||
}, | ||
"encrypted_data": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Sensitive: true, | ||
}, | ||
"plain_text_value": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Sensitive: true, | ||
}, | ||
} | ||
} | ||
|
||
func (EncryptedValueDataSource) Attributes() map[string]*schema.Schema { | ||
return map[string]*schema.Schema{} | ||
} | ||
|
||
func (EncryptedValueDataSource) ModelObject() interface{} { | ||
return &EncryptedValueDataSourceModel{} | ||
} | ||
|
||
func (e EncryptedValueDataSource) ResourceType() string { | ||
return "azurerm_key_vault_encrypted_value" | ||
} | ||
|
||
func (EncryptedValueDataSource) Read() sdk.ResourceFunc { | ||
return sdk.ResourceFunc{ | ||
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { | ||
client := metadata.Client.KeyVault.ManagementClient | ||
ctx, cancel := timeouts.ForCreate(metadata.Client.StopContext, metadata.ResourceData) | ||
defer cancel() | ||
|
||
var model EncryptedValueDataSourceModel | ||
if err := metadata.Decode(&model); err != nil { | ||
return fmt.Errorf("decoding: %+v", err) | ||
} | ||
|
||
if model.EncryptedData == "" && model.PlainTextValue == "" { | ||
return fmt.Errorf("one of `encrypted_data` or `plain_text_value` must be specified - both were empty") | ||
} | ||
if model.EncryptedData != "" && model.PlainTextValue != "" { | ||
return fmt.Errorf("only one of `encrypted_data` or `plain_text_value` must be specified - both were specified") | ||
} | ||
|
||
keyVaultKeyId, err := parse.ParseNestedItemID(model.KeyVaultKeyId) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if model.EncryptedData != "" { | ||
params := keyvault.KeyOperationsParameters{ | ||
Algorithm: keyvault.JSONWebKeyEncryptionAlgorithm(model.Algorithm), | ||
Value: utils.String(model.EncryptedData), | ||
} | ||
result, err := client.Decrypt(ctx, keyVaultKeyId.KeyVaultBaseUrl, keyVaultKeyId.Name, keyVaultKeyId.Version, params) | ||
if err != nil { | ||
return fmt.Errorf("decrypting plain-text value using Key Vault Key ID %q: %+v", model.KeyVaultKeyId, err) | ||
} | ||
if result.Result == nil { | ||
return fmt.Errorf("decrypting plain-text value using Key Vault Key ID %q: `result` was nil", model.KeyVaultKeyId) | ||
} | ||
model.PlainTextValue = *result.Result | ||
} else { | ||
params := keyvault.KeyOperationsParameters{ | ||
Algorithm: keyvault.JSONWebKeyEncryptionAlgorithm(model.Algorithm), | ||
Value: utils.String(model.PlainTextValue), | ||
} | ||
result, err := client.Encrypt(ctx, keyVaultKeyId.KeyVaultBaseUrl, keyVaultKeyId.Name, keyVaultKeyId.Version, params) | ||
if err != nil { | ||
return fmt.Errorf("encrypting plain-text value using Key Vault Key ID %q: %+v", model.KeyVaultKeyId, err) | ||
} | ||
if result.Result == nil { | ||
return fmt.Errorf("encrypting plain-text value using Key Vault Key ID %q: `result` was nil", model.KeyVaultKeyId) | ||
} | ||
model.EncryptedData = *result.Result | ||
} | ||
|
||
metadata.ResourceData.SetId(fmt.Sprintf("%s-%s-%s", model.KeyVaultKeyId, model.Algorithm, sha1.Sum([]byte(model.EncryptedData)))) | ||
return metadata.Encode(&model) | ||
}, | ||
Timeout: 5 * time.Minute, | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
internal/services/keyvault/encrypted_value_data_source_test.go
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,98 @@ | ||
package keyvault_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" | ||
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" | ||
) | ||
|
||
type EncryptedValueDataSourceTest struct{} | ||
|
||
func TestAccEncryptedValueDataSource_encryptAndDecrypt(t *testing.T) { | ||
// since this config includes both Encrypted and Decrypted we're testing both use-cases (and comparing the values below) | ||
// so we only need a single test here | ||
data := acceptance.BuildTestData(t, "data.azurerm_key_vault_encrypted_value", "decrypted") | ||
r := EncryptedValueDataSourceTest{} | ||
data.DataSourceTest(t, []acceptance.TestStep{ | ||
{ | ||
Config: r.decrypt(data), | ||
Check: acceptance.ComposeTestCheckFunc( | ||
check.That(data.ResourceName).Key("encrypted_value").MatchesOtherKey(check.That("data.azurerm_key_vault_encrypted_value.encrypted").Key("encrypted_value")), | ||
check.That(data.ResourceName).Key("plain_text_value").MatchesOtherKey(check.That("data.azurerm_key_vault_encrypted_value.encrypted").Key("plain_text_value")), | ||
), | ||
}, | ||
}) | ||
} | ||
|
||
func (t EncryptedValueDataSourceTest) decrypt(data acceptance.TestData) string { | ||
template := t.template(data) | ||
return fmt.Sprintf(` | ||
provider "azurerm" { | ||
features {} | ||
} | ||
%s | ||
data "azurerm_key_vault_encrypted_value" "encrypted" { | ||
key_vault_key_id = azurerm_key_vault_key.test.id | ||
algorithm = "RSA1_5" | ||
plain_text_value = "some-encrypted-value" | ||
} | ||
data "azurerm_key_vault_encrypted_value" "decrypted" { | ||
key_vault_key_id = azurerm_key_vault_key.test.id | ||
algorithm = "RSA1_5" | ||
encrypted_data = data.azurerm_key_vault_encrypted_value.encrypted.encrypted_data | ||
} | ||
`, template) | ||
} | ||
|
||
func (t EncryptedValueDataSourceTest) template(data acceptance.TestData) string { | ||
return fmt.Sprintf(` | ||
data "azurerm_client_config" "current" {} | ||
resource "azurerm_resource_group" "test" { | ||
name = "acctestRG-%[1]d" | ||
location = "%[2]s" | ||
} | ||
resource "azurerm_key_vault" "test" { | ||
name = "acctestkv-%[3]s" | ||
location = azurerm_resource_group.test.location | ||
resource_group_name = azurerm_resource_group.test.name | ||
tenant_id = data.azurerm_client_config.current.tenant_id | ||
sku_name = "premium" | ||
soft_delete_retention_days = 7 | ||
access_policy { | ||
tenant_id = data.azurerm_client_config.current.tenant_id | ||
object_id = data.azurerm_client_config.current.object_id | ||
key_permissions = [ | ||
"Create", | ||
"Delete", | ||
"Decrypt", | ||
"Encrypt", | ||
"Get", | ||
"Purge", | ||
"Recover", | ||
"Update", | ||
] | ||
} | ||
} | ||
resource "azurerm_key_vault_key" "test" { | ||
name = "key-%[3]s" | ||
key_vault_id = azurerm_key_vault.test.id | ||
key_type = "RSA" | ||
key_size = 2048 | ||
key_opts = [ | ||
"decrypt", | ||
"encrypt", | ||
] | ||
} | ||
`, 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,63 @@ | ||
--- | ||
subcategory: "Key Vault" | ||
layout: "azurerm" | ||
page_title: "Azure Resource Manager: Data Source: azurerm_key_vault_encrypted_value" | ||
description: |- | ||
Encrypts or Decrypts a value using a Key Vault Key. | ||
--- | ||
|
||
# Data Source: azurerm_key_vault_encrypted_value | ||
|
||
Encrypts or Decrypts a value using a Key Vault Key. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
data "azurerm_key_vault" "example" { | ||
name = "mykeyvault" | ||
resource_group_name = "some-resource-group" | ||
} | ||
data "azurerm_key_vault_key" "example" { | ||
name = "some-key" | ||
key_vault_id = data.azurerm_key_vault.example.id | ||
} | ||
data "azurerm_key_vault_encrypted_value" "encrypted" { | ||
key_vault_key_id = azurerm_key_vault_key.test.id | ||
algorithm = "RSA1_5" | ||
plain_text_value = "some-encrypted-value" | ||
} | ||
output "id" { | ||
value = data.azurerm_key_vault_encrypted_value.example.encrypted_data | ||
} | ||
``` | ||
|
||
## Arguments Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `algorithm` - (Required) The Algorithm which should be used to Decrypt/Encrypt this Value. Possible values are `RSA1_5`, `RSA-OAEP` and `RSA-OAEP-256`. | ||
|
||
* `key_vault_key_id` - (Required) The ID of the Key Vault Key which should be used to Decrypt/Encrypt this Value. | ||
|
||
--- | ||
|
||
* `encrypted_data` - (Optional) The Base64 URL Encoded Encrypted Data which should be decrypted into `plain_text_value`. | ||
|
||
* `plain_text_value` - (Optional) The plain-text value which should be Encrypted into `encrypted_data`. | ||
|
||
-> **Note:** One of either `encrypted_data` or `plain_text_value` must be specified and is used to populate the encrypted/decrypted value for the other field. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `id` - The ID of this Encrypted Value | ||
|
||
## 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 encrypting/decrypting this value. |