Lemonldap::NG first job template

This commit is contained in:
Daniel Berteaud 2024-01-03 21:04:11 +01:00
parent d7d37477da
commit 2e0cfb1845
22 changed files with 821 additions and 1 deletions

View File

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

4
bundles.yml Normal file
View File

@ -0,0 +1,4 @@
---
dependencies:
- url: ../common.git

View File

@ -0,0 +1,3 @@
Kind = "service-defaults"
Name = "[[ .instance ]][[ .consul.suffix ]]"
Protocol = "http"

View File

@ -0,0 +1,30 @@
Kind = "service-intentions"
Name = "[[ .instance ]][[ .consul.suffix ]]"
Sources = [
{
Name = "[[ (merge .llng.portal .).traefik.instance ]]"
Permissions = [
[[- if not .llng.api.traefik.enabled ]]
# Prevent access to the API as it's disabled
{
Action = "deny"
HTTP {
PathRegex = "^/index\\.psgi/(config|sessions)"
}
},
[[- end ]]
{
Action = "deny"
HTTP {
PathRegex = "^/reload"
}
},
{
Action = "allow"
HTTP {
Methods = ["GET", "HEAD", "POST", "OPTIONS", "PUT", "DELETE", "PATCH"]
}
}
]
}
]

View File

@ -0,0 +1,54 @@
FROM [[ .docker.repo ]][[ .docker.base_images.alma9.image ]]
MAINTAINER [[ .docker.maintainer ]]
ARG LLNG_VERSION=2.18.1 \
CARETAKERD_VERSION=1.0.7
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 \
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 \
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,106 @@
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 ~ ^(?<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/ {
alias /usr/share/lemonldap-ng/portal/htdocs/static/;
}
}
}

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)
)

8
init/vault-database Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -euo pipefail
[[- template "common/vault.mkpgrole.sh"
dict "ctx" .
"config" (dict "role" .instance "database" "postgres")
]]

130
lemonldap-ng.nomad.hcl Normal file
View File

