diff --git a/doc/source/keycloak.rst b/doc/source/keycloak.rst new file mode 100644 index 0000000000..b14ad60dde --- /dev/null +++ b/doc/source/keycloak.rst @@ -0,0 +1,32 @@ +:title: Keycloak + +.. _keycloak: + +Keycloak +######## + +Keycloak is installed on keycloak.opendev.org. It is in a prototype +phase for use with the Zuul admin API, and may be used by other +OpenDev services in the future. + +At a Glance +=========== + +:Hosts: + * https://keycloak.opendev.org +:Ansible: + * https://opendev.org/opendev/system-config + * :git_file:`playbooks/roles/keycloak` + * :git_file:`playbooks/service-keycloak.yaml` +:Projects: + * https://www.keycloak.org/ + * https://github.com/keycloak/keycloak-containers +:Bugs: + * https://storyboard.openstack.org/#!/project/748 + * https://issues.jboss.org/browse/KEYCLOAK + +Overview +======== + +Apache is configured as a reverse proxy and there is an internal H2 +database stored at ``/var/keycloak/data``. diff --git a/doc/source/systems.rst b/doc/source/systems.rst index addd112d0b..93e397f8e1 100644 --- a/doc/source/systems.rst +++ b/doc/source/systems.rst @@ -14,6 +14,7 @@ Major Systems gitea grafana grafyaml + keycloak zuul logstash elastic-recheck diff --git a/hiera/common.yaml b/hiera/common.yaml index 1cffd93e62..5e43077428 100644 --- a/hiera/common.yaml +++ b/hiera/common.yaml @@ -38,6 +38,7 @@ cacti_hosts: - jvb02.opendev.org - kdc03.openstack.org - kdc04.openstack.org +- keycloak01.opendev.org - lists.openstack.org - logstash-worker01.openstack.org - logstash-worker02.openstack.org diff --git a/inventory/service/groups.yaml b/inventory/service/groups.yaml index 850b107f16..887387d27d 100644 --- a/inventory/service/groups.yaml +++ b/inventory/service/groups.yaml @@ -84,6 +84,7 @@ groups: - kdc03.openstack.org kerberos-kdc-replica: - kdc04.openstack.org + keycloak: keycloak[0-9]*.opendev.org letsencrypt: - codesearch[0-9]*.opendev.org - eavesdrop[0-9]*.opendev.org @@ -93,6 +94,7 @@ groups: - grafana[0-9]*.opendev.org - graphite[0-9]*.opendev.org - insecure-ci-registry[0-9]*.opendev.org + - keycloak[0-9]*.opendev.org - meetpad[0-9]*.opendev.org - mirror[0-9]*.opendev.org - nb[0-9]*.opendev.org @@ -189,6 +191,7 @@ groups: - grafana[0-9]*.opendev.org - graphite*.opendev.org - health[0-9]*.openstack.org + - keycloak[0-9]*.opendev.org - nb[0-9]*.opendev.org - nl[0-9]*.open*.org - paste[0-9]*.opendev.org diff --git a/inventory/service/host_vars/keycloak01.opendev.org.yaml b/inventory/service/host_vars/keycloak01.opendev.org.yaml new file mode 100644 index 0000000000..608bd8edb5 --- /dev/null +++ b/inventory/service/host_vars/keycloak01.opendev.org.yaml @@ -0,0 +1,6 @@ +letsencrypt_certs: + keycloak01-opendev-org-main: + # List the service name first since that determines the filename + # and is referenced in the apache config. + - keycloak.opendev.org + - keycloak01.opendev.org diff --git a/playbooks/roles/keycloak/README.rst b/playbooks/roles/keycloak/README.rst new file mode 100644 index 0000000000..03d041cf54 --- /dev/null +++ b/playbooks/roles/keycloak/README.rst @@ -0,0 +1 @@ +Run a Keycloak server. diff --git a/playbooks/roles/keycloak/handlers/main.yaml b/playbooks/roles/keycloak/handlers/main.yaml new file mode 100644 index 0000000000..9acec0bcc8 --- /dev/null +++ b/playbooks/roles/keycloak/handlers/main.yaml @@ -0,0 +1,4 @@ +- name: keycloak Reload apache2 + service: + name: apache2 + state: reloaded diff --git a/playbooks/roles/keycloak/tasks/main.yaml b/playbooks/roles/keycloak/tasks/main.yaml new file mode 100644 index 0000000000..8492d61a45 --- /dev/null +++ b/playbooks/roles/keycloak/tasks/main.yaml @@ -0,0 +1,72 @@ +- name: Ensure docker-compose directory exists + file: + state: directory + path: /etc/keycloak-docker + +- name: Write settings file + template: + src: docker-compose.yaml.j2 + dest: /etc/keycloak-docker/docker-compose.yaml + +- name: Ensure data directory exists + file: + state: directory + path: /var/keycloak/data + owner: "1000" + group: "root" + mode: "0755" + +- name: Ensure log directory exists + file: + state: directory + path: /var/log/keycloak + owner: "1000" + group: "root" + mode: "0755" + +- name: Install apache2 + apt: + name: + - apache2 + - apache2-utils + state: present + +- name: Apache modules + apache2_module: + state: present + name: "{{ item }}" + loop: + - rewrite + - proxy + - proxy_http + - ssl + - headers + - proxy_wstunnel + +- name: Copy apache config + template: + src: keycloak.vhost.j2 + dest: /etc/apache2/sites-enabled/000-default.conf + owner: root + group: root + mode: 0644 + notify: keycloak Reload apache2 + +- name: Run docker-compose pull + shell: + cmd: docker-compose pull + chdir: /etc/keycloak-docker/ + +- name: Run docker-compose up + shell: + cmd: docker-compose up -d + chdir: /etc/keycloak-docker/ + +- name: Wait for keycloak to start + wait_for: + port: 8080 + timeout: 60 + +- name: Run docker prune to cleanup unneeded images + shell: + cmd: docker image prune -f diff --git a/playbooks/roles/keycloak/templates/docker-compose.yaml.j2 b/playbooks/roles/keycloak/templates/docker-compose.yaml.j2 new file mode 100644 index 0000000000..0e0eeb7429 --- /dev/null +++ b/playbooks/roles/keycloak/templates/docker-compose.yaml.j2 @@ -0,0 +1,19 @@ +# Version 2 is the latest that is supported by docker-compose in +# Ubuntu Xenial. +version: '2' + +services: + keycloak: + image: docker.io/jboss/keycloak + network_mode: host + restart: always + environment: + - KEYCLOAK_USER=admin + - KEYCLOAK_PASSWORD="{{ keycloak_admin_password }}" + - DB_VENDOR=h2 + command: + -Djboss.bind.address.private=127.0.0.1 + -Djboss.bind.address=127.0.0.1 + volumes: + - /var/keycloak/data:/opt/jboss/keycloak/standalone/data + - /var/log/keycloak:/opt/jboss/keycloak/standalone/log diff --git a/playbooks/roles/keycloak/templates/keycloak.vhost.j2 b/playbooks/roles/keycloak/templates/keycloak.vhost.j2 new file mode 100644 index 0000000000..5d78af2262 --- /dev/null +++ b/playbooks/roles/keycloak/templates/keycloak.vhost.j2 @@ -0,0 +1,55 @@ + + ServerName keycloak.opendev.org + ServerAdmin webmaster@openstack.org + + ErrorLog ${APACHE_LOG_DIR}/keycloak-error.log + + LogLevel warn + + CustomLog ${APACHE_LOG_DIR}/keycloak-access.log combined + + Redirect / https://keycloak.opendev.org/ + + + + + ServerName keycloak.opendev.org + ServerAdmin webmaster@openstack.org + + AllowEncodedSlashes On + + ErrorLog ${APACHE_LOG_DIR}/keycloak-ssl-error.log + + LogLevel warn + + CustomLog ${APACHE_LOG_DIR}/keycloak-ssl-access.log combined + + SSLEngine on + SSLProtocol All -SSLv2 -SSLv3 + # Note: this list should ensure ciphers that provide forward secrecy + SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP + SSLHonorCipherOrder on + + SSLCertificateFile /etc/letsencrypt-certs/keycloak.opendev.org/keycloak.opendev.org.cer + SSLCertificateKeyFile /etc/letsencrypt-certs/keycloak.opendev.org/keycloak.opendev.org.key + SSLCertificateChainFile /etc/letsencrypt-certs/keycloak.opendev.org/ca.cer + + BrowserMatch "MSIE [2-6]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + # MSIE 7 and newer should be able to use keepalive + BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown + + RewriteEngine on + + # Do not rewrite the /server-status URL (though by default, this + # is only accessible from localhost). Connect to it with: + # ssh -L 8443:localhost:443 $HOSTNAME + # https://localhost:8443/server-status + RewriteRule ^/server-status$ /server-status [L] + + ProxyPass / http://localhost:8080/ retry=0 + ProxyPassReverse / http://localhost:8080/ + + + diff --git a/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml b/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml index 5b366efa08..eabdf9e8d0 100644 --- a/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml +++ b/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml @@ -249,6 +249,9 @@ - name: letsencrypt updated ethercalc02-openstack-org-main include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml +- name: letsencrypt updated keycloak01-opendev-org-main + include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml + - name: letsencrypt updated storyboard01-opendev-org-main include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml diff --git a/playbooks/service-keycloak.yaml b/playbooks/service-keycloak.yaml new file mode 100644 index 0000000000..48ed3e66cd --- /dev/null +++ b/playbooks/service-keycloak.yaml @@ -0,0 +1,6 @@ +- hosts: "keycloak:!disabled" + name: "Base: configure keycloak" + roles: + - iptables + - install-docker + - keycloak diff --git a/playbooks/zuul/run-base.yaml b/playbooks/zuul/run-base.yaml index 7830b9a0cc..f0da45bad9 100644 --- a/playbooks/zuul/run-base.yaml +++ b/playbooks/zuul/run-base.yaml @@ -59,6 +59,7 @@ - group_vars/gitea.yaml - group_vars/gitea-lb.yaml - group_vars/kerberos-kdc.yaml + - group_vars/keycloak.yaml - group_vars/letsencrypt.yaml - group_vars/meetpad.yaml - group_vars/jvb.yaml diff --git a/playbooks/zuul/templates/group_vars/keycloak.yaml.j2 b/playbooks/zuul/templates/group_vars/keycloak.yaml.j2 new file mode 100644 index 0000000000..293aef7a95 --- /dev/null +++ b/playbooks/zuul/templates/group_vars/keycloak.yaml.j2 @@ -0,0 +1 @@ +keycloak_admin_password: testpassword diff --git a/testinfra/test_keycloak.py b/testinfra/test_keycloak.py new file mode 100644 index 0000000000..02cd0e9f74 --- /dev/null +++ b/testinfra/test_keycloak.py @@ -0,0 +1,22 @@ +# Copyright 2018 Red Hat, Inc. +# Copyright 2021 Acme Gating, LLC +# +# 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. + + +testinfra_hosts = ['keycloak01.opendev.org'] + + +def test_keycloak_listening(host): + keycloak = host.socket("tcp://127.0.0.1:8080") + assert keycloak.is_listening diff --git a/zuul.d/infra-prod.yaml b/zuul.d/infra-prod.yaml index 6d1a505ddb..0cd230917f 100644 --- a/zuul.d/infra-prod.yaml +++ b/zuul.d/infra-prod.yaml @@ -192,6 +192,21 @@ - playbooks/roles/iptables/ - docker/etherpad/ +- job: + name: infra-prod-service-keycloak + parent: infra-prod-service-base + description: Run service-keycloak.yaml playbook. + vars: + playbook_name: service-keycloak.yaml + files: + - inventory/base + - playbooks/service-keycloak.yaml + - inventory/service/host_vars/keycloak01.opendev.org.yaml + - inventory/service/group_vars/keycloak + - playbooks/roles/keycloak/ + - playbooks/roles/install-docker/ + - playbooks/roles/iptables/ + - job: name: infra-prod-service-meetpad parent: infra-prod-service-base diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index c36042eef3..9bd1303c3e 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -61,6 +61,7 @@ - name: system-config-build-image-grafana soft: true - system-config-run-graphite + - system-config-run-keycloak - system-config-run-review-3.3: dependencies: - name: opendev-buildset-registry @@ -221,6 +222,7 @@ - name: system-config-upload-image-grafana soft: true - system-config-run-graphite + - system-config-run-keycloak - system-config-run-review-3.3: dependencies: - name: opendev-buildset-registry @@ -482,6 +484,10 @@ dependencies: - name: infra-prod-letsencrypt soft: true + - infra-prod-service-keycloak: &infra-prod-service-keycloak + dependencies: + - name: infra-prod-letsencrypt + soft: true - infra-prod-service-meetpad: &infra-prod-service-meetpad dependencies: - name: infra-prod-letsencrypt @@ -624,6 +630,7 @@ - infra-prod-service-gitea-lb: *infra-prod-service-gitea-lb - infra-prod-service-grafana: *infra-prod-service-grafana - infra-prod-service-graphite: *infra-prod-service-graphite + - infra-prod-service-keycloak: *infra-prod-service-keycloak - infra-prod-service-meetpad: *infra-prod-service-meetpad - infra-prod-service-lists: *infra-prod-service-lists - infra-prod-service-mirror: *infra-prod-service-mirror diff --git a/zuul.d/system-config-run.yaml b/zuul.d/system-config-run.yaml index 5ad710e0fc..efeddd8e87 100644 --- a/zuul.d/system-config-run.yaml +++ b/zuul.d/system-config-run.yaml @@ -683,6 +683,33 @@ - playbooks/roles/pip3/ - testinfra/test_graphite.py +- job: + name: system-config-run-keycloak + parent: system-config-run + description: | + Run the playbook for the keycloak servers. + timeout: 3600 + nodeset: + nodes: + - name: bridge.openstack.org + label: ubuntu-bionic + - name: keycloak01.opendev.org + label: ubuntu-focal + vars: + run_playbooks: + - playbooks/letsencrypt.yaml + - playbooks/service-keycloak.yaml + files: + - inventory/service/host_vars/keycloak01.opendev.org.yaml + - playbooks/install-ansible.yaml + - playbooks/letsencrypt.yaml + - playbooks/service-keycloak.yaml + - playbooks/roles/keycloak/ + - playbooks/roles/install-docker/ + - playbooks/roles/iptables/ + - playbooks/zuul/templates/group_vars/keycloak.yaml.j2 + - testinfra/test_keycloak.py + - job: name: system-config-run-meetpad parent: system-config-run