Compare commits

...

9 Commits
main ... guac

Author SHA1 Message Date
Dan Ankers 5ca172f4ff WIP: Federating FreeIPA and Keycloak 2023-11-02 20:13:52 +00:00
Dan Ankers 616e8d7f97 WIP: Federating FreeIPA and Keycloak 2023-10-24 07:48:00 +01:00
Dan Ankers d89ba200ba WIP: Federating FreeIPA and Keycloak 2023-10-23 21:53:05 +01:00
Daniel Ankers 630db7a880 WIP: FreeIPA needs to be created talking HTTPS to the backend 2023-10-20 17:19:04 +01:00
Daniel Ankers 2d6bae9ef8 Add ntfy 2023-10-20 16:15:38 +01:00
Dan Ankers d505b5d404 Add group membership in for Guac/Keycloak 2023-10-17 22:11:17 +01:00
Daniel Ankers 932ae6f332 Bring some Keycloak config into TF 2023-10-17 18:54:23 +01:00
Dan Ankers e78595e85f Keycloak database has got messed up -> Keycloak has got messed up -> Keycloak provider can't initialize until Keycloak is running. 2023-10-17 08:21:17 +01:00
Daniel Ankers 27d1b8434b Move Guacamole setup to Helm 2023-10-16 09:24:15 +01:00
2 changed files with 255 additions and 16 deletions

265
main.tf
View File

