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