feat(tenants): add tenant-specific configurations
- Add tenant configuration for 365zon - Configure Zitadel integration for ArgoCD - Add Fourlights tenant Zitadel configuration
This commit is contained in:
parent
f17e210f3e
commit
ed1eef9db0
|
|
@ -0,0 +1,56 @@
|
|||
locals {
|
||||
name = "365Zon"
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "tenant" {
|
||||
metadata {
|
||||
name = lower(local.name)
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [metadata]
|
||||
}
|
||||
}
|
||||
|
||||
module "bootstrap-zitadel" {
|
||||
source = "./zitadel"
|
||||
|
||||
namespace = kubernetes_namespace.tenant.metadata[0].name
|
||||
org_id = var.org_id
|
||||
user_id = var.user_id
|
||||
name = local.name
|
||||
}
|
||||
|
||||
// create uploads bucket in minio
|
||||
|
||||
// create minio secret
|
||||
resource "kubernetes_secret" "storage" {
|
||||
metadata {
|
||||
name = "storage"
|
||||
namespace = kubernetes_namespace.tenant.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
Storage__AccountName = var.minio_access_key
|
||||
Storage__AccountKey = var.minio_secret_key
|
||||
Storage__BlobUri = var.minio_service_uri
|
||||
Storage__S3BucketName = "uploads"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "connection_strings" {
|
||||
metadata {
|
||||
name = "connection-strings"
|
||||
namespace = kubernetes_namespace.tenant.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
ConnectionStrings__DocumentDb = var.mongodb_connection_string
|
||||
ConnectionStrings__ServiceBus = var.rabbitmq_connection_string
|
||||
}
|
||||
}
|
||||
|
||||
// okay, so now we have the identity stuff in order, and we have secrets to use for that
|
||||
// next, we need to set-up:
|
||||
// - the wildcard tls (*.365zon.venus.fourlights.dev)
|
||||
// - argocd for all relevant apps
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
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
|
||||
}
|
||||
|
||||
locals {
|
||||
k8s_config_path = format("%s/%s", path.root, "../kubeconfig")
|
||||
k8s_config_yaml = file(local.k8s_config_path)
|
||||
k8s_config = yamldecode(local.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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
variable "domain" { type = string }
|
||||
variable "jwt_profile_file" { type = string }
|
||||
variable "org_id" { type = string }
|
||||
variable "user_id" { type = string }
|
||||
variable "minio_access_key" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
variable "minio_secret_key" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
variable "minio_service_uri" { type = string }
|
||||
variable "mongodb_connection_string" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
variable "rabbitmq_connection_string" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
locals {
|
||||
tld = "fourlights.dev"
|
||||
cluster_dns = "venus.${local.tld}"
|
||||
domain = "zitadel.${local.cluster_dns}"
|
||||
org_domain = "fourlights.${local.domain}"
|
||||
}
|
||||
|
||||
module "zitadel_project" {
|
||||
source = "../../../modules/zitadel/project"
|
||||
|
||||
org_id = var.org_id
|
||||
name = var.name
|
||||
owners = [var.user_id]
|
||||
}
|
||||
|
||||
// TODO: add action for setting roles as scopes
|
||||
|
||||
module "zitadel_project_operator_roles" {
|
||||
source = "../../../modules/zitadel/project/roles"
|
||||
|
||||
wait_on = [module.zitadel_project.installed]
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
group = "Operator"
|
||||
roles = [
|
||||
"manage:profiles", "manage:contacts", "manage:addresses", "manage:enquiries", "manage:flowstates",
|
||||
"manage:flowevents", "manage:files"
|
||||
]
|
||||
}
|
||||
|
||||
module "zitadel_project_configurator_roles" {
|
||||
source = "../../../modules/zitadel/project/roles"
|
||||
wait_on = [module.zitadel_project_operator_roles.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
group = "Configurator"
|
||||
roles = [
|
||||
"manage:brands", "manage:flows"
|
||||
]
|
||||
}
|
||||
|
||||
module "zitadel_project_developer_roles" {
|
||||
source = "../../../modules/zitadel/project/roles"
|
||||
wait_on = [module.zitadel_project_configurator_roles.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
group = "Developer"
|
||||
roles = [
|
||||
"manage:jobs", "manage:infrastructure"
|
||||
]
|
||||
}
|
||||
|
||||
module "zitadel_project_user_grant" {
|
||||
source = "../../../modules/zitadel/project/user-grant"
|
||||
wait_on = [module.zitadel_project_developer_roles.installed]
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
user_id = var.user_id
|
||||
roles = concat(module.zitadel_project_developer_roles.roles, module.zitadel_project_configurator_roles.roles, module.zitadel_project_operator_roles.roles)
|
||||
}
|
||||
|
||||
// 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" {
|
||||
source = "../../../modules/zitadel/api-m2m-swagger"
|
||||
wait_on = [module.zitadel_project_user_grant.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
|
||||
name = "Core"
|
||||
zitadel_domain = local.domain
|
||||
cluster_domain = local.cluster_dns
|
||||
|
||||
namespace = var.namespace
|
||||
project = var.name
|
||||
|
||||
service_account = false
|
||||
roles = []
|
||||
}
|
||||
|
||||
module "zitadel_project_application_salesforce" {
|
||||
source = "../../../modules/zitadel/api-m2m-swagger"
|
||||
wait_on = [module.zitadel_project_application_core.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
|
||||
name = "Salesforce"
|
||||
zitadel_domain = local.domain
|
||||
cluster_domain = local.cluster_dns
|
||||
|
||||
namespace = var.namespace
|
||||
project = var.name
|
||||
|
||||
roles = module.zitadel_project_operator_roles.roles
|
||||
}
|
||||
|
||||
module "zitadel_project_application_external" {
|
||||
source = "../../../modules/zitadel/api-m2m-swagger"
|
||||
wait_on = [module.zitadel_project_application_salesforce.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
|
||||
name = "External"
|
||||
zitadel_domain = local.domain
|
||||
cluster_domain = local.cluster_dns
|
||||
|
||||
namespace = var.namespace
|
||||
project = var.name
|
||||
|
||||
roles = module.zitadel_project_operator_roles.roles
|
||||
}
|
||||
|
||||
module "zitadel_project_application_module_internal" {
|
||||
source = "../../../modules/zitadel/api-m2m-swagger"
|
||||
wait_on = [module.zitadel_project_application_external.installed]
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
|
||||
name = "Internal"
|
||||
zitadel_domain = local.domain
|
||||
cluster_domain = local.cluster_dns
|
||||
|
||||
namespace = var.namespace
|
||||
project = var.name
|
||||
|
||||
roles = module.zitadel_project_operator_roles.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_id" {
|
||||
value = var.org_id
|
||||
}
|
||||
|
||||
output "project_id" {
|
||||
value = module.zitadel_project.project_id
|
||||
}
|
||||
|
||||
output "installed" {
|
||||
value = true
|
||||
depends_on = [module.zitadel_project_application_external.installed]
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
zitadel = {
|
||||
source = "zitadel/zitadel"
|
||||
version = "2.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
variable "org_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "user_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "namespace" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
type = string
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* sets the roles an additional claim in the token with roles as value an project as key
|
||||
*
|
||||
* The role claims of the token look like the following:
|
||||
*
|
||||
* // added by the code below
|
||||
* "groups": ["{roleName}", "{roleName}", ...],
|
||||
*
|
||||
* Flow: Complement token, Triggers: Pre Userinfo creation, Pre access token creation
|
||||
*
|
||||
* @param ctx
|
||||
* @param api
|
||||
*/
|
||||
function groupsClaim(ctx, api) {
|
||||
if (ctx.v1.user.grants === undefined || ctx.v1.user.grants.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let grants = [];
|
||||
ctx.v1.user.grants.grants.forEach((claim) => {
|
||||
claim.roles.forEach((role) => {
|
||||
grants.push(role);
|
||||
});
|
||||
});
|
||||
|
||||
api.v1.claims.setClaim("groups", grants);
|
||||
api.v1.claims.setClaim("scope", grants);
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
locals {
|
||||
argocd_uri = "https://${var.argocd_service_domain}"
|
||||
}
|
||||
|
||||
module "zitadel_project" {
|
||||
source = "../../../modules/zitadel/project"
|
||||
|
||||
org_id = var.org_id
|
||||
name = var.name
|
||||
owners = [var.user_id]
|
||||
}
|
||||
|
||||
module "zitadel_project_roles_user" {
|
||||
source = "../../../modules/zitadel/project/roles"
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
group = "Users"
|
||||
roles = ["user"]
|
||||
}
|
||||
|
||||
module "zitadel_project_roles_admin" {
|
||||
source = "../../../modules/zitadel/project/roles"
|
||||
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
group = "Admins"
|
||||
roles = ["admin"]
|
||||
}
|
||||
|
||||
module "zitadel_application_argocd" {
|
||||
source = "../../../modules/zitadel/project/application/web"
|
||||
|
||||
name = "ArgoCD"
|
||||
org_id = var.org_id
|
||||
project_id = module.zitadel_project.project_id
|
||||
|
||||
redirect_uris = ["${ local.argocd_uri}/api/dex/callback"]
|
||||
post_logout_redirect_uris = [local.argocd_uri]
|
||||
|
||||
auth_method_type = "OIDC_AUTH_METHOD_TYPE_BASIC"
|
||||
id_token_role_assertion = true
|
||||
id_token_userinfo_assertion = true
|
||||
}
|
||||
|
||||
resource "zitadel_action" "groups-claim" {
|
||||
org_id = var.org_id
|
||||
name = "groupsClaim"
|
||||
script = templatefile("${path.module}/groupsClaim.action.tftpl", {})
|
||||
allowed_to_fail = true
|
||||
timeout = "10s"
|
||||
}
|
||||
|
||||
resource "zitadel_trigger_actions" "groups-claim-pre-user-info" {
|
||||
org_id = var.org_id
|
||||
flow_type = "FLOW_TYPE_CUSTOMISE_TOKEN"
|
||||
trigger_type = "TRIGGER_TYPE_PRE_USERINFO_CREATION"
|
||||
action_ids = [zitadel_action.groups-claim.id]
|
||||
}
|
||||
|
||||
resource "zitadel_trigger_actions" "groups-claim-pre-access-token" {
|
||||
org_id = var.org_id
|
||||
flow_type = "FLOW_TYPE_CUSTOMISE_TOKEN"
|
||||
trigger_type = "TRIGGER_TYPE_PRE_ACCESS_TOKEN_CREATION"
|
||||
action_ids = [zitadel_action.groups-claim.id]
|
||||
}
|
||||
|
||||
module "zitadel_project_user_grant" {
|
||||
source = "../../../modules/zitadel/project/user-grant"
|
||||
|
||||
org_id = var.org_id
|
||||
|
||||
project_id = module.zitadel_project.project_id
|
||||
user_id = var.user_id
|
||||
|
||||
roles = module.zitadel_project_roles_admin.roles
|
||||
}
|
||||
|
||||
output "client_id" {
|
||||
value = module.zitadel_application_argocd.client_id
|
||||
}
|
||||
|
||||
output "client_secret" {
|
||||
value = module.zitadel_application_argocd.client_secret
|
||||
}
|
||||
|
||||
output "scopes" {
|
||||
value = ["openid", "profile", "email", "groups"]
|
||||
}
|
||||
|
||||
output "logoutSuffix" {
|
||||
value = "oidc/v1/end_session"
|
||||
}
|
||||
|
||||
output "user_roles" {
|
||||
value = module.zitadel_project_roles_user.roles
|
||||
}
|
||||
|
||||
output "admin_roles" {
|
||||
value = module.zitadel_project_roles_admin.roles
|
||||
}
|
||||
|
||||
output "project_id" {
|
||||
value = module.zitadel_project.project_id
|
||||
}
|
||||
|
||||
output "installed" {
|
||||
value = true
|
||||
depends_on = [
|
||||
module.zitadel_project_user_grant.installed,
|
||||
zitadel_trigger_actions.groups-claim-pre-access-token, zitadel_trigger_actions.groups-claim-pre-user-info
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
variable "org_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "user_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
type = string
|
||||
default = "argocd"
|
||||
}
|
||||
|
||||
variable "domain" { type = string }
|
||||
variable "jwt_profile_file" { type = string }
|
||||
|
||||
variable "argocd_service_domain" { type = string }
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
module "zitadel-tenant" {
|
||||
source = "../../../modules/zitadel/tenant"
|
||||
|
||||
name = "fourlights"
|
||||
}
|
||||
|
||||
module "zitadel-idp-google" {
|
||||
source = "../../../modules/zitadel/identity-provider/google"
|
||||
wait_on = module.zitadel-tenant.installed
|
||||
|
||||
org_id = module.zitadel-tenant.org_id
|
||||
client_id = "783390190667-quvko2l2kr9ksgeo3pn6pn6t8c1mai9n.apps.googleusercontent.com"
|
||||
client_secret = "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"
|
||||
|
||||
domain = var.domain
|
||||
|
||||
options = {
|
||||
scopes = ["openid", "profile", "email"]
|
||||
is_auto_creation = true
|
||||
is_auto_update = true
|
||||
is_creation_allowed = true
|
||||
is_linking_allowed = true
|
||||
|
||||
auto_linking = "AUTO_LINKING_OPTION_USERNAME"
|
||||
}
|
||||
}
|
||||
|
||||
module "zitadel-user" {
|
||||
source = "../../../modules/zitadel/user"
|
||||
wait_on = module.zitadel-tenant.installed
|
||||
|
||||
org_id = module.zitadel-tenant.org_id
|
||||
|
||||
first_name = "Thomas"
|
||||
last_name = "Rijpstra"
|
||||
user_name = "thomas@fourlights.nl"
|
||||
email = "thomas@fourlights.nl"
|
||||
}
|
||||
|
||||
module "zitadel-org-owner" {
|
||||
source = "../../../modules/zitadel/tenant/role-owner"
|
||||
wait_on = module.zitadel-user.installed
|
||||
|
||||
org_id = module.zitadel-tenant.org_id
|
||||
user_id = module.zitadel-user.user_id
|
||||
}
|
||||
|
||||
output "org_id" {
|
||||
value = module.zitadel-tenant.org_id
|
||||
}
|
||||
|
||||
output "user_id" {
|
||||
value = module.zitadel-user.user_id
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
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
|
||||
}
|
||||
|
||||
locals {
|
||||
k8s_config_path = format("%s/%s", path.root, "../kubeconfig")
|
||||
k8s_config_yaml = file(local.k8s_config_path)
|
||||
k8s_config = yamldecode(local.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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
variable "domain" { type = string }
|
||||
variable "jwt_profile_file" { type = string }
|
||||
Loading…
Reference in New Issue