Browse Source

initial commit

main
Nicolas Massé 4 years ago
commit
c72f2ab75c
  1. 2
      .gitattributes
  2. 5
      .gitignore
  3. 3
      files/postgresql-42.3.3.jar
  4. 3
      files/traefik_v2.6.1_linux_amd64.tar.gz
  5. 6
      group_vars/all/all.yaml
  6. 94
      install-db.yaml
  7. 105
      install-kc.yaml
  8. 68
      install-lb.yaml
  9. 3
      install.yaml
  10. 16
      inventory.yaml
  11. 3
      requirements.yaml
  12. 26
      templates/keycloak-custom.cli
  13. 1
      templates/keycloak.env
  14. 13
      templates/keycloak.service
  15. 12
      templates/module.xml.j2
  16. 27
      templates/traefik-keycloak.yaml
  17. 0
      templates/traefik.env
  18. 19
      templates/traefik.service
  19. 19
      templates/traefik.yaml

2
.gitattributes

@ -0,0 +1,2 @@
*.tar.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text

5
.gitignore

@ -0,0 +1,5 @@
ansible.cfg
vault.yaml
rhsso*.zip
rh-sso*.zip
.ansible-vault-password

3
files/postgresql-42.3.3.jar

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:eed0604f512ba44817954de99a07e2a5470aa4bfcb481d4e63a93e0ff0e0aede
size 1039047

3
files/traefik_v2.6.1_linux_amd64.tar.gz

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f6e10a6f2bf1844fe9e68406d7ed6e693ea9678184e6ead6a0f14a342d643dd5
size 26843817

6
group_vars/all/all.yaml

@ -0,0 +1,6 @@
db_username: keycloak
db_name: keycloak
db_hostname: db.itix.lab
keycloak_dir: /opt/rh-sso-7.5
keycloak_url: http://lb.itix.lab
keycloak_admin_username: admin

94
install-db.yaml

@ -0,0 +1,94 @@
- name: Install PostgreSQL
hosts: db
gather_facts: yes
become: yes
tasks:
- name: Install PostgreSQL
dnf:
name:
- postgresql-server
- postgresql-docs
- postgresql-upgrade
- postgresql-contrib
- python3-psycopg2 # Needed by the community.general.postgresql_* tasks
state: installed
- name: Initialize the database
command: postgresql-setup --initdb
args:
creates: /var/lib/pgsql/data/log/
- name: Listen on all network interfaces
lineinfile:
insertbefore: '^ *#* *listen_addresses *='
path: /var/lib/pgsql/data/postgresql.conf
regexp: '^ *listen_addresses *= *'
line: "listen_addresses = '0.0.0.0'"
register: postgresql_conf1
- name: Enable scram-sha-256
lineinfile:
insertbefore: '^ *#* *password_encryption *='
path: /var/lib/pgsql/data/postgresql.conf
regexp: '^ *password_encryption *= *'
line: "password_encryption = scram-sha-256"
register: postgresql_conf2
- name: Enable password authentication instead of ident
community.general.postgresql_pg_hba:
dest: /var/lib/pgsql/data/pg_hba.conf
contype: host
databases: all
users: all
address: '{{ item.address }}'
method: '{{ item.method }}'
state: '{{ item.state }}'
loop:
- address: 127.0.0.1/32
method: scram-sha-256
state: present
- address: ::1/128
method: scram-sha-256
state: present
- address: 0.0.0.0/0
method: scram-sha-256
state: present
register: pghba_conf
- name: Reload PostgreSQL when needed
systemd:
name: postgresql
enabled: true
state: reloaded
when: postgresql_conf1.changed or postgresql_conf2.changed or pghba_conf.changed
- name: Ensure the PostgreSQL service is started and enabled
systemd:
name: postgresql
enabled: true
state: started
- name: Wait for PostgreSQL to be ready
community.general.postgresql_query:
db: template1
query: SELECT version()
become_user: postgres
retries: 20
delay: 5
register: healthcheck
until: not healthcheck.failed
- name: Create the PostgreSQL database for Keycloak
community.general.postgresql_db:
name: '{{ db_name }}'
become_user: postgres
- name: Create the PostgreSQL user for Keycloak
community.general.postgresql_user:
name: '{{ db_username }}'
password: '{{ db_password }}'
login_db: '{{ db_name }}'
priv: ALL
become_user: postgres
environment:
PGOPTIONS: "-c password_encryption=scram-sha-256"

