mirror of
https://github.com/immich-app/devtools.git
synced 2026-09-30 13:23:00 +08:00
feat: yucca secrets and secret module improvements (#1121)
This commit is contained in:
@@ -7,6 +7,7 @@ export TF_VAR_github_app_id="op://tf/GITHUB_APP_IMMICH_TOFU/app_id"
|
||||
export TF_VAR_github_app_pem_file="op://tf/GITHUB_APP_IMMICH_TOFU/pkcs1"
|
||||
export TF_VAR_github_owner="op://tf/GITHUB_APP_IMMICH_TOFU/owner"
|
||||
export TF_VAR_op_service_account_token="op://tf/1pass_service_account/superuser_token"
|
||||
export TF_VAR_futo_op_service_account_token="op://tf_$ENVIRONMENT/yucca_futo_1pass_superuser_service_account/password"
|
||||
export TF_VAR_discord_token="op://tf/IMMICH_TF_DISCORD_BOT_TOKEN/password"
|
||||
export TF_VAR_zitadel_profile_json="op://tf/ZITADEL_PROFILE_JSON/password"
|
||||
export TF_VAR_zitadel_github_client_id="op://tf/GITHUB_OAUTH_APP_IMMICH_ZITADEL_CLIENT_ID/password"
|
||||
|
||||
@@ -48,13 +48,7 @@ module "manual-secrets" {
|
||||
"GITLAB_OAUTH_APP_FUTO_ZITADEL_ISSUER",
|
||||
"GITHUB_APP_FUTO_ORG_SELFHOSTED_RUNNERS_INSTALLATION_ID"
|
||||
]
|
||||
dev = [
|
||||
"IMMICH_DISCORD_BOT_TOKEN",
|
||||
"MONITORING_GRAFANA_TF_AUTH_TOKEN",
|
||||
"MONITORING_GRAFANA_URL",
|
||||
"IMMICH_DISCORD_SERVER_ID",
|
||||
]
|
||||
prod = [
|
||||
scoped = [
|
||||
"IMMICH_DISCORD_BOT_TOKEN",
|
||||
"MONITORING_GRAFANA_TF_AUTH_TOKEN",
|
||||
"MONITORING_GRAFANA_URL",
|
||||
@@ -83,12 +77,7 @@ module "generated-secrets" {
|
||||
{ name = "IMMICH_GITHUB_ACTION_CHECKS_WEBHOOK_SECRET" },
|
||||
{ name = "OUTLINE_ROLE_SYNC_WEBHOOK_SECRET" }
|
||||
]
|
||||
dev = [
|
||||
{ name = "METRICS_READ_TOKEN" },
|
||||
{ name = "METRICS_WRITE_TOKEN" },
|
||||
{ name = "METRICS_ADMIN_TOKEN" }
|
||||
]
|
||||
prod = [
|
||||
scoped = [
|
||||
{ name = "METRICS_READ_TOKEN" },
|
||||
{ name = "METRICS_WRITE_TOKEN" },
|
||||
{ name = "METRICS_ADMIN_TOKEN" },
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/1password/onepassword" {
|
||||
version = "2.2.1"
|
||||
constraints = "~> 2.0"
|
||||
hashes = [
|
||||
"h1:CosIqZ6jkgylvF23rLyNixIecZAAhFyb61sLl6GrEsc=",
|
||||
"zh:025709a6b5f1b3685d277f2c48f7cb8b53d14b3699c1123d7e9a2135c099c533",
|
||||
"zh:037fc89d150063a8aacdcab08ba26038b489fe2468d509b842d298ea59096ca6",
|
||||
"zh:233777182b25faf1658e8ce171b684460983bb41cff79fb243662f3f9dc5ca6c",
|
||||
"zh:2fb5ca2fc8c37b1d1c54da646ed13bf40897941fe92eece784fba496f677b533",
|
||||
"zh:4b25b5ce1f694ec265e65234fc85d6bdf3810297ffeaced54ad46a1ba28142de",
|
||||
"zh:5509d1e4fb7b45c63124ec66fd1f9d6757daa8bf1f7bdd724d5adb2965b61436",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:a23ba946c629ec912b2fcbf606a2eb8853626ec0e0bee749f2d39146a872c082",
|
||||
"zh:a3d3024485426237d7b4a4350b12dda4d29d88f3942246a9370be35ec2a51e9e",
|
||||
"zh:a6ef65544ab8fc26d468b38636407a3d2d902e35c51b648729bf97c31d1937f9",
|
||||
"zh:afbe9480a0da0ad8dc514b277f1e4be36b8931f045021d05c21665ef1ac0b7c8",
|
||||
"zh:b2e96e69fa9ff7e179dccdef5b785cd020eb46bb2b3d1d507d009d71be6b0c26",
|
||||
"zh:ceefaede9e8a3104463523ba267e3e985b27a706f7628a9ddd37330c2ca59d4d",
|
||||
"zh:ea77786bd6809ff4f8043b84a0212fec4de18b7d51bc420417ba10999ca99887",
|
||||
"zh:f7d8160c3669c8ab76a2da14ea740d91a08ca23d1fb657669e52a840b2b113d9",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/random" {
|
||||
version = "3.8.1"
|
||||
constraints = "3.8.1"
|
||||
hashes = [
|
||||
"h1:EHn3jsqOKhWjbg0X+psk0Ww96yz3N7ASqEKKuFvDFwo=",
|
||||
"zh:25c458c7c676f15705e872202dad7dcd0982e4a48e7ea1800afa5fc64e77f4c8",
|
||||
"zh:2edeaf6f1b20435b2f81855ad98a2e70956d473be9e52a5fdf57ccd0098ba476",
|
||||
"zh:44becb9d5f75d55e36dfed0c5beabaf4c92e0a2bc61a3814d698271c646d48e7",
|
||||
"zh:7699032612c3b16cc69928add8973de47b10ce81b1141f30644a0e8a895b5cd3",
|
||||
"zh:86d07aa98d17703de9fbf402c89590dc1e01dbe5671dd6bc5e487eb8fe87eee0",
|
||||
"zh:8c411c77b8390a49a8a1bc9f176529e6b32369dd33a723606c8533e5ca4d68c1",
|
||||
"zh:a5ecc8255a612652a56b28149994985e2c4dc046e5d34d416d47fa7767f5c28f",
|
||||
"zh:aea3fe1a5669b932eda9c5c72e5f327db8da707fe514aaca0d0ef60cb24892f9",
|
||||
"zh:f56e26e6977f755d7ae56fa6320af96ecf4bb09580d47cb481efbf27f1c5afff",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/tls" {
|
||||
version = "4.1.0"
|
||||
constraints = "4.1.0"
|
||||
hashes = [
|
||||
"h1:E9RjaL6cn8U/IkzfNcmrf/9EtMGjJnwUeXpx85sOGRg=",
|
||||
"h1:M2wp0tzlf2SDIxQbN5Sxc8o5HCGYZFfyfPwM9MJI3PE=",
|
||||
"h1:MByilNnYPdjPTlb/qcNgR0DErA6550hI6wd8OJYB1vw=",
|
||||
"h1:RBhHxjVu41XdAnM4WxxGTz2nYaccHNLalqx4031L8rE=",
|
||||
"h1:Scu4v7p3hVi6JmyWN4e1KkR31MX48T65dfA3Nfaeb/E=",
|
||||
"h1:Xb4aKDd/LTy9kSpauyTIe/Y4py2xK2sbImV1LdgMc/Q=",
|
||||
"h1:m4r9DvgYoUdf1ZeJMd2NGs3b6+8/RPhXUrEex554eQw=",
|
||||
"h1:p4jzSJLVx9DHkNZ1ax2/bMPTirjZxxN9nmiVx0aFQjA=",
|
||||
"h1:ujNwtB97C/kEt12+S3mUTWkGaJO8LNbqWoRg1FZ5a80=",
|
||||
"h1:yNZuPWUgw6Ik2huf9lhsuCGONWo2rsY1MfeceT0BQpw=",
|
||||
"zh:187a99f0d236fd92da224e2f026c4ca8f1dcbf2b5cddc8e6896801bacfab0d73",
|
||||
"zh:61a32a01cc46f382014dcf7aff5bcac61fe97bd69d3ccb51c801e9437ecdb9ce",
|
||||
"zh:683ba18baa2cc336ff83f061b5e4569e2cd7c4a097b53a2d80bb0a26be2fc59a",
|
||||
"zh:85c7640ea13dcf5ae5f7f3abbf2f21e4b93ce7f333ffee5b4a6acd6b5fe71223",
|
||||
"zh:882f2c5214fd6d280a500acfd560925a71030ef70e10d11fa2b94815b58ae9b6",
|
||||
"zh:97cb5e0b81b8687870a6b8a16e9a9cfe546e2fdb7534bdd8302eda0d66393f78",
|
||||
"zh:c0a0110b15ce45140036fe5bf5a44cb822c2f55b30ff2770faf37d7c3cae3b5e",
|
||||
"zh:d98c1c63fd0c76704fd7be38c316c305a2c95f3215330f2fb1e6b0b7081bf8e9",
|
||||
"zh:e703a7adf220ac436f8ebfd06529de865b965fcfc461c7ef7b71afa0de04c8e9",
|
||||
"zh:e93e241150cd438a0708679cb4aa7976742fde02f4c1725cfdefc405c4eeca1a",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
terraform {
|
||||
backend "pg" {
|
||||
schema_name = "prod_1password_futo_account"
|
||||
}
|
||||
required_version = "~> 1.7"
|
||||
|
||||
required_providers {
|
||||
onepassword = {
|
||||
source = "1Password/onepassword"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.8.1"
|
||||
}
|
||||
tls = {
|
||||
source = "hashicorp/tls"
|
||||
version = "4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
provider "onepassword" {
|
||||
service_account_token = var.futo_op_service_account_token
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
terraform {
|
||||
source = "../../../../../"
|
||||
|
||||
extra_arguments custom_vars {
|
||||
commands = get_terraform_commands_that_need_vars()
|
||||
}
|
||||
}
|
||||
|
||||
include "root" {
|
||||
path = find_in_parent_folders("root.hcl")
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
variable "futo_op_service_account_token" {}
|
||||
@@ -0,0 +1,42 @@
|
||||
module "yucca-manual-secrets" {
|
||||
source = "./shared/modules/secrets/manual"
|
||||
|
||||
secrets = {
|
||||
global = [
|
||||
"TF_STATE_S3_ENDPOINT",
|
||||
"TF_STATE_S3_BUCKET",
|
||||
"TF_STATE_S3_REGION",
|
||||
"TF_STATE_S3_ACCESS_KEY",
|
||||
"TF_STATE_S3_SECRET_KEY",
|
||||
"OVH_APPLICATION_KEY",
|
||||
"OVH_APPLICATION_SECRET",
|
||||
"OVH_CONSUMER_KEY",
|
||||
"TAILSCALE_API_KEY",
|
||||
"TAILSCALE_TAILNET_ID"
|
||||
]
|
||||
scoped = []
|
||||
}
|
||||
global_vault = "yucca_tf_manual"
|
||||
copy_global_vault = "yucca_tf"
|
||||
scoped_vaults = {
|
||||
"yucca_tf_prod_manual" = "yucca_tf_prod"
|
||||
"yucca_tf_staging_manual" = "yucca_tf_staging"
|
||||
"yucca_tf_dev_manual" = "yucca_tf_dev"
|
||||
}
|
||||
}
|
||||
|
||||
module "generated-secrets" {
|
||||
source = "./shared/modules/secrets/generated"
|
||||
|
||||
secrets = {
|
||||
global = []
|
||||
scoped = []
|
||||
}
|
||||
|
||||
global_vault = "yucca_tf"
|
||||
scoped_vaults = toset([
|
||||
"yucca_tf_prod",
|
||||
"yucca_tf_staging",
|
||||
"yucca_tf_dev",
|
||||
])
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
data "onepassword_vault" "tf" {
|
||||
name = "tf"
|
||||
data "onepassword_vault" "global" {
|
||||
name = var.global_vault
|
||||
}
|
||||
|
||||
data "onepassword_vault" "tf_dev" {
|
||||
name = "tf_dev"
|
||||
}
|
||||
|
||||
data "onepassword_vault" "tf_prod" {
|
||||
name = "tf_prod"
|
||||
data "onepassword_vault" "scoped" {
|
||||
for_each = var.scoped_vaults
|
||||
name = each.value
|
||||
}
|
||||
|
||||
@@ -2,28 +2,22 @@ locals {
|
||||
secrets = concat(
|
||||
var.secrets.global != null ? [
|
||||
for secret_obj in var.secrets.global : {
|
||||
vault = data.onepassword_vault.tf
|
||||
vault = data.onepassword_vault.global
|
||||
name = secret_obj.name
|
||||
length = secret_obj.length
|
||||
type = secret_obj.type
|
||||
}
|
||||
] : [],
|
||||
var.secrets.dev != null ? [
|
||||
for secret_obj in var.secrets.dev : {
|
||||
vault = data.onepassword_vault.tf_dev
|
||||
name = secret_obj.name
|
||||
length = secret_obj.length
|
||||
type = secret_obj.type
|
||||
}
|
||||
] : [],
|
||||
var.secrets.prod != null ? [
|
||||
for secret_obj in var.secrets.prod : {
|
||||
vault = data.onepassword_vault.tf_prod
|
||||
name = secret_obj.name
|
||||
length = secret_obj.length
|
||||
type = secret_obj.type
|
||||
}
|
||||
] : []
|
||||
var.secrets.scoped != null ? flatten([
|
||||
for vault_name in var.scoped_vaults : [
|
||||
for secret_obj in var.secrets.scoped : {
|
||||
vault = data.onepassword_vault.scoped[vault_name]
|
||||
name = secret_obj.name
|
||||
length = secret_obj.length
|
||||
type = secret_obj.type
|
||||
}
|
||||
]
|
||||
]) : []
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,7 @@ variable "secrets" {
|
||||
length = optional(number)
|
||||
type = optional(string, "alphanumeric")
|
||||
})))
|
||||
dev = optional(list(object({
|
||||
name = string
|
||||
length = optional(number)
|
||||
type = optional(string, "alphanumeric")
|
||||
})))
|
||||
prod = optional(list(object({
|
||||
scoped = optional(list(object({
|
||||
name = string
|
||||
length = optional(number)
|
||||
type = optional(string, "alphanumeric")
|
||||
@@ -18,6 +13,18 @@ variable "secrets" {
|
||||
})
|
||||
}
|
||||
|
||||
variable "global_vault" {
|
||||
type = string
|
||||
description = "Name of the vault for storing global secrets"
|
||||
default = "tf"
|
||||
}
|
||||
|
||||
variable "scoped_vaults" {
|
||||
type = set(string)
|
||||
description = "Names of the vaults for storing scoped secrets"
|
||||
default = ["tf_prod", "tf_dev"]
|
||||
}
|
||||
|
||||
variable "default_secret_length" {
|
||||
type = number
|
||||
description = "The default length for generated secrets if not specified per secret."
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
data "onepassword_vault" "manual" {
|
||||
name = "tf_manual"
|
||||
data "onepassword_vault" "manual_global" {
|
||||
name = var.global_vault
|
||||
}
|
||||
|
||||
data "onepassword_vault" "manual_dev" {
|
||||
name = "tf_dev_manual"
|
||||
data "onepassword_vault" "manual_scoped" {
|
||||
for_each = var.scoped_vaults
|
||||
name = each.key
|
||||
}
|
||||
|
||||
data "onepassword_vault" "manual_prod" {
|
||||
name = "tf_prod_manual"
|
||||
data "onepassword_vault" "copy_global" {
|
||||
name = var.copy_global_vault
|
||||
}
|
||||
|
||||
data "onepassword_vault" "tf" {
|
||||
name = "tf"
|
||||
}
|
||||
|
||||
data "onepassword_vault" "tf_dev" {
|
||||
name = "tf_dev"
|
||||
}
|
||||
|
||||
data "onepassword_vault" "tf_prod" {
|
||||
name = "tf_prod"
|
||||
data "onepassword_vault" "copy_scoped" {
|
||||
for_each = var.scoped_vaults
|
||||
name = each.value
|
||||
}
|
||||
|
||||
@@ -2,25 +2,20 @@ locals {
|
||||
secrets = concat(
|
||||
var.secrets.global != null ? [
|
||||
for name in var.secrets.global : {
|
||||
manual_vault = data.onepassword_vault.manual
|
||||
vault = data.onepassword_vault.tf
|
||||
manual_vault = data.onepassword_vault.manual_global
|
||||
vault = data.onepassword_vault.copy_global
|
||||
name = name
|
||||
}
|
||||
] : [],
|
||||
var.secrets.dev != null ? [
|
||||
for name in var.secrets.dev : {
|
||||
manual_vault = data.onepassword_vault.manual_dev
|
||||
vault = data.onepassword_vault.tf_dev
|
||||
name = name
|
||||
}
|
||||
] : [],
|
||||
var.secrets.prod != null ? [
|
||||
for name in var.secrets.prod : {
|
||||
manual_vault = data.onepassword_vault.manual_prod
|
||||
vault = data.onepassword_vault.tf_prod
|
||||
name = name
|
||||
}
|
||||
] : []
|
||||
var.secrets.scoped != null ? flatten([
|
||||
for manual_vault, copy_vault in var.scoped_vaults : [
|
||||
for name in var.secrets.scoped : {
|
||||
manual_vault = data.onepassword_vault.manual_scoped[manual_vault]
|
||||
vault = data.onepassword_vault.copy_scoped[manual_vault]
|
||||
name = name
|
||||
}
|
||||
]
|
||||
]) : []
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
variable "secrets" {
|
||||
type = object({
|
||||
global = optional(list(string))
|
||||
dev = optional(list(string))
|
||||
prod = optional(list(string))
|
||||
scoped = optional(list(string))
|
||||
})
|
||||
}
|
||||
|
||||
variable "global_vault" {
|
||||
type = string
|
||||
description = "Name of the vault for storing global manual secrets"
|
||||
default = "tf_manual"
|
||||
}
|
||||
|
||||
variable "copy_global_vault" {
|
||||
type = string
|
||||
description = "Name of the vault for copying global secrets to"
|
||||
default = "tf"
|
||||
}
|
||||
|
||||
variable "scoped_vaults" {
|
||||
type = map(string)
|
||||
description = "Map of manual vault names to copy vault names for scoped secrets"
|
||||
default = {
|
||||
"tf_prod_manual" = "tf_prod"
|
||||
"tf_dev_manual" = "tf_dev"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user