This commit is contained in:
Thomas Rijpstra 2025-02-22 11:55:14 +01:00
parent e368bbd94d
commit 8d6cd81788
Signed by: thomas
SSH Key Fingerprint: SHA256:au5M4TrfxCxk778HDa1d+VB33vzyetoOvL8zrsDkJt0
35 changed files with 1438 additions and 0 deletions

View File

@ -0,0 +1,19 @@
resource "zitadel_org" "default" {
depends_on = [var.wait_on]
name = var.name
}
#resource "zitadel_idp_google" "default" {
# name = "Google"
# client_id = "182902..."
# client_secret = "GOCSPX-*****"
# scopes = ["openid", "profile", "email"]
# is_linking_allowed = false
# is_creation_allowed = true
# is_auto_creation = false
# is_auto_update = true
# auto_linking = "AUTO_LINKING_OPTION_USERNAME"
#}
#google_client_id = "783390190667-0nkts50perpmhott4i7ro1ob5n7koi5i.apps.googleusercontent.com"
#google_client_secret = "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"

View File

@ -0,0 +1,56 @@
locals {
k8s_config = yamldecode(var.k8s_config_yaml)
k8s_host = local.k8s_config.clusters[0].cluster.server
k8s_auth = try(
{
token = local.k8s_config.users[0].user.token
using_token = true
},
{
client_certificate = base64decode(local.k8s_config.users[0].user["client-certificate-data"])
client_key = base64decode(local.k8s_config.users[0].user["client-key-data"])
using_token = false
}
)
}
provider "kubernetes" {
host = local.k8s_host
insecure = true
token = local.k8s_auth.using_token ? local.k8s_auth.token : null
client_certificate = local.k8s_auth.using_token ? null : local.k8s_auth.client_certificate
client_key = local.k8s_auth.using_token ? null : local.k8s_auth.client_key
}
provider "helm" {
kubernetes {
host = local.k8s_host
insecure = true
token = local.k8s_auth.using_token ? local.k8s_auth.token : null
client_certificate = local.k8s_auth.using_token ? null : local.k8s_auth.client_certificate
client_key = local.k8s_auth.using_token ? null : local.k8s_auth.client_key
}
}
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "1.2.0"
}
}
}
data "kubernetes_secret" "zitadel_admin" {
depends_on = [var.wait_on]
metadata {
name = var.secret
namespace = var.namespace
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_json = data.kubernetes_secret.zitadel_admin.data["${var.secret}.json"]
}

View File

@ -0,0 +1,32 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "secret" {
type = string
description = "Secret holding the JWT Profile JSON"
}
variable "namespace" {
type = string
description = "Namespace holding the secret"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "k8s_config_yaml" {
description = "Content of k8s config yaml file"
type = string
}
variable "name" {
type = string
description = "Name of the tenant"
default = "fourlights"
}

View File

@ -0,0 +1,3 @@
locals {
service_uri = join(".", [var.service_name, var.server_dns])
}

View File

@ -0,0 +1,141 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.31.0"
}
}
}
resource "kubernetes_namespace" "fusionauth" {
metadata {
name = var.namespace
}
lifecycle {
ignore_changes = [metadata]
}
}
data "kubernetes_secret" "bridge-tls" {
metadata {
name = "bridge-tls"
namespace = "cert-manager"
}
}
resource "kubernetes_secret" "fusionauth-tls" {
metadata {
name = "fusionauth-tls"
namespace = kubernetes_namespace.fusionauth.metadata[0].name
}
data = data.kubernetes_secret.bridge-tls.data
type = data.kubernetes_secret.bridge-tls.type
}
resource "kubernetes_secret" "postgresql-auth" {
metadata {
name = "postgresql-auth"
namespace = kubernetes_namespace.fusionauth.metadata[0].name
}
data = {
password = var.database_password
}
}
resource "random_password" "api_key" {
length = 32
special = false
}
resource "random_password" "admin" {
length = 32
special = false
}
resource "random_uuid" "default_tenant_id" {}
resource "helm_release" "fusionauth" {
depends_on = [var.wait_on, kubernetes_secret.postgresql-auth, kubernetes_secret.fusionauth-tls]
name = "fusionauth"
repository = "https://fusionauth.github.io/charts"
chart = "fusionauth"
namespace = kubernetes_namespace.fusionauth.metadata[0].name
version = "1.0.10"
create_namespace = false
wait = true
wait_for_jobs = true
values = [
templatefile("${path.module}/values.yaml", {
service_uri = local.service_uri,
database = var.database,
database_username = var.database_username,
database_root_username = var.database_root_password != null ? var.database_root_username : null,
# TODO: Add theme customization, and use as default
kickstart_json = jsonencode({
variables = {
defaultTenantId = random_uuid.default_tenant_id.result
adminEmail = "engineering@fourlights.nl"
adminPassword = random_password.admin.result
}
apiKeys = [{ key = random_password.api_key.result, description = "Terraform API Key" }],
requests = [
{
"method" : "POST",
"url" : "/api/user/registration/00000000-0000-0000-0000-000000000001",
"body" : {
"user" : {
"email" : "#{adminEmail}",
"firstName" : "Thomas",
"lastName" : "Rijpstra",
"password" : "#{adminPassword}",
"data" : {
"Company" : "Four Lights",
"user_type" : "iconclast"
}
},
"registration" : {
"applicationId" : "#{FUSIONAUTH_APPLICATION_ID}",
"roles" : [
"admin"
]
}
}
}
],
})
})
]
}
output "installed" {
value = true
depends_on = [helm_release.fusionauth]
}
output "api_key" {
value = random_password.api_key.result
sensitive = true
}
output "admin_password" {
value = random_password.admin.result
sensitive = true
}
output "server" {
value = local.service_uri
}
output "default_tenant_id" {
value = random_uuid.default_tenant_id.result
}
output "uri" {
value = "https://${local.service_uri}"
}

