[DEV-1205] Grant public authentication for KC Realms - Limit Access to admin console

main
Michael Hähnel 2 years ago
parent 5aeedbb6a6
commit 46df2f15bf

@ -3,3 +3,9 @@ keycloak_admin_username: "keycloak-admin"
keycloak_admin_password: "{{ keycloak_admin_password_vault }}" keycloak_admin_password: "{{ keycloak_admin_password_vault }}"
keycloak_default_theme: "mpmx-theme" keycloak_default_theme: "mpmx-theme"
# Use these Realm ACLs to create custom Traefik labels for Keycloak to restrict admin access per realm
# Both variables are mandatory!
# name: <realm_name>
# admin_ips: <ip/range in cidr notation>
keycloak_admin_realm_acls: []

@ -0,0 +1,3 @@
# Used to authorize access to keaycloak via tcp/443 on the hcloud firewall
keycloak_https_whitelisted_ips:
- 0.0.0.0/0 # Public access to keycloak

@ -1,6 +1,3 @@
--- ---
stage_database_management_connect_name: "{{ stage }}_management_smardigo_connect" stage_database_management_connect_name: "{{ stage }}_management_smardigo_connect"
stage_database_management_connect_password: "connect-postgres-admin" stage_database_management_connect_password: "connect-postgres-admin"
management_oidc_realm: "management"
management_oidc_client_id: "smardigo"

@ -1,11 +1,25 @@
# Used to authorize access to keaycloak via tcp/443 on the hcloud firewall
keycloak_https_whitelisted_ips: keycloak_https_whitelisted_ips:
- 195.200.47.243/32 # DEV-230 - sparda berlin - 0.0.0.0/0 # Public access to keycloak
- 195.200.47.244/32 # DEV-230 - sparda berlin
- 92.42.192.128/25 # MOB-486 - mobene # Use these Realm ACLs to create custom Traefik labels for Keycloak to restrict admin access per realm
# Both variables are mandatory!
# name: <realm_name>
# admin_ips: <ip/range in cidr notation>
keycloak_admin_realm_acls:
- name: spkbz
admin_ips:
- 195.140.123.0/24 # DEV-628 - spk bautzen - 195.140.123.0/24 # DEV-628 - spk bautzen
- 195.140.44.0/24 # DEV-628 - spk bautzen - 195.140.44.0/24 # DEV-628 - spk bautzen
- 62.181.145.0/24 # DEV-628 - spk bautzen - 62.181.145.0/24 # DEV-628 - spk bautzen
- 62.181.146.0/24 # DEV-628 - spk bautzen - 62.181.146.0/24 # DEV-628 - spk bautzen
- name: sbsma
admin_ips:
- 195.200.47.243/32 # DEV-230 - sparda berlin
- 195.200.47.244/32 # DEV-230 - sparda berlin
- name: mobene
admin_ips:
- 92.42.192.128/25 # MOB-486 - mobene
- 167.235.150.201/32 # prodwork01-kube-cpl-01 ; DEV-786 mobene (nsodev) migration - 167.235.150.201/32 # prodwork01-kube-cpl-01 ; DEV-786 mobene (nsodev) migration
- 167.235.150.198/32 # prodwork01-kube-cpl-02 ; DEV-786 mobene (nsodev) migration - 167.235.150.198/32 # prodwork01-kube-cpl-02 ; DEV-786 mobene (nsodev) migration
- 167.235.150.195/32 # prodwork01-kube-cpl-03 ; DEV-786 mobene (nsodev) migration - 167.235.150.195/32 # prodwork01-kube-cpl-03 ; DEV-786 mobene (nsodev) migration
@ -16,6 +30,8 @@ keycloak_https_whitelisted_ips:
- 5.75.184.216/32 # prodwork01-kube-node-05 ; DEV-786 mobene (nsodev) migration - 5.75.184.216/32 # prodwork01-kube-node-05 ; DEV-786 mobene (nsodev) migration
- 91.107.228.133/32 # prodwork01-kube-node-06 ; => DEV-987 - 91.107.228.133/32 # prodwork01-kube-node-06 ; => DEV-987
- 167.235.25.0/32 # prodwork01-kube-node-07 ; => DEV-987 - 167.235.25.0/32 # prodwork01-kube-node-07 ; => DEV-987
- name: linde
admin_ips:
- 145.225.17.1/32 # DEV-1142 - Linde - 145.225.17.1/32 # DEV-1142 - Linde
- 20.113.104.205/32 # DEV-1142 - Linde - 20.113.104.205/32 # DEV-1142 - Linde
- 20.113.10.224/32 # DEV-1142 - Linde - 20.113.10.224/32 # DEV-1142 - Linde