@ -0,0 +1,130 @@
job "[[ .instance ]]" {
[[ template "common/job_start" merge .llng . ]]
group "lemonldap-ng" {
[[- $c := merge .llng.engine . ]]
count = [[ $c.count ]]
network {
mode = "bridge"
}
service {
name = "[[ .instance ]][[ .consul.suffix ]]"
port = 8080
[[ template "common/connect" $c ]]
[[- $p := merge .llng.portal . ]]
[[- $m := merge .llng.manager . ]]
[[- $a := merge .llng.api . ]]
tags = [
[[- if $p.traefik.enabled ]]
"[[ $p.traefik.instance ]].enable=true",
"[[ $p.traefik.instance ]].http.routers.[[ .instance ]]-portal[[ .consul.suffix ]].rule=Host(`[[ (urlParse $p.public_url).Hostname ]]`) && !PathRegexp(`^/index\\.psgi/(config|sessions)`)",
"[[ $p.traefik.instance ]].http.routers.[[ .instance ]]-portal[[ .consul.suffix ]].entrypoints=[[ join $p.traefik.entrypoints "," ]]",
"[[ $p.traefik.instance ]].http.routers.[[ .instance ]]-portal[[ .consul.suffix ]].priority=100",
"[[ $p.traefik.instance ]].http.routers.[[ .instance ]]-portal[[ .consul.suffix ]].middlewares=[[ template "common/traefik_middlewares" $p.traefik ]]",
[[- end ]]
[[- if $m.traefik.enabled ]]
[[- if ne $m.traefik.instance $c.traefik.instance ]]
"[[ $m.traefik.instance ]].enable=true",
[[- end ]]
"[[ $m.traefik.instance ]].http.routers.[[ .instance ]]-manager[[ .consul.suffix ]].rule=Host(`[[ (urlParse $m.public_url).Hostname ]]`)",
"[[ $m.traefik.instance ]].http.routers.[[ .instance ]]-manager[[ .consul.suffix ]].entrypoints=[[ join $m.traefik.entrypoints "," ]]",
"[[ $m.traefik.instance ]].http.routers.[[ .instance ]]-manager[[ .consul.suffix ]].middlewares=[[ template "common/traefik_middlewares" $m.traefik ]]",
[[- end ]]
[[- if $a.traefik.enabled ]]
[[- if $a.traefik.instance ne $p.traefik.instance ]]
"[[ $a.traefik.instance ]].enable=true",
[[- end ]]
"[[ $a.traefik.instance ]].http.routers.[[ .instance ]]-api[[ .consul.suffix ]].rule=Host(`[[ (urlParse $p.public_url).Hostname ]]`) && PathRegexp(`^/index\\.psgi/(config|sessions)`)",
"[[ $a.traefik.instance ]].http.routers.[[ .instance ]]-api[[ .consul.suffix ]].entrypoints=[[ join $a.traefik.entrypoints "," ]]",
"[[ $a.traefik.instance ]].http.routers.[[ .instance ]]-api[[ .consul.suffix ]].priority=200",
"[[ $a.traefik.instance ]].http.routers.[[ .instance ]]-api[[ .consul.suffix ]].middlewares=[[ template "common/traefik_middlewares" $a.traefik ]]",
[[- end ]]
]
}
task "lemonldap-ng" {
driver = [[ $c.nomad.driver | toJSON ]]
config {
image = [[ $c.image | toJSON ]]
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",
]
[[ template "common/tmpfs" dict "size" "5000000" "target" "/tmp" ]]
}
vault {
policies = ["[[ .instance ]][[ .consul.suffix ]]"]
}
env {
LLNG_NGINX_LISTEN = "127.0.0.1:8080"
LLNG_LISTEN = "unix:/tmp/llng.sock"
LLNG_MANAGER_VHOST = [[ (urlParse .llng.manager.public_url).Hostname | toJSON ]]
LLNG_PORTAL_VHOST = [[ (urlParse .llng.portal.public_url).Hostname | toJSON ]]
CTD_CONFIG = "/local/caretakerd.yaml"
}
[[ template "common/file_env" $c.env ]]
# Main Lemonldap::NG configuration
template {
data =<<_EOT
[[ template "lemonldap-ng/lemonldap-ng.ini.tpl" $c ]]
_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
[[ template "lemonldap-ng/init.ini.tpl" $c ]]
_EOT
destination = "local/init.ini"
}
# A small script to handle initialization (create tables, indexes, load initial config in the DB)
template {
data = <<_EOT
[[ template "lemonldap-ng/init.sh.tpl" . ]]
_EOT
destination = "local/init-db.sh"
perms = 755
}
# Custom file based config, which will be migrated to the database
template {
data = <<_EOT
[[ template "lemonldap-ng/lmConf-1.json.tpl" . ]]
_EOT
destination = "local/lmConf-1.json"
}
# caretakerd is the init system used to run LL::NG, nginx and cron tasks
template {
data =<<_EOT
[[ template "lemonldap-ng/caretakerd.yaml.tpl" . ]]
_EOT
destination = "local/caretakerd.yaml"
}
[[ template "common/resources" $c.resources ]]
}
}
}

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

@ -0,0 +1 @@
[[ template "common/mv_conf.sh" dict "ctx" . "services" (dict "lemonldap-ng" .instance) ]]

View File

@ -0,0 +1,19 @@
logger:
level: debug
services:
lemonldap:
type: master
command: ["lemonldap-ng"]
local_cache:
command: ["/usr/libexec/lemonldap-ng/bin/purgeLocalCache"]
cronExpression: '1 * * * *'
nginx:
command: ["nginx", "-c", "${LLNG_NGINX_CONF}"]
{{- if eq (env "NOMAD_ALLOC_INDEX") "0" }}
global_cache:
command: ["/usr/libexec/lemonldap-ng/bin/purgeCentralCache"]
cronExpression: '10 * * * *'
rotate_oidc_keys:
command: ["/usr/libexec/lemonldap-ng/bin/rotateOidcKeys"]
cronExpression: '5 5 * * 6'
{{- end }}

