From c3bc04a6ee59918d863bc030c3dddbd69638c455 Mon Sep 17 00:00:00 2001 From: "ryan-distrust.co" Date: Mon, 15 May 2023 21:51:05 -0400 Subject: [PATCH] k/keycloak: add docs and client secret generator --- kustomizations/keycloak/docs/README.md | 34 +++++++++++++ kustomizations/keycloak/docs/realms.md | 17 +++++++ .../generate-keycloak-client-secret.sh | 49 +++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 kustomizations/keycloak/docs/README.md create mode 100644 kustomizations/keycloak/docs/realms.md create mode 100755 kustomizations/keycloak/scripts/generate-keycloak-client-secret.sh diff --git a/kustomizations/keycloak/docs/README.md b/kustomizations/keycloak/docs/README.md new file mode 100644 index 0000000..3849ec8 --- /dev/null +++ b/kustomizations/keycloak/docs/README.md @@ -0,0 +1,34 @@ +# Initial Setup + +To generate the admin password for Keycloak, run: + +```sh +./scripts/generate-keycloak-secret.sh \ + | sops --encrypt --encrypted-regex '^(data|stringData)$' \ + --input-type=yaml --output-type=yaml /dev/stdin \ + > keycloak-config.enc.yaml +``` + + +# Adding Clients + +Clients are how Keycloak authenticates a user with a third party service. This +happens by enabling a "Flow" when adding a client. The "Standard" flow has the +user's browser get a short-lived authorization token from Keycloak, send the +authorization token to the client, then the client request a long-lived access +token from Keycloak. This way, the access token is never given to the client. +"Direct Access Grants" means that a user may pass their Keycloak credentials to +the client, then the client may use those credentials to authenticate with +Keycloak and get an access token. In this manner, the client still does not +expose the access token to the user, but the user exposes their Keycloak +credentials to the client. + +When a Client is created, the Client Secret can be encrypted to a ksops Secret +using the following script (Forgejo used as an example): + +```sh +./kustomizations/keycloak/scripts/generate-keycloak-client-secret.sh \ + | sops --encrypt --encrypted-regex '^(data|stringData)$' \ + --input-type=yaml --output-type=yaml /dev/stdin \ + > kustomizations/forgejo/keycloak-client-config.enc.yaml +``` diff --git a/kustomizations/keycloak/docs/realms.md b/kustomizations/keycloak/docs/realms.md new file mode 100644 index 0000000..01b7cf3 --- /dev/null +++ b/kustomizations/keycloak/docs/realms.md @@ -0,0 +1,17 @@ +By default, Keycloak configures a "master" realm. This realm is used for +administrative purposes, configuring data in Keycloak. In order for Keycloak to +be useful, realms, clients, and users need to be created. Realms are a +collection of clients and users. Clients are third party services that can use +OAuth2 and OpenID Connect to authenticate users. + +# Distrust (distrust) + +This realm is for members of Distrust, enabling them to log into Distrust +hosted services. + +**Clients:** + +``` +- name: forgejo + credential_type: client_id_and_secret +``` diff --git a/kustomizations/keycloak/scripts/generate-keycloak-client-secret.sh b/kustomizations/keycloak/scripts/generate-keycloak-client-secret.sh new file mode 100755 index 0000000..e598e58 --- /dev/null +++ b/kustomizations/keycloak/scripts/generate-keycloak-client-secret.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +if test -t 1; then + # This is not foolproof. Can easily be beat by doing |cat. This is just to + # make it less likely that secrets are output to terminal. + echo "Error: Not outputting secret to stdout; redirect output to a file or" \ + "pipe output to \`sops\`." >/dev/stderr + exit 1 +fi + +printf_stderr() { + printf "$@" > /dev/stderr +} + +printf_stderr "Keycloak domain: " +read KEYCLOAK_DOMAIN +printf_stderr "Keycloak realm: " +read KEYCLOAK_REALM + +AUTH_PROVIDER_URL="https://${KEYCLOAK_DOMAIN}/realms/${KEYCLOAK_REALM}/.well-known/openid-configuration" +printf_stderr "Attempting to verify OIDC provider.\n" +if ! timeout 1 curl --fail "${AUTH_PROVIDER_URL}" > /dev/null; then + printf_stderr "\n" + printf_stderr "Unable to verify OIDC provider using: ${AUTH_PROVIDER_URL}\n" + exit 1 +fi +printf_stderr "OK!\n" + +printf_stderr "Client key (as configured in Keycloak): " +read AUTH_PROVIDER_KEY +printf_stderr "Client name (as configured for your application): " +read AUTH_PROVIDER_NAME +printf_stderr "Client secret: " +stty -echo +read AUTH_PROVIDER_SECRET +stty echo +echo > /dev/stderr + +cat <