@ -0,0 +1,15 @@
# Used to authorize access to keaycloak via tcp/443 on the hcloud firewall
keycloak_https_whitelisted_ips:
- 0.0.0.0/0 # Public access to keycloak
# Use these Realm ACLs to create custom Traefik labels for Keycloak to restrict admin access per realm
# Both variables are mandatory!
# name: <realm_name>
# admin_ips: <ip/range in cidr notation>
keycloak_admin_realm_acls:
- name: management
admin_ips:
- 79.140.117.133/32 # mha
- name: mhel
admin_ips:
- 79.140.117.133/32 # mha

@ -0,0 +1,15 @@
---
server_hcloud_firewall_objects:
- name: "customer-access-to-{{ inventory_hostname }}"
state: present
rules:
- direction: in
protocol: tcp
port: "443"
source_ips: "{{ additional_ip_adresses_vault }}"
destination_ips: []
description: customer specific access to https services
apply_to:
- type: server
server:
id: "{{ stage_server_id }}"

@ -0,0 +1,8 @@
$ANSIBLE_VAULT;1.1;AES256
31396666646138353139636535636563613531356430336362386265636465656638656661613135
6331373138383964363266383331633532383537613837310a366531363137656566306565346263
32653430646463356464653939363431363666373637633332323430303934316439326234663532
6661373662663836660a663138613564623237666434353561366366353936363063313831333165
64333464333061336337393762343362373362353462346236323965653666343264343438306132
32653561656337636365663531333066666663623738643463653865663961303239376262306362
373762363465613031666565383535313033

@ -0,0 +1,26 @@
---
- name: "Generate Traefik labels for custom admin access to specific realm(s)"
ansible.builtin.set_fact:
labels:
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.service={{ keycloak_id }}"'
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.rule=Host(`{{ stage_server_domain }}`) && Method(`POST`,`PUT`,`DELETE`, `PATCH`) && (PathPrefix(`/auth/realms/{{ keycloak_accessible_realm.name }}`) || PathPrefix(`/auth/admin/{{ keycloak_accessible_realm.name }}`) || PathPrefix(`/auth/admin/realms/{{ keycloak_accessible_realm.name }}`))"'
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.entrypoints=websecure"'
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.tls=true"'
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.tls.certresolver=letsencrypt-http"'
- '"traefik.http.routers.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}.middlewares={{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}-ipwhitelist"'
- '"traefik.http.middlewares.{{ keycloak_id }}-admin-{{ keycloak_accessible_realm.name }}-ipwhitelist.ipwhitelist.sourcerange={{ (ip_whitelist + (keycloak_accessible_realm.admin_ips) | default([])) | join(",") }}"'
loop: "{{ keycloak_admin_realm_acls }}"
register: keycloak_accessible_realms
loop_control:
loop_var: keycloak_accessible_realm
tags:
- update_deployment
- name: "Extract keycloak_accessible_realms"
ansible.builtin.set_fact:
keycloak_labels_additional: "{{ keycloak_labels_additional | default([]) + keycloak_accessible_realm.ansible_facts.labels }}"
loop: "{{ keycloak_accessible_realms.results }}"
loop_control:
loop_var: keycloak_accessible_realm
tags:
- update_deployment

