Skip to content

Commit 288f8bb

Browse files
authored
fix(key_manager): add next_rotation_at in key manager resource (#3290)
1 parent 59881e8 commit 288f8bb

File tree

4 files changed

+303
-5
lines changed

4 files changed

+303
-5
lines changed

internal/services/keymanager/helpers.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package keymanager
22

33
import (
4+
"errors"
5+
"fmt"
46
"time"
57

68
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -85,17 +87,29 @@ func ExpandKeyRotationPolicy(v any) (*key_manager.KeyRotationPolicy, error) {
8587

8688
periodStr, ok := m["rotation_period"].(string)
8789
if !ok || periodStr == "" {
88-
return nil, nil
90+
return nil, errors.New("rotation_period is required when rotation_policy block is specified")
8991
}
9092

9193
period, err := time.ParseDuration(periodStr)
9294
if err != nil {
9395
return nil, err
9496
}
9597

96-
return &key_manager.KeyRotationPolicy{
98+
policy := &key_manager.KeyRotationPolicy{
9799
RotationPeriod: scw.NewDurationFromTimeDuration(period),
98-
}, nil
100+
}
101+
102+
// Handle next_rotation_at if provided
103+
if nextRotationStr, ok := m["next_rotation_at"].(string); ok && nextRotationStr != "" {
104+
nextRotation, err := time.Parse(time.RFC3339, nextRotationStr)
105+
if err != nil {
106+
return nil, fmt.Errorf("invalid next_rotation_at format: %w", err)
107+
}
108+
109+
policy.NextRotationAt = &nextRotation
110+
}
111+
112+
return policy, nil
99113
}
100114

101115
func FlattenKeyRotationPolicy(rp *key_manager.KeyRotationPolicy) []map[string]any {

internal/services/keymanager/key_resource.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
88
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
99
key_manager "github.com/scaleway/scaleway-sdk-go/api/key_manager/v1alpha1"
10+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf"
1011
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
1112
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
1213
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
@@ -52,8 +53,8 @@ func ResourceKeyManagerKey() *schema.Resource {
5253
Description: "Key rotation policy.",
5354
Elem: &schema.Resource{
5455
Schema: map[string]*schema.Schema{
55-
"rotation_period": {Type: schema.TypeString, Optional: true, Description: "Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours)."},
56-
"next_rotation_at": {Type: schema.TypeString, Computed: true, Description: "Timestamp indicating the next scheduled rotation."},
56+
"rotation_period": {Type: schema.TypeString, Required: true, DiffSuppressFunc: dsf.Duration, Description: "Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours)."},
57+
"next_rotation_at": {Type: schema.TypeString, Optional: true, Description: "Timestamp indicating the next scheduled rotation."},
5758
},
5859
},
5960
},

internal/services/keymanager/key_resource_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,38 @@ func IsKeyManagerKeyDestroyed(tt *acctest.TestTools) resource.TestCheckFunc {
123123
return nil
124124
}
125125
}
126+
127+
func TestAccKeyManagerKey_WithRotationPolicy(t *testing.T) {
128+
tt := acctest.NewTestTools(t)
129+
defer tt.Cleanup()
130+
131+
resource.ParallelTest(t, resource.TestCase{
132+
PreCheck: func() { acctest.PreCheck(t) },
133+
ProviderFactories: tt.ProviderFactories,
134+
CheckDestroy: IsKeyManagerKeyDestroyed(tt),
135+
Steps: []resource.TestStep{
136+
{
137+
Config: `
138+
resource "scaleway_key_manager_key" "main" {
139+
name = "tf-test-kms-key-rotation"
140+
region = "fr-par"
141+
usage = "symmetric_encryption"
142+
description = "Test key with rotation policy"
143+
unprotected = true
144+
145+
rotation_policy {
146+
rotation_period = "720h"
147+
next_rotation_at = "2026-01-01T00:00:00Z"
148+
}
149+
}
150+
`,
151+
Check: resource.ComposeTestCheckFunc(
152+
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "name", "tf-test-kms-key-rotation"),
153+
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "usage", "symmetric_encryption"),
154+
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "description", "Test key with rotation policy"),
155+
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "rotation_policy.0.rotation_period", "720h0m0s"),
156+
),
157+
},
158+
},
159+
})
160+
}
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
---
2+
version: 2
3+
interactions:
4+
- id: 0
5+
request:
6+
proto: HTTP/1.1
7+
proto_major: 1
8+
proto_minor: 1
9+
content_length: 338
10+
transfer_encoding: []
11+
trailer: {}
12+
host: api.scaleway.com
13+
remote_addr: ""
14+
request_uri: ""
15+
body: '{"project_id":"105bdce1-64c0-48ab-899d-868455867ecf","name":"tf-test-kms-key-rotation","usage":{"symmetric_encryption":"aes_256_gcm"},"description":"Test key with rotation policy","tags":null,"rotation_policy":{"rotation_period":"2592000.000000000s","next_rotation_at":"2026-01-01T00:00:00Z"},"unprotected":true,"origin":"unknown_origin"}'
16+
form: {}
17+
headers:
18+
Content-Type:
19+
- application/json
20+
User-Agent:
21+
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
22+
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys
23+
method: POST
24+
response:
25+
proto: HTTP/2.0
26+
proto_major: 2
27+
proto_minor: 0
28+
transfer_encoding: []
29+
trailer: {}
30+
content_length: 595
31+
uncompressed: false
32+
body: '{"created_at":"2025-09-01T14:08:23.132185Z","deletion_requested_at":null,"description":"Test key with rotation policy","id":"449ede52-42cd-4692-8ad6-8d3d60b31b1f","locked":false,"name":"tf-test-kms-key-rotation","origin":"scaleway_kms","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","rotated_at":"2025-09-01T14:08:23.140726Z","rotation_count":1,"rotation_policy":{"next_rotation_at":"2026-01-01T00:00:00Z","rotation_period":"2592000s"},"state":"enabled","tags":[],"updated_at":"2025-09-01T14:08:23.140726Z","usage":{"symmetric_encryption":"aes_256_gcm"}}'
33+
headers:
34+
Content-Length:
35+
- "595"
36+
Content-Security-Policy:
37+
- default-src 'none'; frame-ancestors 'none'
38+
Content-Type:
39+
- application/json
40+
Date:
41+
- Mon, 01 Sep 2025 14:08:23 GMT
42+
Server:
43+
- Scaleway API Gateway (fr-par-3;edge01)
44+
Strict-Transport-Security:
45+
- max-age=63072000
46+
X-Content-Type-Options:
47+
- nosniff
48+
X-Frame-Options:
49+
- DENY
50+
X-Request-Id:
51+
- 26922321-731c-4928-8fec-69e3fb748202
52+
status: 200 OK
53+
code: 200
54+
duration: 441.486459ms
55+
- id: 1
56+
request:
57+
proto: HTTP/1.1
58+
proto_major: 1
59+
proto_minor: 1
60+
content_length: 0
61+
transfer_encoding: []
62+
trailer: {}
63+
host: api.scaleway.com
64+
remote_addr: ""
65+
request_uri: ""
66+
body: ""
67+
form: {}
68+
headers:
69+
User-Agent:
70+
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
71+
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
72+
method: GET
73+
response:
74+
proto: HTTP/2.0
75+
proto_major: 2
76+
proto_minor: 0
77+
transfer_encoding: []
78+
trailer: {}
79+
content_length: 595
80+
uncompressed: false
81+
body: '{"created_at":"2025-09-01T14:08:23.132185Z","deletion_requested_at":null,"description":"Test key with rotation policy","id":"449ede52-42cd-4692-8ad6-8d3d60b31b1f","locked":false,"name":"tf-test-kms-key-rotation","origin":"scaleway_kms","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","rotated_at":"2025-09-01T14:08:23.140726Z","rotation_count":1,"rotation_policy":{"next_rotation_at":"2026-01-01T00:00:00Z","rotation_period":"2592000s"},"state":"enabled","tags":[],"updated_at":"2025-09-01T14:08:23.140726Z","usage":{"symmetric_encryption":"aes_256_gcm"}}'
82+
headers:
83+
Content-Length:
84+
- "595"
85+
Content-Security-Policy:
86+
- default-src 'none'; frame-ancestors 'none'
87+
Content-Type:
88+
- application/json
89+
Date:
90+
- Mon, 01 Sep 2025 14:08:23 GMT
91+
Server:
92+
- Scaleway API Gateway (fr-par-3;edge01)
93+
Strict-Transport-Security:
94+
- max-age=63072000
95+
X-Content-Type-Options:
96+
- nosniff
97+
X-Frame-Options:
98+
- DENY
99+
X-Request-Id:
100+
- a38c873d-0db5-4b18-be3d-6702c5221289
101+
status: 200 OK
102+
code: 200
103+
duration: 116.597417ms
104+
- id: 2
105+
request:
106+
proto: HTTP/1.1
107+
proto_major: 1
108+
proto_minor: 1
109+
content_length: 0
110+
transfer_encoding: []
111+
trailer: {}
112+
host: api.scaleway.com
113+
remote_addr: ""
114+
request_uri: ""
115+
body: ""
116+
form: {}
117+
headers:
118+
User-Agent:
119+
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
120+
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
121+
method: GET
122+
response:
123+
proto: HTTP/2.0
124+
proto_major: 2
125+
proto_minor: 0
126+
transfer_encoding: []
127+
trailer: {}
128+
content_length: 595
129+
uncompressed: false
130+
body: '{"created_at":"2025-09-01T14:08:23.132185Z","deletion_requested_at":null,"description":"Test key with rotation policy","id":"449ede52-42cd-4692-8ad6-8d3d60b31b1f","locked":false,"name":"tf-test-kms-key-rotation","origin":"scaleway_kms","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","rotated_at":"2025-09-01T14:08:23.140726Z","rotation_count":1,"rotation_policy":{"next_rotation_at":"2026-01-01T00:00:00Z","rotation_period":"2592000s"},"state":"enabled","tags":[],"updated_at":"2025-09-01T14:08:23.140726Z","usage":{"symmetric_encryption":"aes_256_gcm"}}'
131+
headers:
132+
Content-Length:
133+
- "595"
134+
Content-Security-Policy:
135+
- default-src 'none'; frame-ancestors 'none'
136+
Content-Type:
137+
- application/json
138+
Date:
139+
- Mon, 01 Sep 2025 14:08:24 GMT
140+
Server:
141+
- Scaleway API Gateway (fr-par-3;edge01)
142+
Strict-Transport-Security:
143+
- max-age=63072000
144+
X-Content-Type-Options:
145+
- nosniff
146+
X-Frame-Options:
147+
- DENY
148+
X-Request-Id:
149+
- c856061a-4f5d-4f30-b213-7a18e9ab9206
150+
status: 200 OK
151+
code: 200
152+
duration: 123.934916ms
153+
- id: 3
154+
request:
155+
proto: HTTP/1.1
156+
proto_major: 1
157+
proto_minor: 1
158+
content_length: 0
159+
transfer_encoding: []
160+
trailer: {}
161+
host: api.scaleway.com
162+
remote_addr: ""
163+
request_uri: ""
164+
body: ""
165+
form: {}
166+
headers:
167+
User-Agent:
168+
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
169+
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
170+
method: DELETE
171+
response:
172+
proto: HTTP/2.0
173+
proto_major: 2
174+
proto_minor: 0
175+
transfer_encoding: []
176+
trailer: {}
177+
content_length: 0
178+
uncompressed: false
179+
body: ""
180+
headers:
181+
Content-Security-Policy:
182+
- default-src 'none'; frame-ancestors 'none'
183+
Content-Type:
184+
- application/json
185+
Date:
186+
- Mon, 01 Sep 2025 14:08:25 GMT
187+
Server:
188+
- Scaleway API Gateway (fr-par-3;edge01)
189+
Strict-Transport-Security:
190+
- max-age=63072000
191+
X-Content-Type-Options:
192+
- nosniff
193+
X-Frame-Options:
194+
- DENY
195+
X-Request-Id:
196+
- dbc7b22c-f2d3-477f-b5ba-9c620a566ed4
197+
status: 204 No Content
198+
code: 204
199+
duration: 139.486584ms
200+
- id: 4
201+
request:
202+
proto: HTTP/1.1
203+
proto_major: 1
204+
proto_minor: 1
205+
content_length: 0
206+
transfer_encoding: []
207+
trailer: {}
208+
host: api.scaleway.com
209+
remote_addr: ""
210+
request_uri: ""
211+
body: ""
212+
form: {}
213+
headers:
214+
User-Agent:
215+
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
216+
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
217+
method: GET
218+
response:
219+
proto: HTTP/2.0
220+
proto_major: 2
221+
proto_minor: 0
222+
transfer_encoding: []
223+
trailer: {}
224+
content_length: 635
225+
uncompressed: false
226+
body: '{"created_at":"2025-09-01T14:08:23.132185Z","deletion_requested_at":"2025-09-01T14:08:25.319098Z","description":"Test key with rotation policy","id":"449ede52-42cd-4692-8ad6-8d3d60b31b1f","locked":false,"name":"tf-test-kms-key-rotation","origin":"scaleway_kms","project_id":"105bdce1-64c0-48ab-899d-868455867ecf","protected":false,"region":"fr-par","rotated_at":"2025-09-01T14:08:23.140726Z","rotation_count":1,"rotation_policy":{"next_rotation_at":"2026-01-01T00:00:00Z","rotation_period":"2592000s"},"state":"scheduled_for_deletion","tags":[],"updated_at":"2025-09-01T14:08:23.140726Z","usage":{"symmetric_encryption":"aes_256_gcm"}}'
227+
headers:
228+
Content-Length:
229+
- "635"
230+
Content-Security-Policy:
231+
- default-src 'none'; frame-ancestors 'none'
232+
Content-Type:
233+
- application/json
234+
Date:
235+
- Mon, 01 Sep 2025 14:08:25 GMT
236+
Server:
237+
- Scaleway API Gateway (fr-par-3;edge01)
238+
Strict-Transport-Security:
239+
- max-age=63072000
240+
X-Content-Type-Options:
241+
- nosniff
242+
X-Frame-Options:
243+
- DENY
244+
X-Request-Id:
245+
- 9e3d94eb-96df-4b75-83aa-48814dba6768
246+
status: 200 OK
247+
code: 200
248+
duration: 108.039625ms

0 commit comments

Comments
 (0)