[Terraform] Managing Vault Secrets via Terraform and OpenTofu: A K3s Token Implementation

Storing and externalizing sensitive data is a foundational architectural pattern for secure platforms and applications. The following documentation demonstrates the procedure for setting and retrieving secrets within HashiCorp Vault utilizing Terraform or OpenTofu on deploying k3s node.

1. Provider Configuration

To interact with Vault and generate secure tokens, the environment must specify the required providers.

terraform {
  required_providers {
    vault = {
      source  = "hashicorp/vault"
    }
    random = {
      source = "hashicorp/random"
    }
  }
}

2. Generating the Secret Data

In this implementation, a token is required to bootstrap a K3s cluster. The random provider is utilized to generate a secure, 32-character string.

resource "random_password" "k3s_cluster_token" {
  length  = 32
  special = false
}

3. Storing Sensitive Data in Vault (Set)

The generated token is injected into Vault using the vault_kv_secret_v2 resource. This operation assumes the target Vault mount path is configured for KV Version 2.

  • Mount Point: home-lab-secrets

  • Secret Path: k3s-cluster-token

  • Payload Format: JSON encoded key-value pair.

    resource "vault_kv_secret_v2" "k3s_cluster_token" {
      mount     = "home-lab-secrets"
      name      = "k3s-cluster-token"
      data_json = jsonencode({
        token = random_password.k3s_cluster_token.result
      })
    }

4. Retrieving Sensitive Data from Vault (Get)

To utilize the stored secret elsewhere in the infrastructure code, a Terraform data source fetches the values from Vault. The depends_on meta-argument ensures the secret is fully provisioned before retrieval is attempted.

data "vault_kv_secret_v2" "k3s_cluster_token" {
  depends_on = [vault_kv_secret_v2.k3s_cluster_token]
  mount      = "home-lab-secrets"
  name       = "k3s-cluster-token"
}

5. Usage Example: Bootstrapping a Node

Once retrieved, the secret data can be accessed via data.vault_kv_secret_v2.<name>.data.<key>. In the provided example, the token is passed as an environment variable (K3S_TOKEN) over an SSH connection using a remote-exec provisioner to join a node to the existing K3s cluster.

provisioner "remote-exec" {
    inline = [
      "cloud-init status --wait",
      "curl -sfL https://get.k3s.io | K3S_URL='https://${local.master_node.network.ip}:6443' K3S_TOKEN='${data.vault_kv_secret_v2.k3s_cluster_token.data.token}' sh -"
    ]
  }

 

About C.H. Ling 266 Articles
a .net / Java developer from Hong Kong and currently located in United Kingdom. Thanks for Google because it solve many technical problems so I build this blog as return. Besides coding and trying advance technology, hiking and traveling is other favorite to me, so I will write down something what I see and what I feel during it. Happy reading!!!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.