@ -1,33 +1,37 @@
--- ---
### tags: ### tags:
### update_deployment ### update_deployment
### update_realms ### update_realms
- name: "Setup DNS configuration for {{ inventory_hostname }}" - name: "Setup DNS configuration for {{ inventory_hostname }}"
include_role: ansible.builtin.include_role:
name: hetzner-ansible-dns name: hetzner-ansible-dns
vars: vars:
record_data: "{{ stage_server_ip }}" record_data: "{{ stage_server_ip }}"
record_name: "{{ inventory_hostname }}" record_name: "{{ inventory_hostname }}"
- name: "Check if {{ inventory_hostname }}/docker-compose.yml exists" - name: "Check if {{ inventory_hostname }}/docker-compose.yml exists"
stat: ansible.builtin.stat:
path: '{{ service_base_path }}/{{ inventory_hostname }}/docker-compose.yml' path: "{{ service_base_path }}/{{ inventory_hostname }}/docker-compose.yml"
register: check_docker_compose_file register: check_docker_compose_file
tags: tags:
- update_deployment - update_deployment
- name: "Configure Traefik labels to restrict access to admin console"
ansible.builtin.include_tasks: _configure_traefik.yml
tags:
- update_deployment
- name: "Stop {{ inventory_hostname }}" - name: "Stop {{ inventory_hostname }}"
community.docker.docker_compose: community.docker.docker_compose:
project_src: '{{ service_base_path }}/{{ inventory_hostname }}' project_src: "{{ service_base_path }}/{{ inventory_hostname }}"
state: absent state: absent
when: check_docker_compose_file.stat.exists when: check_docker_compose_file.stat.exists
tags: tags:
- update_deployment - update_deployment
- name: "Deploy docker templates for {{ inventory_hostname }}" - name: "Deploy docker templates for {{ inventory_hostname }}"
include_role: ansible.builtin.include_role:
name: hetzner-ansible-sma-deploy name: hetzner-ansible-sma-deploy
tasks_from: templates tasks_from: templates
vars: vars:
@ -41,7 +45,7 @@
- update_deployment - update_deployment
- name: "Deploy service templates for {{ inventory_hostname }}" - name: "Deploy service templates for {{ inventory_hostname }}"
include_role: ansible.builtin.include_role:
name: hetzner-ansible-sma-deploy name: hetzner-ansible-sma-deploy
tasks_from: templates tasks_from: templates
vars: vars:
@ -55,22 +59,22 @@
- name: "Start {{ inventory_hostname }}" - name: "Start {{ inventory_hostname }}"
community.docker.docker_compose: community.docker.docker_compose:
project_src: '{{ service_base_path }}/{{ inventory_hostname }}' project_src: "{{ service_base_path }}/{{ inventory_hostname }}"
state: present state: present
pull: yes pull: true
tags: tags:
- update_deployment - update_deployment
- name: "Wait for <localhost:{{ service_port_keycloak_external }}>" - name: "Wait for <localhost:{{ service_port_keycloak_external }}>"
wait_for: ansible.builtin.wait_for:
host: "localhost" host: "localhost"
port: '{{ service_port_keycloak_external }}' port: "{{ service_port_keycloak_external }}"
delay: 60 delay: 60
tags: tags:
- update_deployment - update_deployment
- name: "Authenticate on keycloak for {{ inventory_hostname }}" - name: "Authenticate on keycloak for {{ inventory_hostname }}"
include_role: ansible.builtin.include_role:
name: keycloak name: keycloak
tasks_from: _authenticate tasks_from: _authenticate
tags: tags:
@ -88,18 +92,18 @@
account_theme: "{{ keycloak_default_theme }}" account_theme: "{{ keycloak_default_theme }}"
admin_theme: "{{ keycloak_default_theme }}" admin_theme: "{{ keycloak_default_theme }}"
login_theme: "{{ keycloak_default_theme }}" login_theme: "{{ keycloak_default_theme }}"
registration_allowed: no registration_allowed: false
reset_password_allowed: no reset_password_allowed: false
login_with_email_allowed: no login_with_email_allowed: false
duplicate_emails_allowed: yes duplicate_emails_allowed: true
internationalization_enabled: yes internationalization_enabled: true
default_locale: "de" default_locale: "de"
supported_locales: supported_locales:
- "de" - "de"
- "en" - "en"
events_enabled: yes events_enabled: true
events_expiration: 604800 events_expiration: 604800
admin_events_enabled: yes admin_events_enabled: true
smtp_server: smtp_server:
host: "{{ shared_service_mail_hostname }}" host: "{{ shared_service_mail_hostname }}"
from: "{{ keycloak_id }}@smardigo.digital" from: "{{ keycloak_id }}@smardigo.digital"

@ -11,6 +11,15 @@ keycloak_labels: [
'"traefik.http.routers.{{ keycloak_id }}.tls=true"', '"traefik.http.routers.{{ keycloak_id }}.tls=true"',
'"traefik.http.routers.{{ keycloak_id }}.tls.certresolver=letsencrypt"', '"traefik.http.routers.{{ keycloak_id }}.tls.certresolver=letsencrypt"',
'"traefik.http.services.{{ keycloak_id }}.loadbalancer.server.port={{ service_port }}"', '"traefik.http.services.{{ keycloak_id }}.loadbalancer.server.port={{ service_port }}"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.service={{ keycloak_id }}"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.rule=Host(`{{ stage_server_domain }}`)&&Method(`POST`,`PUT`,`DELETE`, `PATCH`)"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.entrypoints=websecure"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.tls=true"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.tls.certresolver=letsencrypt"',
'"traefik.http.services.{{ keycloak_id }}-state-change.loadbalancer.server.port={{ service_port }}"',
'"traefik.http.routers.{{ keycloak_id }}-state-change.middlewares={{ keycloak_id }}-state-change-ipwhitelist"',
'"traefik.http.middlewares.{{ keycloak_id }}-state-change-ipwhitelist.ipwhitelist.sourcerange={{ ip_whitelist | join(",") }}"',
] ]
keycloak_docker: { keycloak_docker: {

Loading…
Cancel
Save