Lemonldap::NG first job template
This commit is contained in:
parent
d7d37477da
commit
2e0cfb1845
|
@ -1,3 +1,3 @@
|
||||||
# lemonldap-ng
|
# lemonldap-ng
|
||||||
|
|
||||||
Lemonldap::NG webSSO
|
Lemonldap::NG webSSO
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- url: ../common.git
|
|
@ -0,0 +1,3 @@
|
||||||
|
Kind = "service-defaults"
|
||||||
|
Name = "[[ .instance ]][[ .consul.suffix ]]"
|
||||||
|
Protocol = "http"
|
|
@ -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"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -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"]
|
|
@ -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
|
||||||
|
|
|
@ -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 * * * *'
|
|
@ -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/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||||
|
)
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
[[- template "common/vault.mkpgrole.sh"
|
||||||
|
dict "ctx" .
|
||||||
|
"config" (dict "role" .instance "database" "postgres")
|
||||||
|
]]
|
|
@ -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 ]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
[[ template "common/mv_conf.sh" dict "ctx" . "services" (dict "lemonldap-ng" .instance) ]]
|
|
@ -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 }}
|
|
@ -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 }}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[all]
|
||||||
|
|
||||||
|
[configuration]
|
||||||
|
type = File
|
||||||
|
dirName = /local
|
||||||
|
|
|
@ -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
|
|
@ -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 ]]
|
|
@ -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"
|
||||||
|
}
|
|
@ -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: {}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
path "[[ .vault.prefix ]]kv/sevrice/[[ .instance ]]" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "[[ .vault.prefix ]]database/creds/[[ .instance ]]" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
Loading…
Reference in New Issue