Skip to content

Commit

Permalink
KMS: import of keymaterial (#2731)
Browse files Browse the repository at this point in the history
KMS: import of keymaterial

Summary of the Pull Request

Enhancement to change KMS origin
New resource: resource/opentelekomcloud_kms_key_material_v1
New data source: data_source/opentelekomcloud_kms_key_material_parameters_v1

PR Checklist

 Refers to: #2707
 Tests added/passed.
 Documentation updated.
 Schema updated.
 Release notes added.

Acceptance Steps Performed
2024/11/15 13:58:48 [INFO] Building Swift S3 auth structure
2024/11/15 13:58:48 [INFO] Setting AWS metadata API timeout to 100ms
2024/11/15 13:58:49 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2024/11/15 13:58:49 [INFO] Swift S3 Auth provider used: "StaticProvider"
=== RUN   TestAccKmsImportParamsV1DataSource_basic
--- PASS: TestAccKmsImportParamsV1DataSource_basic (99.13s)
PASS

Process finished with the exit code 0

2024/11/15 14:08:28 [INFO] Building Swift S3 auth structure
2024/11/15 14:08:28 [INFO] Setting AWS metadata API timeout to 100ms
2024/11/15 14:08:30 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2024/11/15 14:08:30 [INFO] Swift S3 Auth provider used: "StaticProvider"
=== RUN   TestAccKmsKeyMaterial_Symmetric
--- PASS: TestAccKmsKeyMaterial_Symmetric (131.59s)
PASS

Process finished with the exit code 0

2024/11/15 15:58:39 [INFO] Building Swift S3 auth structure
2024/11/15 15:58:39 [INFO] Setting AWS metadata API timeout to 100ms
2024/11/15 15:58:40 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2024/11/15 15:58:40 [INFO] Swift S3 Auth provider used: "StaticProvider"
=== RUN   TestAccKmsKeyV1_basic
--- PASS: TestAccKmsKeyV1_basic (195.41s)
=== RUN   TestAccKmsKey_isEnabled
--- PASS: TestAccKmsKey_isEnabled (272.98s)
=== RUN   TestAccKmsKey_rotation
--- PASS: TestAccKmsKey_rotation (113.45s)
=== RUN   TestAccKmsKey_cancelDeletion
--- PASS: TestAccKmsKey_cancelDeletion (113.20s)
=== RUN   TestAccKmsKey_cancelDeletionWithRotation
--- PASS: TestAccKmsKey_cancelDeletionWithRotation (113.36s)
=== RUN   TestAccKmsKey_externalKey
--- PASS: TestAccKmsKey_externalKey (112.90s)
PASS

Process finished with the exit code 0

Reviewed-by: Aloento
Reviewed-by: Anton Sidelnikov
  • Loading branch information
artem-lifshits authored Nov 15, 2024
1 parent 673619d commit f3fc266
Show file tree
Hide file tree
Showing 15 changed files with 860 additions and 76 deletions.
52 changes: 52 additions & 0 deletions docs/data-sources/kms_key_material_parameters_v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
subcategory: "Key Management Service (KMS)"
layout: "opentelekomcloud"
page_title: "OpenTelekomCloud: opentelekomcloud_kms_key_material_parameters_v1"
sidebar_current: "docs-opentelekomcloud-datasource-kms-key-material-parameters-v1"
description: |-
Get the parameters required to import key material into a CMK from OpenTelekomCloud
---

Up-to-date reference of API arguments for Obtaining CMK Import parameters you can get at
[documentation portal](https://docs.otc.t-systems.com/key-management-service/api-ref/apis/cmk_management/obtaining_cmk_import_parameters.html)

# opentelekomcloud_kms_key_material_parameters_v1

Use this data source to get the data required to import key material into a CMK in OpenTelekomCloud KMS.

~> **Warning** This data source returns parameters for a CMK in `Pending_import` state.
Once the key is successfully imported and the state changes to `Enabled`, the data source will no longer fetch
new parameters and its computed attributes will be nulled. If other resources utilize fields from this data source, consider
adding `lifecycle { ignore_changes = [...] }` to handle state transitions properly.

## Example Usage

```hcl
data "opentelekomcloud_kms_key_material_parameters_v1" "params" {
key_id = "0d0466b0-e727-4d9c-b35d-f84bb474a37f"
wrapping_algorithm = "RSAES_PKCS1_V1_5"
}
```

## Argument Reference

* `key_id` - (Required, String) The ID of the CMK to import key material into. Must be 36 bytes and match
regexp `^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$`.

* `wrapping_algorithm` - (Required, String) The algorithm to be used for wrapping the imported key material.
Valid values are:
* `RSAES_PKCS1_V1_5`
* `RSAES_OAEP_SHA_1`
* `RSAES_OAEP_SHA_256`

* `sequence` - (Optional, String) 36-byte serial number of the request message.

## Attributes Reference

`id` is set to the date of the retrieved parameters. In addition, the following attributes are exported:

* `import_token` - The import token to use in subsequent ImportKey requests.

* `expiration_time` - The time at which the import token and public key expire.

* `public_key` - The public key to use to encrypt the key material before import (Base64 encoded).
154 changes: 154 additions & 0 deletions docs/resources/kms_key_material_v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
subcategory: "Key Management Service (KMS)"
layout: "opentelekomcloud"
page_title: "OpenTelekomCloud: opentelekomcloud_kms_key_material_v1"
sidebar_current: "docs-opentelekomcloud-resource-kms-key-material-v1"
description: |-
Manages a KMS Key Material resource within OpenTelekomCloud.
---

Up-to-date reference of API arguments for KMS Key Material you can get at
[documentation portal](https://docs.otc.t-systems.com/key-management-service/api-ref/apis/cmk_management/importing_cmk_material.html)

# opentelekomcloud_kms_key_material_v1

Manages a KMS key material resource within OpenTelekomCloud.

-> NOTE: Please confirm that the state of the imported key is pending import.

## Example Usage

### Basic usage

variable "key_id" {}
variable "import_token" {}
variable "encrypted_key_material" {}

```hcl
resource "opentelekomcloud_kms_key_material_v1" "test" {
key_id = var.key_id
import_token = var.import_token
encrypted_key_material = var.encrypted_key_material
}
```

### Complete key material import workflow

```hcl
locals {
encrypt_script = <<-EOF
#!/bin/bash
INPUT=$(cat)
PUBLIC_KEY=$(echo "$INPUT" | jq -r '.public_key')
KEY_MATERIAL=$(echo "$INPUT" | jq -r '.input')
TRIMMED_INPUT=$(echo -n "$KEY_MATERIAL" | head -c 32)
echo "$PUBLIC_KEY" > public_key.pem
ENCRYPTED=$(echo -n "$TRIMMED_INPUT" | openssl rsautl -encrypt -pubin -inkey public_key.pem -pkcs | base64 -w 0)
rm public_key.pem
printf '{"output":"%s"}' "$ENCRYPTED"
EOF
public_key = <<-EOF
-----BEGIN PUBLIC KEY-----
${data.opentelekomcloud_kms_key_material_parameters_v1.params.public_key}
-----END PUBLIC KEY-----
EOF
}
resource "random_password" "key_material" {
length = 32
special = false
override_special = "!#$%"
lifecycle {
ignore_changes = all
}
}
data "external" "encrypt_key_material" {
program = ["bash", "-c", local.encrypt_script]
query = {
input = random_password.key_material.result
public_key = local.public_key
}
}
data "opentelekomcloud_kms_key_material_parameters_v1" "params" {
key_id = opentelekomcloud_kms_key_v1.key_1.id
wrapping_algorithm = "RSAES_PKCS1_V1_5"
}
resource "opentelekomcloud_kms_key_material_v1" "test" {
depends_on = [data.external.encrypt_key_material]
key_id = opentelekomcloud_kms_key_v1.key_1.id
import_token = data.opentelekomcloud_kms_key_material_parameters_v1.params.import_token
encrypted_key_material = data.external.encrypt_key_material.result.output
lifecycle {
ignore_changes = all
}
}
resource "opentelekomcloud_kms_key_v1" "key_1" {
key_alias = "key_test"
origin = "external"
}
```

## Argument Reference

The following arguments are supported:

* `key_id` - (Required, String, ForceNew) Specifies the ID of the KMS key.
Changing this creates a new resource.

* `import_token` - (Required, String, ForceNew) Specifies the key import token in Base64 format.
The value contains `200` to `6144` characters, including letters, digits, slashes(/) and equals(=). This value is
obtained through the interface [Obtaining Key Import Parameters](https://docs.otc.t-systems.com/key-management-service/api-ref/apis/cmk_management/obtaining_cmk_import_parameters.html)
or by using `data_source/kms_key_material_parameters_v1`.

* `encrypted_key_material` - (Required, String, ForceNew) Specifies the encrypted symmetric key material in Base64 format.
The value contains `344` to `360` characters, including letters, digits, slashes(/) and equals(=).
If an asymmetric key is imported, this parameter is a temporary intermediate key used to encrypt the private key.
This value is obtained refer to
[documentation](https://docs.otc.t-systems.com/key-management-service/umn/user_guide/key_management/creating_cmks_using_imported_key_material/importing_a_key_material.html).

* `expiration_time` - (Optional, String, ForceNew) Specifies the expiration time of the key material.
This field is only valid for symmetric keys. The time is in the format of timestamp, that is, the
offset seconds from 1970-01-01 00:00:00 UTC to the specified time.
The time must be greater than the current time.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The resource ID which equals the `key_id`.

* `key_state` - The status of the kms key. The valid values are as follows:
**1**: To be activated
**2**: Enabled.
**3**: Disabled.
**4**: Pending deletion.
**5**: Pending import.

* `region` - The region in which KMS key is created.

## Import

The KMS key material can be imported using `id`, e.g.

```bash
$ terraform import opentelekomcloud_kms_key_material_v1.test 7056d636-ac60-4663-8a6c-82d3c32c1c64
```

Note that the imported state may not be identical to your resource definition,
due to `import_token`, `encrypted_key_material` and `encrypted_privatekey` are missing from the API response.
It is generally recommended running `terraform plan` after importing a KMS key material.
You can then decide if changes should be applied to the KMS key material, or the resource
definition should be updated to align with the KMS key material. Also you can ignore changes as below.

```hcl
resource "opentelekomcloud_kms_key_material_v1" "test" {
lifecycle {
ignore_changes = [import_token, encrypted_key_material, encrypted_privatekey]
}
}
```
37 changes: 25 additions & 12 deletions docs/resources/kms_key_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,38 @@ resource "opentelekomcloud_kms_key_v1" "key_1" {

The following arguments are supported:

* `allow_cancel_deletion` - (Optional) Specifies whether the key is enabled from Pending Deletion state. The value `true` indicates
* `allow_cancel_deletion` - (Optional, Bool) Specifies whether the key is enabled from Pending Deletion state. The value `true` indicates
that the key state Pending Deletion will be cancelled.

* `key_alias` - (Required) The alias in which to create the key. It is required when
* `key_alias` - (Required, String) The alias in which to create the key. It is required when
we create a new key. Changing this updates the alias of key.

* `key_description` - (Optional) The description of the key as viewed in OpenTelekomCloud console.
* `key_description` - (Optional, String) The description of the key as viewed in OpenTelekomCloud console.
Changing this updates the description of key.

* `realm` - (Optional) Region where a key resides. Changing this creates a new key.
* `origin` - (Optional, String, ForceNew) Specifies the source of the KMS key.
Changing this parameter will create a new resource.
The default value is **kms**. The valid values are as follows:
+ **kms**: The key is generated by KMS.
+ **external**: The key is external imported.

* `pending_days` - (Optional) Duration in days after which the key is deleted
* `realm` - (Optional, String, ForceNew) Region where a key resides. Changing this creates a new key.

* `pending_days` - (Optional, String) Duration in days after which the key is deleted
after destruction of the resource, must be between 7 and 1096 days. Defaults to 7.
It only is used when delete a key.

* `is_enabled` - (Optional) Specifies whether the key is enabled. Defaults to true.
Changing this updates the state of existing key.
* `is_enabled` - (Optional, Bool) Specifies whether the KMS key is enabled.
The default value is **true**.
This parameter is not supported when creating an external import key for the first time.

* `rotation_interval` - (Optional) Rotation interval. The value is an integer ranging from 30 to 365.
* `rotation_interval` - (Optional, Int) Rotation interval. The value is an integer ranging from 30 to 365.
Set the interval based on how often a CMK is used.
If it is frequently used, set a short interval; otherwise, set a long one.

* `rotation_enabled` - (Optional) Specifies whether the key is enabled for rotation.
* `rotation_enabled` - (Optional, Bool) Specifies whether the key is enabled for rotation.

* `tags` - (Optional) Tags key/value pairs to associate with the AutoScaling Group.
* `tags` - (Optional, Map) Tags key/value pairs to associate with the AutoScaling Group.


## Attributes Reference
Expand All @@ -71,13 +78,19 @@ The following attributes are exported:

* `key_description` - See Argument Reference above.

* `key_state` - The current status of the KMS key.
The valid values are as follows:
+ **1**: To be activated.
+ **2**: Enabled.
+ **3**: Disabled.
+ **4**: Pending deletion.
+ **5**: Pending import.

* `realm` - See Argument Reference above.

* `default_key_flag` - Identification of a Master Key. The value `1` indicates a Default
Master Key, and the value `0` indicates a key.

* `origin` - Origin of a key. The default value is kms.

* `scheduled_deletion_date` - Scheduled deletion time (time stamp) of a key.

* `domain_id` - ID of a user domain for the key.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
github.com/mitchellh/go-homedir v1.1.0
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241112162134-960efd8ff98a
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241113151820-d0db3ffba21c
github.com/unknwon/com v1.0.1
golang.org/x/crypto v0.23.0
golang.org/x/sync v0.1.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241112162134-960efd8ff98a h1:MasOCdy6QVtflzeAnkx7rhR1LcpHsQIkygAJLWCHyX0=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241112162134-960efd8ff98a/go.mod h1:M1F6OfSRZRzAmAFKQqSLClX952at5hx5rHe4UTEykgg=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241113151820-d0db3ffba21c h1:tvpCy4VK7F08Mvzk975NSZYDOLRgjKsBR6KVY8SYYR8=
github.com/opentelekomcloud/gophertelekomcloud v0.9.4-0.20241113151820-d0db3ffba21c/go.mod h1:M1F6OfSRZRzAmAFKQqSLClX952at5hx5rHe4UTEykgg=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
7 changes: 7 additions & 0 deletions opentelekomcloud/acceptance/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,10 @@ func TestAccPreCheckOBS(t *testing.T) {
t.Skip("HW_ACCESS_KEY and HW_SECRET_KEY must be set for OBS acceptance tests")
}
}

// lintignore:AT003
func TestAccPreCheckKmsKeyID(t *testing.T) {
if env.OS_KMS_ID == "" {
t.Skip("OS_KMS_ID must be set for KMS key material acceptance tests.")
}
}
38 changes: 38 additions & 0 deletions opentelekomcloud/acceptance/kms/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package acceptance

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"fmt"
)

func generateKeyMaterial(publicKeyB64 string) (string, error) {
publicKeyBytes, err := base64.StdEncoding.DecodeString(publicKeyB64)
if err != nil {
return "", fmt.Errorf("error decoding public key: %s", err)
}

pubKey, err := x509.ParsePKIXPublicKey(publicKeyBytes)
if err != nil {
return "", fmt.Errorf("error parsing public key: %s", err)
}

rsaPublicKey, ok := pubKey.(*rsa.PublicKey)
if !ok {
return "", fmt.Errorf("public key is not RSA")
}

keyMaterial := make([]byte, 32)
if _, err := rand.Read(keyMaterial); err != nil {
return "", fmt.Errorf("error generating random key material: %s", err)
}

encryptedKeyMaterial, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, keyMaterial)
if err != nil {
return "", fmt.Errorf("error encrypting key material: %s", err)
}

return base64.StdEncoding.EncodeToString(encryptedKeyMaterial), nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package acceptance

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/env"

"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/common"
)

func TestAccKmsImportMaterialParamsV1DataSource_basic(t *testing.T) {
dataSourceImportName := "data.opentelekomcloud_kms_key_material_parameters_v1.test"
kmsKeyId := os.Getenv("OS_KMS_ID")
if kmsKeyId == "" {
t.Skip("OS_KMS_ID env var is not set")
}

resource.Test(t, resource.TestCase{
PreCheck: func() { common.TestAccPreCheck(t) },
ProviderFactories: common.TestAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccKmsDataKeyV1ImportMaterialParams_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
dataSourceImportName, "key_id", kmsKeyId),
resource.TestCheckResourceAttrSet(
dataSourceImportName, "import_token"),
resource.TestCheckResourceAttrSet(
dataSourceImportName, "public_key"),
resource.TestCheckResourceAttrSet(
dataSourceImportName, "expiration_time"),
),
},
},
})
}

var testAccKmsDataKeyV1ImportMaterialParams_basic = fmt.Sprintf(`
data "opentelekomcloud_kms_key_material_parameters_v1" "test" {
key_id = "%s"
wrapping_algorithm = "RSAES_PKCS1_V1_5"
}
`, env.OS_KMS_ID)
Loading

0 comments on commit f3fc266

Please sign in to comment.