From 6e5a0fb9474a904ac47ef0889ad6947cf96f26da Mon Sep 17 00:00:00 2001 From: Jacques ROUSSEL Date: Fri, 20 Dec 2024 14:07:01 +0100 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=94=A7(helm)=20modify=20local=20helm?= =?UTF-8?q?=20deployment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify helmfile in order to be abble to use a standalone dev environment or a dinum specific dev environment with pro connect plateform. --- Makefile | 30 ++ .../dev-keycloak/values.meet.yaml.gotmpl | 18 +- src/helm/env.d/dev/secrets.enc.yaml | 103 ------ src/helm/env.d/dev/values.meet.yaml.gotmpl | 21 +- src/helm/env.d/dev/values.secrets.yaml | 8 + src/helm/env.d/production/secrets.enc.yaml | 1 - .../env.d/production/values.meet.yaml.gotmpl | 290 ----------------- src/helm/env.d/staging/secrets.enc.yaml | 1 - .../env.d/staging/values.meet.yaml.gotmpl | 300 ------------------ .../extra/templates/clustersecretstore.yaml | 13 + src/helm/extra/templates/external_secret.yaml | 28 ++ .../templates/external_secret_deployment.yaml | 92 ++++++ src/helm/extra/templates/keydb.yaml | 7 - src/helm/extra/templates/postgresql.yaml | 7 - src/helm/extra/templates/redirect.yaml | 55 ---- src/helm/extra/templates/s3.yaml | 8 - src/helm/extra/templates/summary_keydb.yaml | 7 - src/helm/helmfile.yaml | 23 +- .../meet/templates/backend_deployment.yaml | 1 - .../meet/templates/celery_deployment.yaml | 1 - src/helm/meet/templates/secrets.yaml | 18 -- .../meet/templates/summary_deployment.yaml | 1 - src/helm/meet/templates/summary_secrets.yaml | 14 - src/helm/meet/values.yaml | 10 + 24 files changed, 208 insertions(+), 849 deletions(-) delete mode 100644 src/helm/env.d/dev/secrets.enc.yaml create mode 100644 src/helm/env.d/dev/values.secrets.yaml delete mode 120000 src/helm/env.d/production/secrets.enc.yaml delete mode 100644 src/helm/env.d/production/values.meet.yaml.gotmpl delete mode 120000 src/helm/env.d/staging/secrets.enc.yaml delete mode 100644 src/helm/env.d/staging/values.meet.yaml.gotmpl create mode 100644 src/helm/extra/templates/clustersecretstore.yaml create mode 100644 src/helm/extra/templates/external_secret.yaml create mode 100644 src/helm/extra/templates/external_secret_deployment.yaml delete mode 100644 src/helm/extra/templates/keydb.yaml delete mode 100644 src/helm/extra/templates/postgresql.yaml delete mode 100644 src/helm/extra/templates/redirect.yaml delete mode 100644 src/helm/extra/templates/s3.yaml delete mode 100644 src/helm/extra/templates/summary_keydb.yaml delete mode 100644 src/helm/meet/templates/secrets.yaml delete mode 100644 src/helm/meet/templates/summary_secrets.yaml diff --git a/Makefile b/Makefile index 67cb56c1..12bcbcc6 100644 --- a/Makefile +++ b/Makefile @@ -301,6 +301,36 @@ build-k8s-cluster: ## build the kubernetes cluster using kind ./bin/start-kind.sh .PHONY: build-k8s-cluster +install-secret: + if kubectl -n meet get secrets bitwarden-cli-visio; then \ + echo "Secret already present"; \ + else \ + echo "Please provide the following information:"; \ + read -p "Enter your vaultwarden email login: " LOGIN; \ + read -p "Enter your vaultwarden password: " PASSWORD; \ + read -p "Enter your vaultwarden server url: " URL; \ + echo "\nCreate vaultwarden secret"; \ + echo "apiVersion: v1" > /tmp/secret.yaml; \ + echo "kind: Secret" >> /tmp/secret.yaml; \ + echo "metadata:" >> /tmp/secret.yaml; \ + echo " name: bitwarden-cli-visio" >> /tmp/secret.yaml; \ + echo " namespace: meet" >> /tmp/secret.yaml; \ + echo "type: Opaque" >> /tmp/secret.yaml; \ + echo "stringData:" >> /tmp/secret.yaml; \ + echo " BW_HOST: $$URL" >> /tmp/secret.yaml; \ + echo " BW_PASSWORD: $$PASSWORD" >> /tmp/secret.yaml; \ + echo " BW_USERNAME: $$LOGIN" >> /tmp/secret.yaml; \ + kubectl -n meet apply -f /tmp/secret.yaml;\ + rm -f /tmp/secret.yaml; \ + helm repo add external-secrets https://charts.external-secrets.io; \ + helm upgrade --install external-secrets \ + external-secrets/external-secrets \ + -n meet \ + --create-namespace \ + --set installCRDs=true; \ + fi +.PHONY: build-k8s-cluster + start-tilt: ## start the kubernetes cluster using kind tilt up -f ./bin/Tiltfile .PHONY: build-k8s-cluster diff --git a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl index 55c8eb57..f38284ef 100644 --- a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl +++ b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl @@ -21,14 +21,8 @@ backend: OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/session/end - OIDC_RP_CLIENT_ID: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_ID - OIDC_RP_CLIENT_SECRET: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_SECRET + OIDC_RP_CLIENT_ID: meet + OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly OIDC_RP_SIGN_ALGO: RS256 OIDC_RP_SCOPES: "openid email" OIDC_REDIRECT_ALLOWED_HOSTS: https://meet.127.0.0.1.nip.io @@ -118,7 +112,7 @@ ingressAdmin: posthog: ingress: enabled: false - + ingressAssets: enabled: false @@ -140,12 +134,12 @@ summary: WEBHOOK_URL: https://www.mock-impress.com/webhook/ CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1 CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1 - + image: repository: localhost:5001/meet-summary pullPolicy: Always tag: "latest" - + command: - "uvicorn" - "summary.main:app" @@ -173,7 +167,7 @@ celery: WEBHOOK_URL: https://www.mock-impress.com/webhook/ CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1 CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1 - + image: repository: localhost:5001/meet-summary pullPolicy: Always diff --git a/src/helm/env.d/dev/secrets.enc.yaml b/src/helm/env.d/dev/secrets.enc.yaml deleted file mode 100644 index 3411d7aa..00000000 --- a/src/helm/env.d/dev/secrets.enc.yaml +++ /dev/null @@ -1,103 +0,0 @@ -djangoSecretKey: ENC[AES256_GCM,data:p+9m8eNB/dKMXAdfL0cVCg1uKhAv+YLrM+jjajvRYmOZZ9qbiikuFv0dyDp32va/M9w=,iv:ijUztg7ta6BBTsKs+IIfJMFdN0DfzyAKoxlfY8lisPg=,tag:B+uW6akIV0iI2LdMQotrpw==,type:str] -oidc: - clientId: ENC[AES256_GCM,data:rHzKkQwFQ7hV6kOBBP60RK41NBKVMUs4dMcZavMQ8gCu9ust,iv:8vviSb+XIKS/zjBIScfmWu0VJ8lXCQZ8p7BxuvJtA2w=,tag:k8vn8I/qxKLE/+JNTDj4Jw==,type:str] - clientSecret: ENC[AES256_GCM,data:dOYJoG2PStlOMIJPi2exPzsqlxis73iTkcBMvjr8DBr2isWzstpbexscsog7Tuyelw4tpzrJKzC5BTTwJ+xioQ==,iv:oqkLRTPB8+qR0AHvjyNVfHRmoeGrkUvZjrTsWBjIeBc=,tag:hryfmSeqkdWCN9U38jxXlA==,type:str] -#ENC[AES256_GCM,data:ua1td/VBXGIHDgAw/bm8XnWIRLmgeJKX9dP7g/rNv3jVsXHw6T+iDXxMWpLXNicAZ/RTymdntlwLwsH47r70Z4icEPsjps0yOZ+X734vaL9wVH9IsyFwCihtyck94kgY4CyC7DI=,iv:iGHYu+2aPaI28PQWFheVVuge8BPWLw1VB7Afsz7eLtI=,tag:pfkXsS+/QmHb3kHS/ONHCA==,type:comment] -livekit: - keys: - devkey: ENC[AES256_GCM,data:5RnAMGm3,iv:bY4n8op2KFlXRqzV9h3QwoC3Bws2aEoN1GFxPlrrVBw=,tag:lA+b/6poVRzeJW6Bu8V29A==,type:str] -livekitApi: - key: ENC[AES256_GCM,data:JP7KkPms,iv:LlIJ62IRyGf8fByl6abSZv1to2FUc90laC0oL5HFJK4=,tag:2aLMQ79GlDOaiurh8unO0Q==,type:str] - secret: ENC[AES256_GCM,data:kGDJo1lh,iv:dnI1OuvZGOJZEKZwzoigXqViqYCw/6H7Y0sVXH/p5RA=,tag:G1IB0mc8zuKEmkxrfyImrQ==,type:str] -sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] - age: - - recipient: age15fyxdwmg5mvldtqqus87xspuws2u0cpvwheehrtvkexj4tnsqqysw6re2x - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByR3IybDN3eGx4amYzZkFt - OW5VV3FQN3dkSmZBL0JwUE1qSzNLYmRTc1RjCkVCQ2ZmaHk2SFRJaXdMd0VMZUlP - b0VQeDVUTDBEZzhBQnhrS2RybzYvL1UKLS0tIG1CbllhWGpsOWx4WEkya0NLeUlC - WmRScW9MVkxQLzRxdk85WTZ4U2E0aUUKTpOPYQXutU0xYLih7SNYoQgO+PSEIERL - HLz+C7iV+Fj1/M7JrgiGxTB8wJoKMo7IhJ8AjxaAdxR4Q1TgUpQkPw== - -----END AGE ENCRYPTED FILE----- - - recipient: age16hnlml8yv4ynwy0seer57g8qww075crd0g7nsundz3pj4wk7m3vqftszg7 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0aE15QkRsNmg2UTkxaWNF - T3NZY2RqSDd0WlRKOHYxWFE2R3J5SGJhRjJNClNIcEFwOEtoSmRWQjdaSm1ZSnlj - amhNci9tRDl2Qlp4dlBGZFYzTGxYdm8KLS0tIDZZWTYxQmVqOEZQaTNOODFGWUhn - cXpJL3poT3dpYjZKWTN6dGpOV3kxT2sKozsOz+cSYJdZ0C2L6QCf/VSU9DnOz6ae - lqV5MMzSl1Jf8ETpqt+PhvvWz+MLCAkIriT9yf6R29DQifCacB7XOA== - -----END AGE ENCRYPTED FILE----- - - recipient: age1plkp8td6zzfcavjusmsfrlk54t9vn8jjxm8zaz7cmnr7kzl2nfnsd54hwg - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBySkpOYWxjQVZRbGtkNXlt - OTRKTDlrNjNMenU3V0hPeXYyRnhGVU1mMmhNCmhJTi9ZQzB3ekpSR0k1VDFiNExu - dW9TQkI3Vy9LOXhQaEExZHMyM25xZlEKLS0tIGRYTkpzbjIvL1FMS2lYYXl4dDVZ - U040akh0Z1ZYVmdjS3k2ZjFRK2VRNGMKqSCnviWARWTkZXeht+sdOYKAxylYYyZK - uXYE3nBaXGosIqmTf6deVqCIY+m0mH/J4UMcbH+faMV4pWmVr2JAxg== - -----END AGE ENCRYPTED FILE----- - - recipient: age12g6f5fse25tgrwweleh4jls3qs52hey2edh759smulwmk5lnzadslu2cp3 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJbUhzZStoUVBHUkZLWlE3 - NWNiRkJMdXhUVXRNZTFCMUljVzIxY3BVMFQ4ClpmOGhqeUZiaG1HcU5zdndmWE5y - Ym5OTmoyVVVsb2Ywa3loRTVNZzdlVjQKLS0tIHNEWVV3Mkk2VGVzR3diQW5Ccm1a - MVNUYjZCME9rQWFUaWNycEh5THQyTTAKTBnoF76mJ/GoCIq4TsmV+luYbiWnx0+I - BEISvqsr9gbT0z8kfdo/htPoKHZmnyevZhRhd2AMZdKixYvQMX9sjA== - -----END AGE ENCRYPTED FILE----- - - recipient: age1tl80n23wq6zxegupwn70ew0yp225ua5v4dk800x7g2w6pvlxz46qk592pa - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDWEZkODBNOGw2WFdncjJ0 - TTVzRHlEa1AzaTF4V2hYR3hFRGg2cnBzYmowCmp3WDJ3bEZoTlFYL2hoZ3hhTVU1 - WnQyYk03K2xmSk00dS92OHNNZnRIL2cKLS0tIEVrbjY4enJBZzdQMjRCRmwwVlRI - OHVOMm9NTGdJbnZ2aXYxdi9OdWpkVE0K4b1Hu6rOHVtfH601aXb/uTGYjNMh6yW/ - LetO+HKk+VEzXHntObK2k/4mTl5I0+OP5H8+PR0jdIUZDpr79iEbgQ== - -----END AGE ENCRYPTED FILE----- - - recipient: age1qy04neuzwpasmvljqrcvhwnf0kz5cpyteze38c8avp0czewskasszv9pyw - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqVE9iMmUwTXE2SHZNdG5P - Vi9XQ1Jkc1VDamFlakpkZk45ODZ2YnkwYkVBCnNrbktIdkV4UGltcHBUUHlXbjdx - Z0QwM3ZKbGI1cDBjL2g2cjdKdElOQjAKLS0tIGxrcTJDa1BWVWcxUS80MmxIMWZH - YjBRMDZJZWlmN1FNaXV5c04yVWtleE0K+nGNyFzqSotFP7My/kUnAgxXGu/ji50K - OGVLYgNvU48rCGck3r9ZrKY1HpQdAY8UMQXECsuO4HgdirNjiZ97Zg== - -----END AGE ENCRYPTED FILE----- - - recipient: age18fgn6j2vwwswqcpv9xpcehq8mrf9zs2sglwkamp3tzwx8d9jq9jsrskrk9 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4ZXZud0dqb0dkQ0E3NnE4 - SXB0ZENjQk1mb1BHU2R1bW0waDhTYy9OZldVCjVnRTV5d1c3Q2NzcEVRQ3BoL09I - T1RPQ3hHT3Y2NFNzWG9EdGM2STR2STgKLS0tIHBvL3RhREFNTVdwUGk3S1B4NWJL - TnZpblF1SDdGRlVXM0dEdFAzT1FEMUUK6L8gTv5gt6++A3B7PHyWl+xtBUc8bC6G - 53xoJvyyBpaov3HgUAdrN9VHubfEJmrBGgN7DngGgwYPtlhV87M7/w== - -----END AGE ENCRYPTED FILE----- - - recipient: age1hm2hsfgjezpsc3k0y5w5feq9t8vl3seq04qjhgt6ztd6403wfvpsgxu09m - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlaXY1VmtDejcwTmUxRVZT - YURhMkVPaHNvb0sxT0FYL0pvN3hqclNNcXdRCmxWV3FGeDZTM1VVMVRyalpkVnFJ - OGU3Wk9wVVAvejVTdjc1MENPcy9Qc1kKLS0tIGpJQXhZVzV3REc2SFlFSXg0dUo5 - bjRBaGtJdUFmVUkxeGgwbGYwWjRnNEkKYwzwZ9oOo+C6XD57rkUTO6QADZKzYfSF - cFJ7fX0NyZbzxLncyofWa+dlLWLZ3KohIP0doAFngRm+RVsUEVqY5A== - -----END AGE ENCRYPTED FILE----- - - recipient: age1hnhuzj96ktkhpyygvmz0x9h8mfvssz7ss6emmukags644mdhf4msajk93r - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1aFNsL2xvWmI4UTAxREc4 - NFF3bC9qRTBqS3JrM3B0ZjE5bEtjR0diT0VjClhFNStFU3RydnhvcG9CSmhYM3V4 - VjZ5c0JQZjRoQXh1R2UyeDMyd2NFMEEKLS0tIDNwWUNzZmlrNGZPbERTeFpoUkxO - QnZTWWFMemk5djVNWFRaekVMRkMyUjgKt4dw4BOm3J1Ig6U58NbSjzJbWi3ak/Zq - 8PX5IW7tq1q5+Qd3adqv3cd9S2aVpqjHyN34fxagmuwfvYXVyQ2GDg== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-10-02T07:30:09Z" - mac: ENC[AES256_GCM,data:BdEiR/7AiTz9eppAGOAarFzUJYEfCZzb0lg8LXaHiXe74B5Ob7Ai+XuBBX+x9QPIFzbLZgVveVSrqymW0wAH9Dv5R+e4spDf5KKdRCr9RADfCXNjYC0N9grZVerM70Ic51Lc1kKDnB2mon01W5Sa77Ei29Jo988yvM8AOlXFvr4=,iv:p7PCazxKNv7YcGX7Kpp2L8wXEFaJO8FajEXcVMzmmWQ=,tag:WJKZOkFZSof6IhcXqc60uQ==,type:str] - pgp: [] - unencrypted_suffix: _unencrypted - version: 3.9.0 diff --git a/src/helm/env.d/dev/values.meet.yaml.gotmpl b/src/helm/env.d/dev/values.meet.yaml.gotmpl index a73a41f3..ea6d28ef 100644 --- a/src/helm/env.d/dev/values.meet.yaml.gotmpl +++ b/src/helm/env.d/dev/values.meet.yaml.gotmpl @@ -1,3 +1,14 @@ +secrets: + - name: oidcLogin + itemId: a25effec-eaea-4ce1-9ed8-3a3cc1c734db + field: username + podVariable: OIDC_RP_CLIENT_ID + clusterSecretStore: bitwarden-login-visio + - name: oidcPass + itemId: a25effec-eaea-4ce1-9ed8-3a3cc1c734db + field: password + podVariable: OIDC_RP_CLIENT_SECRET + clusterSecretStore: bitwarden-login-visio image: repository: localhost:5001/meet-backend pullPolicy: Always @@ -21,8 +32,14 @@ backend: OIDC_OP_TOKEN_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/token OIDC_OP_USER_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo OIDC_OP_LOGOUT_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/session/end - OIDC_RP_CLIENT_ID: {{ .Values.oidc.clientId }} - OIDC_RP_CLIENT_SECRET: {{ .Values.oidc.clientSecret }} + OIDC_RP_CLIENT_ID: + secretKeyRef: + name: backend + key: OIDC_RP_CLIENT_ID + OIDC_RP_CLIENT_SECRET: + secretKeyRef: + name: backend + key: OIDC_RP_CLIENT_SECRET OIDC_RP_SIGN_ALGO: RS256 OIDC_RP_SCOPES: "openid email given_name usual_name" OIDC_REDIRECT_ALLOWED_HOSTS: https://meet.127.0.0.1.nip.io diff --git a/src/helm/env.d/dev/values.secrets.yaml b/src/helm/env.d/dev/values.secrets.yaml new file mode 100644 index 00000000..b85ad820 --- /dev/null +++ b/src/helm/env.d/dev/values.secrets.yaml @@ -0,0 +1,8 @@ +djangoSecretKey: u!vbjDW71aru&OZA%NZQi0x +livekit: + keys: + devkey: secret +livekitApi: + key: devkey + secret: secret + diff --git a/src/helm/env.d/production/secrets.enc.yaml b/src/helm/env.d/production/secrets.enc.yaml deleted file mode 120000 index 79d77ee0..00000000 --- a/src/helm/env.d/production/secrets.enc.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../secrets/numerique-gouv/meet/env/production/secrets.enc.yaml \ No newline at end of file diff --git a/src/helm/env.d/production/values.meet.yaml.gotmpl b/src/helm/env.d/production/values.meet.yaml.gotmpl deleted file mode 100644 index eb3f4fb9..00000000 --- a/src/helm/env.d/production/values.meet.yaml.gotmpl +++ /dev/null @@ -1,290 +0,0 @@ -image: - repository: lasuite/meet-backend - pullPolicy: Always - tag: "v0.1.12" - -backend: - migrateJobAnnotations: - argocd.argoproj.io/hook: PostSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded - envVars: - DJANGO_CSRF_TRUSTED_ORIGINS: https://visio.numerique.gouv.fr,https://meet.numerique.gouv.fr - DJANGO_CONFIGURATION: Production - DJANGO_ALLOWED_HOSTS: visio.numerique.gouv.fr,meet.numerique.gouv.fr - DJANGO_SECRET_KEY: - secretKeyRef: - name: backend - key: DJANGO_SECRET_KEY - DJANGO_SETTINGS_MODULE: meet.settings - DJANGO_SILENCED_SYSTEM_CHECKS: security.W004, security.W008 - DJANGO_SUPERUSER_EMAIL: - secretKeyRef: - name: backend - key: DJANGO_SUPERUSER_EMAIL - DJANGO_SUPERUSER_PASSWORD: - secretKeyRef: - name: backend - key: DJANGO_SUPERUSER_PASSWORD - DJANGO_EMAIL_HOST: "snap-mail.numerique.gouv.fr" - DJANGO_EMAIL_PORT: 465 - DJANGO_EMAIL_USE_SSL: True - DJANGO_SENTRY_DSN: https://5aead03f03505da5130af6d642c42faf@sentry.incubateur.net/202 - OIDC_OP_JWKS_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/jwks - OIDC_OP_AUTHORIZATION_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/authorize - OIDC_OP_TOKEN_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/token - OIDC_OP_USER_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/userinfo - OIDC_OP_LOGOUT_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/session/end - OIDC_RP_CLIENT_ID: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_ID - OIDC_RP_CLIENT_SECRET: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_SECRET - OIDC_RP_SIGN_ALGO: RS256 - OIDC_RP_SCOPES: "openid email given_name usual_name" - OIDC_REDIRECT_ALLOWED_HOSTS: https://visio.numerique.gouv.fr - OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}" - LOGIN_REDIRECT_URL: https://visio.numerique.gouv.fr - LOGIN_REDIRECT_URL_FAILURE: https://visio.numerique.gouv.fr - LOGOUT_REDIRECT_URL: https://visio.numerique.gouv.fr - DB_HOST: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: host - DB_NAME: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: database - DB_USER: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: username - DB_PASSWORD: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: password - DB_PORT: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: port - POSTGRES_USER: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: username - POSTGRES_DB: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: database - POSTGRES_PASSWORD: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: password - REDIS_URL: - secretKeyRef: - name: redis.redis.libre.sh - key: url - STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage - LIVEKIT_API_SECRET: - secretKeyRef: - name: backend - key: LIVEKIT_API_SECRET - LIVEKIT_API_KEY: - secretKeyRef: - name: backend - key: LIVEKIT_API_KEY - LIVEKIT_API_URL: https://livekit-preprod.beta.numerique.gouv.fr - ALLOW_UNREGISTERED_ROOMS: False - FRONTEND_SILENCE_LIVEKIT_DEBUG: False - FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio.numerique.gouv.fr'}" - FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}" - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: url - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - RECORDING_ENABLE: True - RECORDING_STORAGE_EVENT_ENABLE: True - RECORDING_STORAGE_EVENT_TOKEN: - secretKeyRef: - name: backend - key: RECORDING_STORAGE_EVENT_TOKEN - SUMMARY_SERVICE_ENDPOINT: http://meet-summary:80/api/v1/tasks/ - SUMMARY_SERVICE_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - - createsuperuser: - command: - - "/bin/sh" - - "-c" - - | - python manage.py createsuperuser --email $DJANGO_SUPERUSER_EMAIL --password $DJANGO_SUPERUSER_PASSWORD - restartPolicy: Never - -frontend: - image: - repository: lasuite/meet-frontend - pullPolicy: Always - tag: "v0.1.12" - -ingress: - enabled: true - host: visio.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt - -ingressAdmin: - enabled: true - host: visio.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt - nginx.ingress.kubernetes.io/auth-signin: https://oauth2-proxy.beta.numerique.gouv.fr/oauth2/start - nginx.ingress.kubernetes.io/auth-url: https://oauth2-proxy.beta.numerique.gouv.fr/oauth2/auth - -posthog: - ingress: - enabled: true - host: product.visio.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt - nginx.ingress.kubernetes.io/upstream-vhost: eu.i.posthog.com - nginx.ingress.kubernetes.io/backend-protocol: https - - ingressAssets: - enabled: true - host: product.visio.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt - nginx.ingress.kubernetes.io/upstream-vhost: eu-assets.i.posthog.com - nginx.ingress.kubernetes.io/backend-protocol: https - -summary: - replicas: 1 - envVars: - APP_NAME: summary-microservice - APP_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: url - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - OPENAI_API_KEY: - secretKeyRef: - name: summary - key: OPENAI_API_KEY - OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 - OPENAI_ASR_MODEL: openai/whisper-large-v3 - OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct - WEBHOOK_API_TOKEN: - secretKeyRef: - name: summary - key: WEBHOOK_API_TOKEN - WEBHOOK_URL: https://docs.numerique.gouv.fr/api/v1.0/documents/create-for-owner/ - CELERY_BROKER_URL: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - CELERY_RESULT_BACKEND: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - - image: - repository: lasuite/meet-summary - pullPolicy: Always - tag: "v0.1.12" - -celery: - replicas: 1 - envVars: - APP_NAME: summary-microservice - APP_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: endpoint - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - OPENAI_API_KEY: - secretKeyRef: - name: summary - key: OPENAI_API_KEY - OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 - OPENAI_ASR_MODEL: openai/whisper-large-v3 - OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct - WEBHOOK_API_TOKEN: - secretKeyRef: - name: summary - key: WEBHOOK_API_TOKEN - WEBHOOK_URL: https://docs.numerique.gouv.fr/api/v1.0/documents/create-for-owner/ - CELERY_BROKER_URL: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - CELERY_RESULT_BACKEND: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - SENTRY_IS_ENABLED: True - SENTRY_DSN: https://5aead03f03505da5130af6d642c42faf@sentry.incubateur.net/202 - - image: - repository: lasuite/meet-summary - pullPolicy: Always - tag: "v0.1.12" - - command: - - "celery" - - "-A" - - "summary.core.celery_worker" - - "worker" - - "--pool=solo" - - "--loglevel=info" diff --git a/src/helm/env.d/staging/secrets.enc.yaml b/src/helm/env.d/staging/secrets.enc.yaml deleted file mode 120000 index ef39be73..00000000 --- a/src/helm/env.d/staging/secrets.enc.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../secrets/numerique-gouv/meet/env/staging/secrets.enc.yaml \ No newline at end of file diff --git a/src/helm/env.d/staging/values.meet.yaml.gotmpl b/src/helm/env.d/staging/values.meet.yaml.gotmpl deleted file mode 100644 index 295bde0e..00000000 --- a/src/helm/env.d/staging/values.meet.yaml.gotmpl +++ /dev/null @@ -1,300 +0,0 @@ -image: - repository: lasuite/meet-backend - pullPolicy: Always - tag: "main" - -backend: - migrateJobAnnotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded - envVars: - DJANGO_CSRF_TRUSTED_ORIGINS: http://visio-staging.beta.numerique.gouv.fr,https://meet-staging.beta.numerique.gouv.fr - DJANGO_CONFIGURATION: Production - DJANGO_ALLOWED_HOSTS: visio-staging.beta.numerique.gouv.fr - DJANGO_SECRET_KEY: - secretKeyRef: - name: backend - key: DJANGO_SECRET_KEY - DJANGO_SETTINGS_MODULE: meet.settings - DJANGO_SUPERUSER_EMAIL: - secretKeyRef: - name: backend - key: DJANGO_SUPERUSER_EMAIL - DJANGO_SUPERUSER_PASSWORD: - secretKeyRef: - name: backend - key: DJANGO_SUPERUSER_PASSWORD - DJANGO_EMAIL_HOST: "snap-mail.numerique.gouv.fr" - DJANGO_EMAIL_PORT: 465 - DJANGO_EMAIL_USE_SSL: True - DJANGO_SENTRY_DSN: https://5aead03f03505da5130af6d642c42faf@sentry.incubateur.net/202 - OIDC_OP_JWKS_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/jwks - OIDC_OP_AUTHORIZATION_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/authorize - OIDC_OP_TOKEN_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/token - OIDC_OP_USER_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo - OIDC_OP_LOGOUT_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/session/end - OIDC_RP_CLIENT_ID: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_ID - OIDC_RP_CLIENT_SECRET: - secretKeyRef: - name: backend - key: OIDC_RP_CLIENT_SECRET - OIDC_RP_SIGN_ALGO: RS256 - OIDC_RP_SCOPES: "openid email given_name usual_name" - OIDC_REDIRECT_ALLOWED_HOSTS: https://visio-staging.beta.numerique.gouv.fr - OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}" - LOGIN_REDIRECT_URL: https://visio-staging.beta.numerique.gouv.fr - LOGIN_REDIRECT_URL_FAILURE: https://visio-staging.beta.numerique.gouv.fr - LOGOUT_REDIRECT_URL: https://visio-staging.beta.numerique.gouv.fr - DB_HOST: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: host - DB_NAME: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: database - DB_USER: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: username - DB_PASSWORD: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: password - DB_PORT: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: port - POSTGRES_USER: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: username - POSTGRES_DB: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: database - POSTGRES_PASSWORD: - secretKeyRef: - name: postgresql.postgres.libre.sh - key: password - REDIS_URL: - secretKeyRef: - name: redis.redis.libre.sh - key: url - STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage - LIVEKIT_API_SECRET: - secretKeyRef: - name: backend - key: LIVEKIT_API_SECRET - LIVEKIT_API_KEY: - secretKeyRef: - name: backend - key: LIVEKIT_API_KEY - LIVEKIT_API_URL: https://livekit-staging.beta.numerique.gouv.fr - ALLOW_UNREGISTERED_ROOMS: False - FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio-staging.beta.numerique.gouv.fr'}" - FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}" - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: url - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - RECORDING_ENABLE: True - RECORDING_STORAGE_EVENT_ENABLE: True - RECORDING_STORAGE_EVENT_TOKEN: - secretKeyRef: - name: backend - key: RECORDING_STORAGE_EVENT_TOKEN - SUMMARY_SERVICE_ENDPOINT: http://meet-summary:80/api/v1/tasks/ - SUMMARY_SERVICE_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - - createsuperuser: - command: - - "/bin/sh" - - "-c" - - | - python manage.py createsuperuser --email $DJANGO_SUPERUSER_EMAIL --password $DJANGO_SUPERUSER_PASSWORD - restartPolicy: Never - -frontend: - image: - repository: lasuite/meet-frontend - pullPolicy: Always - tag: "main" - -ingress: - enabled: true - host: visio-staging.beta.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - tls: - enabled: true - additional: - - secretName: transitional-tls - hosts: - - {{ .Values.newDomain }} - -ingressAdmin: - enabled: true - host: visio-staging.beta.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/auth-signin: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/start - nginx.ingress.kubernetes.io/auth-url: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/auth - tls: - enabled: true - additional: - - secretName: transitional-tls - hosts: - - {{ .Values.newDomain }} - -posthog: - ingress: - enabled: true - host: product.visio-staging.beta.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/upstream-vhost: eu.i.posthog.com - nginx.ingress.kubernetes.io/backend-protocol: https - - ingressAssets: - enabled: true - host: product.visio-staging.beta.numerique.gouv.fr - className: nginx - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/upstream-vhost: eu-assets.i.posthog.com - nginx.ingress.kubernetes.io/backend-protocol: https - -summary: - replicas: 1 - envVars: - APP_NAME: summary-microservice - APP_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: url - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - OPENAI_API_KEY: - secretKeyRef: - name: summary - key: OPENAI_API_KEY - OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 - OPENAI_ASR_MODEL: openai/whisper-large-v3 - OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct - WEBHOOK_API_TOKEN: - secretKeyRef: - name: summary - key: WEBHOOK_API_TOKEN - WEBHOOK_URL: https://impress-staging.beta.numerique.gouv.fr/api/v1.0/documents/create-for-owner/ - CELERY_BROKER_URL: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - CELERY_RESULT_BACKEND: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - - image: - repository: lasuite/meet-summary - pullPolicy: Always - tag: "main" - -celery: - replicas: 1 - envVars: - APP_NAME: summary-microservice - APP_API_TOKEN: - secretKeyRef: - name: summary - key: APP_API_TOKEN - AWS_S3_ENDPOINT_URL: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: endpoint - AWS_S3_ACCESS_KEY_ID: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: accessKey - AWS_S3_SECRET_ACCESS_KEY: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: secretKey - AWS_STORAGE_BUCKET_NAME: - secretKeyRef: - name: meet-media-storage.bucket.libre.sh - key: bucket - AWS_S3_REGION_NAME: local - OPENAI_API_KEY: - secretKeyRef: - name: summary - key: OPENAI_API_KEY - OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 - OPENAI_ASR_MODEL: openai/whisper-large-v3 - OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct - WEBHOOK_API_TOKEN: - secretKeyRef: - name: summary - key: WEBHOOK_API_TOKEN - WEBHOOK_URL: https://impress-staging.beta.numerique.gouv.fr/api/v1.0/documents/create-for-owner/ - CELERY_BROKER_URL: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - CELERY_RESULT_BACKEND: - secretKeyRef: - name: redis-summary.redis.libre.sh - key: url - SENTRY_IS_ENABLED: True - SENTRY_DSN: https://5aead03f03505da5130af6d642c42faf@sentry.incubateur.net/202 - - image: - repository: lasuite/meet-summary - pullPolicy: Always - tag: "main" - - command: - - "celery" - - "-A" - - "summary.core.celery_worker" - - "worker" - - "--pool=solo" - - "--loglevel=info" diff --git a/src/helm/extra/templates/clustersecretstore.yaml b/src/helm/extra/templates/clustersecretstore.yaml new file mode 100644 index 00000000..a4b978af --- /dev/null +++ b/src/helm/extra/templates/clustersecretstore.yaml @@ -0,0 +1,13 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: bitwarden-login-visio + namespace: {{ $.Release.Namespace | quote }} +spec: + provider: + webhook: + url: "http://bitwarden-cli-visio.meet.svc.cluster.local:8087/object/item/{{`{{ .remoteRef.key }}`}}" + headers: + Content-Type: application/json + result: + jsonPath: "$.data.login.{{`{{ .remoteRef.property }}`}}" diff --git a/src/helm/extra/templates/external_secret.yaml b/src/helm/extra/templates/external_secret.yaml new file mode 100644 index 00000000..cdf7ee27 --- /dev/null +++ b/src/helm/extra/templates/external_secret.yaml @@ -0,0 +1,28 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: backend + namespace: {{ .Release.Namespace | quote }} +spec: + refreshInterval: "1m" + target: + name: backend + deletionPolicy: Delete + template: + type: Opaque + data: +{{- range .Values.secrets }} + {{ .podVariable }}: |- + {{`{{`}} {{ print "." .name }} {{`}}`}} +{{- end }} + data: +{{- range .Values.secrets }} + - secretKey: {{ .name }} + sourceRef: + storeRef: + name: {{ .clusterSecretStore }} + kind: ClusterSecretStore + remoteRef: + key: {{ .itemId }} + property: {{ .field }} +{{- end }} diff --git a/src/helm/extra/templates/external_secret_deployment.yaml b/src/helm/extra/templates/external_secret_deployment.yaml new file mode 100644 index 00000000..7620abaa --- /dev/null +++ b/src/helm/extra/templates/external_secret_deployment.yaml @@ -0,0 +1,92 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bitwarden-cli-visio + namespace: {{ $.Release.Namespace | quote }} + labels: + app.kubernetes.io/instance: bitwarden-cli + app.kubernetes.io/name: bitwarden-cli +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/name: bitwarden-cli + app.kubernetes.io/instance: bitwarden-cli + template: + metadata: + labels: + app.kubernetes.io/name: bitwarden-cli + app.kubernetes.io/instance: bitwarden-cli + spec: + containers: + - name: bitwarden-cli + image: lasuite/vaultwarden-api:0.1 + imagePullPolicy: Always + env: + - name: BW_HOST + valueFrom: + secretKeyRef: + name: bitwarden-cli-visio + key: BW_HOST + - name: BW_USER + valueFrom: + secretKeyRef: + name: bitwarden-cli-visio + key: BW_USERNAME + - name: BW_PASSWORD + valueFrom: + secretKeyRef: + name: bitwarden-cli-visio + key: BW_PASSWORD + ports: + - name: http + containerPort: 8087 + protocol: TCP + livenessProbe: + exec: + command: + - wget + - -q + - http://127.0.0.1:8087/sync?force=true + - --post-data='' + initialDelaySeconds: 20 + failureThreshold: 3 + timeoutSeconds: 10 + periodSeconds: 120 + readinessProbe: + tcpSocket: + port: 8087 + initialDelaySeconds: 20 + failureThreshold: 3 + timeoutSeconds: 1 + periodSeconds: 10 + startupProbe: + tcpSocket: + port: 8087 + initialDelaySeconds: 10 + failureThreshold: 30 + timeoutSeconds: 1 + periodSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: bitwarden-cli-visio + namespace: {{ $.Release.Namespace | quote }} + labels: + app.kubernetes.io/instance: bitwarden-cli + app.kubernetes.io/name: bitwarden-cli + annotations: +spec: + type: ClusterIP + ports: + - port: 8087 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: bitwarden-cli + app.kubernetes.io/instance: bitwarden-cli diff --git a/src/helm/extra/templates/keydb.yaml b/src/helm/extra/templates/keydb.yaml deleted file mode 100644 index 00898ae9..00000000 --- a/src/helm/extra/templates/keydb.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: core.libre.sh/v1alpha1 -kind: Redis -metadata: - name: redis - namespace: {{ .Release.Namespace | quote }} -spec: - disableAuth: false diff --git a/src/helm/extra/templates/postgresql.yaml b/src/helm/extra/templates/postgresql.yaml deleted file mode 100644 index b63138a0..00000000 --- a/src/helm/extra/templates/postgresql.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: core.libre.sh/v1alpha1 -kind: Postgres -metadata: - name: postgresql - namespace: {{ .Release.Namespace | quote }} -spec: - database: meet diff --git a/src/helm/extra/templates/redirect.yaml b/src/helm/extra/templates/redirect.yaml deleted file mode 100644 index e55424b0..00000000 --- a/src/helm/extra/templates/redirect.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{ if .Values.addRedirect }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - {{ if .Values.enablePermanentRedirect }} - nginx.ingress.kubernetes.io/permanent-redirect: "https://{{ .Values.newDomain }}$request_uri" - nginx.ingress.kubernetes.io/permanent-redirect-code: "308" - {{ end }} - name: temporary-redirect - namespace: {{ .Release.Namespace | quote }} -spec: - ingressClassName: nginx - rules: - - host: {{ .Values.oldDomain }} - http: - paths: - - backend: - service: - name: meet-frontend - port: - number: 80 - path: / - pathType: Prefix - - backend: - service: - name: meet-backend - port: - number: 80 - path: /api - pathType: Prefix - tls: - - hosts: - - {{ .Values.oldDomain }} - secretName: transitional-tls ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: transitional-tls - namespace: {{ .Release.Namespace | quote }} -spec: - dnsNames: - - {{ .Values.newDomain }} - - {{ .Values.oldDomain }} - issuerRef: - group: cert-manager.io - kind: ClusterIssuer - name: {{ index .Values.ingress.annotations "cert-manager.io/cluster-issuer" }} - secretName: transitional-tls - usages: - - digital signature - - key encipherment -{{ end }} diff --git a/src/helm/extra/templates/s3.yaml b/src/helm/extra/templates/s3.yaml deleted file mode 100644 index 558919e6..00000000 --- a/src/helm/extra/templates/s3.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: core.libre.sh/v1alpha1 -kind: Bucket -metadata: - name: meet-media-storage - namespace: {{ .Release.Namespace | quote }} -spec: - provider: data - versioned: true diff --git a/src/helm/extra/templates/summary_keydb.yaml b/src/helm/extra/templates/summary_keydb.yaml deleted file mode 100644 index 58e7d502..00000000 --- a/src/helm/extra/templates/summary_keydb.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: core.libre.sh/v1alpha1 -kind: Redis -metadata: - name: redis-summary - namespace: {{ .Release.Namespace | quote }} -spec: - disableAuth: false diff --git a/src/helm/helmfile.yaml b/src/helm/helmfile.yaml index 6f970aef..5457ee3c 100644 --- a/src/helm/helmfile.yaml +++ b/src/helm/helmfile.yaml @@ -6,26 +6,7 @@ environments: dev: values: - version: 0.0.1 - secrets: - - env.d/{{ .Environment.Name }}/secrets.enc.yaml - staging: - values: - - version: 0.0.1 - addRedirect: True - enablePermanentRedirect: True - oldDomain: meet-staging.beta.numerique.gouv.fr - newDomain: visio-staging.beta.numerique.gouv.fr - secrets: - - env.d/{{ .Environment.Name }}/secrets.enc.yaml - production: - values: - - version: 0.0.1 - addRedirect: True - enablePermanentRedirect: True - oldDomain: meet.numerique.gouv.fr - newDomain: visio.numerique.gouv.fr - secrets: - - env.d/{{ .Environment.Name }}/secrets.enc.yaml + - env.d/{{ .Environment.Name }}/values.secrets.yaml repositories: - name: bitnami @@ -132,7 +113,7 @@ releases: architecture: standalone - name: extra - installed: {{ not (regexMatch "^dev.*" .Environment.Name) | toYaml }} + installed: {{ regexMatch "^dev.*" .Environment.Name | toYaml }} missingFileHandler: Warn namespace: {{ .Namespace }} chart: ./extra diff --git a/src/helm/meet/templates/backend_deployment.yaml b/src/helm/meet/templates/backend_deployment.yaml index fda7ef41..7990e834 100644 --- a/src/helm/meet/templates/backend_deployment.yaml +++ b/src/helm/meet/templates/backend_deployment.yaml @@ -19,7 +19,6 @@ spec: {{- with .Values.backend.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} - checksum/config: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} labels: {{- include "meet.common.selectorLabels" (list . $component) | nindent 8 }} spec: diff --git a/src/helm/meet/templates/celery_deployment.yaml b/src/helm/meet/templates/celery_deployment.yaml index dc7a914f..99de5f25 100644 --- a/src/helm/meet/templates/celery_deployment.yaml +++ b/src/helm/meet/templates/celery_deployment.yaml @@ -19,7 +19,6 @@ spec: {{- with .Values.celery.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} - checksum/config: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} labels: {{- include "meet.common.selectorLabels" (list . $component) | nindent 8 }} spec: diff --git a/src/helm/meet/templates/secrets.yaml b/src/helm/meet/templates/secrets.yaml deleted file mode 100644 index f896e8ca..00000000 --- a/src/helm/meet/templates/secrets.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: backend - namespace: {{ .Release.Namespace | quote }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation -stringData: - DJANGO_SUPERUSER_EMAIL: {{ .Values.djangoSuperUserEmail }} - DJANGO_SUPERUSER_PASSWORD: {{ .Values.djangoSuperUserPass }} - DJANGO_SECRET_KEY: {{ .Values.djangoSecretKey }} - OIDC_RP_CLIENT_ID: {{ .Values.oidc.clientId }} - OIDC_RP_CLIENT_SECRET: {{ .Values.oidc.clientSecret }} - LIVEKIT_API_SECRET: {{ .Values.livekitApi.secret }} - LIVEKIT_API_KEY: {{ .Values.livekitApi.key }} - RECORDING_STORAGE_EVENT_TOKEN: {{ .Values.recordingStorageEventToken }} diff --git a/src/helm/meet/templates/summary_deployment.yaml b/src/helm/meet/templates/summary_deployment.yaml index 6a6c780c..0add9e32 100644 --- a/src/helm/meet/templates/summary_deployment.yaml +++ b/src/helm/meet/templates/summary_deployment.yaml @@ -19,7 +19,6 @@ spec: {{- with .Values.summary.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} - checksum/config: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} labels: {{- include "meet.common.selectorLabels" (list . $component) | nindent 8 }} spec: diff --git a/src/helm/meet/templates/summary_secrets.yaml b/src/helm/meet/templates/summary_secrets.yaml deleted file mode 100644 index 18693113..00000000 --- a/src/helm/meet/templates/summary_secrets.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: summary - namespace: {{ .Release.Namespace | quote }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation -stringData: - APP_API_TOKEN: {{ .Values.appApiToken }} - OPENAI_API_KEY: {{ .Values.openaiApiKey }} - WEBHOOK_API_TOKEN: {{ .Values.webhookApiToken }} - diff --git a/src/helm/meet/values.yaml b/src/helm/meet/values.yaml index f49831ba..ee9643ef 100644 --- a/src/helm/meet/values.yaml +++ b/src/helm/meet/values.yaml @@ -128,6 +128,16 @@ backend: - "--no-input" restartPolicy: Never + ## @param backend.createsuperuser.command backend migrate command + ## @param backend.createsuperuser.restartPolicy backend migrate job restart policy + createsuperuser: + command: + - "/bin/sh" + - "-c" + - | + python manage.py createsuperuser --email $DJANGO_SUPERUSER_EMAIL --password $DJANGO_SUPERUSER_PASSWORD + restartPolicy: Never + ## @param backend.probes.liveness.path [nullable] Configure path for backend HTTP liveness probe ## @param backend.probes.liveness.targetPort [nullable] Configure port for backend HTTP liveness probe ## @param backend.probes.liveness.initialDelaySeconds [nullable] Configure initial delay for backend liveness probe From 4b9a7e05ecab5eb9558011096d98d15d16b7957a Mon Sep 17 00:00:00 2001 From: Jacques ROUSSEL Date: Mon, 23 Dec 2024 09:15:11 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=91=B7(helm)=20add=20a=20github=20wor?= =?UTF-8?q?kflow=20to=20publish=20a=20chart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to avoid to duplicat helm chart between this repository and the deployement repository, we decide to publish an helm chart --- .github/workflows/release-helm-chart.yaml | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/release-helm-chart.yaml diff --git a/.github/workflows/release-helm-chart.yaml b/.github/workflows/release-helm-chart.yaml new file mode 100644 index 00000000..3f17aacf --- /dev/null +++ b/.github/workflows/release-helm-chart.yaml @@ -0,0 +1,29 @@ +name: Release Charts + +on: + push: + branches: + - main + +jobs: + release: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Cleanup + run: rm -rf ./src/helm/extra + + - name: Publish Helm charts + uses: stefanprodan/helm-gh-pages@v1.7.0 + with: + charts_dir: ./src/helm/ + linting: off + token: ${{ secrets.GITHUB_TOKEN }} From a9b16ed1500440ee34b037ae4551e6fe04239d4d Mon Sep 17 00:00:00 2001 From: Jacques ROUSSEL Date: Mon, 23 Dec 2024 11:53:09 +0100 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=93=9D(self-hosted)=20add=20documenta?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a documentation to deploy a self-hosted visio instance in a standalone way (witout AI features) --- docs/examples/keycloak.values.yaml | 2298 ++++++++++++++++++++++++++ docs/examples/livekit.values.yaml | 40 + docs/examples/meet.values.yaml | 107 ++ docs/examples/postgresql.values.yaml | 7 + docs/examples/redis.values.yaml | 3 + docs/installation.md | 226 +++ 6 files changed, 2681 insertions(+) create mode 100644 docs/examples/keycloak.values.yaml create mode 100644 docs/examples/livekit.values.yaml create mode 100644 docs/examples/meet.values.yaml create mode 100644 docs/examples/postgresql.values.yaml create mode 100644 docs/examples/redis.values.yaml create mode 100644 docs/installation.md diff --git a/docs/examples/keycloak.values.yaml b/docs/examples/keycloak.values.yaml new file mode 100644 index 00000000..e1af58e6 --- /dev/null +++ b/docs/examples/keycloak.values.yaml @@ -0,0 +1,2298 @@ +postgresql: + auth: + username: keycloak + password: keycloak + database: keycloak +extraEnvVars: + - name: KEYCLOAK_EXTRA_ARGS + value: "--import-realm" + - name: KC_HOSTNAME_URL + value: https://keycloak.127.0.0.1.nip.io +extraVolumes: + - name: import + configMap: + name: meet-keycloak +extraVolumeMounts: + - name: import + mountPath: /opt/bitnami/keycloak/data/import/ +auth: + adminUser: su + adminPassword: su +proxy: edge +ingress: + enabled: true + hostname: keycloak.127.0.0.1.nip.io +extraDeploy: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: meet-keycloak + data: + meet.json: | + { + "id": "ccf4fd40-4286-474d-854a-4714282a8bec", + "realm": "meet", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": "false", + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": "false", + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": "true", + "sslRequired": "external", + "registrationAllowed": "true", + "registrationEmailAsUsername": "false", + "rememberMe": "true", + "verifyEmail": "false", + "loginWithEmailAllowed": "true", + "duplicateEmailsAllowed": "false", + "resetPasswordAllowed": "true", + "editUsernameAllowed": "false", + "bruteForceProtected": "false", + "permanentLockout": "false", + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "users": [ + { + "username": "meet", + "email": "meet@meet.world", + "firstName": "John", + "lastName": "Doe", + "enabled": "true", + "credentials": [ + { + "type": "password", + "value": "meet" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-chromium", + "email": "user@chromium.e2e", + "firstName": "E2E", + "lastName": "Chromium", + "enabled": "true", + "credentials": [ + { + "type": "password", + "value": "password-e2e-chromium" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-webkit", + "email": "user@webkit.e2e", + "firstName": "E2E", + "lastName": "Webkit", + "enabled": "true", + "credentials": [ + { + "type": "password", + "value": "password-e2e-webkit" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-firefox", + "email": "user@firefox.e2e", + "firstName": "E2E", + "lastName": "Firefox", + "enabled": "true", + "credentials": [ + { + "type": "password", + "value": "password-e2e-firefox" + } + ], + "realmRoles": ["user"] + } + ], + "roles": { + "realm": [ + { + "id": "1f116065-05b6-4269-80a6-c7d904b584b7", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": "false", + "clientRole": "false", + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + }, + { + "id": "1bfe401a-08fc-4d94-80e0-86c4f5195f99", + "name": "default-roles-meet", + "description": "${role_default-roles}", + "composite": "true", + "composites": { + "realm": ["offline_access", "uma_authorization"], + "client": { + "account": ["view-profile", "manage-account"] + } + }, + "clientRole": "false", + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + }, + { + "id": "8733db03-278a-45ad-a25e-c167fbd95b5a", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": "false", + "clientRole": "false", + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "9dcc0883-e2e5-4671-9159-402bdbe73c57", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "ae911be0-ea2e-466d-93e0-f8e73fa8f444", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e777d332-7205-4b76-8b21-9191a2e85a0d", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b1a95608-d518-4ede-936e-525ab704d363", + "name": "create-client", + "description": "${role_create-client}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "ac58976a-ae55-4d92-a864-b33e21b07c54", + "name": "view-events", + "description": "${role_view-events}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "a149b28f-d252-4ceb-8ba9-8161603c4184", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "00a5b886-7ca4-4fba-90c6-a9071e697d86", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b22d5cc1-879e-4405-8345-cc204fd0fec0", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": "true", + "composites": { + "client": { + "realm-management": [ + "impersonation", + "view-authorization", + "manage-authorization", + "create-client", + "view-events", + "manage-identity-providers", + "manage-clients", + "view-identity-providers", + "query-users", + "manage-users", + "view-clients", + "view-users", + "manage-events", + "view-realm", + "query-realms", + "query-groups", + "manage-realm", + "query-clients" + ] + } + }, + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b3e9faf6-17bf-4f62-abd5-07837806a7e6", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "a8d85f42-023b-48dd-8f49-c9da2b5317ee", + "name": "query-users", + "description": "${role_query-users}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "eb325a4d-db7a-4f6a-a88b-0ff8aa38b0a5", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "267bb612-62f4-4354-abb2-ac6a34bd854b", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": "true", + "composites": { + "client": { + "realm-management": ["query-clients"] + } + }, + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b575be2b-e250-4000-b75e-3038cda8c0dd", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e19cd0bf-8da0-457d-b630-454c611bc1ba", + "name": "view-users", + "description": "${role_view-users}", + "composite": "true", + "composites": { + "client": { + "realm-management": ["query-users", "query-groups"] + } + }, + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "c12145cc-cbdc-4ef3-9774-19b1852811ba", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e7e15b84-4971-4c13-be93-315bb36d30e1", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e03d2989-a620-4918-85ed-3eabd0373bb4", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "daf8d347-4b30-41d6-a431-7b3723dd8e6f", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "432cd3eb-4741-46ba-938a-94ff9dece315", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": "false", + "clientRole": "true", + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "2e713186-38da-44d7-a5a5-19d91ef2dfca", + "name": "read-token", + "description": "${role_read-token}", + "composite": "false", + "clientRole": "true", + "containerId": "41dd8f26-46c2-471a-859e-01886f972ff9", + "attributes": {} + } + ], + "meet": [], + "account": [ + { + "id": "63b1a4e1-a594-4571-99c3-7c5c3efd61ce", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": "true", + "composites": { + "client": { + "account": ["view-consent"] + } + }, + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "36ef5fd6-1167-4ba0-9171-c8cb6cfe904b", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "f984654a-fca5-45d9-bb47-73009eb9bcf0", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "d54168c5-58a5-4f13-9fa8-6dbbee0e4b73", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": "true", + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "092b6808-1ee2-44be-9b5d-085ccd6862b4", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "ddd57af0-2a5e-4f9d-98e5-ec96c8d852ce", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "84c7324a-4724-41fe-8bd4-848ce5cebd5b", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "20d06f75-ea65-4b99-b9ef-2384ffd1de53", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": "false", + "clientRole": "true", + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "1bfe401a-08fc-4d94-80e0-86c4f5195f99", + "name": "default-roles-meet", + "description": "${role_default-roles}", + "composite": "true", + "clientRole": "false", + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec" + }, + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": "false", + "otpSupportedApplications": ["totpAppGoogleName", "totpAppFreeOTPName"], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": ["ES256"], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": "false", + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": "false", + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": ["offline_access"] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": ["manage-account", "view-groups"] + } + ] + }, + "clients": [ + { + "id": "06721011-1061-4ca7-944f-be2a20719e20", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/meet/account/", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/realms/meet/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": "false", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "true", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "987e14a5-caed-40a6-8bac-8c429b74ca48", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/meet/account/", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/realms/meet/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": "false", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "true", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4f958126-eaa1-46d5-967a-3a3c2e2d11f7", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": "false", + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "92da37ad-e8a1-41f1-93c6-541dffa7d601", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": "false", + "consentRequired": "false", + "standardFlowEnabled": "false", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "true", + "serviceAccountsEnabled": "false", + "publicClient": "true", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "41dd8f26-46c2-471a-859e-01886f972ff9", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": "true", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "false", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "869481d0-5774-4e64-bc30-fedc7c58958f", + "clientId": "meet", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "secret": "ThisIsAnExampleKeyForDevPurposeOnly", + "redirectUris": [ + "http://localhost:8070/*", + "http://localhost:8071/*", + "https://meet.127.0.0.1.nip.io/*", + "http://localhost:8088/*", + "http://localhost:3000/*" + ], + "webOrigins": [ + "https://meet.127.0.0.1.nip.io", + "http://localhost:8088", + "http://localhost:8070", + "http://localhost:3000" + ], + "notBefore": 0, + "bearerOnly": "false", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "false", + "frontchannelLogout": "true", + "protocol": "openid-connect", + "attributes": { + "access.token.lifespan": "-1", + "client.secret.creation.time": "1707820779", + "user.info.response.signature.alg": "RS256", + "post.logout.redirect.uris": "http://localhost:8070/*##https://meet.127.0.0.1.nip.io/*##http://localhost:3000/*", + "oauth2.device.authorization.grant.enabled": "false", + "use.jwks.url": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "tls-client-certificate-bound-access-tokens": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "acr.loa.map": "{}", + "require.pushed.authorization.requests": "false", + "display.on.consent.screen": "false", + "client.session.idle.timeout": "-1", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "true", + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": "true", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "false", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "2a4e007a-2fc4-4f43-aace-b93aec9221b4", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/meet/console/", + "surrogateAuthRequired": "false", + "enabled": "true", + "alwaysDisplayInConsole": "false", + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/admin/meet/console/*"], + "webOrigins": ["+"], + "notBefore": 0, + "bearerOnly": "false", + "consentRequired": "false", + "standardFlowEnabled": "true", + "implicitFlowEnabled": "false", + "directAccessGrantsEnabled": "false", + "serviceAccountsEnabled": "false", + "publicClient": "true", + "frontchannelLogout": "false", + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": "false", + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4913be96-5827-46a4-9909-562c2dd5bef6", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "74aeb8e2-a1b6-4897-9eaf-d922becea170", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "994b8f5e-dfc1-4154-a936-347336e6422a", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": "false", + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "d853f97e-80f8-470e-8447-815b289d9ae3", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": "false", + "config": {} + }, + { + "id": "26a9f3ef-cff0-4dee-9fe9-778cd1d2a771", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": "false", + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "af52ccc3-4ecb-49b4-9a67-5d4172f16070", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "efb82630-8835-4de0-944e-ac5ea51eca48", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": "false", + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "2256189a-7970-4244-b496-64cbba3ce582", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "6d7f8b9e-997e-40f8-bae5-83d2647fbeff", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": "false", + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "b83cebb6-f086-48e2-8e5a-9802736342f2", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "b99113c6-ccfb-43d4-acd1-09dd34cdf5bc", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "696211d7-c434-495f-b3a0-a1b88bebfd6e", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": "false", + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "16845bd9-5626-4484-b4c5-00af52d8ad8b", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "5828a7d9-cdc7-456b-a747-16bf83c2f57d", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": "false", + "config": {} + } + ] + }, + { + "id": "ce289e05-eca4-4323-b457-822d39cc6d49", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "abe63488-9a39-4e29-a0a8-824db0887b60", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "15690cfb-e14c-46e8-8494-22a0365a4b0c", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "03cf0e4c-c2a5-4203-88c4-5391d361ba15", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "23b1a1da-2ecc-4db7-8d33-4e9233a81e89", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "26a72777-56eb-4b46-acca-eca8168e29fc", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "4ae1896b-ea82-4604-8f0e-72133fdee05c", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "79712bcf-b7f7-4ca3-b97c-418f48fded9b", + "name": "first name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "first_name", + "jsonType.label": "String" + } + }, + { + "id": "6397c5e9-95ea-4c31-bd44-a8acf1d18472", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "7f741e96-41fe-4021-bbfd-506e7eb94e69", + "name": "last name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "last_name", + "jsonType.label": "String" + } + }, + { + "id": "5ca62964-2d04-4e8e-963d-e3b08cf32d7c", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "954a5dff-cc19-4dde-b996-787f767db4cc", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": "false", + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "1eba19bf-6fa1-4608-ad2d-d4346580c93d", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "e7bdd267-fcce-451f-b3e1-a775cf611dd2", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "a9a8918c-af00-48a5-a8b3-a28a83653f71", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "cd725067-b6ba-42f1-a940-97a16a23cb85", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "a4e1812c-4093-4666-a6b3-03c5d9b5ca9f", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "d6690292-74d1-48ac-855d-2f0f3799829e", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": "false", + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "ce8f1215-0462-4e87-8a3b-18488aee0267", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0ce95430-80aa-4dd6-994b-5a67302ba531", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "8da0d3b1-d609-417e-9adc-1de77549baf9", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "f89a9158-7c03-49b0-8a3c-d0b75e2ce1b4", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "fb109597-e31e-46d7-84c5-62e5fcf32ac8", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "61c135e5-2447-494b-bc70-9612f383be27", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": "false", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": "false", + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": "false", + "adminEventsDetailsEnabled": "false", + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "74dffa9a-5d4f-4ce3-9708-885212f56861", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "48096073-ceae-4e68-a15b-f1aa390dcce5", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "51b0e87c-ee04-4664-a299-f8e49cb7a9ac", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + }, + { + "id": "6379b091-2289-4fe7-894c-c03f1bd0e69b", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "97ae8320-a439-463b-817e-05bd4a6c39d1", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "49131ffc-4831-4e3e-a466-f9f08aa1bee0", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "e12647d2-e21f-49bc-a8c6-28154c5544d2", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-property-mapper", + "saml-user-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper" + ] + } + }, + { + "id": "c9f00ef2-00d9-44bd-9b6c-3b3bf57e44ba", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + } + ], + "org.keycloak.userprofile.UserProfileProvider": [ + { + "id": "96260850-72a5-4b49-b96b-5a33d0b5337d", + "providerId": "declarative-user-profile", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "55d93b4d-fe05-46a1-a832-36f380aaddf7", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + }, + { + "id": "bee288b4-ecdf-4ec4-8c31-ee330f1e8f95", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": ["100"], + "algorithm": ["HS256"] + } + }, + { + "id": "2aa8f54d-8b4b-4eb7-a05b-89211f544358", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": ["100"], + "algorithm": ["RSA-OAEP"] + } + }, + { + "id": "23ad48f4-2275-4a0d-aa0d-1e0691f9c620", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + } + ] + }, + "internationalizationEnabled": "false", + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "0c349304-21fd-47ff-8dc6-46efb107b7e9", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "cf1ed416-7274-4804-88bf-4261b0bacdc6", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "basic-auth-otp", + "authenticatorFlow": "false", + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": "false", + "requirement": "DISABLED", + "priority": 30, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "d949f1f1-4622-49ec-b74a-4b8a58c653d2", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "3deb6d9d-2064-410c-af99-b1601cd9b1c4", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "f777c4be-f7d1-453e-a9d7-a2a235b7975b", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "1bc12f49-e2ef-42bd-959a-0983e1cd4d65", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "Account verification options", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "324cdcf5-8f31-4768-9db9-63208f182b39", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "23d17138-8ebd-4195-91d3-614094f62070", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "Handle Existing Account", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "61fec72a-bfd2-42e8-95c1-fa0b76c1cd2b", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "dc00b9a8-fc37-4591-a1ea-07c7f884d394", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": "false", + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": "true", + "flowAlias": "forms", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "4f27245a-49b8-4870-a5e2-f0ea624a792c", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "client-x509", + "authenticatorFlow": "false", + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "5b2c66e1-7bbf-4707-9db8-244269b68164", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": "true", + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "4bcddec4-4260-4f4f-a757-3aff9b1d30f3", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "04a94e38-b7fb-48f6-8d63-5640f835c619", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "User creation or linking", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "bfcf5112-96ac-485a-8663-b02ad41af919", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "e262d10d-ad0d-4d18-bc05-3a44f7d21736", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "true", + "flowAlias": "Authentication Options", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "b671c4b3-22b6-4aac-a1d1-464a2101767c", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": "true", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "true", + "flowAlias": "registration form", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "f570e064-0e62-4eae-8087-8b06751b8f33", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": "false", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "registration-profile-action", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 40, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": "false", + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "07124099-1d10-4148-ac06-4b0b700908da", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticator": "reset-password", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + }, + { + "authenticatorFlow": "true", + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": "true", + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": "false" + } + ] + }, + { + "id": "0a5fa089-f987-4903-9170-36565edda152", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": "true", + "builtIn": "true", + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": "false", + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": "false", + "userSetupAllowed": "false" + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "d2818365-2189-4003-9817-0ad5368e37f3", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "72508559-0176-4eee-a77e-0795d652be12", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": "true", + "defaultAction": "false", + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": "false", + "defaultAction": "false", + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": "true", + "defaultAction": "false", + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": "true", + "defaultAction": "false", + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": "true", + "defaultAction": "false", + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": "false", + "defaultAction": "false", + "priority": 60, + "config": {} + }, + { + "alias": "CONFIGURE_RECOVERY_AUTHN_CODES", + "name": "Recovery Authentication Codes", + "providerId": "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled": "true", + "defaultAction": "false", + "priority": 70, + "config": {} + }, + { + "alias": "UPDATE_EMAIL", + "name": "Update Email", + "providerId": "UPDATE_EMAIL", + "enabled": "true", + "defaultAction": "false", + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": "true", + "defaultAction": "false", + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": "true", + "defaultAction": "false", + "priority": 80, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": "true", + "defaultAction": "false", + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "20.0.1", + "userManagedAccessAllowed": "false", + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } + } + diff --git a/docs/examples/livekit.values.yaml b/docs/examples/livekit.values.yaml new file mode 100644 index 00000000..675d8314 --- /dev/null +++ b/docs/examples/livekit.values.yaml @@ -0,0 +1,40 @@ +replicaCount: 1 +terminationGracePeriodSeconds: 18000 + +livekit: + keys: + devkey: secret + log_level: debug + rtc: + use_external_ip: false + port_range_start: 50000 + port_range_end: 60000 + tcp_port: 7881 + redis: + address: redis-master:6379 + password: pass + turn: + enabled: true + udp_port: 443 + domain: livekit.127.0.0.1.nip.io + loadBalancerAnnotations: {} + + +loadBalancer: + type: nginx + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + tls: + - hosts: + - livekit.127.0.0.1.nip.io + secretName: livekit-dinum-cert + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 60 + +nodeSelector: {} +resources: {} diff --git a/docs/examples/meet.values.yaml b/docs/examples/meet.values.yaml new file mode 100644 index 00000000..ac621422 --- /dev/null +++ b/docs/examples/meet.values.yaml @@ -0,0 +1,107 @@ +image: + repository: lasuite/meet-backend + pullPolicy: Always + tag: "latest" + +backend: + replicas: 1 + envVars: + DJANGO_CSRF_TRUSTED_ORIGINS: https://meet.127.0.0.1.nip.io,http://meet.127.0.0.1.nip.io + DJANGO_CONFIGURATION: Production + DJANGO_ALLOWED_HOSTS: meet.127.0.0.1.nip.io + DJANGO_SECRET_KEY: AgoodOrAbadKey + DJANGO_SETTINGS_MODULE: meet.settings + DJANGO_SILENCED_SYSTEM_CHECKS: security.W004, security.W008 + DJANGO_SUPERUSER_PASSWORD: admin + DJANGO_EMAIL_HOST: "mailcatcher" + DJANGO_EMAIL_PORT: 1025 + DJANGO_EMAIL_USE_SSL: False + OIDC_OP_JWKS_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/certs + OIDC_OP_AUTHORIZATION_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/auth + OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token + OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo + OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/session/end + OIDC_RP_CLIENT_ID: meet + OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly + OIDC_RP_SIGN_ALGO: RS256 + OIDC_RP_SCOPES: "openid email" + OIDC_REDIRECT_ALLOWED_HOSTS: https://meet.127.0.0.1.nip.io + OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}" + OIDC_VERIFY_SSL: False + LOGIN_REDIRECT_URL: https://meet.127.0.0.1.nip.io + LOGIN_REDIRECT_URL_FAILURE: https://meet.127.0.0.1.nip.io + LOGOUT_REDIRECT_URL: https://meet.127.0.0.1.nip.io + DB_HOST: postgresql + DB_NAME: meet + DB_USER: dinum + DB_PASSWORD: pass + DB_PORT: 5432 + POSTGRES_DB: meet + POSTGRES_USER: dinum + POSTGRES_PASSWORD: pass + REDIS_URL: redis://default:pass@redis-master:6379/1 + STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage + LIVEKIT_API_SECRET: secret + LIVEKIT_API_KEY: devkey + LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/ + ALLOW_UNREGISTERED_ROOMS: False + FRONTEND_SILENCE_LIVEKIT_DEBUG: False + FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}" + + + migrate: + command: + - "/bin/sh" + - "-c" + - | + python manage.py migrate --no-input && + python manage.py create_demo --force + restartPolicy: Never + + command: + - "gunicorn" + - "-c" + - "/usr/local/etc/gunicorn/meet.py" + - "meet.wsgi:application" + - "--reload" + + createsuperuser: + command: + - "/bin/sh" + - "-c" + - | + python manage.py createsuperuser --email admin@example.com --password admin + restartPolicy: Never + +frontend: + envVars: + VITE_PORT: 8080 + VITE_HOST: 0.0.0.0 + VITE_API_BASE_URL: https://meet.127.0.0.1.nip.io/ + + replicas: 1 + + image: + repository: lasuite/meet-frontend + pullPolicy: Always + tag: "latest" + +ingress: + enabled: true + host: meet.127.0.0.1.nip.io + +ingressAdmin: + enabled: true + host: meet.127.0.0.1.nip.io + +posthog: + ingress: + enabled: false + ingressAssets: + enabled: false + +summary: + replicas: 0 + +celery: + replicas: 0 diff --git a/docs/examples/postgresql.values.yaml b/docs/examples/postgresql.values.yaml new file mode 100644 index 00000000..2465a5b1 --- /dev/null +++ b/docs/examples/postgresql.values.yaml @@ -0,0 +1,7 @@ +auth: + username: dinum + password: pass + database: meet +tls: + enabled: true + autoGenerated: true diff --git a/docs/examples/redis.values.yaml b/docs/examples/redis.values.yaml new file mode 100644 index 00000000..b56c2a1a --- /dev/null +++ b/docs/examples/redis.values.yaml @@ -0,0 +1,3 @@ +auth: + password: pass +architecture: standalone diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 00000000..ab1ddedc --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,226 @@ +# Installation on a k8s cluster + +This document is a step-by-step guide that describes how to install Visio on a k8s cluster without AI features. + + +## Prerequisites + +- k8s cluster with an nginx-ingress controller +- an OIDC provider (if you don't have one, we will provide an example) +- a LiveKit server (if you don't have one, we will provide an example) +- a PostgreSQL server (if you don't have one, we will provide an example) +- a Memcached server (if you don't have one, we will provide an example) + +### Test cluster + +If you do not have a test cluster, you can install everything on a local kind cluster. In this case, the simplest way is to use our script **bin/start-kind.sh**. + +To be able to use the script, you will need to install: + +- Docker (https://docs.docker.com/desktop/) +- Kind (https://kind.sigs.k8s.io/docs/user/quick-start/#installation) +- Mkcert (https://github.com/FiloSottile/mkcert#installation) +- Helm (https://helm.sh/docs/intro/quickstart/#install-helm) + +``` +$ ./bin/start-kind.sh +0. Create ca +The local CA is already installed in the system trust store! 👍 +The local CA is already installed in the Firefox and/or Chrome/Chromium trust store! 👍 + + +Created a new certificate valid for the following names 📜 + - "127.0.0.1.nip.io" + - "*.127.0.0.1.nip.io" + +Reminder: X.509 wildcards only go one level deep, so this won't match a.b.127.0.0.1.nip.io ℹī¸ + +The certificate is at "./127.0.0.1.nip.io+1.pem" and the key at "./127.0.0.1.nip.io+1-key.pem" ✅ + +It will expire on 23 March 2027 🗓 + +1. Create registry container unless it already exists +2. Create kind cluster with containerd registry config dir enabled +Creating cluster "visio" ... + ✓ Ensuring node image (kindest/node:v1.27.3) đŸ–ŧ + ✓ Preparing nodes đŸ“Ļ + ✓ Writing configuration 📜 + ✓ Starting control-plane 🕹ī¸ + ✓ Installing CNI 🔌 + ✓ Installing StorageClass 💾 +Set kubectl context to "kind-visio" +You can now use your cluster with: + +kubectl cluster-info --context kind-visio + +Thanks for using kind! 😊 +3. Add the registry config to the nodes +4. Connect the registry to the cluster network if not already connected +5. Document the local registry +configmap/local-registry-hosting created +Warning: resource configmaps/coredns is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically. +configmap/coredns configured +deployment.apps/coredns restarted +6. Install ingress-nginx +namespace/ingress-nginx created +serviceaccount/ingress-nginx created +serviceaccount/ingress-nginx-admission created +role.rbac.authorization.k8s.io/ingress-nginx created +role.rbac.authorization.k8s.io/ingress-nginx-admission created +clusterrole.rbac.authorization.k8s.io/ingress-nginx created +clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created +rolebinding.rbac.authorization.k8s.io/ingress-nginx created +rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created +clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created +clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created +configmap/ingress-nginx-controller created +service/ingress-nginx-controller created +service/ingress-nginx-controller-admission created +deployment.apps/ingress-nginx-controller created +job.batch/ingress-nginx-admission-create created +job.batch/ingress-nginx-admission-patch created +ingressclass.networking.k8s.io/nginx created +validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created +secret/mkcert created +deployment.apps/ingress-nginx-controller patched +7. Setup namespace +namespace/meet created +Context "kind-visio" modified. +secret/mkcert created +$ kind get clusters +visio +$ kubectl -n ingress-nginx get po +NAME READY STATUS RESTARTS AGE +ingress-nginx-admission-create-jgnc9 0/1 Completed 0 2m44s +ingress-nginx-admission-patch-wrt47 0/1 Completed 0 2m44s +ingress-nginx-controller-57c548c4cd-9xwt6 1/1 Running 0 2m44s +``` +When your k8s cluster is ready, you can start the deployment. This cluster is special because it uses the *.127.0.0.1.nip.io domain and mkcert certificates to have full HTTPS support and easy domain name management. + +Please remember that *.127.0.0.1.nip.io will always resolve to 127.0.0.1, except in the k8s cluster where we configure CoreDNS to answer with the ingress-nginx service IP. + +## Preparation + +### What will you use to authenticate your users ? + +Visio uses OIDC, so if you already have an OIDC provider, obtain the necessary information to use it. In the next step, we will see how to configure Django (and thus Visio) to use it. If you do not have a provider, we will show you how to deploy a local Keycloak instance (this is not a production deployment, just a demo). + +``` +$ kubectl create namespace meet +$ kubectl config set-context --current --namespace=meet +$ helm install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak -f examples/keycloak.values.yaml +$ #wait until +$ kubectl get po +NAME READY STATUS RESTARTS AGE +keycloak-0 1/1 Running 0 6m48s +keycloak-postgresql-0 1/1 Running 0 6m48s +``` + +From here the important informations you will need are : + +``` +OIDC_OP_JWKS_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/certs +OIDC_OP_AUTHORIZATION_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/auth +OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token +OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo +OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/session/end +OIDC_RP_CLIENT_ID: meet +OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly +OIDC_RP_SIGN_ALGO: RS256 +OIDC_RP_SCOPES: "openid email" +``` + +You can find these values in **examples/keycloak.values.yaml** + +### Find livekit server connexion values + +Visio use livekit for streaming part so if you have a livekit provider, obtain the necessary information to use it. If you do not have a provider, you can install a livekit testing environment as follow : + +Livekit need a redis (and meet too) so we will start by deploying a redis : + +``` +$ helm install redis oci://registry-1.docker.io/bitnamicharts/redis -f examples/redis.values.yaml +$ kubectl get po +NAME READY STATUS RESTARTS AGE +keycloak-0 1/1 Running 0 26m +keycloak-postgresql-0 1/1 Running 0 26m +redis-master-0 1/1 Running 0 35s +``` +When the redis is ready we can deploy livekit-server. + +``` +$ helm repo add livekit https://helm.livekit.io +$ helm repo update +$ helm install livekit livekit/livekit-server -f examples/livekit.values.yaml +$ kubectl get po +NAME READY STATUS RESTARTS AGE +keycloak-0 1/1 Running 0 30m +keycloak-postgresql-0 1/1 Running 0 30m +livekit-livekit-server-5c5fb87f7f-ct6x5 1/1 Running 0 7s +redis-master-0 1/1 Running 0 4m30s +$ curl https://livekit.127.0.0.1.nip.io +OK +``` + +From here important informations you will need are : + +``` +LIVEKIT_API_SECRET: secret +LIVEKIT_API_KEY: devkey +LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/ +REDIS_URL: redis://default:pass@redis-master:6379/1 +CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1 +CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1 +``` + +### Find postgresql connexion values + +Visio uses a postgresql db as backend so if you have a provider, obtain the necessary information to use it. If you do not have, you can install a postgresql testing environment as follow: + +``` +$ helm install postgresql oci://registry-1.docker.io/bitnamicharts/postgresql -f examples/postgresql.values.yaml +$ kubectl get po +NAME READY STATUS RESTARTS AGE +keycloak-0 1/1 Running 0 45m +keycloak-postgresql-0 1/1 Running 0 45m +livekit-livekit-server-5c5fb87f7f-ct6x5 1/1 Running 0 15m +postgresql-0 1/1 Running 0 50s +redis-master-0 1/1 Running 0 19 +``` +From here important informations you will need are : + +``` +DB_HOST: postgres-postgresql +DB_NAME: meet +DB_USER: dinum +DB_PASSWORD: pass +DB_PORT: 5432 +POSTGRES_DB: meet +POSTGRES_USER: dinum +POSTGRES_PASSWORD: pass +``` + +## Deployment + +Now you are ready to deploy Visio without AI. AI requiered more dependancies (openai API and a docs deployment to push resumes). To deploy meet you need to provide all previous informations to the helm chart. + +``` +$ helm repo add meet https://numerique-gouv.github.io/meet/ +$ helm repo update +$ helm install meet meet/meet -f examples/meet.values.yaml +``` + +## Test your deployment + +In order to test your deployment you have to login to your instance. If you use exclusively our examples you can do : + +``` +$ kubectl get ingress +NAME CLASS HOSTS ADDRESS PORTS AGE +keycloak keycloak.127.0.0.1.nip.io localhost 80 58m +livekit-livekit-server livekit.127.0.0.1.nip.io localhost 80, 443 106m +meet meet.127.0.0.1.nip.io localhost 80, 443 52m +meet-admin meet.127.0.0.1.nip.io localhost 80, 443 52m +``` + +You can use Visio on https://meet.127.0.0.1.nip.io. The provisionning user in keycloak is meet/meet. From 3af31819e22ed401a75fb39f9458010d3678f6e0 Mon Sep 17 00:00:00 2001 From: Jacques ROUSSEL Date: Tue, 24 Dec 2024 08:51:39 +0100 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=91=B7(helm)=20change=20github=20acti?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use another github action to avoid chart replacement to every push --- .github/workflows/release-helm-chart.yaml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release-helm-chart.yaml b/.github/workflows/release-helm-chart.yaml index 3f17aacf..339f73a3 100644 --- a/.github/workflows/release-helm-chart.yaml +++ b/.github/workflows/release-helm-chart.yaml @@ -1,9 +1,10 @@ -name: Release Charts +name: Release Chart +run-name: Release Chart on: push: - branches: - - main + paths: + - src/helm/meet/** jobs: release: @@ -21,9 +22,14 @@ jobs: - name: Cleanup run: rm -rf ./src/helm/extra - - name: Publish Helm charts - uses: stefanprodan/helm-gh-pages@v1.7.0 + - name: Install Helm + uses: azure/setup-helm@v4 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 with: - charts_dir: ./src/helm/ - linting: off - token: ${{ secrets.GITHUB_TOKEN }} + charts_dir: ./src/helm + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From 60c00b0edf0fe1ab3db12ede6588e5421e5d4821 Mon Sep 17 00:00:00 2001 From: Jacques ROUSSEL Date: Tue, 24 Dec 2024 15:00:17 +0100 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=91=B7(helm)=20improve=20local=20stac?= =?UTF-8?q?k?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the common create_cluster.sh in order to improve cooperation between teams --- bin/start-kind.sh | 140 +-------------------------------- docs/examples/meet.values.yaml | 16 +++- 2 files changed, 17 insertions(+), 139 deletions(-) diff --git a/bin/start-kind.sh b/bin/start-kind.sh index 2d1f46bc..326e61cd 100755 --- a/bin/start-kind.sh +++ b/bin/start-kind.sh @@ -1,139 +1,3 @@ -#!/bin/sh -set -o errexit +#!/bin/bash -CURRENT_DIR=$(pwd) - -echo "0. Create ca" -# 0. Create ca -mkcert -install -cd /tmp -mkcert "127.0.0.1.nip.io" "*.127.0.0.1.nip.io" -cd $CURRENT_DIR - -echo "1. Create registry container unless it already exists" -# 1. Create registry container unless it already exists -reg_name='kind-registry' -reg_port='5001' -if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then - docker run \ - -d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \ - registry:2 -fi - -echo "2. Create kind cluster with containerd registry config dir enabled" -# 2. Create kind cluster with containerd registry config dir enabled -# TODO: kind will eventually enable this by default and this patch will -# be unnecessary. -# -# See: -# https://github.com/kubernetes-sigs/kind/issues/2875 -# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration -# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md -cat <