@ -20,7 +20,14 @@ terraform {
source = "techBeck03/guacamole" source = "techBeck03/guacamole"
version = "~> 1.4.1" version = "~> 1.4.1"
} }
freeipa = {
source = "rework-space-com/freeipa"
version = "4.0.0"
}
ldap = {
source = "l-with/ldap"
version = ">= 0.4"
}
} }
backend "kubernetes" { backend "kubernetes" {
secret_suffix = "tfstate" secret_suffix = "tfstate"
@ -46,9 +53,11 @@ provider "keycloak" {
} }
provider "guacamole" { provider "guacamole" {
url = "https://guacamole.${var.domain_suffix}/guacamole" url = "https://guac.${var.domain_suffix}/"
token = var.guacamole_token # token = var.guacamole_token
data_source = var.guacamole_datasource # data_source = var.guacamole_datasource
username = "guacadmin"
password = "guacadmin"
} }
provider "proxmox" { provider "proxmox" {
@ -58,6 +67,21 @@ provider "proxmox" {
pm_tls_insecure = true pm_tls_insecure = true
} }
provider "freeipa" {
host = "${helm_release.freeipa.name}.${var.domain_suffix}"
username = "admin"
password = var.freeipa_admin_password
insecure = true
}
provider "ldap" {
alias = "ldap_provisioner"
host = "${helm_release.freeipa.name}.${var.domain_suffix}"
bind_user = "admin"
bind_password = "${var.freeipa_ds_password}"
port = 389
}
resource "helm_release" "keycloak" { resource "helm_release" "keycloak" {
name = "keycloak" name = "keycloak"
namespace = var.keycloak_namespace namespace = var.keycloak_namespace
@ -83,6 +107,8 @@ resource "helm_release" "keycloak" {
auth: auth:
password: ${var.postgres_password} password: ${var.postgres_password}
proxy: edge proxy: edge
metrics:
enabled: true
EOT EOT
] ]
} }
@ -94,6 +120,59 @@ resource "keycloak_realm" "realm" {
default_signature_algorithm = "RS256" default_signature_algorithm = "RS256"
} }
resource "keycloak_user" "initial_keycloak_user" {
realm_id = keycloak_realm.realm.id
username = var.keycloak_user.username
enabled = true
email = var.keycloak_user.email
first_name = var.keycloak_user.firstname
last_name = var.keycloak_user.lastname
initial_password {
value = var.keycloak_user.password
temporary = false
}
}
resource "keycloak_group" "admin_group" {
realm_id = keycloak_realm.realm.id
name = "Admins"
}
resource "keycloak_user_groups" "initial_user_in_admin_group" {
exhaustive = false
realm_id = keycloak_realm.realm.id
user_id = keycloak_user.initial_keycloak_user.id
group_ids = [
keycloak_group.admin_group.id
]
}
resource "keycloak_openid_client_scope" "openid_client_scope" {
realm_id = keycloak_realm.realm.id
name = "groups"
description = "When requested, this scope will map a user's group memberships to a claim"
include_in_token_scope = true
gui_order = 1
}
resource "keycloak_openid_client" "proxmox_client" {
realm_id = keycloak_realm.realm.id
client_id = "dc-proxmox1"
enabled = true
access_type = "CONFIDENTIAL"
standard_flow_enabled = true
implicit_flow_enabled = true
client_secret = var.keycloak_proxmox_secret
valid_redirect_uris = [
"https://172.29.7.12:8006",
"https://172.29.7.15:8006"
]
}
resource "keycloak_openid_client" "gitea_client" { resource "keycloak_openid_client" "gitea_client" {
realm_id = keycloak_realm.realm.id realm_id = keycloak_realm.realm.id
client_id = "gitea" client_id = "gitea"
@ -149,6 +228,112 @@ resource "helm_release" "gitea" {
] ]
} }
resource "keycloak_openid_client" "guac_client" {
realm_id = keycloak_realm.realm.id
client_id = "guac"
enabled = true
access_type = "CONFIDENTIAL"
standard_flow_enabled = true
implicit_flow_enabled = true
valid_redirect_uris = [
"https://guac.${var.domain_suffix}/*"
]
}
resource "keycloak_openid_group_membership_protocol_mapper" "guac_group_membership_mapper" {
realm_id = keycloak_realm.realm.id
name = "groups"
claim_name = "groups"
client_id = keycloak_openid_client.guac_client.id
full_path = false
}
resource "random_password" "guac_db_pw" {
length = 16
special = false
}
resource "random_password" "guac_db_admin_pw" {
length = 16
special = false
}
resource "helm_release" "guacpg" {
name = "guacpg"
namespace = var.guac_namespace
repository = "https://charts.bitnami.com/bitnami/"
chart = "postgresql"
create_namespace = true
values = [
<<EOT
global:
storageClass: ${var.storageclass}
auth:
username: guacamole
password: ${random_password.guac_db_pw.result}
postgresPassword: ${random_password.guac_db_admin_pw.result}
database: guacamole
EOT
]
}
resource "helm_release" "guac" {
name = "guac"
namespace = var.guac_namespace
repository = "https://charts.beryju.org"
chart = "guacamole"
create_namespace = true
values = [
<<EOT
guacamole:
settings:
OPENID_AUTHORIZATION_ENDPOINT: https://keycloak.${var.domain_suffix}/realms/${var.keycloak_realm}/protocol/openid-connect/auth
OPENID_JWKS_ENDPOINT: https://keycloak.${var.domain_suffix}/realms/${var.keycloak_realm}/protocol/openid-connect/certs
OPENID_ISSUER: https://keycloak.${var.domain_suffix}/realms/${var.keycloak_realm}
OPENID_CLIENT_ID: ${keycloak_openid_client.guac_client.client_id}
OPENID_REDIRECT_URI: https://guac.${var.domain_suffix}/
ingress:
enabled: true
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: guac.${var.domain_suffix}
paths:
- /
tls:
- secretName: guac-tls
hosts:
- guac.${var.domain_suffix}
postgres:
hostname: guacpg-postgresql
password: ${random_password.guac_db_pw.result}
EOT
]
depends_on = [
helm_release.guacpg
]
}
resource "guacamole_connection_group" "routers" {
parent_identifier = "ROOT"
name = "Routers"
type = "organizational"
}
resource "guacamole_user_group" "admingroup" {
identifier = "Admins"
system_permissions = ["ADMINISTER"]
connection_groups = [
guacamole_connection_group.routers.id
]
attributes {
disabled = false
}
}
resource "keycloak_openid_client" "nautobot_client" { resource "keycloak_openid_client" "nautobot_client" {
realm_id = keycloak_realm.realm.id realm_id = keycloak_realm.realm.id
client_id = "nautobot" client_id = "nautobot"
@ -279,6 +464,8 @@ ingress:
- secretName: pushgw-tls - secretName: pushgw-tls
hosts: hosts:
- pushgw.${var.domain_suffix} - pushgw.${var.domain_suffix}
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
persistentVolume: persistentVolume:
enabled: true enabled: true
storageClass: ${var.storageclass} storageClass: ${var.storageclass}
@ -394,15 +581,16 @@ resource "helm_release" "grafana" {
resource "helm_release" "freeipa" { resource "helm_release" "freeipa" {
name = "freeipa" name = "freeipa"
namespace = var.freeipa_namespace namespace = var.freeipa_namespace
repository = "https://improwised.github.io/charts/" # repository = "https://improwised.github.io/charts/"
repository = "https://git.k8s.md1clv.im/api/packages/dan/helm"
chart = "freeipa" chart = "freeipa"
create_namespace = true create_namespace = true
values = [ values = [
<<EOT <<EOT
hostname: freeipa.${var.domain_suffix} hostname: freeipa.${var.domain_suffix}
args: args:
realm: MD1CLV.IM realm: ${var.ldap.realm}
domain: md1clv.im domain: ${var.ldap.domain}
dspassword: ${var.freeipa_ds_password} dspassword: ${var.freeipa_ds_password}
adminpassword: ${var.freeipa_admin_password} adminpassword: ${var.freeipa_admin_password}
nohostdns: true nohostdns: true
@ -417,7 +605,7 @@ ingress:
annotations: annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod cert-manager.io/cluster-issuer: letsencrypt-prod
tls: true tls: true
backendProtocol: http backendProtocol: https
service: service:
annotations: annotations:
traefik.ingress.kubernetes.io/service.serversscheme: https traefik.ingress.kubernetes.io/service.serversscheme: https
@ -426,6 +614,60 @@ EOT
] ]
} }
#resource "ldap_entry" "bind_user" {
# provider = ldap.ldap_provisioner
# dn = "uid=system,cn=sysaccounts,cn=etc,${var.ldap.base_dn}"
# data_json = jsonencode({
# objectClass = ["account","simplesecurityobject"]
# uid = [var.ldap.bind_user]
# userPassword= [var.ldap.bind_password]
# })
#}
# resource freeipa_user "freeipa_users" {
# first_name = var.keycloak_user.firstname
# last_name = var.keycloak_user.lastname
# name = var.keycloak_user.username
# telephone_numbers = [var.keycloak_user.phone]
# email_address = [var.keycloak_user.email]
# userpassword = var.keycloak_user.password
# }
resource "helm_release" "ntfy" {
name = "ntfy"
namespace = "ntfy"
repository = "https://charts.sarabsingh.com"
chart = "ntfy"
create_namespace = true
values = [
<<EOT
ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
hosts:
- host: ntfy.${var.domain_suffix}
paths:
- path: /
pathType: Prefix
tls:
- secretName: ntfy-tls
hosts:
- ntfy.${var.domain_suffix}
config:
enabled: true
data:
base-url: "https://ntfy.${var.domain_suffix}"
behind-proxy: true
persistence:
enabled: true
size: 500Mi
EOT
]
}
resource "random_integer" "proxmox_node" { resource "random_integer" "proxmox_node" {
min=1 min=1
max=2 max=2
@ -471,13 +713,6 @@ resource "proxmox_vm_qemu" "vyos_router" {
EOF EOF
} }
resource "guacamole_connection_group" "routers" {
parent_identifier = "ROOT"
name = "Routers"
type = "organizational"
}
resource "guacamole_connection_ssh" "vyos_vms" { resource "guacamole_connection_ssh" "vyos_vms" {
for_each = { for x in proxmox_vm_qemu.vyos_router: x.name => x } for_each = { for x in proxmox_vm_qemu.vyos_router: x.name => x }
name = each.value.name name = each.value.name

View File

@ -55,7 +55,11 @@ variable "proxmox_api_url" {
} }
variable "guacamole_datasource" { variable "guacamole_datasource" {
default = "mysql" default = "postgresql"
}
variable "guac_namespace" {
default = "guac"
} }
variable "ssh_key" { variable "ssh_key" {