Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions internal/services/keymanager/helpers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package keymanager

import (
"errors"
"fmt"
"time"

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

periodStr, ok := m["rotation_period"].(string)
if !ok || periodStr == "" {
return nil, nil
return nil, errors.New("rotation_period is required when rotation_policy block is specified")
}

period, err := time.ParseDuration(periodStr)
if err != nil {
return nil, err
}

return &key_manager.KeyRotationPolicy{
policy := &key_manager.KeyRotationPolicy{
RotationPeriod: scw.NewDurationFromTimeDuration(period),
}, nil
}

// Handle next_rotation_at if provided
if nextRotationStr, ok := m["next_rotation_at"].(string); ok && nextRotationStr != "" {
nextRotation, err := time.Parse(time.RFC3339, nextRotationStr)
if err != nil {
return nil, fmt.Errorf("invalid next_rotation_at format: %w", err)
}

policy.NextRotationAt = &nextRotation
}

return policy, nil
}

func FlattenKeyRotationPolicy(rp *key_manager.KeyRotationPolicy) []map[string]any {
Expand Down
5 changes: 3 additions & 2 deletions internal/services/keymanager/key_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
key_manager "github.com/scaleway/scaleway-sdk-go/api/key_manager/v1alpha1"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
Expand Down Expand Up @@ -52,8 +53,8 @@ func ResourceKeyManagerKey() *schema.Resource {
Description: "Key rotation policy.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"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)."},
"next_rotation_at": {Type: schema.TypeString, Computed: true, Description: "Timestamp indicating the next scheduled rotation."},
"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)."},
"next_rotation_at": {Type: schema.TypeString, Optional: true, Description: "Timestamp indicating the next scheduled rotation."},
},
},
},
Expand Down
35 changes: 35 additions & 0 deletions internal/services/keymanager/key_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,38 @@ func IsKeyManagerKeyDestroyed(tt *acctest.TestTools) resource.TestCheckFunc {
return nil
}
}

func TestAccKeyManagerKey_WithRotationPolicy(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: IsKeyManagerKeyDestroyed(tt),
Steps: []resource.TestStep{
{
Config: `
resource "scaleway_key_manager_key" "main" {
name = "tf-test-kms-key-rotation"
region = "fr-par"
usage = "symmetric_encryption"
description = "Test key with rotation policy"
unprotected = true

rotation_policy {
rotation_period = "720h"
next_rotation_at = "2026-01-01T00:00:00Z"
}
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "name", "tf-test-kms-key-rotation"),
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "usage", "symmetric_encryption"),
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "description", "Test key with rotation policy"),
resource.TestCheckResourceAttr("scaleway_key_manager_key.main", "rotation_policy.0.rotation_period", "720h0m0s"),
),
},
},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
---
version: 2
interactions:
- id: 0
request:
proto: HTTP/1.1
proto_major: 1
proto_minor: 1
content_length: 338
transfer_encoding: []
trailer: {}
host: api.scaleway.com
remote_addr: ""
request_uri: ""
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"}'
form: {}
headers:
Content-Type:
- application/json
User-Agent:
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys
method: POST
response:
proto: HTTP/2.0
proto_major: 2
proto_minor: 0
transfer_encoding: []
trailer: {}
content_length: 595
uncompressed: false
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"}}'
headers:
Content-Length:
- "595"
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
Content-Type:
- application/json
Date:
- Mon, 01 Sep 2025 14:08:23 GMT
Server:
- Scaleway API Gateway (fr-par-3;edge01)
Strict-Transport-Security:
- max-age=63072000
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Request-Id:
- 26922321-731c-4928-8fec-69e3fb748202
status: 200 OK
code: 200
duration: 441.486459ms
- id: 1
request:
proto: HTTP/1.1
proto_major: 1
proto_minor: 1
content_length: 0
transfer_encoding: []
trailer: {}
host: api.scaleway.com
remote_addr: ""
request_uri: ""
body: ""
form: {}
headers:
User-Agent:
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
method: GET
response:
proto: HTTP/2.0
proto_major: 2
proto_minor: 0
transfer_encoding: []
trailer: {}
content_length: 595
uncompressed: false
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"}}'
headers:
Content-Length:
- "595"
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
Content-Type:
- application/json
Date:
- Mon, 01 Sep 2025 14:08:23 GMT
Server:
- Scaleway API Gateway (fr-par-3;edge01)
Strict-Transport-Security:
- max-age=63072000
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Request-Id:
- a38c873d-0db5-4b18-be3d-6702c5221289
status: 200 OK
code: 200
duration: 116.597417ms
- id: 2
request:
proto: HTTP/1.1
proto_major: 1
proto_minor: 1
content_length: 0
transfer_encoding: []
trailer: {}
host: api.scaleway.com
remote_addr: ""
request_uri: ""
body: ""
form: {}
headers:
User-Agent:
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
method: GET
response:
proto: HTTP/2.0
proto_major: 2
proto_minor: 0
transfer_encoding: []
trailer: {}
content_length: 595
uncompressed: false
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"}}'
headers:
Content-Length:
- "595"
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
Content-Type:
- application/json
Date:
- Mon, 01 Sep 2025 14:08:24 GMT
Server:
- Scaleway API Gateway (fr-par-3;edge01)
Strict-Transport-Security:
- max-age=63072000
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Request-Id:
- c856061a-4f5d-4f30-b213-7a18e9ab9206
status: 200 OK
code: 200
duration: 123.934916ms
- id: 3
request:
proto: HTTP/1.1
proto_major: 1
proto_minor: 1
content_length: 0
transfer_encoding: []
trailer: {}
host: api.scaleway.com
remote_addr: ""
request_uri: ""
body: ""
form: {}
headers:
User-Agent:
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
method: DELETE
response:
proto: HTTP/2.0
proto_major: 2
proto_minor: 0
transfer_encoding: []
trailer: {}
content_length: 0
uncompressed: false
body: ""
headers:
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
Content-Type:
- application/json
Date:
- Mon, 01 Sep 2025 14:08:25 GMT
Server:
- Scaleway API Gateway (fr-par-3;edge01)
Strict-Transport-Security:
- max-age=63072000
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Request-Id:
- dbc7b22c-f2d3-477f-b5ba-9c620a566ed4
status: 204 No Content
code: 204
duration: 139.486584ms
- id: 4
request:
proto: HTTP/1.1
proto_major: 1
proto_minor: 1
content_length: 0
transfer_encoding: []
trailer: {}
host: api.scaleway.com
remote_addr: ""
request_uri: ""
body: ""
form: {}
headers:
User-Agent:
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; arm64) terraform-provider/develop terraform/terraform-tests
url: https://api.scaleway.com/key-manager/v1alpha1/regions/fr-par/keys/449ede52-42cd-4692-8ad6-8d3d60b31b1f
method: GET
response:
proto: HTTP/2.0
proto_major: 2
proto_minor: 0
transfer_encoding: []
trailer: {}
content_length: 635
uncompressed: false
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"}}'
headers:
Content-Length:
- "635"
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
Content-Type:
- application/json
Date:
- Mon, 01 Sep 2025 14:08:25 GMT
Server:
- Scaleway API Gateway (fr-par-3;edge01)
Strict-Transport-Security:
- max-age=63072000
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Request-Id:
- 9e3d94eb-96df-4b75-83aa-48814dba6768
status: 200 OK
code: 200
duration: 108.039625ms
Loading