sync-modules: mirrored modules of release 3.2.0-F-feature-simpl-31668.652.99e22161

+++ kubernetes/README.md
+++ kubernetes/ovh/credentials.tf
+++ kubernetes/ovh/variables.tf
This commit is contained in:
gitops_test 2026-09-14 16:13:54 +00:00
parent 25b528bd66
commit 553136b5fa
3 changed files with 25 additions and 28 deletions

View File

@ -14,15 +14,15 @@ Provisions a managed Kubernetes cluster with one node pool and generates scoped
| `username` | Consumer ServiceAccount name, defaults to `simpl-consumer`, last segment of the Vault credentials path |
| `admin_username` | Management (renewer) ServiceAccount name, defaults to `simpl-renewer` |
| `name_prefix` | Prefix for resource names, defaults to `simpl` |
| `project_id`, `region` | OVH project and region |
| `region` | OVH region for the cluster |
| `project_id` | Optional override of the OVH project; by default the provider resolves it from the `OVH_CLOUD_PROJECT_SERVICE` variable of the runner environment, which the provisioner derives from the `OVH_PROJECT_ID` key of the cloud account configuration |
| `k8s_version`, `k8s_update_policy` | Cluster version and upgrade policy |
| `nodepool_*` | Node pool sizing: flavor, desired/min/max nodes, autoscale, anti affinity, billing |
| `private_network_id`, `nodes_subnet_id`, `gateway_ip` | Optional vRack attachment, all null for a public cluster |
| `token_ttl_seconds` | TTL of the consumer ServiceAccount token, defaults to 3600 |
Cloud credentials are never module inputs, they reach the provider from the runner environment.
Credentials, following the existing Vault contract: the OVH admin kubeconfig (client certificates) is never delivered. A `kubernetes` provider chained on the fresh cluster creates, in the same apply, the consumer ServiceAccount (cluster-admin, bound token with TTL) and the management ServiceAccount (cluster-admin, non expiring legacy token Secret, the credential the renewal workflow uses on day 2 and revocable by deleting the ServiceAccount). Both are delivered as assembled kubeconfigs written by the module to Vault: `secret/{provider}/{cloud_account}/{requester_unique_id}/{username}` with the consumer kubeconfig (companions: token, server, ca_data, ttl_seconds) and the `admin` sibling entry with the root kubeconfig and the management username. No secret material is ever part of an output or of the user body. The Vault provider configuration is generated by the provisioner next to the deployment script, and its token comes from the runner environment.
Credentials, following the existing Vault contract: the OVH admin kubeconfig (client certificates) is never delivered. A `kubernetes` provider chained on the fresh cluster creates, in the same apply, the consumer and the management ServiceAccounts (cluster-admin), each with a non expiring legacy token Secret: credentials stay valid until a renewal is requested, and the renewal revokes them by deleting and recreating the ServiceAccount. Both are delivered as assembled kubeconfigs written by the module to Vault: `secret/{provider}/{cloud_account}/{requester_unique_id}/{username}` with the consumer kubeconfig (companions: token, server, ca_data) and the `admin` sibling entry with the root kubeconfig and the management username. No secret material is ever part of an output or of the user body. The Vault provider configuration is generated by the provisioner next to the deployment script, and its token comes from the runner environment.
Note: this module configures the `kubernetes` provider internally (chained on the cluster it creates), so the module block must not use `count`, `for_each` or `depends_on`.
@ -44,7 +44,6 @@ The provisioner rewrites the `{KUBERNETES_SOURCE}` placeholder to this module's
module "kubernetes" {
source = "{KUBERNETES_SOURCE}"
deployment_id = "{UUID}"
project_id = "<ovh project id>"
region = "<region>"
cloud_account = "{CLOUD_ACCOUNT}"
requester_unique_id = "{REQUESTER_UNIQUE_ID}"

View File

@ -1,8 +1,10 @@
// Consumer and management credentials are generated here, never injected by
// the backend and never delivered through outputs. The OVH admin kubeconfig
// (client certificates) is never delivered either: the consumer receives a
// scoped ServiceAccount token with a TTL, day 2 renewal uses a dedicated
// root token. Vault entries follow the existing contract:
// (client certificates) is never delivered either: consumer and management
// each get a scoped ServiceAccount with a NON EXPIRING legacy token, valid
// until a credential renewal is requested (the renewal deletes and recreates
// the ServiceAccount, which revokes every previously issued token at once).
// Vault entries follow the existing contract:
// secret/{provider}/{cloud_account}/{requester_unique_id}/{username} consumer kubeconfig
// secret/{provider}/{cloud_account}/{requester_unique_id}/admin root kubeconfig + admin username
// Only the Vault path of the consumer entry is exposed as an output.
@ -15,9 +17,9 @@ resource "kubernetes_namespace_v1" "access" {
depends_on = [ovh_cloud_project_kube_nodepool.this]
}
// Consumer access: ServiceAccount + bound token with TTL. The binding
// references the ServiceAccount by name, so it survives the delete/recreate
// performed by the credential renewal workflow.
// Consumer access: ServiceAccount + non expiring legacy token Secret. The
// binding references the ServiceAccount by name, so it survives the
// delete/recreate performed by the credential renewal workflow.
resource "kubernetes_service_account_v1" "consumer" {
metadata {
name = var.username
@ -43,15 +45,17 @@ resource "kubernetes_cluster_role_binding_v1" "consumer_admin" {
}
}
resource "kubernetes_token_request_v1" "consumer" {
resource "kubernetes_secret_v1" "consumer_token" {
metadata {
name = kubernetes_service_account_v1.consumer.metadata[0].name
name = "${var.username}-token"
namespace = kubernetes_namespace_v1.access.metadata[0].name
annotations = {
"kubernetes.io/service-account.name" = kubernetes_service_account_v1.consumer.metadata[0].name
}
}
spec {
expiration_seconds = var.token_ttl_seconds
}
type = "kubernetes.io/service-account-token"
wait_for_service_account_token = true
}
// Management (renewer) access: ServiceAccount + NON EXPIRING legacy token
@ -113,7 +117,7 @@ locals {
}]
users = [{
name = var.username
user = { token = kubernetes_token_request_v1.consumer.token }
user = { token = kubernetes_secret_v1.consumer_token.data["token"] }
}]
contexts = [{
name = "simpl"
@ -150,10 +154,9 @@ resource "vault_kv_secret_v2" "consumer" {
name = "ovh/${var.cloud_account}/${var.requester_unique_id}/${var.username}"
data_json = jsonencode({
kubeconfig = local.consumer_kubeconfig
token = kubernetes_token_request_v1.consumer.token
token = kubernetes_secret_v1.consumer_token.data["token"]
server = local.cluster_server
ca_data = local.cluster_ca
ttl_seconds = var.token_ttl_seconds
})
}

View File

@ -1,6 +1,7 @@
variable "project_id" {
description = "OVH public cloud project id (service_name)"
description = "OVH public cloud project id (service_name). Defaults to the OVH_CLOUD_PROJECT_SERVICE variable of the runner environment, derived from the cloud account configuration."
type = string
default = null
}
variable "region" {
@ -41,12 +42,6 @@ variable "admin_username" {
default = "simpl-renewer"
}
variable "token_ttl_seconds" {
description = "TTL of the consumer ServiceAccount token (TokenRequest expirationSeconds)"
type = number
default = 3600
}
variable "k8s_version" {
description = "Kubernetes version for the cluster, must be one of the versions currently supported by OVH MKS"
type = string