diff options
Diffstat (limited to 'ops/keycloak')
-rw-r--r-- | ops/keycloak/.gitignore | 3 | ||||
-rw-r--r-- | ops/keycloak/README.md | 18 | ||||
-rw-r--r-- | ops/keycloak/clients.tf | 92 | ||||
-rw-r--r-- | ops/keycloak/default.nix | 8 | ||||
-rw-r--r-- | ops/keycloak/main.tf | 34 | ||||
-rw-r--r-- | ops/keycloak/user_sources.tf | 21 |
6 files changed, 176 insertions, 0 deletions
diff --git a/ops/keycloak/.gitignore b/ops/keycloak/.gitignore new file mode 100644 index 000000000000..017878c614d0 --- /dev/null +++ b/ops/keycloak/.gitignore @@ -0,0 +1,3 @@ +.terraform* +*.tfstate* +.envrc diff --git a/ops/keycloak/README.md b/ops/keycloak/README.md new file mode 100644 index 000000000000..e8ffd700b5e2 --- /dev/null +++ b/ops/keycloak/README.md @@ -0,0 +1,18 @@ +Terraform for Keycloak +====================== + +This contains the Terraform configuration for deploying TVL's Keycloak +instance (which lives at `auth.tvl.fyi`). + +Secrets are needed for applying this. The encrypted file +`//ops/secrets/tf-keycloak.age` contains `export` calls which should +be sourced, for example via `direnv`, by users with the appropriate +credentials. + +An example `direnv` configuration used by tazjin is this: + +``` +# //ops/secrets/.envrc +source_up +eval $(age --decrypt -i ~/.ssh/id_ed25519 $(git rev-parse --show-toplevel)/ops/secrets/tf-keycloak.age) +``` diff --git a/ops/keycloak/clients.tf b/ops/keycloak/clients.tf new file mode 100644 index 000000000000..5f2fd21a3557 --- /dev/null +++ b/ops/keycloak/clients.tf @@ -0,0 +1,92 @@ +# All Keycloak clients, that is applications which authenticate +# through Keycloak. +# +# Includes first-party (i.e. TVL-hosted) and third-party clients. + +resource "keycloak_openid_client" "grafana" { + realm_id = keycloak_realm.tvl.id + client_id = "grafana" + name = "Grafana" + enabled = true + access_type = "CONFIDENTIAL" + standard_flow_enabled = true + base_url = "https://status.tvl.su" + + valid_redirect_uris = [ + "https://status.tvl.su/*", + ] +} + +resource "keycloak_openid_client" "gerrit" { + realm_id = keycloak_realm.tvl.id + client_id = "gerrit" + name = "TVL Gerrit" + enabled = true + access_type = "CONFIDENTIAL" + standard_flow_enabled = true + base_url = "https://cl.tvl.fyi" + description = "TVL's code review tool" + direct_access_grants_enabled = true + exclude_session_state_from_auth_response = false + + valid_redirect_uris = [ + "https://cl.tvl.fyi/*", + ] + + web_origins = [ + "https://cl.tvl.fyi", + ] +} + +resource "keycloak_saml_client" "buildkite" { + realm_id = keycloak_realm.tvl.id + client_id = "https://buildkite.com" + name = "Buildkite" + base_url = "https://buildkite.com/sso/tvl" + + client_signature_required = false + assertion_consumer_post_url = "https://buildkite.com/sso/~/1531aca5-f49c-4151-8832-a451e758af4c/saml/consume" + + valid_redirect_uris = [ + "https://buildkite.com/sso/~/1531aca5-f49c-4151-8832-a451e758af4c/saml/consume" + ] +} + +resource "keycloak_saml_user_attribute_protocol_mapper" "buildkite_email" { + realm_id = keycloak_realm.tvl.id + client_id = keycloak_saml_client.buildkite.id + name = "buildkite-email-mapper" + user_attribute = "email" + saml_attribute_name = "email" + saml_attribute_name_format = "Unspecified" +} + +resource "keycloak_saml_user_attribute_protocol_mapper" "buildkite_name" { + realm_id = keycloak_realm.tvl.id + client_id = keycloak_saml_client.buildkite.id + name = "buildkite-name-mapper" + user_attribute = "displayName" + saml_attribute_name = "name" + saml_attribute_name_format = "Unspecified" +} + +resource "keycloak_openid_client" "oauth2_proxy" { + realm_id = keycloak_realm.tvl.id + client_id = "oauth2-proxy" + name = "TVL OAuth2 Proxy" + enabled = true + access_type = "CONFIDENTIAL" + standard_flow_enabled = true + + valid_redirect_uris = [ + "https://login.tvl.fyi/oauth2/callback", + "http://localhost:4774/oauth2/callback", + ] +} + +resource "keycloak_openid_audience_protocol_mapper" "oauth2_proxy_audience" { + realm_id = keycloak_realm.tvl.id + client_id = keycloak_openid_client.oauth2_proxy.id + name = "oauth2-proxy-audience" + included_custom_audience = keycloak_openid_client.oauth2_proxy.client_id +} diff --git a/ops/keycloak/default.nix b/ops/keycloak/default.nix new file mode 100644 index 000000000000..5757debd1a39 --- /dev/null +++ b/ops/keycloak/default.nix @@ -0,0 +1,8 @@ +{ depot, pkgs, ... }: + +depot.nix.readTree.drvTargets { + # Provide a Terraform wrapper with the right provider installed. + terraform = pkgs.terraform.withPlugins (p: [ + p.keycloak + ]); +} diff --git a/ops/keycloak/main.tf b/ops/keycloak/main.tf new file mode 100644 index 000000000000..819267ff96c5 --- /dev/null +++ b/ops/keycloak/main.tf @@ -0,0 +1,34 @@ +# Configure TVL Keycloak instance. +# +# TODO(tazjin): Configure GitHub/GitLab IDP + +terraform { + required_providers { + keycloak = { + source = "mrparkers/keycloak" + } + } + + backend "s3" { + endpoint = "https://objects.dc-sto1.glesys.net" + bucket = "tvl-state" + key = "terraform/tvl-keycloak" + region = "glesys" + + skip_credentials_validation = true + skip_region_validation = true + skip_metadata_api_check = true + } +} + +provider "keycloak" { + client_id = "terraform" + url = "https://auth.tvl.fyi" +} + +resource "keycloak_realm" "tvl" { + realm = "TVL" + enabled = true + display_name = "The Virus Lounge" + default_signature_algorithm = "RS256" +} diff --git a/ops/keycloak/user_sources.tf b/ops/keycloak/user_sources.tf new file mode 100644 index 000000000000..3fde6e07cc91 --- /dev/null +++ b/ops/keycloak/user_sources.tf @@ -0,0 +1,21 @@ +# All user sources, that is services from which Keycloak gets user +# information (either by accessing a system like LDAP or integration +# through protocols like OIDC). + +resource "keycloak_ldap_user_federation" "tvl_ldap" { + name = "tvl-ldap" + realm_id = keycloak_realm.tvl.id + enabled = true + connection_url = "ldap://localhost" + users_dn = "ou=users,dc=tvl,dc=fyi" + username_ldap_attribute = "cn" + uuid_ldap_attribute = "cn" + rdn_ldap_attribute = "cn" + full_sync_period = 86400 + trust_email = true + + user_object_classes = [ + "inetOrgPerson", + "organizationalPerson", + ] +} |