View File

@ -0,0 +1,17 @@
resource "zitadel_project_member" "default" {
depends_on = [var.wait_on]
org_id = var.org_id
project_id = var.project_id
user_id = var.user_id
roles = var.roles
}
output "installed" {
value = true
depends_on = [zitadel_project_member.default]
}
output "project_member_id" {
value = zitadel_project_member.default.id
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,26 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "project_id" {
type = string
description = "Project Id"
}

View File

@ -0,0 +1,27 @@
resource "zitadel_application_oidc" "default" {
depends_on = [var.wait_on]
org_id = var.org_id
project_id = var.project_id
name = var.name
}
output "installed" {
value = true
depends_on = [zitadel_application_oidc.default]
}
output "application_id" {
value = zitadel_application_oidc.default.id
}
output "client_id" {
value = zitadel_application_oidc.default.client_id
sensitive = true
}
output "client_secret" {
value = zitadel_application_oidc.default.client_secret
sensitive = true
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,36 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "project_id" {
type = string
description = "Project Id"
}
variable "name" {
type = string
description = "Application name"
}
variable "api_url" {
type = string
description = "Uri on which the API is available"
}

View File

@ -0,0 +1,44 @@
resource "zitadel_org_idp_google" "default" {
depends_on = [var.wait_on]
org_id = var.org_id
name = "Google"
client_id = var.client_id
client_secret = var.client_secret
scopes = var.options.scopes
is_linking_allowed = var.options.is_linking_allowed
is_creation_allowed = var.options.is_creation_allowed
is_auto_creation = var.options.is_auto_creation
is_auto_update = var.options.is_auto_update
auto_linking = var.options.auto_linking
}
resource "zitadel_login_policy" "default" {
depends_on = [zitadel_org_idp_google.default]
org_id = var.org_id
user_login = true
allow_register = true
allow_external_idp = true
force_mfa = false
force_mfa_local_only = false
passwordless_type = "PASSWORDLESS_TYPE_ALLOWED"
hide_password_reset = "false"
password_check_lifetime = "240h0m0s"
external_login_check_lifetime = "240h0m0s"
multi_factor_check_lifetime = "24h0m0s"
mfa_init_skip_lifetime = "720h0m0s"
second_factor_check_lifetime = "24h0m0s"
ignore_unknown_usernames = true
default_redirect_uri = "https://${var.domain}"
second_factors = ["SECOND_FACTOR_TYPE_OTP", "SECOND_FACTOR_TYPE_U2F"]
multi_factors = ["MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION"]
idps = [zitadel_org_idp_google.default.id]
allow_domain_discovery = true
disable_login_with_email = true
disable_login_with_phone = true
}
output "installed" {
value = true
depends_on = [zitadel_org_idp_google.default, zitadel_login_policy.default]
}

View File

@ -0,0 +1,21 @@
resource "zitadel_project_role" "default" {
count = length(var.roles)
depends_on = [var.wait_on]
org_id = var.org_id
project_id = var.project_id
role_key = var.roles[count.index]
display_name = var.roles[count.index]
group = var.group
}
output "installed" {
value = true
depends_on = [zitadel_project_role.default]
}
output "role_ids" {
value = toset([
for role in zitadel_project_role.default : role.id
])
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,38 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "project_id" {
type = string
description = "Project Id"
}
variable "group" {
type = string
description = "Optional group name"
default = null
}
variable "roles" {
type = list(string)
description = "Roles to be added"
default = []
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,27 @@
resource "zitadel_project" "default" {
depends_on = [var.wait_on]
org_id = var.org_id
name = var.name
project_role_assertion = true
project_role_check = true
has_project_check = true
private_labeling_setting = "PRIVATE_LABELING_SETTING_ENFORCE_PROJECT_RESOURCE_OWNER_POLICY"
}
resource "zitadel_project_member" "default" {
count = length(var.owners)
org_id = var.org_id
project_id = zitadel_project.default.id
user_id = var.owners[count.index]
roles = ["PROJECT_OWNER"]
}
output "installed" {
value = true
depends_on = [zitadel_project.default, zitadel_project_member.default]
}
output "project_id" {
value = zitadel_project.default.id
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,32 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "name" {
type = string
description = "Name of the project"
}
variable "owners" {
type = list(string)
description = "User IDs to be granted `PROJECT_OWNER` role"
default = []
}

View File

@ -0,0 +1,50 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "client_id" {
type = string
description = "Google Client ID"
}
variable "client_secret" {
type = string
description = "Google Client Secret"
}
variable "options" {
type = object({
scopes = list(string)
is_linking_allowed = bool
is_creation_allowed = bool
is_auto_creation = bool
is_auto_update = bool
auto_linking = string
})
default = {
scopes = ["openid", "profile", "email"],
is_linking_allowed = false
is_creation_allowed = true
is_auto_creation = false
is_auto_update = true
auto_linking = "AUTO_LINKING_OPTION_USERNAME"
}
}

View File

@ -0,0 +1,33 @@
locals {
k8s_config = yamldecode(var.k8s_config_yaml)
k8s_host = local.k8s_config.clusters[0].cluster.server
k8s_auth = try(
{
token = local.k8s_config.users[0].user.token
using_token = true
},
{
client_certificate = base64decode(local.k8s_config.users[0].user["client-certificate-data"])
client_key = base64decode(local.k8s_config.users[0].user["client-key-data"])
using_token = false
}
)
}
provider "kubernetes" {
host = local.k8s_host
insecure = true
token = local.k8s_auth.using_token ? local.k8s_auth.token : null
client_certificate = local.k8s_auth.using_token ? null : local.k8s_auth.client_certificate
client_key = local.k8s_auth.using_token ? null : local.k8s_auth.client_key
}
provider "helm" {
kubernetes {
host = local.k8s_host
insecure = true
token = local.k8s_auth.using_token ? local.k8s_auth.token : null
client_certificate = local.k8s_auth.using_token ? null : local.k8s_auth.client_certificate
client_key = local.k8s_auth.using_token ? null : local.k8s_auth.client_key
}
}

View File

@ -0,0 +1,21 @@
resource "zitadel_project_role" "default" {
count = length(var.roles)
depends_on = [var.wait_on]
org_id = var.org_id
project_id = var.project_id
role_key = var.roles[count.index]
display_name = var.roles[count.index]
group = var.group
}
output "installed" {
value = true
depends_on = [zitadel_project_role.default]
}
output "role_ids" {
value = toset([
for role in zitadel_project_role.default : role.id
])
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,38 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}
variable "org_id" {
type = string
description = "Organisation Id"
}
variable "project_id" {
type = string
description = "Project Id"
}
variable "group" {
type = string
description = "Optional group name"
default = null
}
variable "roles" {
type = list(string)
description = "Roles to be added"
default = []
}

View File

View File

View File

@ -0,0 +1,30 @@
resource "zitadel_org" "default" {
depends_on = [var.wait_on]
name = var.name
is_default = true
}
output "org_id" {
value = zitadel_org.default.id
}
output "installed" {
value = true
depends_on = [zitadel_org.default]
}
#resource "zitadel_idp_google" "default" {
# name = "Google"
# client_id = "182902..."
# client_secret = "GOCSPX-*****"
# scopes = ["openid", "profile", "email"]
# is_linking_allowed = false
# is_creation_allowed = true
# is_auto_creation = false
# is_auto_update = true
# auto_linking = "AUTO_LINKING_OPTION_USERNAME"
#}
#google_client_id = "783390190667-0nkts50perpmhott4i7ro1ob5n7koi5i.apps.googleusercontent.com"
#google_client_secret = "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"

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = var.domain
insecure = "false"
jwt_profile_file = var.jwt_profile_file
}

View File

@ -0,0 +1,22 @@
variable "domain" {
type = string
description = "Domain for the zitadel instance"
default = "localhost"
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "name" {
type = string
description = "Name of the tenant"
default = "fourlights"
}
variable "jwt_profile_file" {
type = string
description = "Path to the jwt profile file"
}

View File

@ -0,0 +1,56 @@
variable "service_name" {
type = string
description = "Name of the service"
default = "auth"
}
variable "server_dns" {
type = string
description = "Domain for the server"
}
variable "k8s_config_yaml" {
description = "Content of k8s config yaml file"
type = string
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "namespace" {
type = string
}
variable "database" {
type = string
default = "zitadel"
}
variable "database_username" {
type = string
default = "zitadel"
}
variable "database_password" {
type = string
sensitive = true
}
variable "database_root_username" {
type = string
default = "postgres"
}
variable "database_root_password" {
type = string
sensitive = true
default = null
}
variable "display_on_homepage" {
type = bool
default = false
}

View File

@ -0,0 +1,51 @@
zitadel:
masterkeySecretName: "zitadel"
configmapConfig:
ExternalSecure: false
ExternalDomain: ${ external_domain }
TLS:
Enabled: false
#ExternalPort: 443
#ExternalSecurePort: 443
#ExternalPathPrefix: ${ external_path_prefix }
#ExternalTLS: false
#ExternalTLSAllowInsecure: false
#ExternalTLSAllowInsecureSkipVerify: false
Database:
Postgres:
Host: postgresql-hl.postgresql.svc.cluster.local
Port: 5432
Database: ${ database }
MaxOpenConns: 20
MaxIdleConns: 10
MaxConnLifetime: 30m
MaxConnIdleTime: 5m
User:
Username: ${ database_username }
PasswordSecret: postgresql-auth
PasswordSecretKey: password
SSL:
Mode: disable
Admin:
Username: ${ database_root_username }
PasswordSecret: postgresql-auth
PasswordSecretKey: root-password
ingress:
enabled: true
className: traefik
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
%{ if displayOnHomepage }
gethomepage.dev/enabled: "true"
gethomepage.dev/name: "Zitadel"
gethomepage.dev/description: "Identity and Access Management"
gethomepage.dev/group: "Tools"
gethomepage.dev/icon: "zitadel.png"
%{ endif }
hosts:
- host: ${service_uri}
paths:
- path: /
pathType: Prefix

View File

@ -0,0 +1,51 @@
variable "service_name" {
type = string
description = "Name of the service"
default = "auth"
}
variable "server_dns" {
type = string
description = "Domain for the server"
}
variable "k8s_config_yaml" {
description = "Content of k8s config yaml file"
type = string
}
variable "wait_on" {
type = any
description = "Resources to wait on"
default = true
}
variable "namespace" {
type = string
}
variable "database" {
type = string
default = "fusionauth"
}
variable "database_username" {
type = string
default = "fusionauth"
}
variable "database_password" {
type = string
sensitive = true
}
variable "database_root_username" {
type = string
default = "postgres"
}
variable "database_root_password" {
type = string
sensitive = true
default = null
}

View File

@ -0,0 +1,174 @@
locals {
tld = "fourlights.dev"
cluster_dns = "venus.${local.tld}"
bridge_dns = "bridge.${local.cluster_dns}"
is_installed = true
node_count = 3
}
resource "kubernetes_manifest" "preserve-host-middleware" {
depends_on = [local.is_installed]
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "preserve-host-headers"
namespace = "default" # NOTE: Hardcoded by design
}
spec = {
headers = {
customRequestHeaders = {
"X-Forwarded-Proto" = "https"
"X-Forwarded-Port" = "443"
}
}
}
}
}
resource "kubernetes_manifest" "https-redirect-middleware" {
depends_on = [local.is_installed]
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "redirect-to-https"
namespace = "default" # NOTE: Hardcoded by design
}
spec = {
redirectScheme = {
permanent = true
scheme = "https"
}
}
}
}
module "homepage" {
source = "../../infra/modules/homepage"
wait_on = local.is_installed
k8s_config_yaml = local.k8s_config_yaml
server_dns = local.cluster_dns
service_name = "homepage"
service_uri = local.cluster_dns
namespace = "homepage"
}
module "minio" {
source = "../../infra/modules/minio"
wait_on = local.is_installed
k8s_config_yaml = local.k8s_config_yaml
server_dns = local.cluster_dns
service_name = "storage"
namespace = "minio"
admin_server_dns = local.cluster_dns # Restricted admin access, access via bridge
tls = false
admin = true
ingressClass = "traefik"
storageSize = "10Gi"
displayOnHomepage = true
}
module "mongodb" {
source = "../../infra/modules/mongodb"
wait_on = local.is_installed
k8s_config_yaml = local.k8s_config_yaml
namespace = "mongodb"
replicas = local.node_count
}
module "rabbitmq" {
source = "../../infra/modules/rabbitmq"
wait_on = local.is_installed
k8s_config_yaml = local.k8s_config_yaml
server_dns = "local" # Restricted admin access, access via bridge
service_name = "rabbitmq"
namespace = "rabbitmq"
tls = false
admin = true
ingressClass = "traefik"
}
module "postgresql" {
source = "../../infra/modules/postgresql"
namespace = "postgresql"
k8s_config_yaml = local.k8s_config_yaml
username = "bridge"
}
module "zitadel-db" {
source = "../../infra/modules/postgresql/tenant"
wait_on = module.postgresql.installed
name = "zitadel"
root_password = module.postgresql.root_password
k8s_config_yaml = local.k8s_config_yaml
}
module "zitadel" {
source = "../../infra/modules/zitadel"
wait_on = module.zitadel-db.installed
k8s_config_yaml = local.k8s_config_yaml
server_dns = local.cluster_dns
service_name = "zitadel"
namespace = "zitadel"
database_password = module.zitadel-db.password
database_root_password = module.postgresql.root_password
display_on_homepage = true
}
module "zitadel-tenant" {
source = "../../infra/modules/zitadel/tenant"
wait_on = module.zitadel.installed
domain = module.zitadel.server
name = "fourlights"
jwt_profile_file = module.zitadel.jwt_profile_file
}
module "zitadel-idp-google" {
source = "../../infra/modules/zitadel/identity-provider/google"
wait_on = module.zitadel-tenant.installed
domain = module.zitadel.server
jwt_profile_file = module.zitadel.jwt_profile_file
org_id = module.zitadel-tenant.org_id
client_id = "783390190667-0nkts50perpmhott4i7ro1ob5n7koi5i.apps.googleusercontent.com"
client_secret = "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"
options = {
scopes = ["openid", "profile", "email"]
is_auto_creation = true
is_auto_update = true
is_creation_allowed = true
is_linking_allowed = false
auto_linking = "AUTO_LINKING_OPTION_USERNAME"
}
}
// module "zitadel-machine-user" {
// source = "../../infra/modules/zitadel/tenant"
// wait_on = module.zitadel.installed
// k8s_config_yaml = local.k8s_config_yaml
//
// domain = module.zitadel.server
// secret = "zitadel-admin-sa"
// namespace = "zitadel"
// name = "fourlights"
// }

View File

@ -0,0 +1,295 @@
locals {
tld = "fourlights.dev"
cluster_dns = "venus.${local.tld}"
domain = "zitadel.${local.cluster_dns}"
org_domain = "fourlights.${local.domain}"
jwt_profile_file = "../terraform/zitadel-admin-sa.json"
name = "365Zon"
user_id = "308083708882059797"
}
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "2.0.2"
}
}
}
provider "zitadel" {
domain = local.domain
insecure = "false"
jwt_profile_file = local.jwt_profile_file
}
data "zitadel_orgs" "default" {
domain = local.domain
}
data "zitadel_org" "default" {
for_each = toset(data.zitadel_orgs.default.ids)
id = each.value
}
module "zitadel_project" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
name = local.name
owners = [local.user_id]
}
// TODO: add action for setting roles as scopes
module "zitadel_project_operator_roles" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/roles"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
group = "Operator"
roles = [
"manage:profiles", "manage:contacts", "manage:addresses", "manage:enquiries", "manage:flowstates",
"manage:flowevents", "manage:files"
]
}
module "zitadel_project_configurator_roles" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/roles"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
group = "Configurator"
roles = [
"manage:brands", "manage:flows"
]
}
module "zitadel_project_developer_roles" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/roles"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
group = "Developer"
roles = [
"manage:jobs", "manage:infrastructure"
]
}
// TODO: Move External (and 365zon Push service account) to own project
// TODO: Add grant for external project
// TODO: Add read roles
module "zitadel_project_application_core_api" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/api"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Core API"
}
module "zitadel_project_application_core_ua" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/applicaitn/user-agent"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Core (Swagger)"
}
module "zitadel_project_application_module_365zon_api" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/api"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: Salesforce Pull API"
}
module "zitadel_project_application_module_365zon_ua" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/user-agent"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: Salesforce Pull (Swagger)"
}
module "zitadel_project_application_module_external_api" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/api"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: External API"
}
module "zitadel_project_application_module_external_ua" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/user-agent"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: External (Swagger)"
}
module "zitadel_project_application_module_internal_api" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/api"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: Internal API"
}
module "zitadel_project_application_module_internal_ua" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/application/user-agent"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
project_id = module.zitadel_project[count.index].project_id
jwt_profile_file = local.jwt_profile_file
name = "Module: Internal swagger"
}
module "zitadel_service_account_module_internal" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/service-account"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
user_name = "${local.name}-module-internal@${ local.org_domain }"
name = "Module Internal @ ${local.name}"
with_secret = true
access_token_type = "ACCESS_TOKEN_TYPE_JWT"
}
module "zitadel_project_member_module_internal" {
wait_on = module.zitadel_project_operator_roles[count.index].installed
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/member"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
project_id = module.zitadel_project[count.index].project_id
user_id = module.zitadel_service_account_module_internal[count.index].user_id
roles = module.zitadel_project_operator_roles[count.index].roles
}
module "zitadel_service_account_module_external" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/service-account"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
user_name = "${local.name}-module-external@${ local.org_domain }"
name = "Module External @ ${local.name}"
with_secret = true
access_token_type = "ACCESS_TOKEN_TYPE_JWT"
}
module "zitadel_project_member_module_external" {
wait_on = module.zitadel_project_operator_roles[count.index].installed
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/member"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
project_id = module.zitadel_project[count.index].project_id
user_id = module.zitadel_service_account_module_external[count.index].user_id
roles = module.zitadel_project_operator_roles[count.index].roles
}
module "zitadel_service_account_module_365zon" {
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/service-account"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
user_name = "${local.name}-module-365zon@${ local.org_domain }"
name = "Module 365Zon @ ${local.name}"
with_secret = true
access_token_type = "ACCESS_TOKEN_TYPE_JWT"
}
module "zitadel_project_member_module_365zon" {
wait_on = module.zitadel_project_operator_roles[count.index].installed
count = data.zitadel_org.default.count
source = "../../infra/modules/zitadel/project/member"
domain = local.domain
org_id = data.zitadel_org.default[count.index].id
jwt_profile_file = local.jwt_profile_file
project_id = module.zitadel_project[count.index].project_id
user_id = module.zitadel_service_account_module_365zon[count.index].user_id
roles = module.zitadel_project_operator_roles[count.index].roles
}
// TODO: Application for Front-End End (implicit, authorization_code, refresh_token)
// TODO: Update API applications with callback apiDomain/swagger/oauth2-redirect.html to allow logging in for swagger (and probably hangire?)
// TODO: Put all the relevant secrets into secret manager
// TODO: Set up opentelemetry and update appinsights shit to use that.
output "org_ids" {
value = data.zitadel_orgs.default.ids
}
output "project_ids" {
value = [for project in module.zitadel_project : project.project_id]
}

View File