Secrets support

This commit is contained in:
Greyscale 2025-02-14 21:31:35 +01:00
parent 6bc4be8068
commit 787887da2c
Signed by: grey
GPG key ID: DDB392AE64B32D89
9 changed files with 126 additions and 0 deletions

18
docker/secret/config.tf Normal file
View file

@ -0,0 +1,18 @@
resource "random_id" "randomiser" {
byte_length = 2
keepers = {
stack_name = var.stack_name
data = var.value
}
}
resource "docker_secret" "secret" {
name = local.secret_name
data = base64encode(var.value)
lifecycle {
create_before_destroy = true
ignore_changes = [name]
}
}

14
docker/secret/debug.tf Normal file
View file

@ -0,0 +1,14 @@
resource "local_file" "secret" {
count = var.debug ? 1 : 0
content = var.value
filename = "${local.debug_path}/${local.file_name}"
file_permission = "0600"
}
variable "debug_path" {
type = string
description = "Path to write debug files to"
default = null
}
locals {
debug_path = var.debug_path != null ? var.debug_path : "${path.root}/.debug/docker/secrets/${var.stack_name}"
}

22
docker/secret/inputs.tf Normal file
View file

@ -0,0 +1,22 @@
variable "stack_name" {
type = string
description = "The name of the stack to deploy the service to."
}
variable "name" {
type = string
description = "The name of the docker secret."
}
variable "value" {
type = string
description = "The value of the docker secret."
}
variable "labels" {
type = map(string)
default = {}
description = "A map of labels to apply to the service"
}
variable "debug" {
type = bool
default = true
description = "Emit debug files in .debug directory"
}

24
docker/secret/locals.tf Normal file
View file

@ -0,0 +1,24 @@
locals {
path = var.name
file_name = element(split("/", local.path), length(split("/", local.path)) - 1)
// Name can be 64 bytes long, including a null byte seemingly, limiting the length to 63.
// The hash is 7 bytes long. We lose 2 more bytes to the dashes. So we have 54 bytes left.
// I will share that into 20 bytes for the stack name, remaining bytes for the config name
secret_name = join("-", [
substr(var.stack_name, 0, 20),
substr(local.file_name, 0, 64 - 20 - 1 - (random_id.randomiser.byte_length * 2) - 1),
random_id.randomiser.hex
])
// define secret labels
labels = merge(var.labels, {
"com.docker.stack.namespace" = var.stack_name
"ooo.grey.secret.stack" = var.stack_name
#"ooo.grey.secret.created" = plantimestamp()
"ooo.grey.secret.bytes" = length(var.value)
"ooo.grey.secret.name" = local.secret_name
"ooo.grey.secret.hash" = sha1(var.value)
"ooo.grey.secret.file" = local.file_name
"ooo.grey.secret.path" = local.path
})
}

6
docker/secret/outputs.tf Normal file
View file

@ -0,0 +1,6 @@
output "id" {
value = docker_secret.secret.id
}
output "name" {
value = docker_secret.secret.name
}

View file

@ -0,0 +1,20 @@
terraform {
required_version = "~> 1.6"
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~>3.0"
}
local = {
source = "hashicorp/local"
version = "~>2.1"
}
random = {
source = "hashicorp/random"
version = "~>3.5"
}
}
}

View file

@ -110,6 +110,11 @@ variable "mounts" {
default = {}
description = "A map of host paths to container paths to mount. The key is the host path, and the value is the container path."
}
variable "secrets" {
type = map(string)
default = {}
description = "A map of secret files to create. Key being the path to the file, and the value being the content. The secret will be created using the truncated file name and a timestamp."
}
variable "configs" {
type = map(string)
default = {}

View file

@ -0,0 +1,8 @@
module "secrets" {
for_each = var.secrets
source = "../../docker/secret"
stack_name = var.stack_name
name = each.key
value = each.value
debug_path = "${local.debug_path}/secrets"
}

View file

@ -61,6 +61,15 @@ resource "docker_service" "instance" {
file_name = configs.key
}
}
# Same for secrets
dynamic "secrets" {
for_each = var.secrets
content {
secret_id = module.secrets[secrets.key].id
secret_name = module.secrets[secrets.key].name
file_name = secrets.key
}
}
# Allow overriding DNS server in use
dynamic "dns_config" {