105
install-kc.yaml

@ -0,0 +1,105 @@
- name: Install Keycloak
hosts: keycloak
gather_facts: yes
become: yes
tasks:
- name: Create the keycloak user
user:
name: keycloak
system: true
home: '{{ keycloak_dir }}'
create_home: false
state: present
- name: Install pre-requisites
dnf:
name:
- unzip
- java-11-openjdk-headless
state: installed
- name: Unpack Keycloak
unarchive:
src: 'rh-sso-7.5.0-server-dist.zip'
dest: /opt
owner: keycloak
creates: '{{ keycloak_dir }}'
- name: Upload Keycloak patches
copy:
src: '{{ item }}'
dest: '/tmp/{{ item }}'
loop:
- rh-sso-7.5.1-patch.zip
- rhsso-1974.zip
- rhsso-2054.zip
- name: Apply Keycloak patches
command: '{{ keycloak_dir }}/bin/jboss-cli.sh --command="patch apply /tmp/{{ item }}"'
loop:
- rh-sso-7.5.1-patch.zip
- rhsso-1974.zip
- rhsso-2054.zip
become_user: keycloak
- name: Create modules/system/layers/keycloak/org/postgresql/jdbc/main
file:
state: directory
path: '{{ keycloak_dir }}/modules/system/layers/base/org/postgresql/jdbc/main'
owner: keycloak
- name: Copy postgresql JDBC driver
copy:
src: postgresql-42.3.3.jar
dest: '{{ keycloak_dir }}/modules/system/layers/base/org/postgresql/jdbc/main'
owner: keycloak
- name: Reference the jdbc driver in module.xml
template:
src: module.xml.j2
dest: '{{ keycloak_dir }}/modules/system/layers/base/org/postgresql/jdbc/main/module.xml'
owner: keycloak
# Sample cli scripts are here: https://github.com/keycloak/keycloak-containers/tree/15.0.2/server/tools/cli
- name: Upload the Keycloak configuration script
template:
src: keycloak-custom.cli
dest: '{{ keycloak_dir }}/custom.cli'
owner: keycloak
- name: Configure keycloak
command: '{{ keycloak_dir }}/bin/jboss-cli.sh --file={{ keycloak_dir }}/custom.cli'
become_user: keycloak
- name: Install the keycloak service unit
template:
src: keycloak.service
dest: /etc/systemd/system/keycloak.service
register: systemd_unit
tags: config
- name: Configure the keycloak service unit
template:
src: keycloak.env
dest: '{{ keycloak_dir }}/keycloak.env'
register: unit_config
tags: config
- name: Reload systemd
systemd:
daemon-reload: yes
when: systemd_unit.changed
tags: config
- name: Create the initial admin
command: '{{ keycloak_dir }}/bin/add-user-keycloak.sh --user {{ keycloak_admin_username }} --password {{ keycloak_admin_password }}'
# only one node needs to execute this command
when: ansible_host == "sso1.itix.lab"
- name: Start keycloak
systemd:
name: keycloak.service
state: restarted
when: systemd_unit.changed or unit_config.changed
tags: config

68
install-lb.yaml

@ -0,0 +1,68 @@
- name: Install Traefik
hosts: lb
gather_facts: yes
become: yes
tasks:
- name: Create the traefik user
user:
name: traefik
system: true
home: '/opt/traefik'
create_home: false
state: present
- name: Skaffold /opt/traefik
file:
path: '{{ item }}'
state: directory
owner: traefik
loop:
- /opt/traefik/etc
- /opt/traefik/etc/conf.d
- /opt/traefik/bin
- name: Install traefik
unarchive:
src: traefik_v2.6.1_linux_amd64.tar.gz
dest: /opt/traefik/bin
owner: traefik
- name: Install the systemd units
template:
src: traefik.service
dest: /etc/systemd/system/traefik.service
register: systemd_unit
tags: config
- name: Install the systemd unit configuration
template:
src: traefik.env
dest: /opt/traefik/etc/traefik.env
register: unit_config
tags: config
- name: Reload systemd
systemd:
daemon-reload: yes
when: systemd_unit.changed
tags: config
- name: Configure traefik
template:
src: traefik.yaml
dest: /opt/traefik/etc/traefik.yaml
register: traefik_config
tags: config
- name: Configure traefik
template:
src: traefik-keycloak.yaml
dest: /opt/traefik/etc/conf.d/keycloak.yaml
tags: config
- name: Start traefik
systemd:
name: traefik.service
state: restarted
when: systemd_unit.changed or unit_config.changed or traefik_config.changed
tags: config

