initial: no secrets

This commit is contained in:
2024-02-12 17:01:18 +01:00
commit cf9efd55b5
186 changed files with 8697 additions and 0 deletions
@@ -0,0 +1,8 @@
#!/bin/bash
DIR=/home/sheppy/slapd_backup/
BACKUP_NAME=backup_$(date +%Y%m%d).ldif
mkdir -p $DIR
slapcat > ${DIR}${BACKUP_NAME}
chown -R sheppy:sheppy $DIR
@@ -0,0 +1,23 @@
attributetype ( 1.2.6.1.4.1
NAME 'emailVerified'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.2.6.1.4.2
NAME 'signalVerified'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE )
attributetype ( 1.2.6.1.4.3
NAME 'phoneVerified'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE )
objectclass ( 1.2.6.1.4.100 NAME 'verification'
DESC 'Class for various verification states'
SUP top
AUXILIARY
MAY ( emailVerified $ signalVerified $ phoneVerified ) )
+2
View File
@@ -0,0 +1,2 @@
dependencies:
- global-handlers
@@ -0,0 +1,130 @@
- name: Create LDAP user federation
community.general.keycloak_user_federation:
auth_keycloak_url: https://{{ keycloak_address }}
auth_realm: master
auth_username: admin
auth_password: "{{ keycloak_admin_password }}"
realm: master
name: ldap-ansible
state: present
provider_id: ldap
provider_type: org.keycloak.storage.UserStorageProvider
id: 11111111-0000-0000-0000-000000000001
config:
priority: 0
enabled: true
cachePolicy: DEFAULT
batchSizeForSync: 1000
editMode: WRITABLE
importEnabled: true
syncRegistrations: true
fullSyncPeriod: 600
vendor: other
usernameLDAPAttribute: uid
rdnLDAPAttribute: uid
uuidLDAPAttribute: uid
userObjectClasses: person, inetOrgPerson, organizationalPerson, verification
connectionUrl: "{{ ldap_connection_url }}"
usersDn: "{{ ldap_user_dn }}"
authType: simple
bindDn: "{{ ldap_bind_dn }}"
bindCredential: "{{ ldap_password }}"
searchScope: "1"
validatePasswordPolicy: false
trustEmail: false
useTruststoreSpi: ldapsOnly
connectionPooling: true
pagination: true
allowKerberosAuthentication: false
debug: false
useKerberosForPasswordAuthentication: false
mappers:
- name: "username"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: false
is.mandatory.in.ldap: true
read.only: false
user.model.attribute: username
ldap.attribute: uid
- name: "email"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: false
is.mandatory.in.ldap: true
read.only: false
user.model.attribute: email
ldap.attribute: mail
- name: "first name"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: true
is.mandatory.in.ldap: true
read.only: false
user.model.attribute: firstName
ldap.attribute: cn
- name: "last name"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: true
is.mandatory.in.ldap: true
read.only: false
user.model.attribute: lastName
ldap.attribute: sn
- name: "telephoneNumber"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: true
is.mandatory.in.ldap: false
read.only: false
user.model.attribute: telephoneNumber
ldap.attribute: telephoneNumber
- name: "modify date"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: true
is.mandatory.in.ldap: false
read.only: true
user.model.attribute: modifyTimestamp
ldap.attribute: modifyTimestamp
- name: "creation date"
providerId: "user-attribute-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
always.read.value.from.ldap: true
is.mandatory.in.ldap: false
read.only: true
user.model.attribute: createTimestamp
ldap.attribute: createTimestamp
#- name: "email_verified"
# providerId: "user-attribute-ldap-mapper"
# providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
# config:
# always.read.value.from.ldap: false
# is.mandatory.in.ldap: false
# read.only: false
# user.model.attribute: emailVerified
# ldap.attribute: emailVerified
- name: "group-mapper"
providerId: "group-ldap-mapper"
providerType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
config:
membership.attribute.type: "DN"
group.name.ldap.attribute: "cn"
preserve.group.inheritance: true
membership.user.ldap.attribute: "uid"
groups.dn: "ou=groups,{{ ldap_suffix }}"
mode: "LDAP_ONLY"
user.roles.retrieve.strategy: "LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"
ignore.missing.groups: false
membership.ldap.attribute: "member"
group.object.classes: "groupOfNames"
memberof.ldap.attribute: "memberOf"
groups.path: "/"
drop.non.existing.groups.during.sync : true
+125
View File
@@ -0,0 +1,125 @@
- name: Create data-dir
file:
name: /data/
state: directory
- name: Create keycloak psql mount
file:
name: /data/keycloak-postgres/
state: directory
- name: Clone keycloak Themes
git:
repo: https://github.com/FAUSheppy/atlantis-keycloak-themes
dest: "/data/atlantis-keycloak-themes/"
version: master
- name: Create compose directory keycloak
file:
name: "/opt/keycloak/"
state: directory
- name: Copy compose templates keycloak
template:
src: "keycloak.yaml"
dest: "/opt/keycloak/"
- name: Copy compose environment files keycloak
template:
src: "{{ item }}"
dest: "/opt/keycloak/"
with_items:
- postgres_password
- name: Deploy compose templates
community.docker.docker_compose:
project_src: "/opt/keycloak/"
pull: true
files:
- "keycloak.yaml"
- name: Check/Wait for Keycloak to be up
uri:
url: https://keycloak.atlantishq.de/health
method: GET
return_content: yes
status_code: 200
body_format: json
register: result
until: result.status == 200 and result.json.status == "UP"
retries: 10
delay: 20
check_mode: false
- name: Create Keycloak Clients
local_action:
module: keycloak_client
auth_client_id: admin-cli
auth_keycloak_url: https://keycloak.atlantishq.de/
auth_realm: master
auth_username: admin
auth_password: "{{ keycloak_admin_password }}"
state: present
realm: master
client_id: '{{ keycloak_clients[item]["client_id"] }}'
id: '{{ keycloak_clients[item]["keycloak_id"] }}'
name: '{{ keycloak_clients[item]["client_id"] }}'
description: '{{ keycloak_clients[item]["description"] }}'
enabled: True
client_authenticator_type: client-secret
public_client: false
secret: '{{ keycloak_clients[item]["client_secret"] }}'
authorization_services_enabled: true
service_accounts_enabled: true
redirect_uris: '{{ keycloak_clients[item]["redirect_uris"] }}'
web_origins: '{{ keycloak_clients[item]["redirect_uris"] }}'
frontchannel_logout: False
protocol: openid-connect
protocol_mappers:
- config:
accesss.token.claim: true
claim.name: "groups"
id.token.claim: true
userinfo.token.claim: true
full.path: false
id: "{{ keycloak_clients[item]['keycloak_id'] | regex_replace('^(?P<X>.{2})(.)', '\\g<X>' ~ '1') }}"
consentRequired: false
protocol: "openid-connect"
protocolMapper: "oidc-group-membership-mapper"
name: "client-group-mapper"
- config:
included.client.audience: '{{ keycloak_clients[item]["client_id"] }}'
id.token.claim: false
access.token.claim: true
id: "{{ keycloak_clients[item]['keycloak_id'] | regex_replace('^(?P<X>.{2})(.)', '\\g<X>' ~ '2') }}"
# ist das regex zu stark bist du zu schwach
consentRequired: false
protocol: "openid-connect"
protocolMapper: "oidc-audience-mapper"
name: "aud-mapper-client"
with_items: "{{ keycloak_clients.keys() | list }}"
- name: Update master realm settings
community.general.keycloak_realm:
auth_client_id: admin-cli
auth_keycloak_url: https://keycloak.atlantishq.de/
auth_realm: master
auth_username: admin
auth_password: "{{ keycloak_admin_password }}"
state: present
realm: master
loginTheme: "atlantis"
resetPasswordAllowed: "true"
smtpServer :
password : "{{ smtp_service_pass }}"
replyToDisplayName: ""
starttls: "true"
auth: "true"
replyTo: ""
envelopeFrom: ""
from: "{{ smtp_service_user }}@atlantishq.de"
fromDisplayName: ""
host: "{{ smtp_internal_host }}"
port: "{{ smtp_internal_host_port }}"
ssl: "false"
user: "{{ smtp_service_user }}@atlantishq.de"
+157
View File
@@ -0,0 +1,157 @@
- name: Install LDAP packages
apt:
pkg:
- slapd
- ldap-utils
- python3-ldap
- name: directory /var/lib/slapd/
file:
path: /var/lib/ldap/
owner: root
group: openldap
mode: 0770
state: directory
- name: slapd-LDAP Conf
template:
src: slapd.conf
dest: /etc/ldap/slapd.conf
owner: openldap
notify:
- restart slapd
- name: Disable & mask broken debian slapd unit
systemd:
name: slapd
state: stopped
enabled: false
masked: yes
- name: Copy slapd systemd unit
template:
src: slapd-custom.service
dest: /etc/systemd/system/slapd-custom.service
mode: 0644
notify:
- daemon reload
- restart slapd
- name: Enable and start slapd custom service
systemd:
name: slapd-custom.service
state: started
enabled: yes
- name: LDAP master conf
template:
src: ldap.conf
dest: /etc/ldap/ldap.conf
owner: openldap
notify:
- restart slapd
- name: LDAP extra schemas
copy:
src: verification.schema
dest: /etc/ldap/schema/verification.schema
owner: openldap
notify:
- restart slapd
- meta: flush_handlers
- name: Wait for LDAP to become ready
wait_for:
port: 389
timeout: 30
delay: 5
- name: Create LDAP root (1)
ldap_entry:
dn: "{{ ldap_suffix }}"
objectClass:
- dcObject
- organization
attributes: |
{ "o" : "{{ ldap_org }}", "dc" : "{{ ldap_dc }}" }
state: present
server_uri: "ldap://localhost"
bind_dn: "{{ ldap_bind_dn }}"
bind_pw: "{{ ldap_password }}"
- name: Create LDAP root (2)
ldap_entry:
dn: "cn=Manager,dc=atlantishq,dc=de"
objectClass:
- organizationalRole
attributes: |
{ "cn" : "Manager" }
state: present
server_uri: "ldap://localhost"
bind_dn: "{{ ldap_bind_dn }}"
bind_pw: "{{ ldap_password }}"
- name: Create LDAP Group people
ldap_entry:
dn: "ou=People,{{ ldap_suffix }}"
objectClass:
- organizationalUnit
state: present
server_uri: "ldap://localhost"
bind_dn: "{{ ldap_bind_dn }}"
bind_pw: "{{ ldap_password }}"
- name: Create LDAP groups root
ldap_entry:
dn: "ou=groups,{{ ldap_suffix }}"
objectClass:
- organizationalUnit
state: present
server_uri: "ldap://localhost"
bind_dn: "{{ ldap_bind_dn }}"
bind_pw: "{{ ldap_password }}"
- name: Create LDAP groups
ldap_entry:
dn: "cn={{ item }},ou=groups,{{ ldap_suffix }}"
objectClass:
- groupOfNames
attributes: { "member" : "" }
state: present
server_uri: "ldap://localhost"
bind_dn: "{{ ldap_bind_dn }}"
bind_pw: "{{ ldap_password }}"
with_items:
- nextcloud
- images
- mail
- soundlib
- monitoring
- pki
- name: Deploy Backup Script
copy:
src: slapd_backup.sh
dest: /opt/
mode: 0700
- name: deploy LDAP fixer scripts
template:
src: fix_ldap.py
dest: /opt/fix_ldap.py
mode: 0700
- name: Create cronjob Slapd backup
cron:
hour: "0"
minute: "30"
name: SLAPD Backup (slapcat)
job: "/opt/slapd_backup.sh"
- name: Create cronjob LDAP fixer
cron:
hour: "*"
minute: "*"
name: LDAP keycloak fixer
job: "/opt/fix_ldap.py"
@@ -0,0 +1,18 @@
- name: install certbot
apt:
pkg:
- certbot
- name: Add Cronjob
cron:
name: "Cerbot"
job: "certbot certonly --standalone --preferred-challenges http -d ldap.atlantishq.de --register-unsafely-without-email --non-interactive --agree-tos"
minute: "30"
hour: "4"
day: "1"
register: cron
notify: restart slapd
- name: Run Cronjob job because it changed
command: "certbot certonly --standalone --preferred-challenges http -d ldap.atlantishq.de --register-unsafely-without-email --non-interactive --agree-tos"
when: cron.changed
+11
View File
@@ -0,0 +1,11 @@
- name: cerbot letsencrypt standalone
include: letsencrypt.yaml
- name: Keycloak User federation (ldap-provider)
include: keycloak.yaml
- name: Keycloak User federation (ldap-provider)
include: keycloak-ldap-provider.yaml
- name: Include LDAP setup
include: ldap.yaml
@@ -0,0 +1,45 @@
#!/usr/bin/python3
from ldap3 import Server, Connection, MODIFY_ADD, MODIFY_DELETE
ldap_server = 'ldap://localhost'
ldap_user = '{{ ldap_bind_dn }}'
ldap_password = '{{ ldap_password }}'
base_dn = '{{ ldap_user_dn }}'
groups_base_dn = '{{ ldap_group_dn }}'
new_objectclass = 'verification'
# Connect to the LDAP server
server = Server(ldap_server)
conn = Connection(server, user=ldap_user, password=ldap_password)
if not conn.bind():
print(f"Failed to bind to LDAP server: {conn.last_error}")
exit(1)
# handle groups #
conn.search(groups_base_dn, '(objectClass=*)')
for entry in conn.entries:
dn = entry.entry_dn
# add verification class if it is missing #
conn.modify(dn, {'member': [(MODIFY_DELETE, [""])]})
# handle people #
conn.search(base_dn, '(objectClass=person)')
for entry in conn.entries:
dn = entry.entry_dn
# add verification class if it is missing #
conn.modify(dn, {'objectClass': [(MODIFY_ADD, ["verification"])]})
# set verification value if it is not set #
modifications = {
'emailVerified': [(MODIFY_ADD, ["false"])]
}
conn.modify(dn, modifications)
# Unbind from the LDAP server
conn.unbind()
@@ -0,0 +1,52 @@
---
version: '3.3'
services:
keycloak:
container_name: keycloak-container
command: start --hostname-strict=false --log-level=WARNING
image: quay.io/keycloak/keycloak:23.0.3
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD={{ keycloak_admin_password }}
- PROXY_ADDRESS_FORWARDING=true
- KC_PROXY=edge
- KC_LOG_LEVEL=ALL
- KC_DB_URL_HOST=postgres
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD={{ keycloak_postgres_password }}
- KC_HEALTH_ENABLED=true
- KC_METRICS_ENABLED=true
- KC_DB=postgres
- KEYCLOAK_LOGLEVEL=WARN
restart: unless-stopped
ports:
- 5050:8080
depends_on:
- postgres
secrets:
- postgres_password
volumes:
- /data/atlantis-keycloak-themes/themes/:/opt/keycloak/themes/
postgres:
container_name: postgres-container
image: postgres:15.1
environment:
- POSTGRES_DB=keycloak
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
- POSTGRES_USER=keycloak
restart: unless-stopped
secrets:
- postgres_password
volumes:
- /data/keycloak-postgres/:/var/lib/postgresql/data
secrets:
postgres_password:
file: postgres_password
volumes:
postgres-data:
...
+2
View File
@@ -0,0 +1,2 @@
BASE {{ ldap_bind_dn }}
URI {{ ldap_connection_url }}
@@ -0,0 +1 @@
{{ keycloak_postgres_password }}
@@ -0,0 +1,29 @@
[Unit]
Description=Slapd Custom Service
[Service]
Type=forking
ExecStart=/usr/sbin/slapd -f /etc/ldap/slapd.conf -h "ldap:///"
User=openldap
Group=openldap
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
Restart=on-failure
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectControlGroups=yes
NoNewPrivileges=yes
MountFlags=private
SystemCallArchitectures=native
PrivateDevices=yes
[Install]
WantedBy=multi-user.target
+29
View File
@@ -0,0 +1,29 @@
modulepath /usr/lib/ldap/
moduleload back_bdb.la
pidfile /var/lib/ldap/slapd.pid
argsfile /var/lib/ldap/slapd.args
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/verification.schema
database bdb
suffix "{{ ldap_suffix }}"
rootdn "{{ ldap_bind_dn }}"
rootpw {SSHA}6nIaokLhkEKaA3i33QsWiRov+jDIvx7l
#TLSCACertificateFile /etc/ssl/certs/ca-certificates.crt
#TLSCertificateFile /etc/letsencrypt/live/ldap.atlantishq.de/cert.pem
#TLSCertificateKeyFile /etc/letsencrypt/live/ldap.atlantishq.de/privkey.pem
TLSVerifyClient try
logfile /var/log/slapd.log
#loglevel -1
loglevel none
directory /var/lib/ldap/
cachesize 2000