add keycloak

This commit is contained in:
James Andariese 2023-12-19 16:19:09 -06:00
parent 3f4f1b3291
commit d9b5335739
34 changed files with 735 additions and 5 deletions

81
gitea/cm.yaml Normal file
View File

@ -0,0 +1,81 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-config
namespace: gitea
data:
GITEA____APP_NAME: "git@CASCADE"
GITEA____RUN_MODE: "prod"
GITEA____RUN_USER: "git"
GITEA____WORK_PATH: "/app/gitea"
MINIO__server__ROOT_URL: https://git.strudelline.net/
MINIO__server__DOMAIN: git.strudelline.net
GITEA__actions__DEFAULT_ACTIONS_URL: "https://github.com"
GITEA__actions__ENABLED: "true"
GITEA__attachment__PATH: "/data/gitea/attachments"
GITEA__cron__update_checker__ENABLED: "true"
GITEA__database__CHARSET: "utf8"
GITEA__database__DB_TYPE: "sqlite3"
GITEA__database__HOST: "localhost:3306"
GITEA__database__LOG_SQL: "false"
GITEA__database__NAME: "gitea"
GITEA__database__PASSWD: ""
GITEA__database__PATH: "/data/gitea/gitea.db"
GITEA__database__SCHEMA: ""
GITEA__database__SSL_MODE: "disable"
GITEA__database__USER: "root"
GITEA__indexer__ISSUE_INDEXER_PATH: "/data/gitea/indexers/issues.bleve"
GITEA__lfs__PATH: "/data/git/lfs"
GITEA__log__LEVEL: "info"
GITEA__log__MODE: "console"
GITEA__log__ROOT_PATH: "/data/gitea/log"
GITEA__openid__ENABLE_OPENID_SIGNIN: "true"
GITEA__openid__ENABLE_OPENID_SIGNUP: "false"
GITEA__picture__AVATAR_UPLOAD_PATH: "/data/gitea/avatars"
GITEA__picture__REPOSITORY_AVATAR_UPLOAD_PATH: "/data/gitea/repo-avatars"
GITEA__repository__ROOT: "/data/git/repositories"
GITEA__repository__local__LOCAL_COPY_PATH: "/data/gitea/tmp/local-repo"
GITEA__repository__pull-request__DEFAULT_MERGE_STYLE: "merge"
GITEA__repository__signing__DEFAULT_TRUST_MODEL: "committer"
GITEA__repository__upload__TEMP_PATH: "/data/gitea/uploads"
GITEA__security__INSTALL_LOCK: "true"
GITEA__security__PASSWORD_HASH_ALGO: "pbkdf2"
GITEA__security__REVERSE_PROXY_LIMIT: "1"
GITEA__security__REVERSE_PROXY_TRUSTED_PROXIES: "*"
GITEA__server__APP_DATA_PATH: "/data/gitea"
GITEA__server__DISABLE_SSH: "false"
GITEA__server__DOMAIN: "git.strudelline.net"
GITEA__server__HTTP_PORT: "3000"
GITEA__server__LFS_START_SERVER: "true"
GITEA__server__OFFLINE_MODE: "false"
GITEA__server__ROOT_URL: "https://git.strudelline.net/"
GITEA__server__SSH_DOMAIN: "git-ssh.strudelline.net"
GITEA__server__SSH_LISTEN_PORT: "2222"
GITEA__server__SSH_PORT: "2222"
GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION: "false"
GITEA__service__DEFAULT_ALLOW_CREATE_ORGANIZATION: "true"
GITEA__service__DEFAULT_ENABLE_TIMETRACKING: "true"
GITEA__service__DEFAULT_KEEP_EMAIL_PRIVATE: "false"
GITEA__service__DISABLE_REGISTRATION: "true"
GITEA__service__ENABLE_CAPTCHA: "false"
GITEA__service__ENABLE_NOTIFY_MAIL: "false"
GITEA__service__NO_REPLY_ADDRESS: "noreply.localhost"
GITEA__service__REGISTER_EMAIL_CONFIRM: "false"
GITEA__service__REQUIRE_SIGNIN_VIEW: "false"
GITEA__session__PROVIDER: "file"
GITEA__session__PROVIDER_CONFIG: "/data/gitea/sessions"

