blob: e5abcb07cc379426415fe86f71949003fc555575 [file] [log] [blame]
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Create Keycloak realms
no_log: true
run_once: true
changed_when: false
community.general.keycloak_realm:
# Keycloak settings
auth_keycloak_url: "{{ item.keycloak_server_url }}"
auth_realm: "{{ item.keycloak_user_realm_name }}"
auth_client_id: "{{ item.keycloak_admin_client_id }}"
auth_username: "{{ item.keycloak_admin_user }}"
auth_password: "{{ item.keycloak_admin_password }}"
validate_certs: "{{ cluster_issuer_type != 'self-signed' }}"
# Realm settings
id: "{{ item.keycloak_realm }}"
realm: "{{ item.keycloak_realm }}"
display_name: "{{ item.label }}"
enabled: true
password_policy: "{{ item.keycloak_password_policy | default(keystone_keycloak_realm_default_password_policy | default(omit)) }}"
brute_force_protected: "{{ item.keycloak_brute_force_protected | default(keystone_keycloak_realm_default_brute_force_protected | default(omit)) }}"
failure_factor: "{{ item.keycloak_brute_force_failure_factor | default(keystone_keycloak_realm_default_brute_force_failure_factor | default(omit)) }}"
wait_increment_seconds: "{{ item.keycloak_brute_force_wait_increment_seconds | default(keystone_keycloak_realm_default_brute_force_wait_increment_seconds | default(omit)) }}"
max_failure_wait_seconds: "{{ item.keycloak_brute_force_max_failure_wait_seconds | default(keystone_keycloak_realm_default_brute_force_max_failure_wait_seconds | default(omit)) }}"
max_delta_time_seconds: "{{ item.keycloak_brute_force_max_delta_time_seconds | default(keystone_keycloak_realm_default_brute_force_max_delta_time_seconds | default(omit)) }}"
minimum_quick_login_wait_seconds: "{{ item.keycloak_minimum_quick_login_wait_seconds | default(keystone_keycloak_realm_default_minimum_quick_login_wait_seconds | default(omit)) }}"
quick_login_check_milli_seconds: "{{ item.keycloak_quick_login_check_milli_seconds | default(keystone_keycloak_realm_default_quick_login_check_milli_seconds | default(omit)) }}"
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"
- name: Setup Keycloak Authentication Required Actions (MFA)
community.general.keycloak_authentication_required_actions:
# Keycloak settings
auth_keycloak_url: "{{ item.keycloak_server_url }}"
auth_realm: "{{ item.keycloak_user_realm_name }}"
auth_client_id: "{{ item.keycloak_admin_client_id }}"
auth_username: "{{ item.keycloak_admin_user }}"
auth_password: "{{ item.keycloak_admin_password }}"
validate_certs: "{{ cluster_issuer_type != 'self-signed' }}"
# Realm settings
realm: "{{ item.name }}"
required_actions:
- alias: "CONFIGURE_TOTP"
name: "Configure OTP"
providerId: "CONFIGURE_TOTP"
defaultAction: "{{ item.keycloak_totp_default_action | default(keystone_keycloak_realm_default_totp_default_action | default(omit)) }}"
enabled: true
state: present
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"
- name: Create ConfigMap with all OpenID connect configurations
run_once: true
kubernetes.core.k8s:
template: configmap-openid-metadata.yml.j2
- name: Create Keycloak clients
no_log: true
run_once: true
community.general.keycloak_client:
# Keycloak settings
auth_keycloak_url: "{{ item.keycloak_server_url }}"
auth_realm: "{{ item.keycloak_user_realm_name }}"
auth_client_id: "{{ item.keycloak_admin_client_id }}"
auth_username: "{{ item.keycloak_admin_user }}"
auth_password: "{{ item.keycloak_admin_password }}"
validate_certs: "{{ cluster_issuer_type != 'self-signed' }}"
# Realm settings
realm: "{{ item.keycloak_realm }}"
client_id: "{{ item.keycloak_client_id }}"
secret: "{{ item.keycloak_client_secret }}"
redirect_uris:
- "{{ keystone_oidc_redirect_uri }}"
- "https://{{ openstack_helm_endpoints_horizon_api_host }}/auth/logout/"
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"
- name: Deploy Helm chart
run_once: true
kubernetes.core.helm:
name: "{{ keystone_helm_release_name }}"
chart_ref: "{{ keystone_helm_chart_ref }}"
release_namespace: "{{ keystone_helm_release_namespace }}"
create_namespace: true
kubeconfig: "{{ keystone_helm_kubeconfig }}"
values: "{{ _keystone_helm_values | combine(keystone_helm_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: identity
openstack_helm_ingress_service_name: keystone-api
openstack_helm_ingress_service_port: 5000
openstack_helm_ingress_annotations: "{{ keystone_ingress_annotations }}"
openstack_helm_ingress_class_name: "{{ keystone_ingress_class_name }}"
- name: Validate if ingress is reachable
ansible.builtin.uri:
url: "https://{{ openstack_helm_endpoints_keystone_api_host }}"
status_code: [300]
register: keystone_ingress_validate
until: keystone_ingress_validate.status == 300
retries: 120
delay: 1
- name: Wait until identity service ready
kubernetes.core.k8s_info:
api_version: apps/v1
kind: Deployment
name: keystone-api
namespace: openstack
wait_sleep: 10
wait_timeout: 600
wait: true
wait_condition:
type: Available
status: true
- name: Create Keystone domains
run_once: true
vexxhost.atmosphere.identity_domain:
name: "{{ item.name }}"
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"
# NOTE: This often fails since it takes time for the keystone api ready.
retries: 60
delay: 5
register: keystone_domains_result
until: keystone_domains_result is not failed
- name: Create Keystone identity providers
run_once: true
vexxhost.atmosphere.federation_idp:
name: "{{ item.domain.name }}"
domain_id: "{{ item.domain.id }}"
is_enabled: true
remote_ids:
- "{{ item.item | vexxhost.atmosphere.issuer_from_domain }}"
loop: "{{ keystone_domains_result.results }}"
loop_control:
label: "{{ item.domain.name }}"
- name: Create Keystone federation mappings
run_once: true
vexxhost.atmosphere.federation_mapping:
name: "{{ item.name }}-openid"
rules:
- local:
- user:
type: local
id: "{0}"
name: "{1}"
domain:
name: "{{ item.name }}"
remote:
- type: OIDC-sub
- type: OIDC-preferred_username
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"
- name: Create Keystone federation protocols
run_once: true
vexxhost.atmosphere.keystone_federation_protocol:
name: openid
idp_id: "{{ item.name }}"
mapping_id: "{{ item.name }}-openid"
loop: "{{ keystone_domains }}"
loop_control:
label: "{{ item.name }}"