Skip to content

Commit f0bd00c

Browse files
jremy42protobuf-ci-cd
andauthored
feat(keymanager): add Key Manager Key resource (#3198)
fix lint: add doc: fix lint fix test fix docs fix dead link fix lint fix lint fix docs fix lint fix lint fix lint use types helpers chore: add description fix lint gci refacto resource fix lint use regionial ID use sdk oneOf converter use parseID fix: use usageToString fix go mod Co-authored-by: protobuf-ci-cd <[email protected]>
1 parent e27278f commit f0bd00c

File tree

7 files changed

+1253
-0
lines changed

7 files changed

+1253
-0
lines changed

docs/resources/key_manager_key.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
subcategory: "Key Manager"
3+
page_title: "Scaleway: scaleway_key_manager_key"
4+
---
5+
# Resource: scaleway_key_manager_key
6+
7+
Provides a Scaleway Key Manager Key resource.
8+
This resource allows you to create and manage cryptographic keys in Scaleway Key Manager (KMS).
9+
10+
## Example Usage
11+
12+
```terraform
13+
resource "scaleway_key_manager_key" "main" {
14+
name = "my-kms-key"
15+
region = "fr-par"
16+
project_id = "your-project-id" # optional, will use provider default if omitted
17+
usage = "symmetric_encryption"
18+
description = "Key for encrypting secrets"
19+
tags = ["env:prod", "kms"]
20+
unprotected = true
21+
22+
rotation_policy {
23+
rotation_period = "720h" # 30 days
24+
}
25+
}
26+
```
27+
28+
## Argument Reference
29+
30+
The following arguments are supported:
31+
32+
- `name` (String) – The name of the key.
33+
- `region` (String) – The region in which to create the key (e.g., `fr-par`).
34+
- `project_id` (String, Optional) – The ID of the project the key belongs to.
35+
- `usage` (String, **Required**) – The usage of the key. Valid values are:
36+
- `symmetric_encryption`
37+
- `asymmetric_encryption`
38+
- `asymmetric_signing`
39+
- `description` (String, Optional) – A description for the key.
40+
- `tags` (List of String, Optional) – A list of tags to assign to the key.
41+
- `unprotected` (Boolean, Optional) – If `true`, the key can be deleted. Defaults to `false` (protected).
42+
- `origin` (String, Optional) – The origin of the key. Valid values are:
43+
- `scaleway_kms` (default)
44+
- `external`
45+
- `rotation_policy` (Block, Optional) – Rotation policy for the key:
46+
- `rotation_period` (String, Optional) – The period between key rotations (e.g., `"720h"` for 30 days).
47+
48+
## Attributes Reference
49+
50+
In addition to all arguments above, the following attributes are exported:
51+
52+
- `id` – The ID of the key.
53+
- `state` – The state of the key (e.g., `enabled`).
54+
- `created_at` – The date and time when the key was created.
55+
- `updated_at` – The date and time when the key was last updated.
56+
- `rotation_count` – The number of times the key has been rotated.
57+
- `protected` – Whether the key is protected from deletion.
58+
- `locked` – Whether the key is locked.
59+
- `rotated_at` – The date and time when the key was last rotated.
60+
- `origin_read` – The origin of the key as returned by the API.
61+
- `region_read` – The region of the key as returned by the API.
62+
- `rotation_policy` (Block)
63+
- `rotation_period` – The period between key rotations.
64+
- `next_rotation_at` – The date and time of the next scheduled rotation.
65+
66+
## Import
67+
68+
You can import a key using its ID and region:
69+
70+
```shell
71+
terraform import scaleway_key_manager_key.main fr-par/11111111-2222-3333-4444-555555555555
72+
```
73+
74+
## Notes
75+
76+
- **Protection**: By default, keys are protected and cannot be deleted. To allow deletion, set `unprotected = true` when creating the key.
77+
- **Rotation Policy**: The `rotation_policy` block allows you to set automatic rotation for your key.
78+
- **Origin**: The `origin` argument is optional and defaults to `scaleway_kms`. Use `external` if you want to import an external key (see Scaleway documentation for details).
79+
- **Project and Region**: If not specified, `project_id` and `region` will default to the provider configuration.
80+
81+
## Example: Asymmetric Key
82+
83+
```terraform
84+
resource "scaleway_key_manager_key" "asym" {
85+
name = "asymmetric-key"
86+
region = "fr-par"
87+
usage = "asymmetric_signing"
88+
description = "Key for signing documents"
89+
unprotected = true
90+
}
91+
```

internal/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/ipam"
3333
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/jobs"
3434
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/k8s"
35+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/keymanager"
3536
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/lb"
3637
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/marketplace"
3738
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/mnq"
@@ -195,6 +196,7 @@ func Provider(config *Config) plugin.ProviderFunc {
195196
"scaleway_k8s_acl": k8s.ResourceACL(),
196197
"scaleway_k8s_cluster": k8s.ResourceCluster(),
197198
"scaleway_k8s_pool": k8s.ResourcePool(),
199+
"scaleway_key_manager_key": keymanager.ResourceKeyManagerKey(),
198200
"scaleway_lb": lb.ResourceLb(),
199201
"scaleway_lb_acl": lb.ResourceACL(),
200202
"scaleway_lb_backend": lb.ResourceBackend(),
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package keymanager
2+
3+
import (
4+
"time"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
key_manager "github.com/scaleway/scaleway-sdk-go/api/key_manager/v1alpha1"
8+
"github.com/scaleway/scaleway-sdk-go/scw"
9+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
10+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
12+
)
13+
14+
func UsageToString(u *key_manager.KeyUsage) string {
15+
if u == nil {
16+
return ""
17+
}
18+
19+
if u.SymmetricEncryption != nil {
20+
return "symmetric_encryption"
21+
}
22+
23+
if u.AsymmetricEncryption != nil {
24+
return "asymmetric_encryption"
25+
}
26+
27+
if u.AsymmetricSigning != nil {
28+
return "asymmetric_signing"
29+
}
30+
31+
return ""
32+
}
33+
34+
func newKeyManagerAPI(d *schema.ResourceData, m any) (*key_manager.API, scw.Region, error) {
35+
api := key_manager.NewAPI(meta.ExtractScwClient(m))
36+
37+
region, err := meta.ExtractRegion(d, m)
38+
if err != nil {
39+
return nil, "", err
40+
}
41+
42+
return api, region, nil
43+
}
44+
45+
func NewKeyManagerAPIWithRegionAndID(m any, id string) (*key_manager.API, scw.Region, string, error) {
46+
region, keyID, err := regional.ParseID(id)
47+
if err != nil {
48+
return nil, "", "", err
49+
}
50+
51+
client := key_manager.NewAPI(meta.ExtractScwClient(m))
52+
53+
return client, region, keyID, nil
54+
}
55+
56+
func ExpandKeyUsage(usage string) *key_manager.KeyUsage {
57+
switch usage {
58+
case "symmetric_encryption":
59+
alg := key_manager.KeyAlgorithmSymmetricEncryptionAes256Gcm
60+
61+
return &key_manager.KeyUsage{SymmetricEncryption: &alg}
62+
case "asymmetric_encryption":
63+
alg := key_manager.KeyAlgorithmAsymmetricEncryptionRsaOaep3072Sha256
64+
65+
return &key_manager.KeyUsage{AsymmetricEncryption: &alg}
66+
case "asymmetric_signing":
67+
alg := key_manager.KeyAlgorithmAsymmetricSigningEcP256Sha256
68+
69+
return &key_manager.KeyUsage{AsymmetricSigning: &alg}
70+
default:
71+
return nil
72+
}
73+
}
74+
75+
func ExpandKeyRotationPolicy(v any) (*key_manager.KeyRotationPolicy, error) {
76+
list, ok := v.([]any)
77+
if !ok || len(list) == 0 {
78+
return nil, nil
79+
}
80+
81+
m, ok := list[0].(map[string]any)
82+
if !ok {
83+
return nil, nil
84+
}
85+
86+
periodStr, ok := m["rotation_period"].(string)
87+
if !ok || periodStr == "" {
88+
return nil, nil
89+
}
90+
91+
period, err := time.ParseDuration(periodStr)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
return &key_manager.KeyRotationPolicy{
97+
RotationPeriod: scw.NewDurationFromTimeDuration(period),
98+
}, nil
99+
}
100+
101+
func FlattenKeyRotationPolicy(rp *key_manager.KeyRotationPolicy) []map[string]any {
102+
if rp == nil {
103+
return nil
104+
}
105+
106+
var periodStr string
107+
108+
if rp.RotationPeriod != nil {
109+
periodStr = rp.RotationPeriod.ToTimeDuration().String()
110+
}
111+
112+
return []map[string]any{
113+
{
114+
"rotation_period": periodStr,
115+
"next_rotation_at": types.FlattenTime(rp.NextRotationAt),
116+
},
117+
}
118+
}

0 commit comments

Comments
 (0)