View File

@ -4,11 +4,35 @@ metadata:
name: keycloak-cascade
namespace: keycloak
spec:
ingressClassName: istio
ingressClassName: haproxy
rules:
- host: auth.werts.us
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy
port:
name: http
- path: /
pathType: Prefix
backend:
service:
name: cascade-service
port:
number: 80
- host: auth.strudelline.net
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy
port:
name: http
- path: /
pathType: Prefix
backend:
@ -16,7 +40,3 @@ spec:
name: cascade-service
port:
number: 80
tls:
- hosts:
- auth.werts.us
secretName: wildcard-tls

View File

@ -141,6 +141,10 @@ spec:
- mountPath: /opt/keycloak/themes
name: themes
dnsPolicy: ClusterFirst
hostAliases:
- hostnames:
- cascade.strudelline.net
ip: 172.16.34.1
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}

View File

@ -0,0 +1,70 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: oauth2-proxy
name: oauth2-proxy
namespace: keycloak
spec:
replicas: 3
selector:
matchLabels:
app: oauth2-proxy
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: oauth2-proxy
spec:
containers:
- args:
- --http-address=0.0.0.0:4180
- --config=/config.cfg
image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /ping
port: http
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: oauth2-proxy
ports:
- containerPort: 4180
name: http
protocol: TCP
volumeMounts:
- mountPath: /config.cfg
name: oauth2-proxy-config
subPath: oauth2-proxy.cfg
terminationGracePeriodSeconds: 2
volumes:
- name: oauth2-proxy-config
secret:
defaultMode: 420
optional: false
secretName: oauth2-proxy-oidc-secret
---
apiVersion: v1
kind: Service
metadata:
labels:
app: oauth2-proxy
name: oauth2-proxy
namespace: keycloak
spec:
ports:
- name: http
port: 4180
protocol: TCP
targetPort: 4180
selector:
app: oauth2-proxy

2
keycloak/tf/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.backup
*.tfstate

View File

@ -0,0 +1,15 @@
module "werts_appwrite_cloud_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "appwrite_cloud"
keepers = { epoch = 1 }
redirect_uris = ["https://cloud.appwrite.io/v1/account/sessions/oauth2/callback/oidc/6514da21c115f4a89bcd"]
vault_secret_name = "k8s-ns/appwrite_cloud/werts-oidc"
}
output "appwrite_cloud_client_id" {
value = module.werts_appwrite_cloud_oidc_client
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_budibase_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "budibase"
keepers = { epoch = 1 }
redirect_uris = ["https://bb.strudelline.net/api/global/auth/oidc/callback"]
vault_secret_name = "k8s-ns/budibase/werts-oidc"
}
output "budibase_client_id" {
value = module.werts_budibase_oidc_client
sensitive = true
}

View File

@ -0,0 +1,13 @@
module "werts_concourse_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "concourse"
keepers = { epoch = 1 }
redirect_uris = ["https://cc.strudelline.net/*"]
}
output "concourse_client_id" {
value = module.werts_concourse_oidc_client
sensitive = true
}

View File

@ -0,0 +1,13 @@
module "werts_debugger_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "debugger"
keepers = { epoch = 1 }
redirect_uris = ["https://debug.werts.us/*"]
}
output "debugger_client_id" {
value = module.werts_debugger_oidc_client
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "client_frigate" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "frigate"
keepers = { epoch = 1 }
redirect_uris = ["https://frigate.strudelline.net/oauth2/callback"]
kubernetes_secret_name = "oidc-client"
kubernetes_secret_namespace = "frigate"
}
output "frigate_client_id" {
value = module.client_frigate
sensitive = true
}

View File

@ -0,0 +1,13 @@
module "client_gitea" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "gitea"
keepers = { epoch = 1 }
redirect_uris = ["https://git.strudelline.net/user/oauth2/werts/callback"]
}
output "gitea_client_id" {
value = module.client_gitea
sensitive = true
}

