Add rendered example

This commit is contained in:
Daniel Berteaud 2024-01-05 14:35:36 +01:00
parent 8cdb8a6b7a
commit 03bf83a34e
15 changed files with 835 additions and 0 deletions

9
example/LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2023 nomad
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
example/README.md Normal file
View File

@ -0,0 +1,3 @@
# lemonldap-ng
Lemonldap::NG webSSO

View File

@ -0,0 +1,3 @@
Kind = "service-defaults"
Name = "lemonldap-ng"
Protocol = "http"

View File

@ -0,0 +1,28 @@
Kind = "service-intentions"
Name = "lemonldap-ng"
Sources = [
{
Name = "traefik"
Permissions = [
# Prevent access to the API as it's disabled
{
Action = "deny"
HTTP {
PathRegex = "^/index\\.psgi/(config|sessions)"
}
},
{
Action = "deny"
HTTP {
PathRegex = "^/(reload|status)"
}
},
{
Action = "allow"
HTTP {
Methods = ["GET", "HEAD", "POST", "OPTIONS", "PUT", "DELETE", "PATCH"]
}
}
]
}
]

View File

@ -0,0 +1,56 @@
FROM danielberteaud/alma:9.24.1-3
MAINTAINER Daniel Berteaud <dbd@ehtrace.com>
ARG LLNG_VERSION=2.18.1 \
CARETAKERD_VERSION=1.0.8
ENV PATH=/usr/libexec/lemonldap-ng/bin:${PATH} \
LLNG_LISTEN=unix:/tmp/llng.sock \
LLNG_WORKERS=6 \
LLNG_NGINX_LISTEN=0.0.0.0:8080 \
LLNG_NGINX_CONF=/tmp/nginx.conf \
LLNG_SOCKET_PROTO=uwsgi \
LLNG_MANAGER_VHOST=manager.example.org \
LLNG_PORTAL_VHOST=auth.example.org \
LLNG_CUSTOM_ASSETS_DIR=/usr/share/lemonldap-ng/portal/htdocs \
EDITOR=vi
COPY root/etc/yum.repos.d/ /etc/yum.repos.d/
RUN set -eux &&\
dnf -y install \
glibc-langpack-en \
glibc-langpack-fr \
postgresql \
lemonldap-ng-handler-${LLNG_VERSION} \
lemonldap-ng-portal-${LLNG_VERSION} \
lemonldap-ng-manager-${LLNG_VERSION} \
lemonldap-ng-uwsgi-app-${LLNG_VERSION} \
uwsgi \
uwsgi-plugin-psgi \
lasso \
lasso-perl \
perl-DBD-Pg \
perl-Cache-Cache \
perl-Apache-Session-Browseable \
perl-Authen-Captcha \
perl-Authen-WebAuthn \
perl-Cookie-Baker \
perl-WWW-Form-UrlEncoded \
perl-Class-XSAccessor \
perl-Email-Sender \
perl-Data-Password-zxcvbn \
nginx \
&&\
# dnf is an alias using --nodocs, so install doc manually \
microdnf -y install lemonldap-ng-doc-${LLNG_VERSION} &&\
curl -sSL https://github.com/echocat/caretakerd/releases/download/v${CARETAKERD_VERSION}/caretakerd-linux-amd64.tar.gz | \
tar xvz --exclude caretakerd.html -C /usr/local/bin &&\
chmod +x /usr/local/bin/caretakerd &&\
dnf -y clean all &&\
rm -rf /var/cache/yum/* /var/log/yum/* /var/lib/dnf/history*
COPY root/ /
USER apache
CMD ["caretakerd", "run"]

View File

@ -0,0 +1,10 @@
#!/bin/sh
set -euo pipefail
[ -e "/tmp/nginx.conf" ] || touch /tmp/nginx.conf || true
if [ -w "/tmp/nginx.conf" ]; then
echo Rendering /etc/nginx/lemonldap-ng.conf.template in /tmp/nginx.conf
envsubst < /etc/nginx/lemonldap-ng.conf.template > /tmp/nginx.conf
fi

View File

@ -0,0 +1,9 @@
services:
lemonldap:
type: master
command: ["lemonldap-ng"]
nginx:
command: ["nginx", "-c", "${LLNG_NGINX_CONF}"]
local_cache:
command: ["/usr/libexec/lemonldap-ng/bin/purgeLocalCache"]
cronExpression: '1 * * * *'

View File

@ -0,0 +1,120 @@
worker_processes auto;
daemon off;
error_log /dev/stderr notice;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
proxy_temp_path /tmp/proxy_temp;
client_body_temp_path /tmp/client_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
server {
listen ${LLNG_NGINX_LISTEN};
server_name ${LLNG_MANAGER_VHOST};
root /usr/share/lemonldap-ng/manager/htdocs/;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
proxy_request_buffering off;
if ($uri !~ ^/(.*\.psgi|static|doc|lib|javascript|favicon)) {
rewrite ^/(.*)$ /manager.psgi/$1 break;
}
location ~ ^(?<sc>/.*\.psgi)(?:$|/) {
include /etc/nginx/uwsgi_params;
uwsgi_pass ${LLNG_LISTEN};
uwsgi_param LLTYPE psgi;
uwsgi_param SCRIPT_FILENAME $document_root$sc;
uwsgi_param SCRIPT_NAME $sc;
}
location / {
index manager.psgi;
try_files $uri $uri/ =404;
}
location /doc/ {
alias /usr/share/lemonldap-ng/doc/;
index index.html start.html;
}
location /lib/ {
alias /usr/share/lemonldap-ng/doc/pages/documentation/current/lib/;
}
location /static/ {
alias /usr/share/lemonldap-ng/manager/htdocs/static/;
}
}
server {
listen ${LLNG_NGINX_LISTEN} default_server;
server_name ${LLNG_PORTAL_VHOST};
root /usr/share/lemonldap-ng/portal/htdocs/;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
proxy_request_buffering off;
if ($uri !~ ^/((static|javascript|favicon).*|.*\.psgi)) {
rewrite ^/(.*)$ /index.psgi/$1 break;
}
location = /reload {
allow 127.0.0.1;
deny all;
uwsgi_pass ${LLNG_LISTEN};
uwsgi_param LLTYPE reload;
uwsgi_param SCRIPT_FILENAME $document_root$sc;
uwsgi_param SCRIPT_NAME $sc;
}
location = /status {
allow 127.0.0.1;
deny all;
uwsgi_pass ${LLNG_LISTEN};
uwsgi_param LLTYPE status;
uwsgi_param SCRIPT_FILENAME $document_root$sc;
uwsgi_param SCRIPT_NAME $sc;
}
location ~ ^(?<sc>/.*\.psgi)(?:$|/) {
include /etc/nginx/uwsgi_params;
uwsgi_pass ${LLNG_LISTEN};
uwsgi_param LLTYPE psgi;
uwsgi_param SCRIPT_FILENAME $document_root$sc;
uwsgi_param SCRIPT_NAME $sc;
}
index index.psgi;
location / {
try_files $uri $uri/ =404;
}
location /static/ {
root /usr/share/lemonldap-ng/portal/htdocs;
try_files $uri @customassets;
}
location @customassets {
root ${LLNG_CUSTOM_ASSETS_DIR};
}
}
}

View File

@ -0,0 +1,13 @@
[lemonldap-ng]
name = LemonLDAP::NG packages
baseurl = https://lemonldap-ng.org/redhat/stable/$releasever/noarch
enabled = 1
gpgcheck = 1
gpgkey = https://lemonldap-ng.org/_media/rpm-gpg-key-ow2
[lemonldap-ng-extras]
name = LemonLDAP::NG extra packages
baseurl = https://lemonldap-ng.org/redhat/extras/$releasever
enabled = 1
gpgcheck = 1
gpgkey = https://lemonldap-ng.org/_media/rpm-gpg-key-ow2

View File

@ -0,0 +1,24 @@
#!/bin/sh
set -euo pipefail
# uwsgi wants just a path for unix socket
LISTEN=$(echo ${LLNG_LISTEN} | sed -E 's/^unix://')
exec uwsgi \
--plugin psgi \
--psgi /usr/share/lemonldap-ng/llng-server/llng-server.psgi \
--${LLNG_SOCKET_PROTO}-socket ${LISTEN} \
--chmod-socket=660 \
--master \
--max-worker-lifetime 604800 \
--max-requests 100000 \
--disable-logging \
--buffer-size 65535 \
--limit-post 0 \
--die-on-term \
--cheaper 2 \
--workers ${LLNG_WORKERS} \
--cheaper-initial 2 \
--cheaper-algo spare \
--cheaper-step 1

View File

@ -0,0 +1,68 @@
CREATE UNLOGGED TABLE IF NOT EXISTS sessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX IF NOT EXISTS i_s__whatToTrace ON sessions ((a_session ->> '_whatToTrace'));
CREATE INDEX IF NOT EXISTS i_s__session_kind ON sessions ((a_session ->> '_session_kind'));
CREATE INDEX IF NOT EXISTS i_s__utime ON sessions ((cast (a_session ->> '_utime' as bigint)));
CREATE INDEX IF NOT EXISTS i_s_ipAddr ON sessions ((a_session ->> 'ipAddr'));
CREATE INDEX IF NOT EXISTS i_s__httpSessionType ON sessions ((a_session ->> '_httpSessionType'));
CREATE INDEX IF NOT EXISTS i_s_user ON sessions ((a_session ->> 'user'));
CREATE INDEX IF NOT EXISTS i_s_mail ON sessions ((a_session ->> 'mail'));
CREATE INDEX IF NOT EXISTS i_s__session_uid ON sessions ((a_session ->> '_session_uid'));
CREATE TABLE IF NOT EXISTS psessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX IF NOT EXISTS i_p__session_kind ON psessions ((a_session ->> '_session_kind'));
CREATE INDEX IF NOT EXISTS i_p__httpSessionType ON psessions ((a_session ->> '_httpSessionType'));
CREATE INDEX IF NOT EXISTS i_p__session_uid ON psessions ((a_session ->> '_session_uid'));
CREATE INDEX IF NOT EXISTS i_p_ipAddr ON psessions ((a_session ->> 'ipAddr'));
CREATE INDEX IF NOT EXISTS i_p__whatToTrace ON psessions ((a_session ->> '_whatToTrace'));
CREATE UNLOGGED TABLE IF NOT EXISTS samlsessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX IF NOT EXISTS i_a__session_kind ON samlsessions ((a_session ->> '_session_kind'));
CREATE INDEX IF NOT EXISTS i_a__utime ON samlsessions ((cast(a_session ->> '_utime' as bigint)));
CREATE INDEX IF NOT EXISTS i_a_ProxyID ON samlsessions ((a_session ->> 'ProxyID'));
CREATE INDEX IF NOT EXISTS i_a__nameID ON samlsessions ((a_session ->> '_nameID'));
CREATE INDEX IF NOT EXISTS i_a__assert_id ON samlsessions ((a_session ->> '_assert_id'));
CREATE INDEX IF NOT EXISTS i_a__art_id ON samlsessions ((a_session ->> '_art_id'));
CREATE INDEX IF NOT EXISTS i_a__saml_id ON samlsessions ((a_session ->> '_saml_id'));
CREATE UNLOGGED TABLE IF NOT EXISTS oidcsessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX IF NOT EXISTS i_o__session_kind ON oidcsessions ((a_session ->> '_session_kind'));
CREATE INDEX IF NOT EXISTS i_o__utime ON oidcsessions ((cast(a_session ->> '_utime' as bigint )));
CREATE UNLOGGED TABLE IF NOT EXISTS cassessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX IF NOT EXISTS i_c__session_kind ON cassessions ((a_session ->> '_session_kind'));
CREATE INDEX IF NOT EXISTS i_c__utime ON cassessions ((cast(a_session ->> '_utime' as bigint)));
CREATE INDEX IF NOT EXISTS i_c__cas_id ON cassessions ((a_session ->> '_cas_id'));
CREATE INDEX IF NOT EXISTS i_c_pgtIou ON cassessions ((a_session ->> 'pgtIou'));
CREATE TABLE IF NOT EXISTS lmConfig (
cfgnum integer not null primary key,
data text
);
CREATE TABLE IF NOT EXISTS notifications (
date date NOT NULL,
uid varchar(255) NOT NULL,
ref varchar(255) NOT NULL,
cond varchar(255) DEFAULT NULL,
xml text NOT NULL,
done date DEFAULT NULL,
PRIMARY KEY (date, uid, ref)
)

12
example/init/vault-database Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
set -euo pipefail
vault write database/roles/lemonldap-ng \
db_name="postgres" \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT \"lemonldap-ng\" TO \"{{name}}\"; \
ALTER ROLE \"{{name}}\" SET role = \"lemonldap-ng\"" \
default_ttl="12h" \
max_ttl="720h"

View File

@ -0,0 +1,454 @@
job "lemonldap-ng" {
datacenters = ["dc1"]
group "lemonldap-ng" {
count = 1
network {
mode = "bridge"
}
service {
name = "lemonldap-ng"
port = 8080
connect {
sidecar_service {
proxy {
upstreams {
destination_name = "postgres"
local_bind_port = 5432
}
}
}
sidecar_task {
resources {
cpu = 50
memory = 64
}
}
}
tags = [
"traefik.enable=true",
"traefik.http.routers.lemonldap-ng-portal.rule=Host(`sso.example.org`) && !PathRegexp(`^/index\\.psgi/(config|sessions)`)",
"traefik.http.routers.lemonldap-ng-portal.entrypoints=https",
"traefik.http.routers.lemonldap-ng-portal.priority=100",
"traefik.http.routers.lemonldap-ng-portal.middlewares=rate-limit-std@file,inflight-std@file,security-headers@file,hsts@file,compression@file",
"traefik.http.routers.lemonldap-ng-manager.rule=Host(`manager.example.org`)",
"traefik.http.routers.lemonldap-ng-manager.entrypoints=https",
"traefik.http.routers.lemonldap-ng-manager.middlewares=rate-limit-std@file,inflight-std@file,security-headers@file,hsts@file,compression@file",
]
}
# wait for required services tp be ready before starting the main task
task "wait-for" {
driver = "docker"
user = 1053
config {
image = "danielberteaud/wait-for:24.1-1"
readonly_rootfs = true
pids_limit = 20
}
lifecycle {
hook = "prestart"
}
env {
SERVICE_0 = "postgres.service.consul"
}
resources {
cpu = 10
memory = 10
memory_max = 30
}
}
task "lemonldap-ng" {
driver = "docker"
config {
image = "danielberteaud/lemonldap-ng:2.18.1-5"
readonly_rootfs = true
pids_limit = 200
volumes = [
"secrets/lemonldap-ng.ini:/etc/lemonldap-ng/lemonldap-ng.ini:ro",
"local/init-db.sh:/entrypoint.d/20-initdb.sh:ro",
]
mount {
type = "tmpfs"
target = "/tmp"
tmpfs_options {
size = 5000000
}
}
}
vault {
policies = ["lemonldap-ng"]
env = false
disable_file = true
}
artifact {
source = "git::https://git.lapiole.org/nomad/lemonldap-ng.git//files/assets"
destination = "local/assets/static/common"
}
env {
LLNG_NGINX_LISTEN = "127.0.0.1:8080"
LLNG_LISTEN = "unix:/tmp/llng.sock"
LLNG_MANAGER_VHOST = "manager.example.org"
LLNG_PORTAL_VHOST = "sso.example.org"
LLNG_CUSTOM_ASSETS_DIR = "/local/assets"
CTD_CONFIG = "/local/caretakerd.yaml"
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT
LANG=fr_FR.utf8
LLNG_WORKERS=6
PGDATABASE=lemonldap-ng
PGHOST=127.0.0.1
PGPASSWORD={{ with secret "database/creds/lemonldap-ng" }}{{ .Data.password }}{{ end }}
PGPORT=5432
PGSSLMODE=disable
PGUSER={{ with secret "database/creds/lemonldap-ng" }}{{ .Data.username }}{{ end }}
TZ=Europe/Paris
_EOT
destination = "secrets/.env"
perms = 400
env = true
}
# Main Lemonldap::NG configuration
template {
data = <<_EOT
[all]
logLevel = notice
localSessionStorage = Cache::FileCache
localSessionStorageOptions = { \
'namespace' => 'sessions', \
'default_expires_in' => '300', \
'directory_umask' => '007', \
'cache_root' => '/tmp', \
'cache_depth' => 3 \
}
globalStorage = Apache::Session::Browseable::PgJSON
globalStorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => 'sessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
persistentStorage = Apache::Session::Browseable::PgJSON
persistentStorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => 'psessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
samlStorage = Apache::Session::Browseable::PgJSON
samlStorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => 'samlsessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
oidcStorage = Apache::Session::Browseable::PgJSON
oidcStorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => 'oidcsessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
casStorage = Apache::Session::Browseable::PgJSON
casStorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => 'cassessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
notificationStorage = DBI
notificationStorageOptions = { \
'dbiChain' => 'DBI:Pg:', \
'dbiTable' => 'notifications', \
'type' => 'CDBI', \
}
status = 1
[configuration]
useServerEnv = 1
type = CDBI
dbiChain = DBI:Pg:
localStorage = Cache::FileCache
localStorageOptions = { \
'namespace' => 'config', \
'default_expires_in' => '600', \
'directory_umask' => '007', \
'cache_root' => '/tmp', \
'cache_depth' => 0 \
}
[manager]
protection = manager
enabledModules = conf, sessions, notifications, 2ndFA
staticPrefix = /static
templateDir = /usr/share/lemonldap-ng/manager/htdocs/templates
languages = en
[portal]
staticPrefix = /static
templateDir = /usr/share/lemonldap-ng/portal/templates
languages = en, fr, es, it, de
forceGlobalStorageUpgradeOTT = 1
_EOT
destination = "secrets/lemonldap-ng.ini"
uid = 100048
gid = 100048
perms = 440
}
# This is a striped down config, just used to migrate file based config to database on first start
template {
data = <<_EOT
[all]
[configuration]
type = File
dirName = /local
_EOT
destination = "local/init.ini"
}
# A small script to handle initialization (create tables, indexes, load initial config in the DB)
template {
data = <<_EOT
#!/bin/sh
set -euo pipefail
echo "Create tables if needed"
psql -f /usr/share/lemonldap-ng/ressources/lemonldap-ng.postgres.sql
if [ "$(psql -qAtc 'SELECT COUNT(1) FROM lmConfig')" = "0" ]; then
echo "Load initial configuration in database"
/usr/libexec/lemonldap-ng/bin/convertConfig \
--current=/local/init.ini \
--new=/etc/lemonldap-ng/lemonldap-ng.ini
fi
_EOT
destination = "local/init-db.sh"
perms = 755
}
# Custom file based config, which will be migrated to the database
template {
data = <<_EOT
{
"applicationList" : {
"2administration" : {
"catname" : "Administration",
"manager" : {
"options" : {
"description" : "Configure LemonLDAP::NG WebSSO",
"display" : "auto",
"logo" : "configure.png",
"name" : "WebSSO Manager",
"uri" : "https://manager.example.org/manager.html"
},
"type" : "application"
},
"notifications" : {
"options" : {
"description" : "Explore WebSSO notifications",
"display" : "auto",
"logo" : "database.png",
"name" : "Notifications Explorer",
"uri" : "https://manager.example.org/notifications.html"
},
"type" : "application"
},
"sessions" : {
"options" : {
"description" : "Explore WebSSO sessions",
"display" : "auto",
"logo" : "database.png",
"name" : "Sessions Explorer",
"uri" : "https://manager.example.org/sessions.html"
},
"type" : "application"
},
"type" : "category"
},
"3documentation" : {
"catname" : "Documentation",
"localdoc" : {
"options" : {
"description" : "Documentation supplied with LemonLDAP::NG",
"display" : "on",
"logo" : "help.png",
"name" : "Local documentation",
"uri" : "https://manager.example.org/doc/"
},
"type" : "application"
},
"officialwebsite" : {
"options" : {
"description" : "Official LemonLDAP::NG Website",
"display" : "on",
"logo" : "network.png",
"name" : "Official Website",
"uri" : "https://lemonldap-ng.org/"
},
"type" : "application"
},
"type" : "category"
}
},
"authentication" : "Demo",
"cfgAuthor" : "Daniel Berteaud",
"cfgDate" : "1627287638",
"cfgNum" : 1,
"cfgVersion" : "2.18.0",
"cookieName" : "lemonldap",
"demoExportedVars" : {
"cn" : "cn",
"mail" : "mail",
"uid" : "uid"
},
"domain" : "example.com",
"exportedHeaders" : {
"test1.example.com" : {
"Auth-Groups" : "$groups",
"Auth-User" : "$uid"
},
"test2.example.com" : {
"Auth-Groups" : "$groups",
"Auth-User" : "$uid"
}
},
"exportedVars" : {},
"groups" : {},
"localSessionStorage" : "Cache::FileCache",
"localSessionStorageOptions" : {
"cache_depth" : 3,
"cache_root" : "/tmp",
"default_expires_in" : 600,
"directory_umask" : "007",
"namespace" : "sessions"
},
"globalStorage" : "Apache::Session::Browseable::PgJSON",
"globalStorageOptions" : {
"DataSource" : "DBI:Pg:",
"TableName" : "sessions",
"generateModule" : "Lemonldap::NG::Common::Apache::Session::Generate::SHA256",
"Commit" : 1
},
"locationRules" : {
"sso.example.org" : {
"(?#checkUser)^/checkuser" : "inGroup(\"timelords\")",
"(?#errors)^/lmerror/" : "accept",
"default" : "accept"
},
"manager.example.org" : {
"(?#Configuration)^/(.*?\\.(fcgi|psgi)/)?(manager\\.html|confs|prx/|$)" : "inGroup(\"timelords\")",
"(?#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,
"macros" : {
"UA" : "$ENV{HTTP_USER_AGENT}",
"_whatToTrace" : "$_auth eq 'SAML' ? lc($_user.'@'.$_idpConfKey) : $_auth eq 'OpenIDConnect' ? lc($_user.'@'.$_oidc_OP) : lc($_user)"
},
"notification" : 1,
"oidcServiceIgnoreScopeForClaims" : 1,
"passwordDB" : "Demo",
"portal" : "https://sso.example.org/",
"portalSkin" : "bootstrap",
"portalSkinBackground" : "1280px-Cedar_Breaks_National_Monument_partially.jpg",
"registerDB" : "Demo",
"reloadUrls" : {
"localhost" : "http://localhost:8080/reload"
},
"securedCookie" : 0,
"sessionDataToRemember" : {},
"timeout" : 72000,
"userDB" : "Same",
"whatToTrace" : "_whatToTrace"
}
_EOT
destination = "local/lmConf-1.json"
}
# caretakerd is the init system used to run LL::NG, nginx and cron tasks
template {
data = <<_EOT
services:
lemonldap:
type: master
command: ["lemonldap-ng"]
local_cache:
command: ["/usr/libexec/lemonldap-ng/bin/purgeLocalCache"]
cronExpression: "@every 1h"
logger:
level: debug
nginx:
command: ["nginx", "-c", "${LLNG_NGINX_CONF}"]
{{- if eq (env "NOMAD_ALLOC_INDEX") "0" }}
global_cache:
command: ["/usr/libexec/lemonldap-ng/bin/purgeCentralCache"]
cronExpression: "@every 10m"
logger:
level: debug
rotate_oidc_keys:
command: ["/usr/libexec/lemonldap-ng/bin/rotateOidcKeys"]
cronExpression: "15 5 0 * * 6"
logger:
level: debug
{{- end }}
_EOT
destination = "local/caretakerd.yaml"
}
resources {
cpu = 500
memory = 512
}
}
}
}

19
example/prep.d/10-mv-conf.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
set -eu
if [ "lemonldap-ng" != "lemonldap-ng" ]; then
for DIR in vault consul nomad; do
if [ -d output/${DIR} ]; then
for FILE in $(find output/${DIR} -name "*lemonldap-ng*.hcl" -type f); do
NEW_FILE=$(echo "${FILE}" | sed -E "s/lemonldap-ng/lemonldap-ng/g")
mv "${FILE}" "${NEW_FILE}"
done
fi
done
fi

View File

@ -0,0 +1,7 @@
path "kv/sevrice/lemonldap-ng" {
capabilities = ["read"]
}
path "database/creds/lemonldap-ng" {
capabilities = ["read"]
}