Skip to content

Latest commit

 

History

389 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

terraform-keycloak-instance

Engineering controls follow the accepted repository-topology, branching and release-governance, mandatory-CI and artifact-assurance ADRs, together with the Lightning IT secure-SDLC, quality-gate, and software-supply-chain assurance standards. Internal knowledge-base locations are intentionally not published.

Release and Quality Model

This repository follows the Lightning IT shared release and quality model.

See RELEASE.md for:

  • branch and release flow
  • required quality checks
  • test matrix
  • release evidence
  • artifact publishing
  • supported repository-specific release behavior

Repository classification: Terraform Module. Required test profiles: pre-commit, terraform-fmt, terraform-validate, docs. Publishing targets: terraform-registry.

Supported and Tested Platforms

Platform / Product Status Validation
ubuntu-latest Supported Terraform validate
terraform Tested where applicable Terraform validate
keycloak-provider Tested where applicable Terraform validate

CI Latest Release OpenSSF Scorecard OpenSSF Best Practices License: MIT

Terraform Registry: lightning-it/instance/keycloak

Terraform module for configuring a full Keycloak instance using the official keycloak/keycloak provider. It acts as a central, GitOps- friendly source of truth for realms, applications, identity providers, user federation and security policies.

Use cases

  • Provision base realms and platform tenants as code
  • Manage clients, client scopes, roles, and role bindings with repeatable Terraform plans
  • Define groups, default groups, and user/service account assignments consistently across environments
  • Integrate with existing identity directories via LDAP/Kerberos user federation
  • Enforce consistent auth and session policies (SMTP, password/OTP, brute-force detection, events, and timeouts)

Example usage