View File

@ -0,0 +1,13 @@
module "client_grafana" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "grafana"
keepers = { epoch = 1 }
redirect_uris = ["https://grafana.strudelline.net/login/generic_oauth"]
}
output "grafana_client_id" {
value = module.client_grafana
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_grist_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "grist"
keepers = { epoch = 1 }
redirect_uris = ["https://grist.strudelline.net/oauth2/callback"]
vault_secret_name = "k8s-ns/grist/werts-oidc"
}
output "grist_client_id" {
value = module.werts_grist_oidc_client
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "werts_harbor_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "harbor"
keepers = { epoch = 1 }
# vvvvvvvvvvvvvvv REMEMBER TO CHANGE THE REDIRECT vvvvvvvvvvvvvvv
redirect_uris = ["https://harbor.strudelline.net/*"]
kubernetes_secret_name = "oidc-client"
}
output "harbor_client_id" {
value = module.werts_harbor_oidc_client
sensitive = true
}

View File

@ -0,0 +1,13 @@
module "client_jenkins" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "jenkins"
keepers = { epoch = 1 }
redirect_uris = ["https://jenkins.strudelline.net/securityRealm/finishLogin"]
}
output "jenkins_client_id" {
value = module.client_jenkins
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "client_longhorn" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "longhorn"
keepers = { epoch = 1 }
redirect_uris = ["https://longhorn.strudelline.net/oauth2/callback"]
kubernetes_secret_name = "oidc-client"
kubernetes_secret_namespace = "longhorn-system"
}
output "longhorn" {
value = module.client_longhorn
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_mastodon_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "mastodon"
keepers = { epoch = 1 }
redirect_uris = ["https://mastodon.werts.us/auth/auth/openid_connect/callback"]
vault_secret_name = "k8s-ns/mastodon/werts-oidc"
}
output "mastodon_client_id" {
value = module.werts_mastodon_oidc_client
sensitive = true
}

View File

@ -0,0 +1,18 @@
module "werts_matrix_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "matrix"
keepers = { epoch = 1 }
redirect_uris = ["https://chat.werts.us/_synapse/client/oidc/callback"]
vault_secret_name = "k8s-ns/synapse/werts-oidc"
backchannel_logout_url = "https://chat.werts.us/_synapse/client/oidc/backchannel_logout"
backchannel_logout_session_required = true
}
output "matrix_client_id" {
value = module.werts_matrix_oidc_client
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_minio_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "minio"
keepers = { epoch = 1 }
redirect_uris = ["https://minio-admin.strudelline.net/oauth_callback"]
vault_secret_name = "noctowl-docker-services/minio/werts-oidc"
}
output "minio_client_id" {
value = module.werts_minio_oidc_client
sensitive = true
}

View File

@ -0,0 +1,10 @@
module "werts_nodered1_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "node-red-1"
keepers = { epoch = 1 }
redirect_uris = ["https://red-1.werts.us/oauth2/callback"]
vault_secret_name = "k8s-ns/node-red/node-red-1-werts-oidc"
}

View File

@ -0,0 +1,19 @@
module "werts_oauth_proxy_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "oauthproxy"
keepers = { epoch = 1 }
redirect_uris = [
"https://auth.werts.us/oauth2/callback",
"https://auth.strudelline.net/oauth2/callback",
]
kubernetes_secret_name = "oidc-client"
kubernetes_secret_namespace = "keycloak"
}
output "oauth_proxy_client_id" {
value = module.werts_oauth_proxy_oidc_client
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_peertube_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "peertube"
keepers = { epoch = 1 }
redirect_uris = ["https://tube.werts.us/plugins/auth-openid-connect/router/code-cb"]
vault_secret_name = "k8s-ns/peertube/werts-oidc"
}
output "peertube_client_id" {
value = module.werts_peertube_oidc_client
sensitive = true
}

View File