5
templates/cron.tpl Normal file
View File

@ -0,0 +1,5 @@
1 * * * * /usr/libexec/lemonldap-ng/bin/purgeLocalCache
{{- if eq (env "NOMAD_ALLOC_INDEX") "0" }}
10 * * * * /usr/libexec/lemonldap-ng/bin/purgeCentralCache
5 5 * * 6 /usr/libexec/lemonldap-ng/bin/rotateOidcKeys
{{- end }}

6
templates/init.ini.tpl Normal file
View File

@ -0,0 +1,6 @@
[all]
[configuration]
type = File
dirName = /local

13
templates/init.sh.tpl Normal file
View File

@ -0,0 +1,13 @@
#!/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

View File

@ -0,0 +1,54 @@
[all]
logLevel = notice
localSessionStorage = Cache::FileCache
localSessionStorageOptions = { \
'namespace' => 'sessions', \
'default_expires_in' => '300', \
'directory_umask' => '007', \
'cache_root' => '/tmp', \
'cache_depth' => 3 \
}
[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 = [[ .llng.manager.protection ]]
enabledModules = conf, sessions, notifications, 2ndFA
staticPrefix = /static
templateDir = /usr/share/lemonldap-ng/manager/htdocs/templates
languages = [[ join .llng.manager.languages ", " ]]
[portal]
staticPrefix = /static
templateDir = /usr/share/lemonldap-ng/portal/templates
languages = [[ join .llng.portal.languages ", " ]]
forceGlobalStorageUpgradeOTT = 1
notificationStorage = DBI
notificationStorageOptions = { \
'dbiChain' => 'DBI:Pg:', \
'dbiTable' => 'notifications', \
'type' => 'CDBI', \
}
[[- range $stor := coll.Slice "global" "persistent" "saml" "oidc" "cas" ]]
[[ $stor ]]Storage = Apache::Session::Browseable::PgJSON
[[ $stor ]]StorageOptions = { \
'DataSource' => 'DBI:Pg:', \
'TableName' => '[[ if eq $stor "global" ]][[ else if eq $stor "persistent" ]]p[[ else ]][[ $stor ]][[ end ]]sessions', \
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', \
'Commit' => 1 \
}
[[- end ]]

132
templates/lmConf-1.json.tpl Normal file
View File

@ -0,0 +1,132 @@
{
"applicationList" : {
"2administration" : {
"catname" : "Administration",
"manager" : {
"options" : {
"description" : "Configure LemonLDAP::NG WebSSO",
"display" : "auto",
"logo" : "configure.png",
"name" : "WebSSO Manager",
"uri" : "[[ .llng.manager.public_url ]]/manager.html"
},
"type" : "application"
},
"notifications" : {
"options" : {
"description" : "Explore WebSSO notifications",
"display" : "auto",
"logo" : "database.png",
"name" : "Notifications Explorer",
"uri" : "[[ .llng.manager.public_url ]]/notifications.html"
},
"type" : "application"
},
"sessions" : {
"options" : {
"description" : "Explore WebSSO sessions",
"display" : "auto",
"logo" : "database.png",
"name" : "Sessions Explorer",
"uri" : "[[ .llng.manager.public_url ]]/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" : "[[ .llng.manager.public_url ]]/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" : "/var/cache/lemonldap-ng",
"default_expires_in" : 600,
"directory_umask" : "007",
"namespace" : "lemonldap-ng-sessions"
},
"globalStorage" : "Lemonldap::NG::Common::Apache::Session::REST",
"globalStorageOptions" : {
"baseUrl" : "[[ .llng.portal.public_url ]]/index.psgi/sessions/global",
"generateModule" : "Lemonldap::NG::Common::Apache::Session::Generate::SHA256"
},
"locationRules" : {
"[[ (urlParse .llng.portal.public_url).Hostname ]]" : {
"(?#checkUser)^/checkuser" : "inGroup(\"timelords\")",
"(?#errors)^/lmerror/" : "accept",
"default" : "accept"
},
"[[ (urlParse .llng.manager.public_url).Hostname ]]" : {
"(?#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" : "[[ .llng.portal.public_url ]]/",
"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"
}

124
variables.yml Normal file
View File

@ -0,0 +1,124 @@
---
instance: lemonldap-ng
llng:
# The same engine can run portal, manager and handler
# The settings below are for the uwsgi engine itself
engine:
# Number of instance to run
count: 1
# Docker image to use
image: '[[ .docker.repo ]]lemonldap-ng:2.18.1-1'
# Resource allocation
resources:
cpu: 500
memory: 512
# Connect to the database from the service mesh
consul:
connect:
upstreams:
- destination_name: postgres[[ .consul.suffix ]]
local_bind_port: 5432
# Additional env vars to pass to the container
env:
# Database settings
PGHOST: 127.0.0.1
PGPORT: 5432
PGUSER: '{{ with secret "[[ .vault.prefix ]]database/creds/[[ .instance ]]" }}{{ .Data.username }}{{ end }}'
PGPASSWORD: '{{ with secret "[[ .vault.prefix ]]database/creds/[[ .instance ]]" }}{{ .Data.password }}{{ end }}'
PGDATABASE: '[[ .instance ]]'
# No need for SSL if postgres is accessed from the mesh
PGSSLMODE: disable
# Max number of uwsgi workers. You might need to allocation more memory
# if you need to rise this value (or you can just run several instances instead)
LLNG_WORKERS: 6
# Settings for the portal itself
portal:
# URL used by users to reach the portal
public_url: https://sso.example.org
# Available languages on the portal
languages:
- en
- fr
- es
- it
- de
# Traefik settings
traefik:
# If disabled, the portal won't be exposed by Traefik
enabled: true
# Override base_middleware to remove csp-relaxed@file as Lemonldap::NG handle CSP itself
base_middlewares:
- rate-limit-std@file
- inflight-std@file
- security-headers@file
- hsts@file
- compression@file
# List of middlewares to apply
middlewares: {}
# Settings for the configuration manager
manager:
# protection can be "none" (no authentication) or "manager" (the manager is protected by Lemonldap::NG itself, and you must add appropriate
# access rules to access the manager). On initial configuration, you will likely need to set this to none, and switch back to manager only after
# the configuration is working
protection: manager
# The URL to reach the manager
public_url: https://manager.example.org
# Available languages for the manager
languages:
- en
# Traefik settings
traefik:
# If disabled, the manager will not be exposed by Traefik
enabled: true
# Override base_middleware to remove csp-relaxed@file as Lemonldap::NG handle CSP itself
base_middlewares:
- rate-limit-std@file
- inflight-std@file
- security-headers@file
- hsts@file
- compression@file
# List of middlewares to apply
middlewares: {}
# The API is exposed by the portal, but usually must be secured differently
# The following settings only apply to the REST/SOAP API
api:
# Traefik settings
traefik:
# If disabled, Traefik won't expose the API
enabled: false
# Override base_middleware to remove csp-relaxed@file as Lemonldap::NG handle CSP itself
base_middlewares:
- rate-limit-std@file
- inflight-std@file
- security-headers@file
- hsts@file
- compression@file
# List of middlewares to apply
middlewares: {}

View File

@ -0,0 +1,7 @@
path "[[ .vault.prefix ]]kv/sevrice/[[ .instance ]]" {
capabilities = ["read"]
}
path "[[ .vault.prefix ]]database/creds/[[ .instance ]]" {
capabilities = ["read"]
}