3
install.yaml

@ -0,0 +1,3 @@
- import_playbook: install-db.yaml
- import_playbook: install-kc.yaml
- import_playbook: install-lb.yaml

16
inventory.yaml

@ -0,0 +1,16 @@
all:
vars:
ansible_user: nicolas
children:
db:
hosts:
db.itix.lab:
keycloak:
hosts:
sso1.itix.lab:
sso2.itix.lab:
sso3.itix.lab:
lb:
hosts:
lb.itix.lab:

3
requirements.yaml

@ -0,0 +1,3 @@
collections:
- name: community.general
version: '>=2.2.0' # fix a bug with nmcli and bridge interfaces

26
templates/keycloak-custom.cli

@ -0,0 +1,26 @@
embed-server --server-config=standalone-ha.xml --std-out=echo
/subsystem=undertow/server=default-server/http-listener=default: write-attribute(name=proxy-address-forwarding, value=true)
/subsystem=undertow/server=default-server/https-listener=https: write-attribute(name=proxy-address-forwarding, value=true)
/subsystem=datasources/data-source=KeycloakDS: remove()
/subsystem=datasources/data-source=KeycloakDS: add(jndi-name=java:jboss/datasources/KeycloakDS,enabled=true,use-java-context=true,use-ccm=true, connection-url=jdbc:postgresql://{{ db_hostname }}/{{ db_name }}, driver-name=postgresql)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=user-name, value={{ db_username }})
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=password, value={{ db_password }})
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=check-valid-connection-sql, value="SELECT 1")
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=background-validation, value=true)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=background-validation-millis, value=60000)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=flush-strategy, value=IdleConnections)
/subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql, driver-module-name=org.postgresql.jdbc, driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
/subsystem=keycloak-server/spi=connectionsJpa/provider=default:write-attribute(name=properties.schema,value=public)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=clientSessions: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineClientSessions: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens: write-attribute(name=owners, value=3)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=authenticationSessions: write-attribute(name=owners, value=1)
stop-embedded-server

1
templates/keycloak.env

@ -0,0 +1 @@
KEYCLOAK_OPTIONS="-b 0.0.0.0"

13
templates/keycloak.service

@ -0,0 +1,13 @@
[Unit]
Description=Red Hat SSO
After=network.target
[Service]
ExecStart={{ keycloak_dir }}/bin/standalone.sh --server-config=standalone-ha.xml $KEYCLOAK_OPTIONS
WorkingDirectory={{ keycloak_dir }}
User=keycloak
EnvironmentFile={{ keycloak_dir }}/keycloak.env
Type=simple
[Install]
WantedBy=multi-user.target default.target

12
templates/module.xml.j2

@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.3" name="org.postgresql.jdbc">
<resources>
<resource-root path="postgresql-42.3.3.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>

27
templates/traefik-keycloak.yaml

@ -0,0 +1,27 @@
http:
routers:
keycloak-http:
rule: "Host(`lb.itix.lab`)"
entryPoints:
- http
- https
middlewares:
service: "keycloak"
keycloak-https:
rule: "Host(`lb.itix.lab`)"
entryPoints:
- http
- https
middlewares:
service: "keycloak"
tls: {}
services:
keycloak:
loadBalancer:
servers:
- url: "http://sso1.itix.lab:8080"
- url: "http://sso2.itix.lab:8080"
- url: "http://sso3.itix.lab:8080"
# Sticky session is required for users to login
sticky:
cookie: {}

0
templates/traefik.env

19
templates/traefik.service

@ -0,0 +1,19 @@
[Unit]
Description=The Cloud Native Application Proxy
Wants=network.target
After=network-online.target
[Service]
Restart=always
Type=simple
EnvironmentFile=/opt/traefik/etc/traefik.env
ExecStart=/opt/traefik/bin/traefik
WorkingDirectory=/opt/traefik/etc
User=traefik
Group=traefik
# Allow traefik to bind to <1024 ports
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target default.target

19
templates/traefik.yaml

@ -0,0 +1,19 @@
log:
level: "INFO"
accesslog: true
providers:
file:
directory: /opt/traefik/etc/conf.d/
watch: true
global:
sendanonymoususage: false
checknewversion: false
entryPoints:
http:
address: ":80"
https:
address: ":443"
Loading…
Cancel
Save