@ -0,0 +1,15 @@
module "werts_pleroma_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "pleroma"
keepers = { epoch = 1 }
redirect_uris = ["http://toots.werts.us/oauth/keycloak/callback"]
#vault_secret_name = "k8s-ns/pleroma/werts-oidc"
}
output "pleroma_client_id" {
value = module.werts_pleroma_oidc_client
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "client_tubearchivist" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "tubearchivist"
keepers = { epoch = 1 }
redirect_uris = ["https://tubearchivist.strudelline.net/oauth2/callback"]
kubernetes_secret_name = "oidc-client"
kubernetes_secret_namespace = "tubearchivist"
}
output "tubearchivist" {
value = module.client_tubearchivist
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "client_tubesync" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "tubesync"
keepers = { epoch = 1 }
redirect_uris = ["https://tubesync.strudelline.net/oauth2/callback"]
kubernetes_secret_name = "oidc-client"
kubernetes_secret_namespace = "tubesync"
}
output "tubesync" {
value = module.client_tubesync
sensitive = true
}

View File

@ -0,0 +1,14 @@
module "k8s_windmill_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "k8s-windmill"
keepers = { epoch = 1 }
# vvvvvvvvvvvvvvv REMEMBER TO CHANGE THE REDIRECT vvvvvvvvvvvvvvv
redirect_uris = ["https://windmill.strudelline.net/user/login_callback/keycloak"]
}
output "k8s_windmill_client_id" {
value = module.k8s_windmill_oidc_client
sensitive = true
}

View File

@ -0,0 +1,16 @@
module "werts_windmill_oidc_client" {
source = "./oidc-client"
realm_id = keycloak_realm.werts.id
client_id = "windmill"
keepers = { epoch = 1 }
# vvvvvvvvvvvvvvv REMEMBER TO CHANGE THE REDIRECT vvvvvvvvvvvvvvv
redirect_uris = ["https://windmill.strudelline.net/user/login_callback/keycloak_werts"]
vault_secret_name = "k8s-ns/windmill/werts-oidc"
}
output "windmill_client_id" {
value = module.werts_windmill_oidc_client
sensitive = true
}

8
keycloak/tf/main.tf Normal file
View File

@ -0,0 +1,8 @@
#resource "keycloak_realm" "master" {
# realm = "master"
# enabled = true
#
# default_signature_algorithm = "RS256"
# display_name = "Keycloak"
# display_name_html = "<div class=\"kc-logo-text\"><span>Keycloak</span></div>"
#}

View File

@ -0,0 +1,12 @@
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
version = "~> 4.2"
}
#vault = {
# source = "hashicorp/vault"
# version = "~> 3.14"
#}
}
}

View File

@ -0,0 +1,118 @@
variable "realm_id" { }
variable "client_id" { }
variable "client_name" { default = "" }
variable "client_secret" {
type = string
default = ""
description = "sets client_secret if set. a random 128 digit secret will be generated if this is not set or set to an empty string. this secret is very long because of the lack of specials."
}
variable "keepers" {
type = map
default = {}
description = "keepers used to determine when to rotate a random client_secret. only used if client_secret is unset."
}
variable "redirect_uris" {
type = list(string)
default = []
}
variable "vault_kv_path" {
default = "kvv2"
}
variable "vault_secret_name" {
description = "secret object name (path-like thing in kvv2, not secret object key either -- those are client_id and client_secret)"
type = string
default = ""
}
variable "backchannel_logout_url" { default = "" }
variable "backchannel_logout_session_required" { default = false }
variable "secret_metadata" {
type = map
default = {}
}
resource "random_password" "client_secret" {
keepers = var.keepers
count = var.client_secret == "" ? 1 : 0
special = false
length = 86 # 62**86 > 2**512 (but 62**85 is not)
}
variable "kubernetes_secret_name" {
default = ""
}
variable "kubernetes_secret_namespace" {
default = ""
}
variable "kubernetes_secret_client_id_key" {
default = "client_id"
}
variable "kubernetes_secret_client_secret_key" {
default = "client_secret"
}
locals {
client_name = var.client_name == "" ? var.client_id : var.client_name
client_secret = var.client_secret == "" ? random_password.client_secret.0.result : var.client_secret
kubernetes_secret_namespace = var.kubernetes_secret_namespace == "" ? local.client_name : var.kubernetes_secret_namespace
}
resource "keycloak_openid_client" "openid_client" {
realm_id = var.realm_id
client_id = var.client_id
client_secret = local.client_secret
name = local.client_name
enabled = true
standard_flow_enabled = true
access_type = "CONFIDENTIAL"
valid_redirect_uris = var.redirect_uris
backchannel_logout_url = var.backchannel_logout_url
backchannel_logout_session_required = var.backchannel_logout_session_required
login_theme = "keycloak"
}
#resource "vault_kv_secret_v2" "oidc_client" {
# count = var.vault_secret_name == "" ? 0 : 1
# mount = var.vault_kv_path
# name = var.vault_secret_name
# data_json = jsonencode(
# {
# client_id = keycloak_openid_client.openid_client.client_id
# client_secret = keycloak_openid_client.openid_client.client_secret
# }
# )
# custom_metadata {
# data = var.secret_metadata
# }
#}
resource "kubernetes_secret" "oidc_client" {
count = var.kubernetes_secret_name == "" ? 0 : 1
metadata {
name = var.kubernetes_secret_name
namespace = local.kubernetes_secret_namespace
}
data = {
"${var.kubernetes_secret_client_id_key}" = keycloak_openid_client.openid_client.client_id
"${var.kubernetes_secret_client_secret_key}" = keycloak_openid_client.openid_client.client_secret
}
}
output "client_id" {
value = resource.keycloak_openid_client.openid_client.client_id
sensitive = true
}
output "client_secret" {
value = resource.keycloak_openid_client.openid_client.client_secret
sensitive = true
}

