Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ In order to run the full suite of Acceptance tests you will need to have the fol
- a [Load Balancer](https://www.ovh.ie/solutions/load-balancer/)
- a registered [Domain](https://www.ovh.ie/domains/)
- a [Cloud Project](https://www.ovh.ie/public-cloud/instances/)
- a [KMS](https://www.ovhcloud.com/en-gb/identity-security-operations/key-management-service/)

You will also need to setup your [OVH API](https://api.ovh.com) credentials. (see [documentation](https://www.terraform.io/docs/providers/ovh/index.html#configuration-reference))

Expand Down Expand Up @@ -158,6 +159,7 @@ export OVH_DOMAIN_NS3_HOST_TEST="..."
export OVH_DOMAIN_DS_RECORD_ALGORITHM_TEST="..."
export OVH_DOMAIN_DS_RECORD_PUBLIC_KEY_TEST="..."
export OVH_DOMAIN_DS_RECORD_TAG_TEST="..."
export OVH_OKMS="..."

$ make testacc
```
Expand Down
90 changes: 90 additions & 0 deletions docs/data-sources/okms_secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
subcategory : "Key Management Service (KMS)"
---

# ovh_okms_secret (Data Source)

Retrieves metadata (and optionally the payload) of a secret stored in OVHcloud KMS.

> WARNING: If `include_data = true` the secret value is stored in cleartext (JSON) in the Terraform state file. Marked **Sensitive** only hides it from CLI output. If you use this option it is recommended to protect your state with encryption and access controls.

## Example Usage

Get the latest secret version (metadata only):

```terraform
data "ovh_okms_secret" "latest" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"
}
```

Get the latest secret version including its data:

```terraform
data "ovh_okms_secret" "latest_with_data" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"
include_data = true
}

locals {
secret_obj = jsondecode(data.ovh_okms_secret.latest_with_data.data)
}

output "api_key" {
value = local.secret_obj.api_key
sensitive = true
}
```

Get a specific version including its payload:

```terraform
data "ovh_okms_secret" "v3" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"
version = 3
include_data = true
}
```

## Argument Reference

The following arguments are supported:

### Required

- `okms_id` (String) OKMS service ID that owns the secret.
- `path` (String) Secret path (identifier within the OKMS instance).

### Optional

- `version` (Number) Specific version to retrieve. If omitted, the latest (current) version is selected.
- `include_data` (Boolean) If true, retrieves the secret payload (`data` attribute). Defaults to false. When false only metadata is returned.

## Attributes Reference (Read-Only)

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

- `version` (Number) The resolved version number (requested or current latest).
- `data` (String, Sensitive) Raw JSON secret payload (present only if `include_data` is true).
- `metadata` (Block) Secret metadata:
- `cas_required` (Boolean)
- `created_at` (String)
- `updated_at` (String)
- `current_version` (Number)
- `oldest_version` (Number)
- `max_versions` (Number)
- `deactivate_version_after` (String)
- `custom_metadata` (Map of String)
- `iam` (Block) IAM resource metadata:
- `display_name` (String)
- `id` (String)
- `tags` (Map of String)
- `urn` (String)

## Behavior & Notes

- The `data` attribute retains the raw JSON returned by the API. Use `jsondecode()` to work with individual keys.
- Changing only `include_data` (true -> false) will cause the `data` attribute to become null in subsequent refreshes (state no longer holds the payload).
131 changes: 131 additions & 0 deletions docs/resources/okms_secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@

---
subcategory : "Key Management Service (KMS)"
---

# ovh_okms_secret (Resource)

Manages a secret stored in OVHcloud KMS.

> WARNING: `version.data` is marked **Sensitive** but still ends up in the state file. To mitigate that, it is recommended to protect your state with encryption and access controls. Avoid committing it to source control.

## Example Usage

Create a secret whose value is a JSON object. Use `jsonencode()` to produce a deterministic JSON string (ordering/whitespace) to minimize diffs.

```terraform
resource "ovh_okms_secret" "example" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"

metadata = {
max_versions = 10 # keep last 10 versions
cas_required = true # enforce optimistic concurrency control (server will require current secret version on the cas attribute to allow update)
deactivate_version_after = "0s" # keep versions active indefinitely (example)
custom_metadata = {
environment = "prod"
owner = "payments-team"
}
}

# Initial version (will create version 1)
version = {
data = jsonencode({
api_key = var.api_key
api_secret = var.api_secret
})
}
}

# Reading a field from the secret version data
locals {
secret_json = jsondecode(ovh_okms_secret.example.version.data)
}

output "api_key" {
value = local.secret_json.api_key
sensitive = true
}
```

Updating the secret (new version) while enforcing optimistic concurrency control using CAS:

```terraform
resource "ovh_okms_secret" "example" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"

# Ensure no concurrent update happened: set cas to the current version
# (metadata.current_version is populated after first apply)
cas = ovh_okms_secret.example.metadata.current_version

metadata = {
cas_required = true
}

version = {
data = jsonencode({
api_key = var.api_key
api_secret = var.new_api_secret # changed value -> creates new version
})
}
}
```

## Argument Reference

The following arguments are supported:

### Required

- `okms_id` (String) ID of the OKMS service to create the secret in.
- `path` (String) Secret path (acts as the secret identifier within the OKMS instance). Immutable after creation.
- `version` (Block) Definition of the version to create/update. See Version Block below. (On updates providing a new `version.data` creates a new version.)

### Optional

- `cas` (Number) Check‑and‑set parameter used only on update (if `cas_required` metadata is set to true) to enforce optimistic concurrency control: its value must equal the current secret version (`metadata.current_version`) for the update to succeed. Ignored on create.
- `metadata` (Block) Secret metadata configuration (subset of fields are user-settable). See Metadata Block below.

### Metadata Block

User configurable attributes inside `metadata`:

- `cas_required` (Boolean) If true, the server will enforce optimistic concurrency control by requiring the `cas` parameter to match the current version number on every write (update) request.
- `custom_metadata` (Map of String) Arbitrary key/value metadata.
- `deactivate_version_after` (String) Duration (e.g. `"24h"`) after which a version is deactivated. `"0s"` (default) means never automatically deactivate.
- `max_versions` (Number) Number of versions to retain (default 10). Older versions beyond this limit are pruned.

Computed (read‑only) metadata attributes:

- `created_at` (String) Creation timestamp of the secret.
- `updated_at` (String) Last update timestamp.
- `current_version` (Number) Current (latest) version number.
- `oldest_version` (Number) Oldest retained version number.

### Version Block

Required attribute:

- `data` (String, Sensitive) Secret payload. Commonly set with `jsonencode(...)` so that Terraform comparisons are stable. Any valid JSON (object, array, string, number, bool) is accepted. Changing `data` creates a new secret version.

Computed (read‑only) attributes:

- `id` (Number) Version number.
- `created_at` (String) Version creation timestamp.
- `deactivated_at` (String) Deactivation timestamp if the version was deactivated.
- `state` (String) Version state (e.g. `ACTIVE`).

## Attributes Reference (Read-Only)

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

- `iam` (Block) IAM metadata: `display_name`, `id`, `tags`, `urn`.
- `metadata.*` computed fields as listed above.
- `version.*` computed fields as listed above.

## Behavior & Notes

- Updating with a new `version.data` performs an API PUT that creates a new version; the previous version remains (subject to `max_versions`).
- If `cas_required` is true, all write operations must include a correct `cas` query parameter (the expected current version number). Set `cas = ovh_okms_secret.example.metadata.current_version` to enforce optimistic concurrency. A mismatch causes the API to reject the update (preventing overwriting unseen changes).
- `cas` is ignored on create (no existing version).
14 changes: 14 additions & 0 deletions examples/data-sources/okms_secret/example_1.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
data "ovh_okms_secret" "latest_with_data" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"
include_data = true
}

locals {
secret_obj = jsondecode(data.ovh_okms_secret.latest_with_data.data)
}

output "api_key" {
value = local.secret_obj.api_key
sensitive = true
}
37 changes: 37 additions & 0 deletions examples/resources/okms_secret/example_1.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
resource "ovh_okms_secret" "example" {
okms_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
path = "app/api_credentials"

# Check‑and‑set parameter used only on update (if `cas_required` metadata is set to true)
# to enforce optimistic concurrency control: its value must equal the current secret version (`metadata.current_version`)
# for the update to succeed. Ignored on create.
cas = 1

metadata = {
max_versions = 10 # keep last 10 versions
cas_required = true # enforce optimistic concurrency control (server will require current secret version on the cas attribute to allow update)
deactivate_version_after = "0s" # keep versions active indefinitely (example)
custom_metadata = {
environment = "prod"
appname = "helloworld"
}
}

# Initial version (will create version 1)
version = {
data = jsonencode({
api_key = "mykey"
api_secret = "mysecret"
})
}
}

# Reading a field from the secret version data
locals {
secret_json = jsondecode(ovh_okms_secret.example.version.data)
}

output "api_key" {
value = local.secret_json.api_key
sensitive = true
}
Loading