terraform {
  required_providers {
    keycloak = {
      source  = "keycloak/keycloak"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.6.0, < 2.0.0"
}

provider "keycloak" {
  url           = "https://keycloak.example.com"
  realm         = "master"
  client_id     = "terraform"
  client_secret = "replace-me"
}

module "keycloak_instance" {
  source  = "lightning-it/instance/keycloak"
  version = "1.0.0" # or the current version

  realms = [
    {
      name         = "demo01"
      display_name = "Demo 01"
    },
    {
      name         = "demo02"
      display_name = "Demo 02"
    }
  ]
}

Additional ready-to-run samples mirroring the test fixtures live in:

  • examples/keycloak-smoke (minimal realm)
  • examples/keycloak-advanced (broader feature coverage)
  • examples/keycloak-empty (baseline wiring with everything else omitted)

Example with clients and roles

module "keycloak_instance" {
  source  = "lightning-it/instance/keycloak"
  version = "1.0.0"

  realms = [
    {
      name         = "demo01"
      display_name = "Demo 01"
    }
  ]

  clients = [
    {
      client_id   = "frontend"
      client_type = "public"
      realm       = "demo01"
      name        = "Frontend App"
    }
  ]

  realm_roles = [
    {
      name        = "platform-admin"
      realm       = "demo01"
      description = "Platform administrator"
    }
  ]

  client_roles = [
    {
      client_id   = "frontend"
      realm       = "demo01"
      name        = "app-reader"
      description = "Read access to frontend app"
    }
  ]

  groups = [
    {
      name   = "admins"
      realm  = "demo01"
      attributes = {
        team = ["platform"]
      }
    }
  ]

  users = [
    {
      username   = "alice"
      realm      = "demo01"
      email      = "alice@example.com"
      first_name = "Alice"
      last_name  = "Admin"
      enabled    = true
      initial_password = {
        value     = "ChangeMe123!"
        temporary = true
      }
    }
  ]

  identity_providers = [
    {
      name               = "google"
      alias              = "google"
      realm              = "demo01"
      provider_type      = "oidc"
      enabled            = true
      client_id          = "google-client-id"
      client_secret      = "google-client-secret"
      authorization_url  = "https://accounts.google.com/o/oauth2/v2/auth"
      token_url          = "https://oauth2.googleapis.com/token"
      userinfo_url       = "https://openidconnect.googleapis.com/v1/userinfo"
      issuer             = "https://accounts.google.com"
      default_scopes     = ["openid", "email", "profile"]
      trust_email        = true
      hide_on_login_page = false
    }
  ]
}

Testing

For local testing against a Dockerized Keycloak 26 instance:

make test-keycloak

This will:

  • start a local Keycloak container (tests/keycloak-smoke/docker-compose.yml)
  • run terraform init/apply in tests/keycloak-smoke, tests/keycloak-advanced, and tests/keycloak-empty via the container-wunder-devtools-ee image
  • tear down the Keycloak container again

Future scope

This module started as a realms-only foundation and has been extended to cover clients and client scopes, roles and role bindings, groups and default groups, users and service accounts, identity providers, auth policies, themes, events, sessions and user federation.

Future work may include more advanced features such as:

  • user federation mappers and fine-grained tuning
  • user profile configuration
  • custom authentication flows / executions
  • client authorization services (fine-grained IAM policies)
  • keystore and certificate management

If you tell me you’re ready to move from “realms-only” to the fuller scope (clients, roles, users, IdPs, etc.), we can turn those Codex prompts into a concrete plan for how to grow this module in a way that still feels clean and maintainable.

Security & production notes

  • Do not check real secrets (SMTP passwords, LDAP bind credentials, IdP client secrets, etc.) into version control.
  • Use secret managers or Terraform Cloud/HCP/CI variables for sensitive values.
  • Review password policies, brute-force settings, and token/session lifetimes carefully before using this in production realms.
  • Treat the examples in this README as starting points, not production defaults.

Requirements

Name Version
terraform >= 1.6.0, < 2.0.0
keycloak ~> 5.0

Providers

No providers.

Modules

Name Source Version
clients ./modules/clients n/a
groups_users ./modules/groups_users n/a
idps_federation ./modules/idps_federation n/a
realms ./modules/realms n/a
roles ./modules/roles n/a

Resources

No resources.

Inputs

Name Description Type Default Required
auth_flow_settings Authentication flow and login UX settings per realm.
list(object({
realm = string
login_with_email_allowed = optional(bool)
duplicate_emails_allowed = optional(bool)
reset_password_allowed = optional(bool)
remember_me = optional(bool)
verify_email = optional(bool)
registration_allowed = optional(bool)
registration_email_as_username = optional(bool)
}))
[] no
bruteforce_settings Brute-force protection settings per realm.
list(object({
realm = string
enabled = bool
permanent_lockout = bool
max_login_failures = number
wait_increment_seconds = number
quick_login_check_milli = number
minimum_quick_login_wait_seconds = number
max_failure_wait_seconds = number
failure_reset_time_seconds = number
}))
[] no
client_roles Client-specific roles to configure.
list(object({
client_id = string
name = string
realm = optional(string)
description = optional(string)
composite = optional(bool)
composites = optional(list(string))
}))
[] no
client_scopes List of reusable client scopes.
list(object({
name = string
realm = optional(string)
description = optional(string)
protocol = optional(string)
mappers = optional(list(object({
name = string
protocol = optional(string)
protocol_mapper = string
consent_required = optional(bool)
consent_text = optional(string)
config = optional(map(string))
})))
}))
[] no
clients List of Keycloak clients to configure for this instance.
list(object({
client_id = string
client_type = string
name = optional(string)
realm = optional(string)
redirect_uris = optional(list(string))
web_origins = optional(list(string))
base_url = optional(string)
standard_flow_enabled = optional(bool)
implicit_flow_enabled = optional(bool)
direct_access_grants_enabled = optional(bool)
service_accounts_enabled = optional(bool)
frontchannel_logout_enabled = optional(bool)
default_scopes = optional(list(string))
optional_scopes = optional(list(string))
}))
[] no
custom_theme_hooks Optional hooks or metadata describing custom theme deployments.
list(object({
name = string
realm = optional(string)
source_path = optional(string)
notes = optional(string)
}))
[] no
default_groups Default groups to assign to new users per realm.
list(object({
realm = string
names = list(string)
}))
[] no
event_listener_hooks Optional metadata for custom event listener deployments.
list(object({
name = string
realm = optional(string)
target_url = optional(string)
notes = optional(string)
}))
[] no
event_settings Event configuration per realm (enabled events, storage, listeners).
list(object({
realm = string
events_enabled = optional(bool)
events_expiration = optional(number)
events_listeners = optional(list(string))
enabled_event_types = optional(list(string))
admin_events_enabled = optional(bool)
admin_events_details_enabled = optional(bool)
}))
[] no
groups List of Keycloak groups to create, including optional attributes and hierarchy.
list(object({
name = string
realm = optional(string)
parent = optional(string)
attributes = optional(map(list(string)))
path = optional(string)
}))
[] no
identity_provider_mappers List of identity provider mappers to map external attributes/claims into Keycloak.
list(object({
identity_provider_alias = string
realm = optional(string)
name = string
mapper_type = string
config = optional(map(string))
}))
[] no
identity_providers List of identity providers (OIDC/SAML) to configure for this Keycloak instance.
list(object({
name = string
realm = optional(string)
provider_type = string
enabled = optional(bool)
alias = optional(string)
display_name = optional(string)
trust_email = optional(bool)
store_token = optional(bool)
link_only = optional(bool)
hide_on_login_page = optional(bool)

# OIDC-specific
client_id = optional(string)
client_secret = optional(string)
authorization_url = optional(string)
token_url = optional(string)
userinfo_url = optional(string)
issuer = optional(string)
jwks_url = optional(string)
default_scopes = optional(list(string))

# SAML-specific
single_sign_on_service_url = optional(string)
single_logout_service_url = optional(string)
entity_id = optional(string)
x509_certificate = optional(string)
name_id_policy_format = optional(string)
force_authn = optional(bool)
}))
[] no
kerberos_user_federations Kerberos user federation providers per realm.
list(object({
realm = string
name = string
enabled = optional(bool)
priority = optional(number)
kerberos_realm = string
server_principal = string
key_tab = string
debug = optional(bool)
allow_password_auth = optional(bool)
allow_kerberos_auth = optional(bool)
update_profile_first_login = optional(bool)
}))
[] no
ldap_user_federations LDAP user federation providers per realm.
list(object({
realm = string
name = string
enabled = optional(bool)
priority = optional(number)
edit_mode = optional(string)
import_enabled = optional(bool)
sync_registrations = optional(bool)
vendor = optional(string)
username_ldap_attribute = optional(string)
rdn_ldap_attribute = optional(string)
uuid_ldap_attribute = optional(string)
user_object_classes = optional(list(string))
connection_url = string
users_dn = string
bind_dn = optional(string)
bind_credential = optional(string)
use_truststore_spi = optional(string)
trust_email = optional(bool)
pagination = optional(bool)
start_tls = optional(bool)
}))
[] no
localization_settings Localization settings per realm (internationalization and locales).
list(object({
realm = string
internationalization_enabled = optional(bool)
supported_locales = optional(list(string))
default_locale = optional(string)
}))
[] no
otp_settings OTP/MFA configuration per realm.
list(object({
realm = string
otp_type = optional(string)
otp_alg = optional(string)
otp_digits = optional(number)
otp_initial_counter = optional(number)
otp_look_ahead_window = optional(number)
otp_period = optional(number)
}))
[] no
password_policies Password policies per realm.
list(object({
realm = string
policies = list(string)
}))
[] no
realm_roles Realm-level roles to configure.
list(object({
name = string
realm = optional(string)
description = optional(string)
composite = optional(bool)
composites = optional(list(string))
}))
[] no
realms List of Keycloak realms to manage with this module.
list(object({
# Required
name = string

# Optional fields — handled with try()/coalesce() in main.tf
display_name = optional(string)
enabled = optional(bool)
login_theme = optional(string)
registration_allowed = optional(bool)
remember_me = optional(bool)
login_with_email_allowed = optional(bool)
}))
[] no
role_bindings Role bindings to users and groups.
list(object({
realm = string
user_id = optional(string)
username = optional(string)
group_id = optional(string)
group_name = optional(string)
realm_roles = optional(list(string))
client_roles = optional(map(list(string)))
}))
[] no
service_accounts Configuration for client service accounts, including optional role assignments.
list(object({
client_id = string
realm = optional(string)
enabled = optional(bool)
attributes = optional(map(list(string)))
realm_roles = optional(list(string))
client_roles = optional(map(list(string)))
}))
[] no
session_settings Session timeout settings per realm.
list(object({
realm = string
sso_session_idle_timeout = optional(number)
sso_session_max_lifespan = optional(number)
sso_session_idle_timeout_remember_me = optional(number)
sso_session_max_lifespan_remember_me = optional(number)
offline_session_idle_timeout = optional(number)
offline_session_max_lifespan = optional(number)
}))
[] no
smtp_settings SMTP settings per realm for outgoing email.
list(object({
realm = string
host = string
port = number
from = string
auth = bool
user = optional(string)
password = optional(string)
ssl = optional(bool)
starttls = optional(bool)
reply_to = optional(string)
from_display = optional(string)
}))
[] no
theme_settings Theme settings per realm (login, account, admin, email).
list(object({
realm = string
login_theme = optional(string)
account_theme = optional(string)
admin_theme = optional(string)
email_theme = optional(string)
}))
[] no
token_settings Token and login timeout settings per realm.
list(object({
realm = string
login_timeout = optional(number)
login_action_timeout = optional(number)
access_token_lifespan = optional(number)
access_token_lifespan_for_implicit_flow = optional(number)
client_session_idle_timeout = optional(number)
client_session_max_lifespan = optional(number)
}))
[] no
users List of users to seed in Keycloak, including credentials and attributes.
list(object({
username = string
realm = optional(string)
enabled = optional(bool)
email = optional(string)
first_name = optional(string)
last_name = optional(string)
attributes = optional(map(list(string)))
required_actions = optional(list(string))
initial_password = optional(object({
value = string
temporary = optional(bool)
}))
}))
[] no

Outputs

Name Description
client_roles Map of configured client roles keyed by "<client_id>:<role_name>".
client_scopes Map of configured client scopes keyed by scope name.
clients Map of configured clients keyed by client_id.
custom_theme_hooks Custom theme hook metadata passed to the module.
default_groups Default groups configured per realm.
event_listener_hooks Event listener hook metadata passed to the module.
event_settings Event configuration per realm.
groups Map of configured groups keyed by "/".
identity_provider_mappers Map of identity provider mappers keyed by "//".
identity_providers Map of configured identity providers keyed by "/".
kerberos_user_federations Map of Kerberos user federation providers keyed by "/".
ldap_user_federations Map of LDAP user federation providers keyed by "/".
localization_settings Localization settings per realm.
realm_roles Map of configured realm roles keyed by ":<role_name>".
realms Map of managed realms, keyed by realm name.
role_bindings Applied role bindings for users and groups.
service_accounts Map of client service account users keyed by "/<client_id>".
session_settings Summary of session timeout settings per realm.
theme_settings Effective theme settings per realm.
token_settings Summary of token timeout settings per realm.
users Map of seeded users keyed by "/".

Contributing

See CONTRIBUTING.md for contribution and review expectations.

License

See LICENSE.

Security

See SECURITY.md for supported versions and vulnerability reporting.

Release and Quality Model

This repository follows the Lightning IT shared release and quality model. The README shows the current supported and tested matrix. Exact per-version validation proof is stored with each GitHub Release as release-evidence.md and release-evidence.json. Releases are created from the protected main branch after a reviewed develop -> main release promotion. Repository checks validate the managed structure, documentation, and release model for this repository type.

See:

Repository classification: Terraform Module. Required test profiles: pre-commit, terraform-fmt, terraform-validate, docs. Publishing targets: terraform-registry.

Compatibility Matrix

Platform / Product Status Validation
ubuntu-latest Supported Terraform validate
terraform Tested where applicable Terraform validate
keycloak-provider Tested where applicable Terraform validate

Validation proof for each released version is stored in the corresponding GitHub Release evidence.

Release Evidence

This repository does not publish release artifacts by default; release evidence is recorded when artifact releases are enabled. The evidence records:

  • tested matrix combinations
  • GitHub Actions run links
  • artifact references
  • publish status
  • security scan status

See GitHub Releases, RELEASE.md, and TESTING.md for the release process and validation model.

About

Terraform module for full Keycloak instance configuration using the official keycloak provider.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages