From df5c5b9a8ee52d7d68b11ceaa89f80124cf3bb4b Mon Sep 17 00:00:00 2001 From: Thomas Rijpstra Date: Sat, 22 Feb 2025 11:55:35 +0100 Subject: [PATCH] WIP --- bridge/.idea/workspace.xml | 70 +++++++ infra/modules/homepage/values.yaml.tftpl | 15 -- infra/modules/minio/main.tf | 1 + infra/modules/minio/values.yaml.tftpl | 7 + infra/modules/minio/variables.tf | 6 +- infra/modules/postgresql/main.tf | 10 +- infra/modules/postgresql/tenant/main.tf | 3 +- infra/modules/postgresql/tenant/variables.tf | 5 + infra/modules/postgresql/variables.tf | 5 + .../zitadel/identity-provider/google/main.tf | 55 ++++-- .../identity-provider/google/provider.tf | 46 +---- .../identity-provider/google/variables.tf | 48 +++-- infra/modules/zitadel/main.tf | 131 ++++--------- .../zitadel/project/application/api/main.tf | 24 ++- .../project/application/api/variables.tf | 5 + .../project/application/user-agent/main.tf | 33 +++- .../application/user-agent/variables.tf | 10 +- infra/modules/zitadel/project/main.tf | 53 ++---- infra/modules/zitadel/project/member/main.tf | 20 +- .../zitadel/project/member/variables.tf | 7 +- infra/modules/zitadel/project/roles/main.tf | 34 ++-- .../zitadel/project/roles/variables.tf | 14 +- infra/modules/zitadel/project/variables.tf | 30 +-- infra/modules/zitadel/service-account/main.tf | 32 ++-- .../zitadel/service-account/variables.tf | 28 +-- infra/modules/zitadel/tenant/main.tf | 14 ++ infra/modules/zitadel/tenant/provider.tf | 14 ++ .../modules/zitadel/tenant/role-owner/main.tf | 29 +-- .../zitadel/tenant/role-owner/variables.tf | 10 +- infra/modules/zitadel/tenant/variables.tf | 54 +----- infra/modules/zitadel/values.yaml.tftpl | 55 ++++-- infra/modules/zitadel/variables.tf | 14 +- shuttles/terraform-configure/main.tf | 174 ------------------ .../.terraform.lock.hcl | 25 +++ shuttles/terraform-zitadel-bootstrap/main.tf | 115 ++++++++++++ shuttles/terraform/.terraform.lock.hcl | 69 +++++-- shuttles/terraform/main.tf | 73 ++++++++ shuttles/terraform/zitadel-admin-sa.json | 1 + 38 files changed, 747 insertions(+), 592 deletions(-) create mode 100644 bridge/.idea/workspace.xml delete mode 100644 shuttles/terraform-configure/main.tf create mode 100644 shuttles/terraform-zitadel-bootstrap/.terraform.lock.hcl create mode 100644 shuttles/terraform-zitadel-bootstrap/main.tf mode change 100644 => 100755 shuttles/terraform/zitadel-admin-sa.json diff --git a/bridge/.idea/workspace.xml b/bridge/.idea/workspace.xml new file mode 100644 index 0000000..8165e1c --- /dev/null +++ b/bridge/.idea/workspace.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + { + "associatedIndex": 1 +} + + + + + + + + + + + + + + + 1731596143702 + + + + + + \ No newline at end of file diff --git a/infra/modules/homepage/values.yaml.tftpl b/infra/modules/homepage/values.yaml.tftpl index 8c40e6e..9b86d45 100644 --- a/infra/modules/homepage/values.yaml.tftpl +++ b/infra/modules/homepage/values.yaml.tftpl @@ -4,21 +4,6 @@ config: - Github: - abbr: GH href: https://github.com/ - services: - - My First Group: - - My First Service: - href: http://localhost/ - description: Homepage is awesome - - - My Second Group: - - My Second Service: - href: http://localhost/ - description: Homepage is the best - - - My Third Group: - - My Third Service: - href: http://localhost/ - description: Homepage is 😎 widgets: # show the kubernetes widget, with the cluster summary and individual nodes - kubernetes: diff --git a/infra/modules/minio/main.tf b/infra/modules/minio/main.tf index 4873dd8..ae332c1 100644 --- a/infra/modules/minio/main.tf +++ b/infra/modules/minio/main.tf @@ -58,6 +58,7 @@ resource "helm_release" "minio" { admin = var.admin, tls = var.mode == "distributed" ? false : var.tls ingressClass = var.ingressClass + displayOnHomepage = var.displayOnHomepage }) ] } diff --git a/infra/modules/minio/values.yaml.tftpl b/infra/modules/minio/values.yaml.tftpl index 0fe6965..68568d3 100644 --- a/infra/modules/minio/values.yaml.tftpl +++ b/infra/modules/minio/values.yaml.tftpl @@ -22,6 +22,13 @@ ingress: ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/proxy-body-size: "0" %{ endif } + %{ if displayOnHomepage } + gethomepage.dev/enabled: "true" + gethomepage.dev/name: "Minio" + gethomepage.dev/description: "S3-Compatible cloud storage" + gethomepage.dev/group: "Tools" + gethomepage.dev/icon: "minio.png" + %{ endif } apiIngress: enabled: true diff --git a/infra/modules/minio/variables.tf b/infra/modules/minio/variables.tf index e4c0dfd..5b72ab1 100644 --- a/infra/modules/minio/variables.tf +++ b/infra/modules/minio/variables.tf @@ -61,7 +61,11 @@ variable "ingressClass" { } variable "storageSize" { - type = string + type = string default = "6Gi" } +variable "displayOnHomepage" { + type = bool + default = false +} diff --git a/infra/modules/postgresql/main.tf b/infra/modules/postgresql/main.tf index 0e2ef9f..cbc4c0f 100644 --- a/infra/modules/postgresql/main.tf +++ b/infra/modules/postgresql/main.tf @@ -1,4 +1,6 @@ resource "kubernetes_namespace" "postgresql" { + count = var.enabled ? 1 : 0 + metadata { name = var.namespace } @@ -19,11 +21,12 @@ resource "random_password" "postgresql_root_password" { } resource "kubernetes_secret" "postgresql_auth" { - type = "generic" + count = var.enabled ? 1 : 0 + type = "generic" depends_on = [var.wait_on] metadata { name = "postgresql-auth" - namespace = kubernetes_namespace.postgresql.metadata.0.name + namespace = kubernetes_namespace.postgresql[count.index].metadata.0.name } data = { @@ -33,11 +36,12 @@ resource "kubernetes_secret" "postgresql_auth" { } resource "helm_release" "postgresql" { + count = var.enabled ? 1 : 0 depends_on = [var.wait_on, kubernetes_secret.postgresql_auth] name = "postgresql" repository = "https://charts.bitnami.com/bitnami" chart = "postgresql" - namespace = kubernetes_namespace.postgresql.metadata.0.name + namespace = kubernetes_namespace.postgresql[count.index].metadata.0.name version = "16.0.5" wait = true diff --git a/infra/modules/postgresql/tenant/main.tf b/infra/modules/postgresql/tenant/main.tf index d2cad9b..b8b3182 100644 --- a/infra/modules/postgresql/tenant/main.tf +++ b/infra/modules/postgresql/tenant/main.tf @@ -17,6 +17,7 @@ resource "random_password" "tenant" { } resource "kubernetes_job" "create-tenant" { + count = var.enabled ? 1 : 0 depends_on = [var.wait_on] metadata { @@ -108,5 +109,5 @@ output "username" { } output "job_name" { - value = kubernetes_job.create-tenant.metadata[0].name + value = var.enabled ? kubernetes_job.create-tenant[0].metadata[0].name : null } diff --git a/infra/modules/postgresql/tenant/variables.tf b/infra/modules/postgresql/tenant/variables.tf index 46c3a52..bc30f8c 100644 --- a/infra/modules/postgresql/tenant/variables.tf +++ b/infra/modules/postgresql/tenant/variables.tf @@ -38,3 +38,8 @@ variable "k8s_config_yaml" { description = "Content of k8s config yaml file" type = string } + +variable "enabled" { + type = bool + default = true +} diff --git a/infra/modules/postgresql/variables.tf b/infra/modules/postgresql/variables.tf index 3c3eb32..1e10dd0 100644 --- a/infra/modules/postgresql/variables.tf +++ b/infra/modules/postgresql/variables.tf @@ -16,3 +16,8 @@ variable "namespace" { variable "username" { type = string } + +variable "enabled" { + type = bool + default = true +} diff --git a/infra/modules/zitadel/identity-provider/google/main.tf b/infra/modules/zitadel/identity-provider/google/main.tf index fdb6abc..e116eeb 100644 --- a/infra/modules/zitadel/identity-provider/google/main.tf +++ b/infra/modules/zitadel/identity-provider/google/main.tf @@ -1,19 +1,44 @@ -resource "zitadel_org" "default" { +resource "zitadel_org_idp_google" "default" { depends_on = [var.wait_on] - name = var.name + 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_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" -#} +resource "zitadel_login_policy" "default" { + depends_on = [zitadel_org_idp_google.default] -#google_client_id = "783390190667-0nkts50perpmhott4i7ro1ob5n7koi5i.apps.googleusercontent.com" -#google_client_secret = "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" + 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] +} diff --git a/infra/modules/zitadel/identity-provider/google/provider.tf b/infra/modules/zitadel/identity-provider/google/provider.tf index 2550782..653009c 100644 --- a/infra/modules/zitadel/identity-provider/google/provider.tf +++ b/infra/modules/zitadel/identity-provider/google/provider.tf @@ -1,56 +1,14 @@ -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" + version = "2.0.2" } } } -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"] + jwt_profile_file = var.jwt_profile_file } diff --git a/infra/modules/zitadel/identity-provider/google/variables.tf b/infra/modules/zitadel/identity-provider/google/variables.tf index d3009d3..c648d93 100644 --- a/infra/modules/zitadel/identity-provider/google/variables.tf +++ b/infra/modules/zitadel/identity-provider/google/variables.tf @@ -4,29 +4,47 @@ variable "domain" { 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" +variable "jwt_profile_file" { type = string + description = "Path to the jwt profile file" } -variable "name" { +variable "org_id" { type = string - description = "Name of the tenant" - default = "fourlights" + 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" + } } diff --git a/infra/modules/zitadel/main.tf b/infra/modules/zitadel/main.tf index a9f8d18..c874912 100644 --- a/infra/modules/zitadel/main.tf +++ b/infra/modules/zitadel/main.tf @@ -7,7 +7,8 @@ terraform { } } -resource "kubernetes_namespace" "fusionauth" { +resource "kubernetes_namespace" "zitadel" { + count = var.enabled ? 1 : 0 metadata { name = var.namespace } @@ -17,125 +18,73 @@ resource "kubernetes_namespace" "fusionauth" { } } -data "kubernetes_secret" "bridge-tls" { - metadata { - name = "bridge-tls" - namespace = "cert-manager" - } +resource "random_password" "zitadel_masterkey" { + length = 32 + special = true } -resource "kubernetes_secret" "fusionauth-tls" { +resource "kubernetes_secret" "zitadel" { + count = var.enabled ? 1 : 0 metadata { - name = "fusionauth-tls" - namespace = kubernetes_namespace.fusionauth.metadata[0].name + name = "zitadel" + namespace = kubernetes_namespace.zitadel[count.index].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 + masterkey = random_password.zitadel_masterkey.result } } -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" +resource "helm_release" "zitadel" { + count = var.enabled ? 1 : 0 + depends_on = [var.wait_on, kubernetes_secret.zitadel] + name = "zitadel" + repository = "https://charts.zitadel.com" + chart = "zitadel" + namespace = kubernetes_namespace.zitadel[count.index].metadata[0].name + version = "8.12.0" create_namespace = false wait = true wait_for_jobs = true values = [ - templatefile("${path.module}/values.yaml", { + templatefile("${path.module}/values.yaml.tftpl", { service_uri = local.service_uri, database = var.database, database_username = var.database_username, + database_password = var.database_password, 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" - ] - } - } - } - ], - }) + database_root_password = var.database_root_password + display_on_homepage = var.display_on_homepage }) ] } +data "kubernetes_secret" "zitadel_admin" { + depends_on = [helm_release.zitadel] + metadata { + name = "zitadel-admin-sa" + namespace = var.namespace + } +} + +resource "local_file" "zitadel_jwt_profile_file" { + content = data.kubernetes_secret.zitadel_admin.data["zitadel-admin-sa.json"] + filename = format("%s/%s", path.root, "zitadel-admin-sa.json") +} + +output "jwt_profile_file" { + value = local_file.zitadel_jwt_profile_file.filename +} + 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 + depends_on = [helm_release.zitadel, local_file.zitadel_jwt_profile_file] } output "server" { value = local.service_uri } -output "default_tenant_id" { - value = random_uuid.default_tenant_id.result -} - output "uri" { value = "https://${local.service_uri}" } diff --git a/infra/modules/zitadel/project/application/api/main.tf b/infra/modules/zitadel/project/application/api/main.tf index 9895069..dbd13e8 100644 --- a/infra/modules/zitadel/project/application/api/main.tf +++ b/infra/modules/zitadel/project/application/api/main.tf @@ -1,17 +1,29 @@ -resource "zitadel_project_member" "default" { +resource "zitadel_application_api" "default" { depends_on = [var.wait_on] org_id = var.org_id project_id = var.project_id - user_id = var.user_id - roles = var.roles + + name = var.name + auth_method_type = "API_AUTH_METHOD_TYPE_BASIC" + // TODO: Change this to private key jwt in the future } output "installed" { value = true - depends_on = [zitadel_project_member.default] + depends_on = [zitadel_application_api.default] } -output "project_member_id" { - value = zitadel_project_member.default.id +output "application_id" { + value = zitadel_application_api.default.id +} + +output "client_id" { + value = zitadel_application_api.default.client_id + sensitive = true +} + +output "client_secret" { + value = zitadel_application_api.default.client_secret + sensitive = true } diff --git a/infra/modules/zitadel/project/application/api/variables.tf b/infra/modules/zitadel/project/application/api/variables.tf index ae9b5e2..622dd71 100644 --- a/infra/modules/zitadel/project/application/api/variables.tf +++ b/infra/modules/zitadel/project/application/api/variables.tf @@ -24,3 +24,8 @@ variable "project_id" { type = string description = "Project Id" } + +variable "name" { + type = string + description = "Application name" +} diff --git a/infra/modules/zitadel/project/application/user-agent/main.tf b/infra/modules/zitadel/project/application/user-agent/main.tf index 220b565..4391c5b 100644 --- a/infra/modules/zitadel/project/application/user-agent/main.tf +++ b/infra/modules/zitadel/project/application/user-agent/main.tf @@ -1,10 +1,37 @@ resource "zitadel_application_oidc" "default" { depends_on = [var.wait_on] - org_id = var.org_id - project_id = var.project_id - name = var.name + org_id = var.org_id + grant_types = ["OIDC_GRANT_TYPE_AUTHORIZATION_CODE"] + name = var.name + project_id = var.project_id + + redirect_uris = var.redirect_uris + response_types = ["OIDC_RESPONSE_TYPE_CODE"] + + # // If selected, the requested roles of the authenticated user are added to the access token. + #access_token_type = "OIDC_TOKEN_TYPE_JWT" + #access_token_role_assertion = true + + # BEARER uses an Opaque token, which needs the introspection endpoint and `urn:zitadel:iam:org:project:id::aud` scope + access_token_type = "OIDC_TOKEN_TYPE_BEARER" + + # // If you want to add additional Origins to your app which is not used as a redirect you can do that here. + #additional_origins = [] + + app_type = "OIDC_APP_TYPE_USER_AGENT" + auth_method_type = "OIDC_AUTH_METHOD_TYPE_NONE" + + # // Redirect URIs must begin with https:// unless dev_mode is true + #dev_mode = false + + # // If selected, the requested roles of the authenticated user are added to the ID token. + #id_token_role_assertion = false + # // Enables clients to retrieve profile, email, phone and address claims from ID token. + #id_token_userinfo_assertion = false + + post_logout_redirect_uris = var.post_logout_redirect_uris } output "installed" { diff --git a/infra/modules/zitadel/project/application/user-agent/variables.tf b/infra/modules/zitadel/project/application/user-agent/variables.tf index 6ed21a6..2459275 100644 --- a/infra/modules/zitadel/project/application/user-agent/variables.tf +++ b/infra/modules/zitadel/project/application/user-agent/variables.tf @@ -30,7 +30,11 @@ variable "name" { description = "Application name" } -variable "api_url" { - type = string - description = "Uri on which the API is available" +variable "redirect_uris" { + type = list(string) +} + +variable "post_logout_redirect_uris" { + type = list(string) + default = [] } diff --git a/infra/modules/zitadel/project/main.tf b/infra/modules/zitadel/project/main.tf index e116eeb..611f668 100644 --- a/infra/modules/zitadel/project/main.tf +++ b/infra/modules/zitadel/project/main.tf @@ -1,44 +1,27 @@ -resource "zitadel_org_idp_google" "default" { +resource "zitadel_project" "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 + 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_login_policy" "default" { - depends_on = [zitadel_org_idp_google.default] +resource "zitadel_project_member" "default" { + count = length(var.owners) - 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 + 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_org_idp_google.default, zitadel_login_policy.default] + depends_on = [zitadel_project.default, zitadel_project_member.default] +} + +output "project_id" { + value = zitadel_project.default.id } diff --git a/infra/modules/zitadel/project/member/main.tf b/infra/modules/zitadel/project/member/main.tf index a7322b4..9895069 100644 --- a/infra/modules/zitadel/project/member/main.tf +++ b/infra/modules/zitadel/project/member/main.tf @@ -1,21 +1,17 @@ -resource "zitadel_project_role" "default" { - count = length(var.roles) +resource "zitadel_project_member" "default" { 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 + 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_role.default] + depends_on = [zitadel_project_member.default] } -output "role_ids" { - value = toset([ - for role in zitadel_project_role.default : role.id - ]) +output "project_member_id" { + value = zitadel_project_member.default.id } diff --git a/infra/modules/zitadel/project/member/variables.tf b/infra/modules/zitadel/project/member/variables.tf index 0b5b575..a4b6976 100644 --- a/infra/modules/zitadel/project/member/variables.tf +++ b/infra/modules/zitadel/project/member/variables.tf @@ -25,14 +25,13 @@ variable "project_id" { description = "Project Id" } -variable "group" { +variable "user_id" { type = string - description = "Optional group name" - default = null + description = "User Id" } variable "roles" { type = list(string) - description = "Roles to be added" + description = "Roles to be granted" default = [] } diff --git a/infra/modules/zitadel/project/roles/main.tf b/infra/modules/zitadel/project/roles/main.tf index 611f668..e8132b5 100644 --- a/infra/modules/zitadel/project/roles/main.tf +++ b/infra/modules/zitadel/project/roles/main.tf @@ -1,27 +1,25 @@ -resource "zitadel_project" "default" { +resource "zitadel_project_role" "default" { + count = length(var.roles) 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"] + 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.default, zitadel_project_member.default] + depends_on = [zitadel_project_role.default] } -output "project_id" { - value = zitadel_project.default.id +output "role_ids" { + value = toset([ + for role in zitadel_project_role.default : role.id + ]) +} + +output "roles" { + value = var.roles } diff --git a/infra/modules/zitadel/project/roles/variables.tf b/infra/modules/zitadel/project/roles/variables.tf index 28d991a..0b5b575 100644 --- a/infra/modules/zitadel/project/roles/variables.tf +++ b/infra/modules/zitadel/project/roles/variables.tf @@ -20,13 +20,19 @@ variable "org_id" { description = "Organisation Id" } -variable "name" { +variable "project_id" { type = string - description = "Name of the project" + description = "Project Id" } -variable "owners" { +variable "group" { + type = string + description = "Optional group name" + default = null +} + +variable "roles" { type = list(string) - description = "User IDs to be granted `PROJECT_OWNER` role" + description = "Roles to be added" default = [] } diff --git a/infra/modules/zitadel/project/variables.tf b/infra/modules/zitadel/project/variables.tf index c648d93..28d991a 100644 --- a/infra/modules/zitadel/project/variables.tf +++ b/infra/modules/zitadel/project/variables.tf @@ -20,31 +20,13 @@ variable "org_id" { description = "Organisation Id" } -variable "client_id" { +variable "name" { type = string - description = "Google Client ID" + description = "Name of the project" } -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" - } +variable "owners" { + type = list(string) + description = "User IDs to be granted `PROJECT_OWNER` role" + default = [] } diff --git a/infra/modules/zitadel/service-account/main.tf b/infra/modules/zitadel/service-account/main.tf index a7322b4..316714c 100644 --- a/infra/modules/zitadel/service-account/main.tf +++ b/infra/modules/zitadel/service-account/main.tf @@ -1,21 +1,29 @@ -resource "zitadel_project_role" "default" { - count = length(var.roles) +resource "zitadel_machine_user" "default" { 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 + org_id = var.org_id + user_name = var.user_name + name = var.name + description = var.description + with_secret = var.with_secret + access_token_type = var.access_token_type } output "installed" { value = true - depends_on = [zitadel_project_role.default] + depends_on = [zitadel_machine_user.default] } -output "role_ids" { - value = toset([ - for role in zitadel_project_role.default : role.id - ]) +output "user_id" { + value = zitadel_machine_user.default.id +} + +output "client_id" { + value = zitadel_machine_user.default.client_id + sensitive = true +} + +output "client_secret" { + value = zitadel_machine_user.default.client_secret + sensitive = true } diff --git a/infra/modules/zitadel/service-account/variables.tf b/infra/modules/zitadel/service-account/variables.tf index 0b5b575..b80205d 100644 --- a/infra/modules/zitadel/service-account/variables.tf +++ b/infra/modules/zitadel/service-account/variables.tf @@ -20,19 +20,25 @@ variable "org_id" { description = "Organisation Id" } -variable "project_id" { - type = string - description = "Project Id" +variable "user_name" { + type = string } -variable "group" { - type = string - description = "Optional group name" - default = null +variable "name" { + type = string } -variable "roles" { - type = list(string) - description = "Roles to be added" - default = [] +variable "description" { + type = string + default = null +} + +variable "with_secret" { + type = bool + default = false +} + +variable "access_token_type" { + type = string + default = "ACCESS_TOKEN_TYPE_JWT" } diff --git a/infra/modules/zitadel/tenant/main.tf b/infra/modules/zitadel/tenant/main.tf index e69de29..82c80b0 100644 --- a/infra/modules/zitadel/tenant/main.tf +++ b/infra/modules/zitadel/tenant/main.tf @@ -0,0 +1,14 @@ +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] +} diff --git a/infra/modules/zitadel/tenant/provider.tf b/infra/modules/zitadel/tenant/provider.tf index e69de29..653009c 100644 --- a/infra/modules/zitadel/tenant/provider.tf +++ b/infra/modules/zitadel/tenant/provider.tf @@ -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 +} diff --git a/infra/modules/zitadel/tenant/role-owner/main.tf b/infra/modules/zitadel/tenant/role-owner/main.tf index e8f5117..4605410 100644 --- a/infra/modules/zitadel/tenant/role-owner/main.tf +++ b/infra/modules/zitadel/tenant/role-owner/main.tf @@ -1,30 +1,11 @@ -resource "zitadel_org" "default" { +resource "zitadel_org_member" "default" { depends_on = [var.wait_on] - name = var.name - is_default = true -} - -output "org_id" { - value = zitadel_org.default.id + org_id = var.org_id + user_id = var.user_id + roles = ["ORG_OWNER"] } output "installed" { value = true - depends_on = [zitadel_org.default] + depends_on = [zitadel_org_member.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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" diff --git a/infra/modules/zitadel/tenant/role-owner/variables.tf b/infra/modules/zitadel/tenant/role-owner/variables.tf index f7674df..c5318a6 100644 --- a/infra/modules/zitadel/tenant/role-owner/variables.tf +++ b/infra/modules/zitadel/tenant/role-owner/variables.tf @@ -10,10 +10,14 @@ variable "wait_on" { default = true } -variable "name" { +variable "org_id" { type = string - description = "Name of the tenant" - default = "fourlights" + description = "Zitadel Organization ID" +} + +variable "user_id" { + type = string + description = "Zitadel User ID" } variable "jwt_profile_file" { diff --git a/infra/modules/zitadel/tenant/variables.tf b/infra/modules/zitadel/tenant/variables.tf index 5916ab1..f7674df 100644 --- a/infra/modules/zitadel/tenant/variables.tf +++ b/infra/modules/zitadel/tenant/variables.tf @@ -1,17 +1,7 @@ -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" +variable "domain" { type = string + description = "Domain for the zitadel instance" + default = "localhost" } variable "wait_on" { @@ -20,37 +10,13 @@ variable "wait_on" { default = true } -variable "namespace" { - type = string +variable "name" { + type = string + description = "Name of the tenant" + default = "fourlights" } -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 +variable "jwt_profile_file" { + type = string + description = "Path to the jwt profile file" } diff --git a/infra/modules/zitadel/values.yaml.tftpl b/infra/modules/zitadel/values.yaml.tftpl index 1a11e3f..47bc5ed 100644 --- a/infra/modules/zitadel/values.yaml.tftpl +++ b/infra/modules/zitadel/values.yaml.tftpl @@ -1,16 +1,26 @@ zitadel: masterkeySecretName: "zitadel" configmapConfig: - ExternalSecure: false - ExternalDomain: ${ external_domain } + Log: + Level: 'info' + LogStore: + Access: + Stdout: + Enabled: true + ExternalSecure: true + ExternalDomain: ${ service_uri } + ExternalPort: 443 TLS: Enabled: false - #ExternalPort: 443 - #ExternalSecurePort: 443 - #ExternalPathPrefix: ${ external_path_prefix } - #ExternalTLS: false - #ExternalTLSAllowInsecure: false - #ExternalTLSAllowInsecureSkipVerify: false + FirstInstance: + Org: + Machine: + Machine: + Username: zitadel-admin-sa + Name: Admin + MachineKey: + ExpirationDate: "2026-01-01T00:00:00Z" + Type: 1 Database: Postgres: Host: postgresql-hl.postgresql.svc.cluster.local @@ -22,14 +32,28 @@ zitadel: MaxConnIdleTime: 5m User: Username: ${ database_username } - PasswordSecret: postgresql-auth - PasswordSecretKey: password + Password: "${ database_password }" SSL: Mode: disable - Admin: + %{ if database_root_username != null }Admin: Username: ${ database_root_username } - PasswordSecret: postgresql-auth - PasswordSecretKey: root-password + Password: "${ database_root_password }" + SSL: + Mode: disable + %{ endif } + +readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 10 + +startupProbe: + periodSeconds: 5 + failureThreshold: 30 + +service: + annotations: + traefik.ingress.kubernetes.io/service.serversscheme: h2c ingress: enabled: true @@ -37,8 +61,8 @@ ingress: annotations: kubernetes.io/ingress.class: traefik traefik.ingress.kubernetes.io/router.entrypoints: web - %{ if displayOnHomepage } - gethomepage.dev/enabled: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-preserve-host-headers@kubernetescrd + %{ if display_on_homepage }gethomepage.dev/enabled: "true" gethomepage.dev/name: "Zitadel" gethomepage.dev/description: "Identity and Access Management" gethomepage.dev/group: "Tools" @@ -49,3 +73,4 @@ ingress: paths: - path: / pathType: Prefix + diff --git a/infra/modules/zitadel/variables.tf b/infra/modules/zitadel/variables.tf index 8f92245..68e3db6 100644 --- a/infra/modules/zitadel/variables.tf +++ b/infra/modules/zitadel/variables.tf @@ -26,12 +26,12 @@ variable "namespace" { variable "database" { type = string - default = "fusionauth" + default = "zitadel" } variable "database_username" { type = string - default = "fusionauth" + default = "zitadel" } variable "database_password" { @@ -49,3 +49,13 @@ variable "database_root_password" { sensitive = true default = null } + +variable "display_on_homepage" { + type = bool + default = false +} + +variable "enabled" { + type = bool + default = true +} diff --git a/shuttles/terraform-configure/main.tf b/shuttles/terraform-configure/main.tf deleted file mode 100644 index 58151c5..0000000 --- a/shuttles/terraform-configure/main.tf +++ /dev/null @@ -1,174 +0,0 @@ -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" -// } - diff --git a/shuttles/terraform-zitadel-bootstrap/.terraform.lock.hcl b/shuttles/terraform-zitadel-bootstrap/.terraform.lock.hcl new file mode 100644 index 0000000..287ac57 --- /dev/null +++ b/shuttles/terraform-zitadel-bootstrap/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/zitadel/zitadel" { + version = "2.0.2" + constraints = "2.0.2" + hashes = [ + "h1:iymeaNBrZ4smcr7eHrxO4gbXQ6bx/enKyj3RQ6xZRYA=", + "zh:01e16af0dda9372696b5e1d43ec709aed79829b49ee69a4f9606a248752f672d", + "zh:048c4e726fb846cfe9ab0a0a1f86d3f8922442154b086e2bd8e389b32f69f2f0", + "zh:3a3f6bea621c9d480f1f288cffebace8620979b9260cfeae8f9af5d9a25ed490", + "zh:4d349e584786589bc2037cee691ff1678296f5351e6491aa34dcb08ecbe1dcb7", + "zh:80741c78179788be8d7e33e471e1311197cd4e1067803d438463d0a8ac871a60", + "zh:89178d30f5ec49551e6a6ebc5eb589ab6631012dcec0d03ea7130b1029890e51", + "zh:94cd3b1fe3d1d39bcb3b70208b044bde4c5ce5152e12b29f0fa0ff1085e12863", + "zh:97299c172ada852705f8ca9fa91eeee12c6259263baae3ca53cf41e3130b1731", + "zh:a33d53acc640dc93b81352ba633cf392bc8c7614a72d320d59d3dcdb22d73fc4", + "zh:a95c15960baf8157f79a6490361455767d48e4dd3ce2ef1d0051743f6152733b", + "zh:ae66ad95c7039e6ef844c39389c9077ce7dbb501b6af02afb26a223fd289dbcb", + "zh:b8a9cb3b53653c06d52607368c406112ee1abc6d66dc4aedaedddbb46a66ea8f", + "zh:d48693ecdc985bb4167af0c3164240c13c4ea48167d28f706e7893cbdb20540a", + "zh:f6db1ec30bfbcf4423ab2d29979b775423ba37008fd48a766b5a1cf87a131859", + "zh:fed4e95dc9aaf361c8ff57f819d31fa25152b9e6cb90b7202d8be9ab1446b081", + ] +} diff --git a/shuttles/terraform-zitadel-bootstrap/main.tf b/shuttles/terraform-zitadel-bootstrap/main.tf new file mode 100644 index 0000000..aa8550f --- /dev/null +++ b/shuttles/terraform-zitadel-bootstrap/main.tf @@ -0,0 +1,115 @@ +locals { + tld = "fourlights.dev" + cluster_dns = "venus.${local.tld}" + domain = "zitadel.${local.cluster_dns}" + jwt_profile_file = "../terraform/zitadel-admin-sa.json" +} + + +module "zitadel-tenant" { + source = "../../infra/modules/zitadel/tenant" + + domain = local.domain + name = "fourlights" + jwt_profile_file = local.jwt_profile_file +} + +module "zitadel-idp-google" { + source = "../../infra/modules/zitadel/identity-provider/google" + wait_on = module.zitadel-tenant.installed + + domain = local.domain + jwt_profile_file = local.jwt_profile_file + org_id = module.zitadel-tenant.org_id + client_id = "783390190667-quvko2l2kr9ksgeo3pn6pn6t8c1mai9n.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" + } +} + +// TODO: Create default user thomas@fourlights.nl + +# module "zitadel-user" { +# source = "../../infra/modules/zitadel/user" +# wait_on = module.zitadel-idp-google.installed +# +# domain = local.domain +# org_id = module.zitadel-tenant.org_id +# jwt_profile_file = local.jwt_profile_file +# +# email = "thomas@fourlights.nl" +# idp_id = module.zitadel-idp-google.idp_id +# idp_user_id = "105558048282918392820" +# user_id = "308083708882059797" +# } +module "zitadel-owner" { + source = "../../infra/modules/zitadel/owner" + #wait_on = module.zitadel-user.installed + wait_on = module.zitadel-idp-google.installed + + domain = local.domain + org_id = module.zitadel-tenant.org_id + jwt_profile_file = local.jwt_profile_file + #user_id = module.zitadel-user.user_id + user_id = "308083708882059797" +} + +module "zitadel-org-owner" { + source = "../../infra/modules/zitadel/tenant/role-owner" + #wait_on = module.zitadel-user.installed + wait_on = module.zitadel-idp-google.installed + + domain = local.domain + org_id = module.zitadel-tenant.org_id + jwt_profile_file = local.jwt_profile_file + #user_id = module.zitadel-user.user_id + user_id = "308083708882059797" +} + +module "zitadel-project" { + source = "../../infra/modules/zitadel/tenant/role-owner" + #wait_on = module.zitadel-user.installed + wait_on = module.zitadel-idp-google.installed + + domain = local.domain + org_id = module.zitadel-tenant.org_id + jwt_profile_file = local.jwt_profile_file + #user_id = module.zitadel-user.user_id + user_id = "308083708882059797" +} + +#resource "zitadel_project" "default" { +# name = "365zon" +# org_id = module.zitadel-tenant.org_id +# 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_user_grant" "default" { +# project_id = data.zitadel_project.default.id +# org_id = data.zitadel_org.default.id +# role_keys = ["super-user"] +# user_id = data.zitadel_human_user.default.id +#} + +// 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" +// } + diff --git a/shuttles/terraform/.terraform.lock.hcl b/shuttles/terraform/.terraform.lock.hcl index 8c5ae0a..e232ef7 100644 --- a/shuttles/terraform/.terraform.lock.hcl +++ b/shuttles/terraform/.terraform.lock.hcl @@ -39,21 +39,41 @@ provider "registry.terraform.io/hashicorp/helm" { } provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.35.1" + version = "2.31.0" + constraints = "2.31.0" hashes = [ - "h1:Av0Wk8g2XjY2oap7nyWNHEgfCRfphdJvrkqJjEM2ZKM=", - "zh:12212ca5ae47823ce14bfafb909eeb6861faf1e2435fb2fc4a8b334b3544b5f5", - "zh:3f49b3d77182df06b225ab266667de69681c2e75d296867eb2cf06a8f8db768c", - "zh:40832494d19f8a2b3cd0c18b80294d0b23ef6b82f6f6897b5fe00248a9997460", - "zh:739a5ddea61a77925ee7006a29c8717377a2e9d0a79a0bbd98738d92eec12c0d", - "zh:a02b472021753627c5c39447a56d125a32214c29ff9108fc499f2dcdf4f1cc4f", - "zh:b78865b3867065aa266d6758c9601a2756741478f5735a838c20d633d65e085b", - "zh:d362e87464683f5632790e66920ea803adb54c2bc0cb24b6fd9a314d2b1efffd", - "zh:d98206fe88c2c9a52b8d2d0cb2c877c812a4a51d19f9d8428e63cbd5fd8a304d", - "zh:dfa320946b1ce3f3615c42b3447a28dc9f604c06d8b9a6fe289855ab2ade4d11", + "h1:wGHbATbv/pBVTST1MtEn0zyVhZbzZJD2NYq2EddASHY=", + "zh:0d16b861edb2c021b3e9d759b8911ce4cf6d531320e5dc9457e2ea64d8c54ecd", + "zh:1bad69ed535a5f32dec70561eb481c432273b81045d788eb8b37f2e4a322cc40", + "zh:43c58e3912fcd5bb346b5cb89f31061508a9be3ca7dd4cd8169c066203bcdfb3", + "zh:4778123da9206918a92dfa73cc711475d2b9a8275ff25c13a30513c523ac9660", + "zh:8bfa67d2db03b3bfae62beebe6fb961aee8d91b7a766efdfe4d337b33dfd23dd", + "zh:9020bb5729db59a520ade5e24984b737e65f8b81751fbbd343926f6d44d22176", + "zh:90431dbfc5b92498bfbce38f0b989978c84421a6c33245b97788a46b563fbd6e", + "zh:b71a061dda1244f6a52500e703a9524b851e7b11bbf238c17bbd282f27d51cb2", + "zh:d6232a7651b834b89591b94bf4446050119dcde740247e6083a4d55a2cefd28a", + "zh:d89fba43e699e28e2b5e92fff2f75fc03dbc8de0df9dacefe1a8836f8f430753", + "zh:ef85c0b744f5ba1b10dadc3c11e331ba4225c45bb733e024d7218c24b02b0512", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - "zh:fc1debd2e695b5222d2ccc8b24dab65baba4ee2418ecce944e64d42e79474cb5", - "zh:fdaf960443720a238c09e519aeb30faf74f027ac5d1e0a309c3b326888e031d7", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.5.2" + hashes = [ + "h1:JlMZD6nYqJ8sSrFfEAH0Vk/SL8WLZRmFaMUF9PJK5wM=", + "zh:136299545178ce281c56f36965bf91c35407c11897f7082b3b983d86cb79b511", + "zh:3b4486858aa9cb8163378722b642c57c529b6c64bfbfc9461d940a84cd66ebea", + "zh:4855ee628ead847741aa4f4fc9bed50cfdbf197f2912775dd9fe7bc43fa077c0", + "zh:4b8cd2583d1edcac4011caafe8afb7a95e8110a607a1d5fb87d921178074a69b", + "zh:52084ddaff8c8cd3f9e7bcb7ce4dc1eab00602912c96da43c29b4762dc376038", + "zh:71562d330d3f92d79b2952ffdda0dad167e952e46200c767dd30c6af8d7c0ed3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:805f81ade06ff68fa8b908d31892eaed5c180ae031c77ad35f82cb7a74b97cf4", + "zh:8b6b3ebeaaa8e38dd04e56996abe80db9be6f4c1df75ac3cccc77642899bd464", + "zh:ad07750576b99248037b897de71113cc19b1a8d0bc235eb99173cc83d0de3b1b", + "zh:b9f1c3bfadb74068f5c205292badb0661e17ac05eb23bfe8bd809691e4583d0e", + "zh:cc4cbcd67414fefb111c1bf7ab0bc4beb8c0b553d01719ad17de9a047adff4d1", ] } @@ -75,3 +95,26 @@ provider "registry.terraform.io/hashicorp/random" { "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", ] } + +provider "registry.terraform.io/zitadel/zitadel" { + version = "2.0.2" + constraints = "2.0.2" + hashes = [ + "h1:iymeaNBrZ4smcr7eHrxO4gbXQ6bx/enKyj3RQ6xZRYA=", + "zh:01e16af0dda9372696b5e1d43ec709aed79829b49ee69a4f9606a248752f672d", + "zh:048c4e726fb846cfe9ab0a0a1f86d3f8922442154b086e2bd8e389b32f69f2f0", + "zh:3a3f6bea621c9d480f1f288cffebace8620979b9260cfeae8f9af5d9a25ed490", + "zh:4d349e584786589bc2037cee691ff1678296f5351e6491aa34dcb08ecbe1dcb7", + "zh:80741c78179788be8d7e33e471e1311197cd4e1067803d438463d0a8ac871a60", + "zh:89178d30f5ec49551e6a6ebc5eb589ab6631012dcec0d03ea7130b1029890e51", + "zh:94cd3b1fe3d1d39bcb3b70208b044bde4c5ce5152e12b29f0fa0ff1085e12863", + "zh:97299c172ada852705f8ca9fa91eeee12c6259263baae3ca53cf41e3130b1731", + "zh:a33d53acc640dc93b81352ba633cf392bc8c7614a72d320d59d3dcdb22d73fc4", + "zh:a95c15960baf8157f79a6490361455767d48e4dd3ce2ef1d0051743f6152733b", + "zh:ae66ad95c7039e6ef844c39389c9077ce7dbb501b6af02afb26a223fd289dbcb", + "zh:b8a9cb3b53653c06d52607368c406112ee1abc6d66dc4aedaedddbb46a66ea8f", + "zh:d48693ecdc985bb4167af0c3164240c13c4ea48167d28f706e7893cbdb20540a", + "zh:f6db1ec30bfbcf4423ab2d29979b775423ba37008fd48a766b5a1cf87a131859", + "zh:fed4e95dc9aaf361c8ff57f819d31fa25152b9e6cb90b7202d8be9ab1446b081", + ] +} diff --git a/shuttles/terraform/main.tf b/shuttles/terraform/main.tf index 957d491..5a25254 100644 --- a/shuttles/terraform/main.tf +++ b/shuttles/terraform/main.tf @@ -6,6 +6,44 @@ locals { 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 @@ -32,6 +70,8 @@ module "minio" { admin = true ingressClass = "traefik" storageSize = "10Gi" + + displayOnHomepage = true } module "mongodb" { @@ -57,3 +97,36 @@ module "rabbitmq" { 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 +} diff --git a/shuttles/terraform/zitadel-admin-sa.json b/shuttles/terraform/zitadel-admin-sa.json old mode 100644 new mode 100755 index e69de29..2f69f87 --- a/shuttles/terraform/zitadel-admin-sa.json +++ b/shuttles/terraform/zitadel-admin-sa.json @@ -0,0 +1 @@ +{"type":"serviceaccount","keyId":"308082423731192134","key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA6/zPM5/433GWDALxbB5O7XlLWvdjEy1lBJITx73XZaoo23o1\nt89QOcACGCR4gIHUzN45GDsEF46n8QFzsZknYiL7Rz4din4q0UShxASD960hgmHT\ni443UgpvJBSoZdByzsXJq4BraoCQAQe0MiFagV+ELvF3Gl6vE/a24TpgfFrk+kLf\nHykXccllUNM+43RfjM+GI0GX5Ru5PUwsUMlgg2PRLHh70Yy+r/U9M9nRWuB4d2pR\neDs9WUM+LtsoyGcYLSIqzsj+dzD/zPOWDjDQjSK+QnsisWN86fZG4E+8fSEM6Vti\nv2gwQCBrquHFjYJx0M8IHkyMhmTUWO/X1/bDdwIDAQABAoIBAQCqo8K8BLfz8nFa\nPCKQWJYf924619nHOzLpjCtLaoW/WLx0f7kqMXlEWQfqpyyPV9IlVacZU0tRMXFU\nvwUGbcVhnAPw7wRzaWnSqnsCf3VhecpaOhy6s9pis3LMNzfRb1olFDYQkiqZ916p\nsAVnnmCQXh35x9aktcSJfgOddxXftIKARZdGzuPFL6q8xbk5TeJHqkrH5yh2bwH2\nDGdzv2Uet3DlNbTxj74LmFB08DbFZejWYko0iPSQTexZIF1OfgVzsrSyEzRUzVKS\nGyWSA1rt+pAiU/6OXzQziC9pp2prUleaiiMaDX1eKk7+Wnt2QYFgt2cj9rOwnjMX\nokzhhdH5AoGBAPu7TaXpAqOrlFeeNLR4oo0CuFhJouzlFS3nqN+7CdN0GGgG3fBJ\nwACPHJJ1nyAc+em1YW33adiBIaopl/McD1dWBjR6PHYTxcVhwy8ZR6zd2+ANjTxt\n4xWzesTo43HaL9CDgxijFuhu9p2K8qibPUH3bvt76BIY4LIi7q4wi4PTAoGBAO/9\nKk6THS88x+pT7Gaxa0bSbq4L08TD0Q+2bkI3rq5UpimkR5WOKOTPl2otBGtGozVb\nZ60VWmgjXRFnKTDZlAOUTPZoNo/EgHecgZ/cjDJVVw1UcGSmMDpAqc8yHMGN5aS3\n53Xkwla5Kd0eDTFlDH5upwzF14dQwum43OKFJk9NAoGAcLwzTAgMPIxMxOh/JguY\nkJoVQMTJiFoXoBVNVdUH04D8pSneHwyIRjfRTe4LM3CGo5mtZngVGPbLws8Z07BP\nVoeaA8pyZVb5jSn5JZCmvs4k+DRZeiSkPEXCx4icw5I5M6KSBWiUi8eV/nwJrGTJ\njE9pjoqxJdmqV1y5k5z9/i0CgYBqRJRjTslxjVyI6riXkKCML8pKz3nqezsr1gBk\n2ftDvsAFWHVKSDTbfQDzRxPZ3OGQUvVJs1bhHier+R5IP1BHdXfO9L6UUtMAJBFS\nFHsQHrH5eRZ7uwtIADIxSWNqYcb6dWTM04sqk7tx6ki1QqWRprXZ9hFGHgDxNaa5\nt3QLUQKBgQC2lAXCfWng3CXMLaLLOlc6zGe4M3wIfAiG4DCS8alFfkkxqnfYe628\n6kNlLwp8FUPdKrvWnQuTQMnn+Lleowi22Ii2yULVRK/KZPb+2GmrHxLUunlou2pm\noI5X9kOJafUP+Go+OiK0KbQnTE0UXUDwuihjQq59HGPO2AaEM9uYoA==\n-----END RSA PRIVATE KEY-----\n","expirationDate":"2026-01-01T00:00:00Z","userId":"308082423731126598"}