diff --git a/.compose/examples/tom+fed+chat+admin.pgsql.yml b/.compose/examples/tom+fed+chat+admin.pgsql.yml new file mode 100644 index 00000000..f975a7aa --- /dev/null +++ b/.compose/examples/tom+fed+chat+admin.pgsql.yml @@ -0,0 +1,239 @@ +services: + pgsql: + image: postgres + container_name: pgsql + volumes: + - ../pgsql/init-llng-db.sh:/docker-entrypoint-initdb.d/init-llng-db.sh + - ../pgsql/init-synapse-db.sh:/docker-entrypoint-initdb.d/init-synapse-db.sh + - ../pgsql/init-twake-db.sh:/docker-entrypoint-initdb.d/init-twake-db.sh + - ../pgsql/init-users-db.sh:/docker-entrypoint-initdb.d/init-users-db.sh + # - ../pgsql/data:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=postgres!! + healthcheck: + test: ["CMD-SHELL", "pg_isready"] + interval: 10s + timeout: 5s + retries: 5 + # ports: + # - 5432:5432 + networks: + - db + + auth: + image: yadd/lemonldap-ng-full + volumes: + - ../lemon/lmConf-pgsql.json:/var/lib/lemonldap-ng/conf/lmConf-1.json + - ../lemon/ssl.conf:/etc/nginx/sites-enabled/0000default.conf + - ../lemon/root.conf:/etc/nginx/sites-enabled/root.conf + - ../lemon/sessions:/var/lib/lemonldap-ng/session + - ../synapse/wellknownserver.conf:/var/www/matrix-server.json + - ../synapse/wellknownclient.conf:/var/www/matrix-client.json + - ../ssl:/etc/nginx/ssl + depends_on: + pgsql: + condition: service_healthy + environment: + - SSODOMAIN=docker.localhost + - PORTAL=https://auth.docker.localhost + - LOGLEVEL=debug + - LOGGER=stderr + - USERLOGGER=stderr + deploy: + mode: replicated + replicas: 1 + restart_policy: + condition: on-failure + networks: + frontend: + aliases: + - auth + db: + + synapse: + image: matrixdotorg/synapse + restart: unless-stopped + env_file: + - path: ../.env + required: true + volumes: + - ../synapse:/data + - ../synapse/homeserver-pgsql.yaml:/data/homeserver.yaml + - ../ssl:/etc/ssl/certs + depends_on: + auth: + condition: service_started + pgsql: + condition: service_healthy + networks: + frontend: + aliases: + - synapse + db: + + tom: + image: tom + build: + context: ../.. + # dockerfile: ./packages/tom-server/Dockerfile + dockerfile: ./Dockerfile + depends_on: + synapse: + condition: service_started + pgsql: + condition: service_healthy + # ports: + # - 3000:3000 + # - 9229:9229 + networks: + frontend: + aliases: + - tom.server + db: + environment: + # - NODE_OPTIONS="--inspect=0.0.0.0:9229" + - NODE_TLS_REJECT_UNAUTHORIZED=0 + + - SERVER_NAME=docker.localhost + - BASE_URL=https://tom.docker.localhost + - OIDC_ISSUER=https://auth.docker.localhost + - TRUSTED_PROXIES=uniquelocal + + - ADDITIONAL_FEATURES=true + - FEDERATED_IDENTITY_SERVICES=fed.docker.localhost + + - CRON_SERVICE=true + - UPDATE_FEDERATED_IDENTITY_HASHES_CRON=0-59/2 * * * * + - UPDATE_USERS_CRON=1-59/2 * * * * + + - DATABASE_ENGINE=pg + - DATABASE_HOST=pgsql + - DATABASE_NAME=tom + - DATABASE_USER=twake + - DATABASE_PASSWORD=twake!1 + + - USERDB_ENGINE=pg + - USERDB_HOST=pgsql + - USERDB_NAME=lemonldapng + - USERDB_USER=lemonldap + - USERDB_PASSWORD=lemondldap + + - MATRIX_INTERNAL_HOST=http://synapse:8008 + - MATRIX_SERVER=matrix.docker.localhost + - MATRIX_DATABASE_ENGINE=pg + - MATRIX_DATABASE_HOST=pgsql + - MATRIX_DATABASE_NAME=synapse + - MATRIX_DATABASE_USER=synapse + - MATRIX_DATABASE_PASSWORD=synapse!1 + + - SMS_API_KEY=SOME_SECRET_KEY + - SMS_API_LOGIN=login@domain.com + - SMS_API_URL=https://api.octopush.com/v1/public + + - LOG_LEVEL=silly + - LOG_TRANSPORTS=Console + + fed: + image: fed + build: + context: ../.. + dockerfile: ./packages/federated-identity-service/Dockerfile + # ports: + # - 3001:3001 + # - 9229:9229 + networks: + frontend: + aliases: + - fed.server + db: + depends_on: + pgsql: + condition: service_healthy + tom: + condition: service_started + environment: + # - NODE_OPTIONS="--inspect=0.0.0.0:9229" + - NODE_TLS_REJECT_UNAUTHORIZED=0 + + - BASE_URL=https://fed.docker.localhost + - SERVER_NAME=docker.localhost + - TRUSTED_PROXIES=uniquelocal + - TRUSTED_SERVERS_ADDRESSES=172.0.0.0/8 + + - ADDITIONAL_FEATURES=true + + - CRON_SERVICE=true + # - UPDATE_FEDERATED_IDENTITY_HASHES_CRON=0-59/2 * * * * + # - UPDATE_USERS_CRON=1-59/2 * * * * + + - DATABASE_ENGINE=pg + - DATABASE_HOST=pgsql + - DATABASE_NAME=fed + - DATABASE_USER=twake + - DATABASE_PASSWORD=twake!1 + + ## For storing the federated identity raw users + # - USERDB_ENGINE=pg + # - USERDB_HOST=pgsql + # - USERDB_NAME=lemonldapng + # - USERDB_USER=lemonldap + # - USERDB_PASSWORD=lemondldap + + - LOG_LEVEL=silly + - LOG_TRANSPORTS=Console + + chat: + image: linagora/twake-web + volumes: + - ../chat/config.json:/usr/share/nginx/html/web/config.json + - ../ssl:/etc/nginx/ssl + # ports: + # - 80:80 + networks: + - frontend + + admin: + image: ghcr.io/etkecc/synapse-admin + volumes: + - ../synapse-admin/config.json:/app/config.json:ro + networks: + - frontend + + haproxy: + image: haproxy:2.6-bookworm + ports: + - 443:443 + volumes: + # Reverse proxy routing configuration + - ../haproxy/haproxy.tom+fed+chat+admin.cfg:/usr/local/etc/haproxy/haproxy.cfg + - ../haproxy/cors.lua:/usr/local/etc/haproxy/cors.lua + - ../haproxy/lua_endpoint_to_function.map_rewrite.cfg:/usr/local/etc/haproxy/lua_endpoint_to_function.map_rewrite.cfg + - ../haproxy/lua_endpoint_to_worker.map_rewrite.lua:/usr/local/etc/haproxy/lua_endpoint_to_worker.map_rewrite.lua + - ../haproxy/synapse_worker_endpoint_indexer.lua:/usr/local/etc/haproxy/synapse_worker_endpoint_indexer.lua + # HTTPS SSL Certs + - ../ssl/both.pem:/etc/ssl/certs/both.pem + sysctls: + - net.ipv4.ip_unprivileged_port_start=0 + depends_on: + - auth + - synapse + - tom + - fed + - chat + - admin + networks: + frontend: + aliases: + - admin.docker.localhost + - auth.docker.localhost + - chat.docker.localhost + - matrix.docker.localhost + - tom.docker.localhost + - fed.docker.localhost + - docker.localhost + +networks: + db: + name: db + frontend: + name: frontend diff --git a/.compose/examples/tom+fed+chat.pgsql.yml b/.compose/examples/tom+fed+chat.pgsql.yml new file mode 100644 index 00000000..64b2c7bf --- /dev/null +++ b/.compose/examples/tom+fed+chat.pgsql.yml @@ -0,0 +1,230 @@ +services: + pgsql: + image: postgres + container_name: pgsql + volumes: + - ../pgsql/init-llng-db.sh:/docker-entrypoint-initdb.d/init-llng-db.sh + - ../pgsql/init-synapse-db.sh:/docker-entrypoint-initdb.d/init-synapse-db.sh + - ../pgsql/init-twake-db.sh:/docker-entrypoint-initdb.d/init-twake-db.sh + - ../pgsql/init-users-db.sh:/docker-entrypoint-initdb.d/init-users-db.sh + # - ../pgsql/data:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=postgres!! + healthcheck: + test: ["CMD-SHELL", "pg_isready"] + interval: 10s + timeout: 5s + retries: 5 + # ports: + # - 5432:5432 + networks: + - db + + auth: + image: yadd/lemonldap-ng-full + volumes: + - ../lemon/lmConf-pgsql.json:/var/lib/lemonldap-ng/conf/lmConf-1.json + - ../lemon/ssl.conf:/etc/nginx/sites-enabled/0000default.conf + - ../lemon/root.conf:/etc/nginx/sites-enabled/root.conf + - ../lemon/sessions:/var/lib/lemonldap-ng/session + - ../synapse/wellknownserver.conf:/var/www/matrix-server.json + - ../synapse/wellknownclient.conf:/var/www/matrix-client.json + - ../ssl:/etc/nginx/ssl + depends_on: + pgsql: + condition: service_healthy + environment: + - SSODOMAIN=docker.localhost + - PORTAL=https://auth.docker.localhost + - LOGLEVEL=debug + - LOGGER=stderr + - USERLOGGER=stderr + deploy: + mode: replicated + replicas: 1 + restart_policy: + condition: on-failure + networks: + frontend: + aliases: + - auth + db: + + synapse: + image: matrixdotorg/synapse + restart: unless-stopped + env_file: + - path: ../.env + required: true + volumes: + - ../synapse:/data + - ../synapse/homeserver-pgsql.yaml:/data/homeserver.yaml + - ../ssl:/etc/ssl/certs + depends_on: + auth: + condition: service_started + pgsql: + condition: service_healthy + networks: + frontend: + aliases: + - synapse + db: + + tom: + image: tom + build: + context: ../.. + # dockerfile: ./packages/tom-server/Dockerfile + dockerfile: ./Dockerfile + depends_on: + synapse: + condition: service_started + pgsql: + condition: service_healthy + # ports: + # - 3000:3000 + # - 9229:9229 + networks: + frontend: + aliases: + - tom.server + db: + environment: + # - NODE_OPTIONS="--inspect=0.0.0.0:9229" + - NODE_TLS_REJECT_UNAUTHORIZED=0 + + - SERVER_NAME=docker.localhost + - BASE_URL=https://tom.docker.localhost + - OIDC_ISSUER=https://auth.docker.localhost + - TRUSTED_PROXIES=uniquelocal + + - ADDITIONAL_FEATURES=true + - FEDERATED_IDENTITY_SERVICES=fed.docker.localhost + + - CRON_SERVICE=true + - UPDATE_FEDERATED_IDENTITY_HASHES_CRON=0-59/2 * * * * + - UPDATE_USERS_CRON=1-59/2 * * * * + + - DATABASE_ENGINE=pg + - DATABASE_HOST=pgsql + - DATABASE_NAME=tom + - DATABASE_USER=twake + - DATABASE_PASSWORD=twake!1 + + - USERDB_ENGINE=pg + - USERDB_HOST=pgsql + - USERDB_NAME=lemonldapng + - USERDB_USER=lemonldap + - USERDB_PASSWORD=lemonldap + + - MATRIX_INTERNAL_HOST=http://synapse:8008 + - MATRIX_SERVER=matrix.docker.localhost + - MATRIX_DATABASE_ENGINE=pg + - MATRIX_DATABASE_HOST=pgsql + - MATRIX_DATABASE_NAME=synapse + - MATRIX_DATABASE_USER=synapse + - MATRIX_DATABASE_PASSWORD=synapse!1 + + - SMS_API_KEY=SOME_SECRET_KEY + - SMS_API_LOGIN=login@domain.com + - SMS_API_URL=https://api.octopush.com/v1/public + + - LOG_LEVEL=silly + - LOG_TRANSPORTS=Console + + fed: + image: fed + build: + context: ../.. + dockerfile: ./packages/federated-identity-service/Dockerfile + # ports: + # - 3001:3001 + # - 9229:9229 + networks: + frontend: + aliases: + - fed.server + db: + depends_on: + pgsql: + condition: service_healthy + tom: + condition: service_started + environment: + # - NODE_OPTIONS="--inspect=0.0.0.0:9229" + - NODE_TLS_REJECT_UNAUTHORIZED=0 + + - SERVER_NAME=docker.localhost + - BASE_URL=https://fed.docker.localhost + - TRUSTED_PROXIES=uniquelocal + - TRUSTED_SERVERS_ADDRESSES=172.0.0.0/8 + + - ADDITIONAL_FEATURES=true + + - CRON_SERVICE=true + # - UPDATE_FEDERATED_IDENTITY_HASHES_CRON=0-59/2 * * * * + # - UPDATE_USERS_CRON=1-59/2 * * * * + + - DATABASE_ENGINE=pg + - DATABASE_HOST=pgsql + - DATABASE_NAME=fed + - DATABASE_USER=twake + - DATABASE_PASSWORD=twake!1 + + ## For storing the federated identity raw users + # - USERDB_ENGINE=pg + # - USERDB_HOST=pgsql + # - USERDB_NAME=lemonldapng + # - USERDB_USER=lemonldap + # - USERDB_PASSWORD=lemonldap + + - LOG_LEVEL=silly + - LOG_TRANSPORTS=Console + + chat: + image: linagora/twake-web + volumes: + - ../chat/config.json:/usr/share/nginx/html/web/config.json + - ../ssl:/etc/nginx/ssl + # ports: + # - 80:80 + networks: + - frontend + + haproxy: + image: haproxy:2.6-bookworm + ports: + - 443:443 + volumes: + # Reverse proxy routing configuration + - ../haproxy/haproxy.tom+fed+chat.cfg:/usr/local/etc/haproxy/haproxy.cfg + - ../haproxy/cors.lua:/usr/local/etc/haproxy/cors.lua + - ../haproxy/lua_endpoint_to_function.map_rewrite.cfg:/usr/local/etc/haproxy/lua_endpoint_to_function.map_rewrite.cfg + - ../haproxy/lua_endpoint_to_worker.map_rewrite.lua:/usr/local/etc/haproxy/lua_endpoint_to_worker.map_rewrite.lua + - ../haproxy/synapse_worker_endpoint_indexer.lua:/usr/local/etc/haproxy/synapse_worker_endpoint_indexer.lua + # HTTPS SSL Certs + - ../ssl/both.pem:/etc/ssl/certs/both.pem + sysctls: + - net.ipv4.ip_unprivileged_port_start=0 + depends_on: + - auth + - synapse + - tom + - fed + - chat + networks: + frontend: + aliases: + - auth.docker.localhost + - chat.docker.localhost + - matrix.docker.localhost + - tom.docker.localhost + - fed.docker.localhost + - docker.localhost + +networks: + db: + name: db + frontend: + name: frontend diff --git a/.compose/examples/tom+fed+chat.sqlite.yml b/.compose/examples/tom+fed+chat.sqlite.yml index 0e44b4cd..a4a47f72 100644 --- a/.compose/examples/tom+fed+chat.sqlite.yml +++ b/.compose/examples/tom+fed+chat.sqlite.yml @@ -84,12 +84,14 @@ services: - DATABASE_HOST=file:tom?mode=memory&cache=shared - USERDB_ENGINE=sqlite - - USERDB_HOST=/opt/lemon/db/lemon.db + # - USERDB_HOST=/opt/lemon/db/lemon.db + - USERDB_HOST=file:lemon?mode=memory&cache=shared - MATRIX_INTERNAL_HOST=http://synapse:8008 - MATRIX_SERVER=matrix.docker.localhost - MATRIX_DATABASE_ENGINE=sqlite - - MATRIX_DATABASE_HOST=/opt/synapse/db/homeserver.db + # - MATRIX_DATABASE_HOST=/opt/synapse/db/homeserver.db + - MATRIX_DATABASE_HOST=file:synapse?mode=memory&cache=shared - SMS_API_KEY=SOME_SECRET_KEY - SMS_API_LOGIN=login@domain.com diff --git a/.compose/lemon/create-user.sh b/.compose/lemon/create-user.sh deleted file mode 100755 index 6131dd27..00000000 --- a/.compose/lemon/create-user.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -readonly nickname="${1:-dwho}" -readonly fullname="${2:-Doctor Who}" -readonly mail="${3:-${nickname}@docker.localhost}" -readonly mobile="${4:-330123456789}" -readonly password="${5:-$nickname}" - -echo -e "Adding user: ${fullname} (${nickname})\n\tpass: ${password}\n\tmail: ${mail}\n\tmobile: ${mobile}" -sqlite3 lemon.db "insert into users values ('${nickname}','${fullname}','${mail}','${mobile}','${password}')" -[[ "$?" == '0' ]] && echo "Done." diff --git a/.compose/lemon/init-db.sh b/.compose/lemon/init-db.sh index 34b59a87..2a3de6f6 100755 --- a/.compose/lemon/init-db.sh +++ b/.compose/lemon/init-db.sh @@ -1,10 +1,103 @@ #!/usr/bin/env bash +# vim: set filetype=sh ts=2 sw=2 sts=2 expandtab : -echo "Inflating Auth DB." -sqlite3 lemon.db "Create table if not exists users (uid text,name text,mail text,phone text,password text);" -[[ "$?" == '0' ]] && echo "Done." +echo "Inflating Authentication Database (lemon.db)." - # nickname # Full Name # mail # mobile # password -./create-user.sh 'dwho' 'Doctor Who' '' '33745718646' 'dwho' -./create-user.sh 'rtyler' 'R. Tyler' '' '17759865200' 'rtyler' -./create-user.sh 'jbinks' 'Jar Jar Binks' '' '4915510829025' 'jbinks' +# Create the users table if it doesn't already exist +sqlite3 lemon.db "CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT, + password TEXT, + sn TEXT, + mail TEXT, + givenname TEXT, + mobile TEXT, + isadmin INTEGER DEFAULT 0, + isblocked INTEGER DEFAULT 0 +);" +[[ "$?" == '0' ]] && echo "Table 'users' created or already exists." || { echo "Error creating table 'users'. Exiting."; exit 1; } + +# Create unique indexes for frequently searched fields +# Note: The UNIQUE constraint on 'mail' above handles its uniqueness. +sqlite3 lemon.db "CREATE UNIQUE INDEX IF NOT EXISTS u__username ON users (username);" +[[ "$?" == '0' ]] && echo "Index 'u__username' created or already exists." || { echo "Error creating index 'u__username'. Exiting."; exit 1; } + +sqlite3 lemon.db "CREATE UNIQUE INDEX IF NOT EXISTS u__mail ON users (mail);" +[[ "$?" == '0' ]] && echo "Index 'u__mail' created or already exists." || { echo "Error creating index 'u__mail'. Exiting."; exit 1; } + +sqlite3 lemon.db "CREATE UNIQUE INDEX IF NOT EXISTS u__mobile ON users (mobile);" +[[ "$?" == '0' ]] && echo "Index 'u__mobile' created or already exists." || { echo "Error creating index 'u__mobile'. Exiting."; exit 1; } + +echo "Inserting user data..." + +# Insert user data matching the PostgreSQL schema +# Using INSERT OR IGNORE to skip rows that would violate unique constraints (e.g., duplicate emails) +# Derivation Logic: +# givenname: Use 'givenName' from LDIF if present. Otherwise, use the first word of 'cn'. +# sn: If 'cn' has multiple words, use the last word of 'cn'. Otherwise, use 'sn' from LDIF if present, else NULL. +sqlite3 lemon.db "INSERT OR IGNORE INTO users (username, password, givenname, sn, mail, mobile) VALUES +('dwho', 'dwho', 'Doctor', 'Who', 'dwho@docker.localhost', '+33612345678'), +('rtyler', 'rtyler', 'R.', 'Tyler', 'rtyler@docker.localhost', '+11234567890'), +('jbinks', 'jbinks', 'Jar Jar', 'Binks', 'jbinks@docker.localhost', '+84123456789'), +('msmith', 'msmith', 'Mr', 'Smith', 'msmith@docker.localhost', NULL), +('okenobi', 'okenobi', 'Obi-Wan', 'Kenobi', 'okenobi@docker.localhost', NULL), +('qjinn', 'qjinn', 'Qui-Gon', 'Jinn', 'qjinn@docker.localhost', NULL), +('chewbacca', 'chewbacca', 'Chewbacca', 'Chewbacca', 'chewbacca@docker.localhost', NULL), +('lorgana', 'lorgana', 'Leia', 'Organa', 'lorgana@docker.localhost', NULL), +('pamidala', 'pamidala', 'Padme', 'Amidala', 'pamidala@docker.localhost', NULL), +('cdooku', 'cdooku', 'Comte', 'Dooku', 'cdooku@docker.localhost', NULL), +('kren', 'kren', 'Kylo', 'Ren', 'kren@docker.localhost', NULL), +('dmaul', 'dmaul', 'Dark', 'Maul', 'dmaul@docker.localhost', NULL), +('askywalker', 'askywalker', 'Anakin', 'Skywalker', 'askywalker@docker.localhost', NULL), +('bfett', 'bfett', 'Boba', 'Fett', 'bfett@docker.localhost', NULL), +('jfett', 'jfett', 'Jango', 'Ffett', 'jfett@docker.localhost', NULL), +('lskywalker', 'lskywalker', 'Luc', 'Skywalker', 'lskywalker@docker.localhost', NULL), +('myoda', 'myoda', 'Master', 'Yoda', 'myoda@docker.localhost', NULL), +('hsolo', 'hsolo', 'Han', 'Solo', 'hsolo@docker.localhost', NULL), +('r2d2', 'r2d2', 'R2D2', 'R2D2', 'r2d2@docker.localhost', NULL), +('c3po', 'c3po', 'C3PO', 'C3po', 'c3po@docker.localhost', NULL), +('synapseadmin', 'synapseadmin', 'Synapse', 'Syadmin', 'synapseadmin@docker.localhost', NULL), +('annasmith', 'annasmith', 'Anna', 'Smith', 'annasmith@docker.localhost', NULL), +('johnjohnson', 'johnjohnson', 'John', 'Johnson', 'johnjohnson@docker.localhost', NULL), +('emilybrown', 'emilybrown', 'Emily', 'Brown', 'emilybrown@docker.localhost', NULL), +('daviddavis', 'daviddavis', 'David', 'Davis', 'daviddavis@docker.localhost', NULL), +('sarahwilson', 'sarahwilson', 'Sarah', 'Wilson', 'sarahwilson@docker.localhost', NULL), +('miketaylor', 'miketaylor', 'Mike', 'Taylor', 'miketaylor@docker.localhost', NULL), +('graceadams', 'graceadams', 'Grace', 'Adams', 'graceadams@docker.localhost', NULL), +('mattmoore', 'mattmoore', 'Matt', 'Moore', 'mattmoore@docker.localhost', NULL), +('lilyparker', 'lilyparker', 'Lily', 'Parker', 'lilyparker@docker.localhost', NULL), +('danieldixon', 'danieldixon', 'Daniel', 'Dixon', 'danieldixon@docker.localhost', NULL), +('mialopez', 'mialopez', 'Mia', 'Lopez', 'mialopez@docker.localhost', NULL), +('ethanjackson', 'ethanjackson', 'Ethan', 'Jackson', 'ethanjackson@docker.localhost', NULL), +('oliviaroberts', 'oliviaroberts', 'Olivia', 'Roberts', 'oliviaroberts@docker.localhost', NULL), +('jamessmith', 'jamessmith', 'James', 'Smith', 'jamessmith@docker.localhost', NULL), +('sophiathomas', 'sophiathomas', 'Sophia', 'Thomas', 'sophiathomas@docker.localhost', NULL), +('benjaminclark', 'benjaminclark', 'Benjamin', 'Clark', 'benjaminclark@docker.localhost', NULL), +('avamartin', 'avamartin', 'Ava', 'Martin', 'avamartin@docker.localhost', NULL), +('williamrogers', 'williamrogers', 'William', 'Rogers', 'williamrogers@docker.localhost', NULL), +('emmawright', 'emmawright', 'Emma', 'Wright', 'emmawright@docker.localhost', NULL), +('chloescott', 'chloescott', 'Chloe', 'Scott', 'chloescott@docker.localhost', NULL), +('danieltaylor', 'danieltaylor', 'Daniel', 'Taylor', 'danieltaylor@docker.localhost', NULL), +('sophiarichardson', 'sophiarichardson', 'Sophia', 'Richardson', 'sophiarichardson@docker.localhost', NULL), +('henryjones', 'henryjones', 'Henry', 'Jones', 'henryjones@docker.localhost', NULL), +('gracelewis', 'gracelewis', 'Lewis', 'gracelewis@docker.localhost', 'Grace', NULL), +('samuelharris', 'samuelharris', 'Harris', 'samuelharris@docker.localhost', 'Samuel', NULL), +('ameliahall', 'ameliahall', 'Amelia', 'Hall', 'ameliahall@docker.localhost', NULL), +('lucyedwards', 'lucyedwards', 'Edwards', 'lucyedwards@docker.localhost', 'Lucy', NULL), +('christophermiller', 'christophermiller', 'Miller', 'christophermiller@docker.localhost', 'Christopher', NULL), +('emilyperez', 'emilyperez', 'Perez', 'emilyperez@docker.localhost', 'Emily', NULL), +('andrewcook', 'andrewcook', 'Andrew', 'Cook', 'andrewcook@docker.localhost', NULL), +('oliviaparker', 'oliviaparker', 'Parker', 'oliviaparker@docker.localhost', 'Olivia', NULL), +('josephmartin', 'josephmartin', 'Joseph', 'Martin', 'josephmartin@docker.localhost', NULL), +('lilybrown', 'lilybrown', 'Brown', 'lilybrown@docker.localhost', 'Lily', NULL), +('elizabethlee', 'elizabethlee', 'Lee', 'elizabethlee@docker.localhost', 'Elizabeth', NULL), +('ethangreen', 'ethangreen', 'Green', 'ethangreen@docker.localhost', 'Ethan', NULL), +('noahroberts', 'noahroberts', 'Noah', 'Roberts', 'noahroberts@docker.localhost', NULL), +('gracegarcia', 'gracegarcia', 'Garcia', 'gracegarcia@docker.localhost', 'Grace', NULL), +('avaclark', 'avaclark', 'Clark', 'avaclark@docker.localhost', 'Ava', NULL), +('sophiedavis', 'sophiedavis', 'Davis', 'sophiedavis@docker.localhost', 'Sophie', NULL), +('benjaminharrison', 'benjaminharrison', 'Harrison', 'benjaminharrison@docker.localhost', 'Benjamin', NULL); +" +[[ "$?" == '0' ]] && echo "All user data inserted successfully (or ignored if duplicates existed)." || { echo "Error inserting user data. Exiting."; exit 1; } + +echo "Database setup complete: lemon.db" diff --git a/.compose/lemon/lmConf-pgsql.json b/.compose/lemon/lmConf-pgsql.json new file mode 100755 index 00000000..4a900d9d --- /dev/null +++ b/.compose/lemon/lmConf-pgsql.json @@ -0,0 +1,529 @@ +{ + "ADPwdExpireWarning" : 0, + "ADPwdMaxAge" : 0, + "SMTPServer" : "", + "SMTPTLS" : "", + "SSLAuthnLevel" : 5, + "SSLIssuerVar" : "SSL_CLIENT_I_DN", + "SSLVar" : "SSL_CLIENT_S_DN_Email", + "SSLVarIf" : {}, + "activeTimer" : 1, + "apacheAuthnLevel" : 3, + "applicationList" : { + "1matrix" : { + "catname" : "Matrix clients", + "Twake" : { + "options" : { + "description" : "Twake web client", + "display" : "on", + "logo" : "demo.png", + "name" : "Twake", + "uri" : "https://chat.docker.localhost/" + }, + "type" : "application" + }, + "type" : "category" + } + }, + "authChoiceParam" : "lmAuth", + "authentication" : "DBI", + "available2F" : "UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius,Password", + "available2FSelfRegistration" : "Password,TOTP,U2F,WebAuthn,Yubikey", + "bruteForceProtectionLockTimes" : "15, 30, 60, 300, 600", + "bruteForceProtectionMaxAge" : 300, + "bruteForceProtectionMaxFailed" : 3, + "bruteForceProtectionMaxLockTime" : 900, + "bruteForceProtectionTempo" : 30, + "captcha_login_enabled" : 0, + "captcha_mail_enabled" : 1, + "captcha_register_enabled" : 1, + "captcha_size" : 6, + "casAccessControlPolicy" : "none", + "casAuthnLevel" : 1, + "casTicketExpiration" : 0, + "certificateResetByMailCeaAttribute" : "description", + "certificateResetByMailCertificateAttribute" : "userCertificate;binary", + "certificateResetByMailURL" : "https://auth.docker.localhost/certificateReset", + "certificateResetByMailValidityDelay" : 0, + "cfgAuthor" : "The LemonLDAP::NG team", + "cfgDate" : "1627287638", + "cfgNum" : "1", + "cfgVersion" : "2.0.16", + "checkDevOpsCheckSessionAttributes" : 1, + "checkDevOpsDisplayNormalizedHeaders" : 1, + "checkDevOpsDownload" : 1, + "checkHIBPRequired" : 1, + "checkHIBPURL" : "https://api.pwnedpasswords.com/range/", + "checkMsg" : 5, + "checkTime" : 600, + "checkUserDisplayComputedSession" : 1, + "checkUserDisplayEmptyHeaders" : 0, + "checkUserDisplayEmptyValues" : 0, + "checkUserDisplayHiddenAttributes" : 0, + "checkUserDisplayHistory" : 0, + "checkUserDisplayNormalizedHeaders" : 0, + "checkUserDisplayPersistentInfo" : 0, + "checkUserHiddenAttributes" : "_loginHistory, _session_id, hGroups", + "checkUserIdRule" : 1, + "checkXSS" : 1, + "confirmFormMethod" : "post", + "contextSwitchingIdRule" : 1, + "contextSwitchingPrefix" : "switching", + "contextSwitchingRule" : 0, + "contextSwitchingStopWithLogout" : 1, + "cookieName" : "lemonldap", + "corsAllow_Credentials" : "true", + "corsAllow_Headers" : "*", + "corsAllow_Methods" : "POST,GET", + "corsAllow_Origin" : "*", + "corsEnabled" : 1, + "corsExpose_Headers" : "*", + "corsMax_Age" : "86400", + "crowdsecAction" : "reject", + "cspConnect" : "'self'", + "cspDefault" : "'self'", + "cspFont" : "'self'", + "cspFormAction" : "*", + "cspFrameAncestors" : "", + "cspImg" : "'self' data:", + "cspScript" : "'self'", + "cspStyle" : "'self'", + "dbiAuthChain" : "DBI:Pg:database=lemonldapng;host=pgsql", + "dbiAuthLoginCol" : "username", + "dbiAuthPassword" : "lemonldap", + "dbiAuthPasswordCol" : "password", + "dbiAuthTable" : "users", + "dbiAuthUser" : "lemonldap", + "dbiAuthnLevel" : 2, + "dbiExportedVars" : { + "uid" : "username", + "name" : "sn", + "email" : "mail", + "phone" : "mobile" + }, + "decryptValueRule" : 0, + "defaultNewKeySize" : 2048, + "demoExportedVars" : {}, + "displaySessionId" : 1, + "domain" : "docker.localhost", + "eventQueueName" : "llng_events", + "exportedHeaders" : {}, + "exportedVars" : {}, + "ext2fActivation" : 0, + "ext2fCodeActivation" : "\\d{6}", + "facebookAuthnLevel" : 1, + "facebookExportedVars" : {}, + "facebookUserField" : "id", + "failedLoginNumber" : 5, + "findUserControl" : "^[*\\w]+$", + "findUserWildcard" : "*", + "formTimeout" : 120, + "githubAuthnLevel" : 1, + "githubScope" : "user:email", + "githubUserField" : "login", + "globalLogoutRule" : 0, + "globalLogoutTimer" : 1, + "globalStorage" : "Apache::Session::File", + "globalStorageOptions" : { + "Directory" : "/var/lib/lemonldap-ng/sessions", + "LockDirectory" : "/var/lib/lemonldap-ng/sessions/lock", + "generateModule" : "Lemonldap::NG::Common::Apache::Session::Generate::SHA256" + }, + "gpgAuthnLevel" : 5, + "gpgDb" : "", + "grantSessionRules" : {}, + "groups" : {}, + "handlerInternalCache" : 15, + "handlerServiceTokenTTL" : 30, + "hiddenAttributes" : "_password, _2fDevices", + "hideOldPassword" : 1, + "httpOnly" : 1, + "https" : -1, + "ignorePollersDelay" : 300, + "ignorePollersLimit" : 10, + "impersonationHiddenAttributes" : "_2fDevices, _loginHistory", + "impersonationIdRule" : 1, + "impersonationMergeSSOgroups" : 0, + "impersonationPrefix" : "real_", + "impersonationRule" : 0, + "impersonationSkipEmptyValues" : 1, + "infoFormMethod" : "get", + "issuerDBCASPath" : "^/cas/", + "issuerDBCASRule" : 1, + "issuerDBGetParameters" : {}, + "issuerDBGetPath" : "^/get/", + "issuerDBGetRule" : 1, + "issuerDBJitsiMeetTokensPath" : "^/jitsi/", + "issuerDBJitsiMeetTokensRule" : 1, + "issuerDBOpenIDConnectActivation" : 1, + "issuerDBOpenIDConnectPath" : "^/oauth2/", + "issuerDBOpenIDConnectRule" : 1, + "issuerDBOpenIDPath" : "^/openidserver/", + "issuerDBOpenIDRule" : 1, + "issuerDBSAMLPath" : "^/saml/", + "issuerDBSAMLRule" : 1, + "issuersTimeout" : 120, + "jitsiExpiration" : "300", + "jitsiSigningAlg" : "RS256", + "jsRedirect" : 0, + "key" : "^vmTGvh{+]5!ToB?", + "krbAuthnLevel" : 3, + "krbRemoveDomain" : 1, + "ldapAuthnLevel" : 2, + "ldapBase" : "dc=docker,dc=localhost", + "ldapExportedVars" : {}, + "ldapGroupAttributeName" : "member", + "ldapGroupAttributeNameGroup" : "dn", + "ldapGroupAttributeNameSearch" : "cn", + "ldapGroupAttributeNameUser" : "dn", + "ldapGroupObjectClass" : "groupOfNames", + "ldapIOTimeout" : 10, + "ldapPasswordResetAttribute" : "pwdReset", + "ldapPasswordResetAttributeValue" : "TRUE", + "ldapPwdEnc" : "utf-8", + "ldapSearchDeref" : "find", + "ldapServer" : "ldap://localhost", + "ldapTimeout" : 10, + "ldapUsePasswordResetAttribute" : 1, + "ldapVerify" : "require", + "ldapVersion" : 3, + "linkedInAuthnLevel" : 1, + "linkedInFields" : "id,first-name,last-name,email-address", + "linkedInScope" : "r_liteprofile r_emailaddress", + "linkedInUserField" : "emailAddress", + "localSessionStorage" : "Cache::FileCache", + "localSessionStorageOptions" : { + "cache_depth" : 3, + "cache_root" : "/var/lib/lemonldap-ng/cache", + "default_expires_in" : 600, + "directory_umask" : "007", + "namespace" : "lemonldap-ng-sessions" + }, + "locationDetectGeoIpLanguages" : "en, fr", + "locationRules" : { + "auth.docker.localhost" : { + "(?#checkUser)^/checkuser" : "inGroup(\"timelords\")", + "(?#errors)^/lmerror/" : "accept", + "default" : "accept" + }, + "chat.docker.localhost" : { + "default" : "accept" + }, + "manager.docker.localhost" : { + "(?#Configuration)^/(.*?\\.(fcgi|psgi)/)?(manager\\.html|confs|prx/|$)" : "accept", + "(?#Notifications)/(.*?\\.(fcgi|psgi)/)?notifications" : "inGroup(\"timelords\") or $uid eq \"rtyler\"", + "(?#Sessions)/(.*?\\.(fcgi|psgi)/)?sessions" : "inGroup(\"timelords\") or $uid eq \"rtyler\"", + "default" : "inGroup(\"timelords\") or $uid eq \"rtyler\"" + } + }, + "loginHistoryEnabled" : 1, + "logoutServices" : {}, + "lwpOpts" : { + "timeout" : 10 + }, + "lwpSslOpts" : { + "SSL_verify_mode" : 0, + "verify_hostname" : false + }, + "macros" : { + "UA" : "$ENV{HTTP_USER_AGENT}", + "_whatToTrace" : "$_auth eq 'SAML' ? lc($_user.'@'.$_idpConfKey) : $_auth eq 'OpenIDConnect' ? lc($_user.'@'.$_oidc_OP) : lc($_user)" + }, + "mail2fActivation" : 0, + "mail2fCodeRegex" : "\\d{6}", + "mailCharset" : "utf-8", + "mailFrom" : "noreply@docker.localhost", + "mailSessionKey" : "mail", + "mailTimeout" : 0, + "mailUrl" : "https://auth.docker.localhost/resetpwd", + "managerDn" : "", + "managerPassword" : "", + "max2FDevices" : 10, + "max2FDevicesNameLength" : 20, + "messageBrokerOptions" : {}, + "multiValuesSeparator" : "; ", + "mySessionAuthorizedRWKeys" : [ + "_appsListOrder", + "_oidcConnectedRP", + "_oidcConsents" + ], + "newLocationWarningLocationAttribute" : "ipAddr", + "newLocationWarningLocationDisplayAttribute" : "", + "newLocationWarningMaxValues" : "0", + "notification" : 0, + "notificationDefaultCond" : "", + "notificationServerPOST" : 1, + "notificationServerSentAttributes" : "uid reference date title subtitle text check", + "notificationStorage" : "File", + "notificationStorageOptions" : { + "dirName" : "/var/lib/lemonldap-ng/notifications" + }, + "notificationWildcard" : "allusers", + "notificationsMaxRetrieve" : 3, + "notifyDeleted" : 1, + "nullAuthnLevel" : 0, + "oidcAuthnLevel" : 1, + "oidcOPMetaDataExportedVars" : {}, + "oidcOPMetaDataJSON" : {}, + "oidcOPMetaDataJWKS" : {}, + "oidcOPMetaDataOptions" : {}, + "oidcRPCallbackGetParam" : "openidconnectcallback", + "oidcRPMetaDataExportedVars" : { + "matrix" : { + "name" : "name", + "nickname" : "uid", + "preferred_username" : "uid", + "email" : "mail", + "phone_number" : "phone" + } + }, + "oidcRPMetaDataMacros" : null, + "oidcRPMetaDataOptions" : { + "matrix" : { + "oidcRPMetaDataOptionsAccessTokenClaims" : 0, + "oidcRPMetaDataOptionsAccessTokenJWT" : 0, + "oidcRPMetaDataOptionsAccessTokenSignAlg" : "RS256", + "oidcRPMetaDataOptionsAllowClientCredentialsGrant" : 0, + "oidcRPMetaDataOptionsAllowOffline" : 0, + "oidcRPMetaDataOptionsAllowPasswordGrant" : 0, + "oidcRPMetaDataOptionsBypassConsent" : 1, + "oidcRPMetaDataOptionsClientID" : "matrix1", + "oidcRPMetaDataOptionsClientSecret" : "matrix1", + "oidcRPMetaDataOptionsIDTokenForceClaims" : 0, + "oidcRPMetaDataOptionsIDTokenSignAlg" : "RS256", + "oidcRPMetaDataOptionsLogoutBypassConfirm" : 0, + "oidcRPMetaDataOptionsLogoutSessionRequired" : 1, + "oidcRPMetaDataOptionsLogoutType" : "back", + "oidcRPMetaDataOptionsLogoutUrl" : "https://matrix.docker.localhost/_synapse/client/oidc/backchannel_logout", + "oidcRPMetaDataOptionsPublic" : 0, + "oidcRPMetaDataOptionsRedirectUris" : "https://matrix.docker.localhost/_synapse/client/oidc/callback", + "oidcRPMetaDataOptionsRefreshToken" : 0, + "oidcRPMetaDataOptionsRequirePKCE" : 0, + "oidcRPMetaDataOptionsTokenXAuthorizedMatrix" : "docker.localhost" + } + }, + "oidcRPMetaDataOptionsExtraClaims" : null, + "oidcRPMetaDataScopeRules" : null, + "oidcRPStateTimeout" : 600, + "oidcServiceAccessTokenExpiration" : 3600, + "oidcServiceAllowAuthorizationCodeFlow" : 1, + "oidcServiceAllowImplicitFlow" : 0, + "oidcServiceAuthorizationCodeExpiration" : 60, + "oidcServiceDynamicRegistrationExportedVars" : {}, + "oidcServiceDynamicRegistrationExtraClaims" : {}, + "oidcServiceEncAlgorithmAlg" : "RSA-OAEP", + "oidcServiceEncAlgorithmEnc" : "A256GCM", + "oidcServiceIDTokenExpiration" : 3600, + "oidcServiceIgnoreScopeForClaims" : 1, + "oidcServiceKeyIdSig" : "oMGHInscAW3Nsa0FcnCnDA", + "oidcServiceKeyTypeEnc" : "RSA", + "oidcServiceKeyTypeSig" : "RSA", + "oidcServiceMetaDataAuthnContext" : { + "loa-1" : 1, + "loa-2" : 2, + "loa-3" : 3, + "loa-4" : 4, + "loa-5" : 5 + }, + "oidcServiceMetaDataAuthorizeURI" : "authorize", + "oidcServiceMetaDataBackChannelURI" : "blogout", + "oidcServiceMetaDataCheckSessionURI" : "checksession.html", + "oidcServiceMetaDataEndSessionURI" : "logout", + "oidcServiceMetaDataFrontChannelURI" : "flogout", + "oidcServiceMetaDataIntrospectionURI" : "introspect", + "oidcServiceMetaDataJWKSURI" : "jwks", + "oidcServiceMetaDataRegistrationURI" : "register", + "oidcServiceMetaDataTokenURI" : "token", + "oidcServiceMetaDataUserInfoURI" : "userinfo", + "oidcServiceNewKeyTypeSig" : "RSA", + "oidcServiceOfflineSessionExpiration" : 2592000, + "oidcServiceOldKeyTypeEnc" : "RSA", + "oidcServiceOldKeyTypeSig" : "RSA", + "oidcServicePrivateKeySig" : "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDywteBzIOlhKc4\nO+vhMStDYOpPYrWDOodkUZ7OsxlWVNZ/b/lqIFS56+MHPkKNQuT4zZCyO8bEKmmR\nZ6kPFJoGbO1zJCPQ/RKjimX4J/5gDb1BAlo+6agJi55e3Bw0zKNJDU0mRyedcIzW\n7ywTgyj6B35pl/Sfloi4Q1XEizHar+26h66SOEtnppMxGvwsxO8gFWz26CPmalvY\n5GNYR0txbXUZn7I4kDa4mMWgNfeocWc78Qbt4RV5EuQdbRh1sou4tL9Nn4EuGhg0\nmfsSI0xVAj7f82Wn3kW6qEbhuejrY7aqmZjN7yrMKtCBuV7o4hVrjYLuM2j0mInY\nMy5nRNOVAgMBAAECggEAJ145nK8R2lG83H27LvXOUkrxNJaJYRKoyjgCTPr2bO2t\nK1V5WSCNHOmIE7ChEk962m5bvMu83CsUm6P34p4wrEIV78o4lLe1whe7mZbCxcj0\nnApJoFI8EfA2aqO/X0CgakRh8ocvgXSzIlf/CdsHViTI907ROOAso9Unn4wDNbdp\nMrhi3H2SnA+ewzj85WygBVTNQmVBjJSSLXTQRkfHye0ztvQm59gqqaJaM2rkBjvA\nlPWAVsgakOk4pgClKElCsIjWPJwdYtcd8VJrwnro5J9KhMwB//AArGgqOaXUHnLH\nv5aZZp6FjV/M3BxbSp4cG6hXmK1hrDFLecRddYP1gQKBgQD+Y4/ee57Z0E2V8833\nYfrK3F23sfxmZ7zUwEbgFXUfRy3RVW7Hbc7PAJzxzrk+LYk/zaZrrfEJguqG2O6m\nVNYkqxKu69Nn964CMdV15JGxVzpzsN5adKlcvKVVv9gx2rF3SMUOHiRutj2BlUtO\niCq0G3jFsXWIRzePig9PbWP6CQKBgQD0TG2DeDDUgKbeJYIzXfmCvGxlm5MZqCc/\nK7d8P9U0svG//jJRTsa9hcLjk7N24CzhLNHyJmT7dh1Xy1oLyHNPZ4nQRmCe+HUf\nu0SK10WZ2K55ekUmqS+xSuDFWJtWa5SE46cKg0fKu7YkiDKI1s6I3qrF4lew2aDE\n2p8GJRrgLQKBgCh2PZPtpb6PW0fWl5QZiYJqup1VOggvx+EvFBbgUti+wZLiO9SM\nqrBSMKRldSFmrMXxN984s3YH1LXOG2dpZwY+D6Ky79VBl/PRaVpvGJ1Uen+cSkGo\n/Kc7ejDBaunDFycZ8/3i3Xiek/ngfTHohqJPHE6Vg1RBv5ydIQJJK/XBAoGAU1XO\n9c4GOjc4tQbuhz9DYgmMoIyVfWcTHEV5bfUIcdWpCelYmMval8QNWzyDN8X5CUcU\nxxm50N3V3KENsn9KdofHRzj6tL/klFJ5azNMFtMHkYDYHfwQvNXiHu++7Zf9LefK\nj5eA4fNuir+7HVrJUX9DmgVADJ/wa7Z4EMyPgnECgYA/NLUs4920h10ie5lFffpM\nqq6CRcBjsQ7eGK9UI1Z2KZUh94eqIENSJ7whBjXKvJJvhAlH4//lVFMMRs7oJePY\nThg+8In7PB64yMOIJZLc5Fekn9aGG6YtErPzePQkXSYCKZxWl5EpjQZGgPRVkNtD\n2nflyJLjiCbTjeNgWIOZlw==\n-----END PRIVATE KEY-----\n", + "oidcServicePublicKeySig" : "-----BEGIN CERTIFICATE-----\nMIICuDCCAaCgAwIBAgIEFU77HjANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBNt\nYXRyaXgubGluYWdvcmEuY29tMB4XDTIzMDIxNTAzMTk0NloXDTQzMDIxMDAzMTk0\nNlowHjEcMBoGA1UEAwwTbWF0cml4LmxpbmFnb3JhLmNvbTCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPLC14HMg6WEpzg76+ExK0Ng6k9itYM6h2RRns6z\nGVZU1n9v+WogVLnr4wc+Qo1C5PjNkLI7xsQqaZFnqQ8UmgZs7XMkI9D9EqOKZfgn\n/mANvUECWj7pqAmLnl7cHDTMo0kNTSZHJ51wjNbvLBODKPoHfmmX9J+WiLhDVcSL\nMdqv7bqHrpI4S2emkzEa/CzE7yAVbPboI+ZqW9jkY1hHS3FtdRmfsjiQNriYxaA1\n96hxZzvxBu3hFXkS5B1tGHWyi7i0v02fgS4aGDSZ+xIjTFUCPt/zZafeRbqoRuG5\n6OtjtqqZmM3vKswq0IG5XujiFWuNgu4zaPSYidgzLmdE05UCAwEAATANBgkqhkiG\n9w0BAQsFAAOCAQEArNmGxZVvmvdOLctv+zQ+npzQtOTaJcf+r/1xYuM4FZVe4yLc\ny9ElDskoDWjvQU7jKeJeaDOYgMJQNrek8Doj8uHPWNe6jYFa62Csg9aPz6e8qbtq\nWI+sXds5GJd6xZ8mi2L4MdT/tf8dBgcgybuoRyhBtJwG1rLNAYkeXMxkBzOFcU7K\nR/SZ0q9ToLAWFDhn42MTjPN3t6GwKDzGNsM/SI/3WvUwpQbtK91hjPnNDwKiAtGG\nfUteuigfXY+0hEcQwJdR0St/FQ8UYYcAB5YT9IkT1wCcU5LfPHCBf3OXNpbnQsHh\netQMKLibM6wWdXNwmsd1szO66ft3QZ4h4EG3Vw==\n-----END CERTIFICATE-----\n", + "oidcStorage": "Apache::Session::Browseable::PgJSON", + "oidcStorageOptions" : { + "DataSource": "DBI:Pg:database=lemonldapng;host=pgsql", + "UserName":"lemonldap", + "Password":"lemonldap", + "TableName":"oidcsessions" + }, + "okta2fActivation" : 0, + "openIdAuthnLevel" : 1, + "openIdExportedVars" : {}, + "openIdIDPList" : "0;", + "openIdSPList" : "0;", + "openIdSreg_email" : "mail", + "openIdSreg_fullname" : "cn", + "openIdSreg_nickname" : "uid", + "openIdSreg_timezone" : "_timezone", + "pamAuthnLevel" : 2, + "pamService" : "login", + "password2fActivation" : 0, + "password2fSelfRegistration" : 0, + "password2fUserCanRemoveKey" : 1, + "passwordDB" : "DBI", + "passwordPolicyActivation" : 1, + "passwordPolicyMaxSize" : 0, + "passwordPolicyMinDigit" : 0, + "passwordPolicyMinLower" : 0, + "passwordPolicyMinSize" : 0, + "passwordPolicyMinSpeChar" : 0, + "passwordPolicyMinUpper" : 0, + "passwordPolicySpecialChar" : "__ALL__", + "passwordResetAllowedRetries" : 3, + "persistentSessionAttributes" : "_loginHistory _2fDevices notification_", + "persistentStorage": "Apache::Session::Browseable::PgJSON", + "persistentStorageOptions" : { + "DataSource": "DBI:Pg:database=lemonldapng;host=pgsql", + "UserName":"lemonldap", + "Password":"lemonldap", + "TableName":"psessions" + }, + "port" : -1, + "portal" : "https://auth.docker.localhost/", + "portalAntiFrame" : 1, + "portalCheckLogins" : 1, + "portalDisplayAppslist" : 1, + "portalDisplayChangePassword" : "$_auth =~ /^(LDAP|DBI|Demo)$/", + "portalDisplayGeneratePassword" : 1, + "portalDisplayLoginHistory" : 1, + "portalDisplayLogout" : 1, + "portalDisplayOidcConsents" : "$_oidcConsents && $_oidcConsents =~ /\\w+/", + "portalDisplayOrder" : "Appslist ChangePassword LoginHistory OidcConsents Logout", + "portalDisplayRefreshMyRights" : 1, + "portalDisplayRegister" : 1, + "portalErrorOnExpiredSession" : 1, + "portalFavicon" : "common/favicon.ico", + "portalForceAuthnInterval" : 5, + "portalMainLogo" : "common/logos/logo_llng_400px.png", + "portalPingInterval" : 60000, + "portalRequireOldPassword" : 1, + "portalSkin" : "bootstrap", + "portalSkinBackground" : "1280px-Cedar_Breaks_National_Monument_partially.jpg", + "portalUserAttr" : "_user", + "proxyAuthServiceChoiceParam" : "lmAuth", + "proxyAuthnLevel" : 2, + "radius2fActivation" : 0, + "radius2fRequestAttributes" : {}, + "radius2fTimeout" : 20, + "radiusAuthnLevel" : 3, + "radiusExportedVars" : {}, + "radiusRequestAttributes" : {}, + "randomPasswordRegexp" : "[A-Z]{3}[a-z]{5}.\\d{2}", + "redirectFormMethod" : "get", + "registerDB" : "Null", + "registerTimeout" : 0, + "registerUrl" : "https://auth.docker.localhost/register", + "reloadTimeout" : 5, + "reloadUrls" : { + "localhost" : "https://reload.docker.localhost/reload" + }, + "rememberAuthChoiceRule" : 0, + "rememberCookieName" : "llngrememberauthchoice", + "rememberCookieTimeout" : 31536000, + "rememberTimer" : 5, + "remoteGlobalStorage" : "Lemonldap::NG::Common::Apache::Session::SOAP", + "remoteGlobalStorageOptions" : { + "ns" : "https://auth.docker.localhost/Lemonldap/NG/Common/PSGI/SOAPService", + "proxy" : "https://auth.docker.localhost/sessions" + }, + "requireToken" : 1, + "rest2fActivation" : 0, + "restAuthnLevel" : 2, + "restClockTolerance" : 15, + "sameSite" : "", + "samlAttributeAuthorityDescriptorAttributeServiceSOAP" : "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;", + "samlAuthnContextMapKerberos" : 4, + "samlAuthnContextMapPassword" : 2, + "samlAuthnContextMapPasswordProtectedTransport" : 3, + "samlAuthnContextMapTLSClient" : 5, + "samlEntityID" : "#PORTAL#/saml/metadata", + "samlIDPSSODescriptorArtifactResolutionServiceArtifact" : "1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact", + "samlIDPSSODescriptorSingleLogoutServiceHTTPPost" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn", + "samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn", + "samlIDPSSODescriptorSingleLogoutServiceSOAP" : "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleLogoutSOAP;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/singleSignOnArtifact;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPPost" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleSignOn;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleSignOn;", + "samlIDPSSODescriptorWantAuthnRequestsSigned" : 1, + "samlMetadataForceUTF8" : 1, + "samlNameIDFormatMapEmail" : "mail", + "samlNameIDFormatMapKerberos" : "uid", + "samlNameIDFormatMapWindows" : "uid", + "samlNameIDFormatMapX509" : "mail", + "samlOrganizationDisplayName" : "Example", + "samlOrganizationName" : "Example", + "samlOrganizationURL" : "https://www.docker.localhost", + "samlOverrideIDPEntityID" : "", + "samlRelayStateTimeout" : 600, + "samlSPSSODescriptorArtifactResolutionServiceArtifact" : "1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact", + "samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact" : "0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact", + "samlSPSSODescriptorAssertionConsumerServiceHTTPPost" : "1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost", + "samlSPSSODescriptorAuthnRequestsSigned" : 1, + "samlSPSSODescriptorSingleLogoutServiceHTTPPost" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn", + "samlSPSSODescriptorSingleLogoutServiceHTTPRedirect" : "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn", + "samlSPSSODescriptorSingleLogoutServiceSOAP" : "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/proxySingleLogoutSOAP;", + "samlSPSSODescriptorWantAssertionsSigned" : 1, + "samlServiceSignatureMethod" : "RSA_SHA256", + "scrollTop" : 400, + "securedCookie" : 0, + "sessionDataToRemember" : {}, + "sfEngine" : "::2F::Engines::Default", + "sfManagerRule" : 1, + "sfRemovedMsgRule" : 0, + "sfRemovedNotifMsg" : "_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!", + "sfRemovedNotifRef" : "RemoveSF", + "sfRemovedNotifTitle" : "Second factor notification", + "sfRequired" : 0, + "showLanguages" : 1, + "singleIP" : 0, + "singleSession" : 0, + "singleUserByIP" : 0, + "slaveAuthnLevel" : 2, + "slaveExportedVars" : {}, + "soapProxyUrn" : "urn:Lemonldap/NG/Common/PSGI/SOAPService", + "statusQueueName" : "llng_status", + "stayConnected" : 0, + "stayConnectedCookieName" : "llngconnection", + "stayConnectedTimeout" : 2592000, + "successLoginNumber" : 5, + "timeout" : 72000, + "timeoutActivity" : 0, + "timeoutActivityInterval" : 60, + "totp2fActivation" : 0, + "totp2fDigits" : 6, + "totp2fInterval" : 30, + "totp2fRange" : 1, + "totp2fSelfRegistration" : 0, + "totp2fUserCanRemoveKey" : 1, + "trustedBrowserRule" : 0, + "trustedBrowserUseTotp" : 1, + "twitterAuthnLevel" : 1, + "twitterUserField" : "screen_name", + "u2fActivation" : 0, + "u2fSelfRegistration" : 0, + "u2fUserCanRemoveKey" : 1, + "upgradeSession" : 1, + "useRedirectAjaxOnUnauthorized" : 1, + "useRedirectOnError" : 1, + "useSafeJail" : 1, + "userControl" : "^[\\w\\.\\-@]+$", + "userDB" : "Same", + "utotp2fActivation" : 0, + "viewerHiddenKeys" : "samlIDPMetaDataNodes, samlSPMetaDataNodes", + "webIDAuthnLevel" : 1, + "webIDExportedVars" : {}, + "webauthn2fActivation" : 0, + "webauthn2fAttestation" : "none", + "webauthn2fSelfRegistration" : 0, + "webauthn2fUserCanRemoveKey" : 1, + "webauthn2fUserVerification" : "preferred", + "webauthnAppId" : 1, + "webauthnAuthnLevel" : 3, + "whatToTrace" : "_whatToTrace", + "yubikey2fActivation" : 0, + "yubikey2fPublicIDSize" : 12, + "yubikey2fSelfRegistration" : 0, + "yubikey2fUserCanRemoveKey" : 1 +} diff --git a/.compose/lemon/lmConf-sqlite.json b/.compose/lemon/lmConf-sqlite.json index cc8acb8c..17aefd67 100755 --- a/.compose/lemon/lmConf-sqlite.json +++ b/.compose/lemon/lmConf-sqlite.json @@ -89,17 +89,17 @@ "cspScript" : "'self'", "cspStyle" : "'self'", "dbiAuthChain" : "dbi:SQLite:dbname=/db/lemon.db", - "dbiAuthLoginCol" : "uid", + "dbiAuthLoginCol" : "username", "dbiAuthPassword" : "", "dbiAuthPasswordCol" : "password", "dbiAuthTable" : "users", "dbiAuthUser" : "", "dbiAuthnLevel" : 2, "dbiExportedVars" : { - "uid" : "uid", - "name" : "name", + "uid" : "username", + "name" : "sn", "email" : "mail", - "phone" : "phone" + "phone" : "mobile" }, "decryptValueRule" : 0, "defaultNewKeySize" : 2048, @@ -356,7 +356,7 @@ "password2fActivation" : 0, "password2fSelfRegistration" : 0, "password2fUserCanRemoveKey" : 1, - "passwordDB" : "Demo", + "passwordDB" : "DBI", "passwordPolicyActivation" : 1, "passwordPolicyMaxSize" : 0, "passwordPolicyMinDigit" : 0, diff --git a/.compose/pgsql/init-users-db.sh b/.compose/pgsql/init-users-db.sh new file mode 100644 index 00000000..9a94ed2a --- /dev/null +++ b/.compose/pgsql/init-users-db.sh @@ -0,0 +1,96 @@ +#!/bin/sh +set -e + +DATABASE=${PG_DATABASE:-lemonldapng} +USER=${PG_USER:-lemonldap} +PASSWORD=${PG_PASSWORD:-lemonldap} +TABLE=${PG_TABLE:-users} + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE" <<-EOSQL +CREATE TABLE IF NOT EXISTS $TABLE ( + id SERIAL PRIMARY KEY, + username VARCHAR(64), + password VARCHAR(64), + sn VARCHAR(64), + mail VARCHAR(64), + givenname VARCHAR(64), + mobile VARCHAR(20), + isadmin BOOLEAN DEFAULT FALSE, + isblocked BOOLEAN DEFAULT FALSE +); + +-- Create unique indexes for frequently searched fields +CREATE UNIQUE INDEX u__username ON $TABLE USING btree(username); +CREATE UNIQUE INDEX u__mail ON $TABLE USING btree(mail); +CREATE UNIQUE INDEX u__mobile ON $TABLE USING btree(mobile); + +-- Grant privileges to the specified user (replace $TABLE and $USER with actual values) +GRANT ALL PRIVILEGES ON TABLE $TABLE TO $USER; + +-- Insert user data based on LDIF reference with international phone number format +-- Derivation Logic: +-- givenname: Use 'givenName' from LDIF if present. Otherwise, use the first word of 'cn'. +-- sn: If 'cn' has multiple words, use the last word of 'cn'. Otherwise, use 'sn' from LDIF if present, else NULL. +INSERT INTO $TABLE (username, password, sn, mail, givenname, mobile) VALUES +('dwho', 'dwho', 'Who', NULL, 'Dr', '+33671298765'), +('rtyler', 'rtyler', 'Tyler', 'rtyler@docker.localhost', 'Rose', '+33671298767'), +('msmith', 'msmith', 'Smith', 'msmith@docker.localhost', 'Mr', NULL), +('okenobi', 'okenobi', 'Kenobi', 'okenobi@docker.localhost', 'Obi-Wan', NULL), +('qjinn', 'qjinn', 'Jinn', 'qjinn@docker.localhost', 'Qui-Gon', NULL), +('chewbacca', 'chewbacca', 'Chewbacca', 'chewbacca@docker.localhost', 'Chewbacca', NULL), +('lorgana', 'lorgana', 'Organa', 'lorgana@docker.localhost', 'Leia', NULL), +('pamidala', 'pamidala', 'Amidala', 'pamidala@docker.localhost', 'Padme', NULL), +('cdooku', 'cdooku', 'Dooku', 'cdooku@docker.localhost', 'Comte', NULL), +('kren', 'kren', 'Ren', 'kren@docker.localhost', 'Kylo', NULL), +('dmaul', 'dmaul', 'Maul', 'dmaul@docker.localhost', 'Dark', NULL), +('askywalker', 'askywalker', 'Skywalker', 'askywalker@docker.localhost', 'Anakin', NULL), +('jbinks', 'jbinks', 'Binks', 'jbinks@docker.localhost', 'Jar Jar', NULL), +('bfett', 'bfett', 'Fett', 'bfett@docker.localhost', 'Boba', NULL), +('jfett', 'jfett', 'Ffett', 'jfett@docker.localhost', 'Jango', NULL), +('lskywalker', 'lskywalker', 'Skywalker', 'lskywalker@docker.localhost', 'Luc', NULL), +('myoda', 'myoda', 'Yoda', 'myoda@docker.localhost', 'Master', NULL), +('hsolo', 'hsolo', 'Solo', 'hsolo@docker.localhost', 'Han', NULL), +('r2d2', 'r2d2', 'R2D2', 'r2d2@docker.localhost', 'R2D2', NULL), +('c3po', 'c3po', 'C3po', 'c3po@docker.localhost', 'C3PO', NULL), +('synapseadmin', 'synapseadmin', 'Syadmin', 'synapseadmin@docker.localhost', 'Synapse', NULL), +('annasmith', 'annasmith', 'Smith', 'annasmith@docker.localhost', 'Anna', NULL), +('johnjohnson', 'johnjohnson', 'Johnson', 'johnjohnson@docker.localhost', 'John', NULL), +('emilybrown', 'emilybrown', 'Brown', 'emilybrown@docker.localhost', 'Emily', NULL), +('daviddavis', 'daviddavis', 'Davis', 'daviddavis@docker.localhost', 'David', NULL), +('sarahwilson', 'sarahwilson', 'Wilson', 'sarahwilson@docker.localhost', 'Sarah', NULL), +('miketaylor', 'miketaylor', 'Taylor', 'miketaylor@docker.localhost', 'Mike', NULL), +('graceadams', 'graceadams', 'Adams', 'graceadams@docker.localhost', 'Grace', NULL), +('mattmoore', 'mattmoore', 'Moore', 'mattmoore@docker.localhost', 'Matt', NULL), +('lilyparker', 'lilyparker', 'Parker', 'lilyparker@docker.localhost', 'Lily', NULL), +('danieldixon', 'danieldixon', 'Dixon', 'danieldixon@docker.localhost', 'Daniel', NULL), +('mialopez', 'mialopez', 'Lopez', 'mialopez@docker.localhost', 'Mia', NULL), +('ethanjackson', 'ethanjackson', 'Jackson', 'ethanjackson@docker.localhost', 'Ethan', NULL), +('oliviaroberts', 'oliviaroberts', 'Roberts', 'oliviaroberts@docker.localhost', 'Olivia', NULL), +('jamessmith', 'jamessmith', 'Smith', 'jamessmith@docker.localhost', 'James', NULL), +('sophiathomas', 'sophiathomas', 'Thomas', 'sophiathomas@docker.localhost', 'Sophia', NULL), +('benjaminclark', 'benjaminclark', 'Clark', 'benjaminclark@docker.localhost', 'Benjamin', NULL), +('avamartin', 'avamartin', 'Martin', 'avamartin@docker.localhost', 'Ava', NULL), +('williamrogers', 'williamrogers', 'Rogers', 'williamrogers@docker.localhost', 'William', NULL), +('emmawright', 'emmawright', 'Wright', 'emmawright@docker.localhost', 'Emma', NULL), +('chloescott', 'chloescott', 'Scott', 'chloescott@docker.localhost', 'Chloe', NULL), +('danieltaylor', 'danieltaylor', 'Taylor', 'danieltaylor@docker.localhost', 'Daniel', NULL), +('sophiarichardson', 'sophiarichardson', 'Richardson', 'sophiarichardson@docker.localhost', 'Sophia', NULL), +('henryjones', 'henryjones', 'Jones', 'henryjones@docker.localhost', 'Henry', NULL), +('gracelewis', 'gracelewis', 'Lewis', 'gracelewis@docker.localhost', 'Grace', NULL), +('samuelharris', 'samuelharris', 'Harris', 'samuelharris@docker.localhost', 'Samuel', NULL), +('ameliahall', 'ameliahall', 'Hall', 'ameliahall@docker.localhost', 'Amelia', NULL), +('lucyedwards', 'lucyedwards', 'Edwards', 'lucyedwards@docker.localhost', 'Lucy', NULL), +('christophermiller', 'christophermiller', 'Miller', 'christophermiller@docker.localhost', 'Christopher', NULL), +('emilyperez', 'emilyperez', 'Perez', 'emilyperez@docker.localhost', 'Emily', NULL), +('andrewcook', 'andrewcook', 'Cook', 'andrewcook@docker.localhost', 'Andrew', NULL), +('oliviaparker', 'oliviaparker', 'Parker', 'oliviaparker@docker.localhost', 'Olivia', NULL), +('josephmartin', 'josephmartin', 'Martin', 'josephmartin@docker.localhost', 'Joseph', NULL), +('lilybrown', 'lilybrown', 'Brown', 'lilybrown@docker.localhost', 'Lily', NULL), +('elizabethlee', 'elizabethlee', 'Lee', 'elizabethlee@docker.localhost', 'Elizabeth', NULL), +('ethangreen', 'ethangreen', 'Green', 'ethangreen@docker.localhost', 'Ethan', NULL), +('noahroberts', 'noahroberts', 'Roberts', 'noahroberts@docker.localhost', 'Noah', NULL), +('gracegarcia', 'gracegarcia', 'Garcia', 'gracegarcia@docker.localhost', 'Grace', NULL), +('avaclark', 'avaclark', 'Clark', 'avaclark@docker.localhost', 'Ava', NULL), +('sophiedavis', 'sophiedavis', 'Davis', 'sophiedavis@docker.localhost', 'Sophie', NULL), +('benjaminharrison', 'benjaminharrison', 'Harrison', 'benjaminharrison@docker.localhost', 'Benjamin', NULL); +EOSQL diff --git a/server.mjs b/server.mjs index 3154a8ed..5ffa39b0 100644 --- a/server.mjs +++ b/server.mjs @@ -140,6 +140,10 @@ let conf = { update_users_cron: process.env.UPDATE_USERS_CRON || '*/10 * * * *', userdb_engine: process.env.USERDB_ENGINE || 'ldap', userdb_host: process.env.USERDB_HOST, + userdb_name: process.env.USERDB_NAME, + userdb_user: process.env.USERDB_USER, + userdb_password: process.env.USERDB_PASSWORD, + userdb_ssl: process.env.USERDB_SSL, sms_api_key: process.env.SMS_API_KEY, sms_api_login: process.env.SMS_API_LOGIN, sms_api_url: process.env.SMS_API_URL,