| # 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 }}" |
| 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 }}" |