85 lines
2.9 KiB
HCL
85 lines
2.9 KiB
HCL
// Consumer and management credentials are generated here, never injected by
|
|
// the backend. The consumer password opens SSH on the head node only (the
|
|
// single entry point); the management keypair opens every node. The Vault
|
|
// layout follows the existing contract:
|
|
// secret/{provider}/{cloud_account}/{requester_unique_id}/{username} password + head node access
|
|
// secret/{provider}/{cloud_account}/{requester_unique_id}/admin ssh keypair + admin username
|
|
// Only the Vault path of the consumer entry is exposed as an output.
|
|
|
|
resource "random_bytes" "munge_key" {
|
|
length = 128
|
|
}
|
|
|
|
resource "tls_private_key" "admin" {
|
|
algorithm = "ED25519"
|
|
}
|
|
|
|
// Regenerated whenever the rotation marker changes; the special set avoids
|
|
// shell quoting issues in the password application command.
|
|
resource "random_password" "consumer" {
|
|
length = 24
|
|
special = true
|
|
override_special = "-_=+"
|
|
|
|
keepers = {
|
|
rotation = var.credentials_version
|
|
}
|
|
}
|
|
|
|
// Applies the consumer password on the head node, on day 0 and on every
|
|
// rotation. The password never travels through user data, so a rotation
|
|
// never touches the instances: this resource is replaced (triggered by the
|
|
// rotation marker), re-runs chpasswd over SSH with the management key, and
|
|
// the Vault entry below is updated in the same apply.
|
|
// null_resource instead of terraform_data: the tofu-controller runner ships a
|
|
// Terraform older than 1.4, which has no terraform_data built-in.
|
|
resource "null_resource" "consumer_password" {
|
|
// Re-applied on rotation AND whenever the head node is recreated: a fresh
|
|
// instance boots without the consumer password (it never travels through
|
|
// user data).
|
|
triggers = {
|
|
rotation = var.credentials_version
|
|
head_node = ovh_cloud_project_instance.head.id
|
|
}
|
|
|
|
connection {
|
|
type = "ssh"
|
|
host = local.head_public_ip
|
|
user = var.admin_username
|
|
private_key = tls_private_key.admin.private_key_openssh
|
|
timeout = "15m"
|
|
}
|
|
|
|
provisioner "remote-exec" {
|
|
inline = [
|
|
"cloud-init status --wait > /dev/null || true",
|
|
"echo '${var.username}:${random_password.consumer.result}' | sudo chpasswd",
|
|
]
|
|
}
|
|
|
|
depends_on = [ovh_cloud_project_instance.head]
|
|
}
|
|
|
|
resource "vault_kv_secret_v2" "consumer" {
|
|
mount = "secret"
|
|
name = "ovh/${var.cloud_account}/${var.requester_unique_id}/${var.username}"
|
|
data_json = jsonencode({
|
|
username = var.username
|
|
password = random_password.consumer.result
|
|
host = local.head_public_ip
|
|
port = 22
|
|
})
|
|
|
|
depends_on = [null_resource.consumer_password]
|
|
}
|
|
|
|
resource "vault_kv_secret_v2" "admin" {
|
|
mount = "secret"
|
|
name = "ovh/${var.cloud_account}/${var.requester_unique_id}/admin"
|
|
data_json = jsonencode({
|
|
username = var.admin_username
|
|
ssh_private_key = tls_private_key.admin.private_key_openssh
|
|
ssh_public_key = trimspace(tls_private_key.admin.public_key_openssh)
|
|
})
|
|
}
|