简体   繁体   中英

terraform-kubernetes-provider how to create secret from file?

I'm using the terraform kubernetes-provider and I'd like to translate something like this kubectl command into TF:

kubectl create secret generic my-secret --from-file mysecret.json

It seems, however the secret resource's data field expects only a TF map .

I've tried something like

data "template_file" "my-secret" {
  template = "${file("${path.module}/my-secret.json")}"
}

resource "kubernetes_secret" "sgw-config" {
   metadata {
     name = "my-secret"
   }
   type = "Opaque"
   data = "{data.template_file.my-secret.template}"
}

But it complains that this is not a map. So, I can do something like this:

   data = {
      "my-secret.json" = "{data.template_file.my-secret.template}"
   }

But this will write the secret with a top-level field named my-secret.json and when I volume mount it, it won't work with other resources.

What is the trick here?

as long the file is UTF-8 encoded you can use something like this

resource "kubernetes_secret" "some-secret" {

      metadata {
        name      = "some-secret"
        namespace = kubernetes_namespace.some-ns.metadata.0.name
        labels = {
          "sensitive" = "true"
          "app"       = "my-app"
        }
      }
      data = {
        "file.txt" = file("${path.cwd}/your/relative/path/to/file.txt")
      }
    }

If the file is a binary one you will have an error like

Call to function "file" failed: contents of /your/relative/path/to/file.txt are not valid UTF-8; use the filebase64 function to obtain the Base64 encoded contents or the other file functions (eg filemd5, filesha256) to obtain file hashing results instead.

I tried encoding the file in base64 but then the problem is that the resulting text will be re-encoded in base64 by the provider. So I guess there is no solution for binary files at the moment... I'll edit with what I find next for binaries.

Just use https://www.terraform.io/docs/providers/kubernetes/r/config_map.html#binary_data

resource "kubernetes_config_map" "example" {

  metadata {
    name = "my-config"
  }

  binary_data = {
    "my_payload.bin" = "${filebase64("${path.module}/my_payload.bin")}"
  }
}

This might be a bit off-topic, but I've been facing similar problem except that the file might not be present in which case the terraform [plan|apply] fails.

To be exact: I needed to duplicate a secret from one namespace to another one.

I realized that by using hashicorp/external provider.

The steps are pretty simple:

  1. Load data by calling external program
  2. Refer to the data in kubernetes_secret resource

The program should accept (and process) JSON on STDIN and produce valid JSON on STDOUT as response to the parameters passed-in in the STDIN's JSON.

Example shell script:

#!/bin/bash

set -e

/bin/echo -n '{ "token": "'
kubectl get -n consul secrets/hashicorp-consul-bootstrap-acl-token --template={{.data.token}}
/bin/echo -n '"}'

tarraform source:


data "external" "token" {
  program = ["sh", "${path.module}/consul-token.sh"]
}

resource "kubernetes_secret" "consul-token" {
  depends_on = [data.external.token]

  metadata {
    name      = "consul-token"
    namespace = "app"
  }

  data = {
    token = base64decode(data.external.token.result.token)
  }
}

and requirements:


terraform {
  required_providers {
    external = {
      source  = "hashicorp/external"
      version = ">= 2.0.0"
    }
  }
}

I believe you can use binary_data attribute in the secret now. eg

binary_data = {
    "my_payload.bin" = "${filebase64("${path.module}/my_payload.bin")}"
}

reference: https://github.com/hashicorp/terraform-provider-kubernetes/pull/1228 https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret#binary_data

It seems if you run the command kubectl create secret generic my-secret --from-file mysecret.json

and then

$ kubectl get secrets my-secret -o yaml
apiVersion: v1
data:
  my-secret.json: ewogICA.....
kind: Secret
metadata:
  creationTimestamp: "2019-03-25T18:20:43Z"
  name: my-secret
  namespace: default
  resourceVersion: "67026"
  selfLink: /api/v1/namespaces/default/secrets/my-secret
  uid: b397a29c-4f2a-11e9-9806-000c290425d0
type: Opaque

it stores it similarly with the filename as the single key. When I mount this in a volume/volumeMount it works as expected. I was afraid that it wouldn't but when I create the secret using the --from-file argument, this is exactly how it stores it.

Basically you need to provide a map like this :

resource "kubernetes_secret" "sgw-config" {
   metadata {
     name = "my-secret"
   }
   type = "Opaque"
   data {
           "key1" = "value1"
           "key2" = "value2"
  }
}

you can refer to your internal variables using

resource "kubernetes_secret" "sgw-config" {
       metadata {
         name = "my-secret"
       }
       type = "Opaque"
       data {
               "USERNAME" = "${var.some_variable}"
               "PASSWORD" = "${random_string.root_password.result}"
      }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM