Lemonldap::NG first job template
This commit is contained in:
parent
d7d37477da
commit
2e0cfb1845
|
@ -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