23
keycloak/tf/providers.tf Normal file
View File

@ -0,0 +1,23 @@
provider "keycloak" {
client_id = "admin-cli"
url = "https://auth.werts.us"
username = data.kubernetes_secret_v1.keycloak_admin.data.username
password = data.kubernetes_secret_v1.keycloak_admin.data.password
initial_login = false
}
data "kubernetes_secret_v1" "keycloak_admin" {
metadata {
name = "keycloak-admin"
namespace = "keycloak"
}
}
provider "kubernetes" {
config_path = "~/.kube/config"
config_context = "mew"
}
#provider "vault" {
# address = "https://vault.strudelline.net"
#}

16
keycloak/tf/versions.tf Normal file
View File

@ -0,0 +1,16 @@
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
version = "4.2.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.18.1"
}
#vault = {
# source = "hashicorp/vault"
# version = "3.14.0"
#}
}
}

25
keycloak/tf/werts.tf Normal file
View File

@ -0,0 +1,25 @@
resource "keycloak_realm" "werts" {
realm = "werts"
enabled = true
default_signature_algorithm = "RS256"
display_name = "werts.us"
display_name_html = "<div class=\"kc-logo-text\"><span>werts.us</span></div>"
ssl_required = "none"
account_theme = "keycloak"
admin_theme = "keycloak.v2"
email_theme = "keycloak"
login_theme = "keycloak"
}
module "werts_cascade_federation" {
#source = "github.com/jamesandariese/terraform-keycloak-ad-federation"
source = "/home/james/src/github.com/jamesandariese/terraform-keycloak-ad-federation"
realm_id = keycloak_realm.werts.id
connection_url = "ldaps://cascade.strudelline.net"
bind_dn = "CN=ldapsearch,OU=ldapsearch,DC=cascade,DC=strudelline,DC=net"
bind_credential = "2Nblech%"
federation_name = "cascade"
users_dn = "DC=cascade,DC=strudelline,DC=net"
}

24
nvidia/README.md Normal file
View File

@ -0,0 +1,24 @@
# Installing NVIDIA stuff on a new k3s node
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit nvidia-kernel-dkms
# Installing k3s stuff
There is a `deploy.sh` in this folder.
It installs the RuntimeClass needed to target the nvidia runtime
and installs the device plugin with GFD (node finder for GPUs) via
helm.
# Wrap up
With these two pieces installed, you should be able to find a GPU-bearing node.
```bash
kubectl get node -l 'nvidia.com/gpu.count'
```