Merge branch 'develop'

This commit is contained in:
Emmanuel Garette 2022-08-25 11:12:09 +02:00
commit b1e7064488
55 changed files with 702 additions and 180 deletions

View file

@ -1,12 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from os.path import join
from filecmp import dircmp from filecmp import dircmp
from difflib import unified_diff from difflib import unified_diff
from sys import stdout, argv from sys import stdout, argv
from os import walk from os import walk
from os.path import join from os.path import join, islink
from datetime import datetime, timezone from datetime import datetime, timezone
@ -87,10 +86,13 @@ for filename in old - new:
for filename in new - old: for filename in new - old:
print(f'\n- fichier {filename} ajouté :\n') if islink(join(NEW_DIR, filename)):
with open(join(NEW_DIR, filename), 'r') as fh: print(f'\n- lien {filename} ajouté\n')
if WEBSITE: else:
print('```') print(f'\n- fichier {filename} ajouté :\n')
print(fh.read()) with open(join(NEW_DIR, filename), 'r') as fh:
if WEBSITE: if WEBSITE:
print('```') print('```')
print(fh.read())
if WEBSITE:
print('```')

View file

@ -14,7 +14,7 @@ for image in *; do
if [ -f "host/configurations/$HOST_NAME/etc/systemd/nspawn/$osname.nspawn" ]; then if [ -f "host/configurations/$HOST_NAME/etc/systemd/nspawn/$osname.nspawn" ]; then
MACHINES="$MACHINES$osname " MACHINES="$MACHINES$osname "
fi fi
echo echo
echo "Install machine $image" echo "Install machine $image"
./install_machine "$HOST_NAME" "$image" "$osname" ./install_machine "$HOST_NAME" "$image" "$osname"
fi fi
@ -23,5 +23,39 @@ for image in *; do
done done
machinectl enable $MACHINES machinectl enable $MACHINES
machinectl start $MACHINES machinectl start $MACHINES
STARTED=""
DEGRADED=""
found=true
idx=0
while [ $found = true ]; do
found=false
echo "tentative $idx"
for machine in $MACHINES; do
if ! echo $STARTED | grep -q " $machine "; then
status=$(machinectl -q shell $machine /usr/bin/systemctl is-system-running || true)
if echo "$status" | grep -q degraded; then
STARTED="$STARTED $machine "
DEGRADED="$DEGRADED $machine"
elif echo "$status" | grep -q running; then
STARTED="$STARTED $machine "
else
found=true
echo "status actuel de $machine : $status"
fi
fi
done
sleep 2
idx=$((idx+1))
if [ $idx = 60 ]; then
break
fi
done
retcode=0
for machine in $DEGRADED; do
echo
echo "========= $machine"
machinectl -q shell $machine /usr/bin/systemctl --state=failed --no-legend --no-pager
retcode=1
done
exit 0 exit $retcode

View file

@ -2,12 +2,14 @@ from os import fdopen
from dbus import SystemBus, Array from dbus import SystemBus, Array
def run(host, cmd): def run(host, cmd, user=None):
bus = SystemBus() bus = SystemBus()
remote_object = bus.get_object('org.freedesktop.machine1', remote_object = bus.get_object('org.freedesktop.machine1',
'/org/freedesktop/machine1', '/org/freedesktop/machine1',
False, False,
) )
if user is not None:
cmd = ['/bin/su', '-', user, '-s', '/bin/bash', '-c', ' '.join(cmd)]
res = remote_object.OpenMachineShell(host, res = remote_object.OpenMachineShell(host,
'', '',
cmd[0], cmd[0],

View file

@ -18,7 +18,7 @@
</service> </service>
<service name='dovecot-init'> <service name='dovecot-init'>
<override/> <override/>
<file>/etc/nginx/conf.d/autoconfig.conf</file> <file>/etc/nginx/default.d/autoconfig.conf</file>
</service> </service>
<service name='nginx'> <service name='nginx'>
<file source='config-v1.1.xml' file_type="variable" variable="mail_domains">well_known_filenames</file> <file source='config-v1.1.xml' file_type="variable" variable="mail_domains">well_known_filenames</file>
@ -90,8 +90,8 @@
<variable name="revprox_client_external_domainnames" redefine="True"/> <variable name="revprox_client_external_domainnames" redefine="True"/>
<variable name="revprox_client_web_address" redefine="True"/> <variable name="revprox_client_web_address" redefine="True"/>
</family> </family>
<variable name="nginx_default_https" redefine="True"> <variable name="nginx_root" redefine='True'>
<value>False</value> <value>/var/www/html</value>
</variable> </variable>
</family> </family>
</variables> </variables>

View file

@ -1,12 +1,2 @@
server { # To allow POST on static pages
listen 443 ssl; error_page 405 =200 $uri;
server_name %%domain_name_eth0;
ssl_client_certificate %%revprox_ca_file;
ssl_certificate %%revprox_cert_file;
ssl_certificate_key %%revprox_key_file;
root /var/www/html/;
# To allow POST on static pages
error_page 405 =200 $uri;
}

View file

@ -1,5 +1,5 @@
[Unit] [Unit]
After=network.target After=risotto.target
[Service] [Service]
ExecStart= ExecStart=

View file

@ -1,7 +1,7 @@
#ORIGIN https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/systemd/gitea.service #ORIGIN https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/systemd/gitea.service
[Unit] [Unit]
Description=Gitea (Git with a cup of tea) Description=Gitea (Git with a cup of tea)
After=network.target postgresqlclient.service After=risotto.target
[Service] [Service]
# Modify these two values and uncomment them if you have # Modify these two values and uncomment them if you have

View file

@ -2,7 +2,7 @@
<rougail version="0.10"> <rougail version="0.10">
<services> <services>
<service name="ldap_client" manage="False"> <service name="ldap-client" target="risotto" engine="creole">
<file source="ldap.conf" file_type="variable">ldap_client_file</file> <file source="ldap.conf" file_type="variable">ldap_client_file</file>
<file source="ca_LDAP.crt" file_type="variable">ldap_ca_file</file> <file source="ca_LDAP.crt" file_type="variable">ldap_ca_file</file>
<file source="ldap_client.crt" file_type="variable">ldap_cert_file</file> <file source="ldap_client.crt" file_type="variable">ldap_cert_file</file>

View file

@ -0,0 +1,8 @@
[Unit]
After=network-online.target
Before=risotto.target
[Service]
Type=oneshot
ExecStart=/usr/bin/timeout 90 bash -c 'while ! 3<> /dev/tcp/%%ldap_server_address/%%ldap_port; do sleep 1; done'

View file

@ -25,10 +25,10 @@
</services> </services>
<variables> <variables>
<family name="nginx"> <family name="nginx">
<variable name="oauth2_client_external_domain" type="domainname" hidden="True" supplier="OAuth2Client:external_domain"/>
<variable name="nginx_default_https" redefine="True"> <variable name="nginx_default_https" redefine="True">
<value>False</value> <value>False</value>
</variable> </variable>
<variable name="oauth2_client_external_domain" type="domainname" hidden="True" supplier="OAuth2Client:external_domain"/>
</family> </family>
<family name="lemonldap" description="LemonLDAP" help="Configuration de la solution d'authentification unique LemonLDAP::NG"> <family name="lemonldap" description="LemonLDAP" help="Configuration de la solution d'authentification unique LemonLDAP::NG">
<variable name="lemon_proc" type="number" description="Nombre de processus dédié à LemonLdap (équivalent au nombre de processeurs)" mandatory="True"> <variable name="lemon_proc" type="number" description="Nombre de processus dédié à LemonLdap (équivalent au nombre de processeurs)" mandatory="True">

View file

@ -1,7 +1,6 @@
[Unit] [Unit]
After=nginx.service After=risotto.target nginx.service
[Service] [Service]
ExecStartPre=/usr/bin/timeout 90 bash -c 'while ! 3<> /dev/tcp/%%ldap_server_address/%%ldap_port; do sleep 1; done'
ExecStartPost=-/usr/bin/timeout 10 bash -c 'while ! /usr/local/lib/sbin/interne_well_known.pl > /var/www/html/.well-known/openid-configuration/int; do sleep 1; done' ExecStartPost=-/usr/bin/timeout 10 bash -c 'while ! /usr/local/lib/sbin/interne_well_known.pl > /var/www/html/.well-known/openid-configuration/int; do sleep 1; done'
ExecStartPost=-/bin/bash -c '/usr/local/lib/sbin/interne_well_known.pl no > /var/www/html/.well-known/openid-configuration/ext' ExecStartPost=-/bin/bash -c '/usr/local/lib/sbin/interne_well_known.pl no > /var/www/html/.well-known/openid-configuration/ext'

View file

@ -1,7 +1,6 @@
%echo "#!/usr/bin/env perl" %echo "#!/usr/bin/env perl"
use HTTP::Tiny; use HTTP::Tiny;
use JSON qw(from_json to_json);
my $response = HTTP::Tiny->new->get('https://%%domain_name_eth0/.well-known/openid-configuration'); my $response = HTTP::Tiny->new->get('https://%%domain_name_eth0/.well-known/openid-configuration');

View file

@ -5,5 +5,5 @@ depends:
- postgresql-client - postgresql-client
- relay-lmtp-client - relay-lmtp-client
- reverse-proxy-client - reverse-proxy-client
- nginx-common - nginx-https
- oauth2-client - oauth2-client

View file

@ -11,8 +11,9 @@
<service name="postorius" target="multi-user" engine="creole"> <service name="postorius" target="multi-user" engine="creole">
<file engine="none">/etc/postorius/gunicorn_config.py</file> <file engine="none">/etc/postorius/gunicorn_config.py</file>
<file engine="none" source="sysuser-postorius.conf">/sysusers.d/0postorius.conf</file> <file engine="none" source="sysuser-postorius.conf">/sysusers.d/0postorius.conf</file>
<file source="config-nginx.conf">/etc/nginx/conf.d/postorius.conf</file> <file source="config-nginx.conf">/etc/nginx/default.d/postorius.conf</file>
<file source="postorius-settings.py">/etc/mailman3.d/postorius.py</file> <file source="postorius-settings.py">/etc/mailman3.d/postorius.py</file>
<file>/tests/mailman.yml</file>
</service> </service>
<service name="postgresqlclient" target="multi-user" engine="creole"> <service name="postgresqlclient" target="multi-user" engine="creole">
<file owner="postorius" mode="400">/etc/pki/tls/private/postgresql_postorius.key</file> <file owner="postorius" mode="400">/etc/pki/tls/private/postgresql_postorius.key</file>
@ -47,6 +48,11 @@
<variable name="oauth2_client_external" redefine="True" remove_fill="True"/> <variable name="oauth2_client_external" redefine="True" remove_fill="True"/>
</family> </family>
</family> </family>
<family name="nginx">
<variable name="nginx_root" redefine="True">
<value>/usr/share/webapps/postorius</value>
</variable>
</family>
<family name="postgresql"> <family name="postgresql">
<variable name="pg_client_key_owner" redefine="True"> <variable name="pg_client_key_owner" redefine="True">
<value>mailman</value> <value>mailman</value>

View file

@ -3,7 +3,7 @@
<variables> <variables>
<family name="list_" description="Listes du domaine " dynamic="mailman_domains"> <family name="list_" description="Listes du domaine " dynamic="mailman_domains">
<variable name="name_" description="Nom des listes" type="unix_user" multi="True" mandatory="True"/> <variable name="name_" description="Nom des listes" type="unix_user" multi="True" mandatory="True"/>
<variable name="names_" description="Address names" type="string" multi="True" mandatory="True" hidden="True"/> <variable name="names_" description="Address names" type="string" mandatory="True" hidden="True"/>
</family> </family>
<variable name="names_" description="Address names" type="string" multi="True" mandatory="True" hidden="True" supplier="LMTP:criteria"/> <variable name="names_" description="Address names" type="string" multi="True" mandatory="True" hidden="True" supplier="LMTP:criteria"/>
</variables> </variables>

View file

@ -1,20 +1,18 @@
from risotto.utils import multi_function as _multi_function from risotto.utils import multi_function as _multi_function
from itertools import chain
@_multi_function
def mailman_emails(lists, domain): def mailman_emails(lists, domain):
ret = [] return '.*@' + domain
for lst in lists: # ret = []
for suffix in [None, 'bounces(\+.*)?', 'confirm(\+.*)?', 'join', 'leave', 'owner', 'request', 'subscribe', 'unsubscribe']: # for lst in lists:
if suffix: # for suffix in [None, 'bounces(\+.*)?', 'confirm(\+.*)?', 'join', 'leave', 'owner', 'request', 'subscribe', 'unsubscribe']:
lst_name = lst + '-' + suffix # if suffix:
else: # lst_name = lst + '-' + suffix
lst_name = lst # else:
ret.append(lst_name + '@' + domain) # lst_name = lst
return ret # ret.append(lst_name + '@' + domain)
# return ret
@_multi_function @_multi_function
def mailman_concat(lists): def mailman_concat(lists):
# list of lists to a single list return lists
return list(chain(*lists))

View file

@ -1,42 +1,31 @@
server { charset utf-8;
listen 443 ssl; client_max_body_size 75M;
server_name %%domain_name_eth0; location /mailman/postorius_static {
alias /usr/lib/python3.10/site-packages/postorius/static;
ssl_client_certificate %%revprox_ca_file; }
ssl_certificate %%revprox_cert_file; #FIXME user-profile seems to be in hyperkitty redirect in existing page
ssl_certificate_key %%revprox_key_file; location /mailman/user-profile {
proxy_pass http://127.0.0.1:8002/postorius/users;
charset utf-8; proxy_set_header Host $http_host;
client_max_body_size 75M; proxy_set_header X-Real-IP $remote_addr;
root /usr/share/webapps/postorius; proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
location /mailman/postorius_static { proxy_set_header X-Forwarded-Server $host;
alias /usr/lib/python3.10/site-packages/postorius/static; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} proxy_set_header X-Forwarded-Proto $scheme;
#FIXME user-profile seems to be in hyperkitty redirect in existing page }
location /mailman/user-profile { %for %%location in ['accounts', 'admin', 'postorius']
proxy_pass http://127.0.0.1:8002/postorius/users; location /mailman/%%location {
proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:8002/%%location;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} proxy_set_header X-Forwarded-Proto $scheme;
%for %%location in ['accounts', 'admin', 'postorius'] }
location /mailman/%%location { %end for
proxy_pass http://127.0.0.1:8002/%%location; location /mailman {
proxy_set_header Host $http_host; rewrite ^(/mailman/.*)$ /mailman/postorius/ permanent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
%end for
location /mailman {
rewrite ^(/mailman/.*)$ /mailman/postorius/ permanent;
}
} }

View file

@ -0,0 +1,12 @@
%set %%username="rougail_test@silique.fr"
ip: %%ip_eth0
revprox_ip: %%revprox_client_server_ip
%set %%domain = %%revprox_client_external_domainnames[0]
domain_name: %%domain
base_url: https://%%domain%%domain.revprox_client_location
auth_url: %%oauth2_client_external[0]
auth_server: %%oauth2_server_domainname
username: %%username
password: %%get_password(server_name='test', username=%%username, description='test', type="cleartext", hide=%%hide_secret, temporary=True)
mailman_domain: %%mailman_domains[0]
internal_address: %%domain_name_eth0

View file

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Postorius WSGI Service Description=Postorius WSGI Service
After=postgresqlclient.service After=risotto.target
[Service] [Service]
%for %%domain in %%mailman_domains %for %%domain in %%mailman_domains

View file

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Postorius WSGI Service Description=Postorius WSGI Service
After=network.target postgresqlclient.service After=risotto.target
[Service] [Service]
Type=notify Type=notify

View file

@ -0,0 +1,396 @@
from yaml import load, SafeLoader
from os import environ
from os.path import join, isdir
from revprox import Authentication
from execute import run
from re import search
from time import sleep
from imaplib2 import IMAP4_SSL
from smtplib import SMTP
from email import message_from_bytes
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
DATA = None
DATA_IMAP = None
IMAP = None
IMAP_FAMILY = None
def get_data():
global DATA
if not DATA:
conf_file = f'{environ["MACHINE_TEST_DIR"]}/mailman.yml'
with open(conf_file) as yaml:
DATA = load(yaml, Loader=SafeLoader)
return DATA
def get_imap_data():
global DATA_IMAP
if not DATA_IMAP:
machine_test_dir = environ['MACHINE_TEST_DIR']
print("FIXME")
machine_test_dir = machine_test_dir.replace('mailman', 'dovecot')
if not isdir(machine_test_dir):
print('!!! No local IMAP server found !!!')
return
conf_file = f'{machine_test_dir}/imap.yml'
with open(conf_file) as yaml:
DATA_IMAP = load(yaml, Loader=SafeLoader)
return DATA_IMAP
def get_authentication(data, family=False):
if family:
username = data['username_family']
password = data['password_family']
else:
username = data['username']
password = data['password']
return Authentication(data['auth_url'],
data['auth_server'],
data['revprox_ip'],
username,
password,
f"""<title>
Listes - {data["domain_name"]}
</title>""",
)
def check_mail(subject, family=False, reply=False):
global IMAP, IMAP_FAMILY
data = get_imap_data()
if data is None:
return
if family:
if IMAP_FAMILY is None:
IMAP_FAMILY = IMAP4_SSL(data['address'])
IMAP_FAMILY.LOGIN(data['username_family'], data['password_family'] + '2')
imap = IMAP_FAMILY
else:
if IMAP is None:
IMAP = IMAP4_SSL(data['address'])
IMAP.LOGIN(data['username'], data['password'])
imap = IMAP
imap.SELECT(readonly=False)
typ, req = imap.SEARCH(None, 'ALL')
assert typ == 'OK'
if not req[0].decode():
raise Exception('pas de mail')
num = req[0].decode().split()[-1]
field = imap.FETCH(num, '(RFC822)')
assert field[0] == 'OK'
msg = message_from_bytes(field[1][-2][-1])
#if msg.is_multipart():
# for part in msg.walk():
# # extract content type of email
# try:
# print(part.get_payload(decode=True).decode())
# except:
# pass
#else:
# print(msg.get_payload(decode=True).decode())
if subject is not None:
assert subject == msg['Subject']
if reply:
reply_message(msg)
ret = imap.store(num, '+FLAGS', '\\Deleted')
assert ret[0] == 'OK', f'error when deleting mail: {ret}'
imap.expunge()
# imap.CLOSE()
# imap.LOGOUT()
def reply_message(msg):
data = get_imap_data()
body = MIMEText('resend')
message = MIMEMultipart()
message["to"] = msg["From"]
message['from'] = msg["To"]
message['subject'] = f'Re: {msg["Subject"]}'
message.add_header('reply-to', msg["From"])
message.attach(body)
#
smtp = SMTP(data['address'], '587')
smtp.starttls()
smtp.login(data['username_family'], data['password_family'] + '2')
smtp.sendmail(msg["To"],
msg["From"],
message.as_string(),
)
smtp.quit()
def send_mail(subject, data, data_mm, family=False, add_mail=''):
list_name = 'test'
smtp = SMTP(data['address'], '587')
smtp.starttls()
if not family:
sender = data['username']
smtp.login(sender, data['password'])
else:
sender = data['username_family']
smtp.login(sender, data['password_family'] + '2')
list_addr = f'{list_name}{add_mail}@{data_mm["mailman_domain"]}'
msg = f"""From: {sender}\r\n\
To: {list_addr}\r\n\
Subject: {subject}\r\n\
\r\n\
MESSAGE"""
smtp.sendmail(sender,
list_addr,
msg,
)
smtp.quit()
def test_mailman():
data = get_data()
get_authentication(data)
def test_mailman_login():
data = get_data()
authentication = get_authentication(data)
content = authentication.get(data['auth_url'])
login = data['username'].split('@')[0]
assert f'Successfully signed in as {login}.' in content
def test_mailman_list():
data = get_data()
authentication = get_authentication(data)
list_name = 'test'
search_list = f'href="/mailman/postorius/lists/{list_name}.{data["mailman_domain"]}/"'
if 'FIRST_RUN' in environ:
content = authentication.get(data['auth_url'])
assert search_list not in content
result = run(data['internal_address'],
['/usr/bin/mailman3', 'create', '--language', 'fr', '-o', data['username'], '-N', '-d', f'{list_name}@{data["mailman_domain"]}'],
'mailman',
)
assert list(result) == [f'Liste de diffusion créée : {list_name}@{data["mailman_domain"]}']
content = authentication.get(data['auth_url'])
assert search_list in content
def test_mailman_inscription():
data = get_data()
authentication = get_authentication(data)
list_name = 'test'
search_inscription = f'<td>Adresse principale ({data["username"]})</td>'
url = join(data['base_url'], f'postorius/lists/{list_name}.{data["mailman_domain"]}/')
if 'FIRST_RUN' in environ:
content = authentication.get(url)
assert search_inscription not in content
pattern_csrf = r'name="csrfmiddlewaretoken" value="([a-zA-Z0-9\-\_=]+)"'
pattern_sub = r'<option value="([a-zA-Z0-9\-\_=]+)">Adresse principale'
csrf = search(pattern_csrf, content)[1]
subscriber = search(pattern_sub, content)[1]
headers = {'Referer': url}
authentication.post(url + 'subscribe', {'csrfmiddlewaretoken': csrf, 'subscriber': subscriber, 'delivery_mode': 'regular', 'display_name': ''}, headers=headers)
subject = f'=?utf-8?q?Bienvenue_sur_la_liste_de_diffusion_=22{list_name.capitalize()}=22?='
idx = 0
while True:
try:
check_mail(subject)
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived')
sleep(1)
content = authentication.get(url)
assert search_inscription in content
def test_send_mail():
data = get_imap_data()
if data is None:
return
data_mm = get_data()
subject = 'TEST MAILMAN'
send_mail(subject, data, data_mm)
idx = 0
while True:
try:
check_mail("=?utf-8?b?W1Rlc3Rd?= TEST MAILMAN")
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived')
sleep(1)
def test_send_wrong_mail():
data = get_imap_data()
if data is None:
return
data_mm = get_data()
url = f'{data_mm["base_url"]}postorius/lists/test.{data_mm["mailman_domain"]}/held_messages'
# no moderated mail
authentication = get_authentication(data_mm)
content = authentication.get(url)
subject = 'TEST MAILMAN'
assert subject not in content
# send mail
smtp = SMTP(data['address'], '587')
smtp.starttls()
smtp.login(data['username_family'], data['password_family'] + '2')
list_name = 'test'
list_addr = f'{list_name}@{data_mm["mailman_domain"]}'
msg = f"""From: {data["username_family"]}\r\n\
To: {list_addr}\r\n\
Subject: {subject}\r\n\
\r\n\
MESSAGE"""
smtp.sendmail(data['username_family'], list_addr, msg)
smtp.quit()
idx = 0
mailman_domain = data_mm['mailman_domain'].replace('.', '=2E')
while True:
try:
check_mail(f'=?utf-8?q?Votre_message_=C3=A0_test=40{mailman_domain}_attend_la_validation_d=27un_mod=C3=A9rateur?=', family=True)
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived...')
sleep(1)
#
mail = data['username_family'].replace('@', '=40').replace('.', '=2E').replace('_', '=5F')
while True:
try:
check_mail(f'=?utf-8?q?Le_message_test=40{mailman_domain}_de_{mail}_n=C3=A9cessite_une_validation?=')
break
except:
idx += 1
if idx == 10:
raise Exception('mail 2 not arrived...')
sleep(1)
# reject mail
content = authentication.get(url)
assert subject in content
pattern_csrf = r'name="csrfmiddlewaretoken" value="([a-zA-Z0-9\-\_=]+)"'
csrf = search(pattern_csrf, content)[1]
pattern_msg_id = r'class="message-checkbox" name="choices" value="([a-zA-Z0-9\-\_=]+)"'
msg_id = search(pattern_msg_id, content)[1]
#
headers = {'Referer': url}
authentication.post(url, {'csrfmiddlewaretoken': csrf, 'reject': 'Rejeter', 'choices': msg_id}, headers=headers)
content = authentication.get(url)
assert subject not in content
while True:
try:
check_mail('=?utf-8?q?Requ=C3=AAte_pour_la_liste_de_diffusion_=22Test=22_rejet=C3=A9e?=', family=True)
break
except:
idx += 1
if idx == 10:
raise Exception('mail reject not arrived...')
sleep(1)
def test_mailman_create_delete():
data = get_data()
authentication = get_authentication(data)
list_name = 'test_tmp'
search_list = f'href="/mailman/postorius/lists/{list_name}.{data["mailman_domain"]}/"'
#
content = authentication.get(data['auth_url'])
assert search_list not in content
#
result = run(data['internal_address'],
['/usr/bin/mailman3', 'create', '--language', 'fr', '-o', data['username'], '-N', '-d', f'{list_name}@{data["mailman_domain"]}'],
'mailman',
)
assert list(result) == [f'Liste de diffusion créée : {list_name}@{data["mailman_domain"]}']
content = authentication.get(data['auth_url'])
assert search_list in content
#
result = run(data['internal_address'],
['/usr/bin/mailman3', 'remove', f'{list_name}@{data["mailman_domain"]}'],
'mailman',
)
assert list(result) == [f'Liste supprimée : {list_name}@{data["mailman_domain"]}']
content = authentication.get(data['auth_url'])
assert search_list not in content
def test_mailman_inscription_desinscription_mail():
list_name = 'test'
data = get_imap_data()
if data is None:
return
data_mm = get_data()
send_mail('subscribe', data, data_mm, family=True, add_mail='-join')
idx = 0
# inscription + validation
mailman_domain = data_mm['mailman_domain'].replace('.', '=2E')
while True:
try:
check_mail(f'=?utf-8?q?Votre_validation_est_n=C3=A9cessaire_pour_vous_abonner_de_la_liste_de_diffusion_test=40{mailman_domain}?=', family=True, reply=True)
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived...')
sleep(1)
idx = 0
while True:
try:
check_mail(f'=?utf-8?q?Bienvenue_sur_la_liste_de_diffusion_=22{list_name.capitalize()}=22?=', family=True)
break
except:
idx += 1
if idx == 10:
raise Exception('confirmation not arrived...')
sleep(1)
# send mail and check
subject = 'TEST MAILMAN'
send_mail(subject, data, data_mm)
idx = 0
while True:
try:
check_mail("=?utf-8?b?W1Rlc3Rd?= TEST MAILMAN")
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived')
sleep(1)
while True:
try:
check_mail("=?utf-8?b?W1Rlc3Rd?= TEST MAILMAN", family=True)
break
except:
idx += 1
if idx == 10:
raise Exception('mail not arrived')
sleep(1)
# unsubscribe
send_mail('unsubscribe', data, data_mm, family=True, add_mail="-leave")
idx = 0
while True:
try:
check_mail(f'=?utf-8?q?Votre_validation_est_n=C3=A9cessaire_pour_vous_d=C3=A9sabonner_de_la_liste_de_diffusion_test=40{mailman_domain}?=', family=True, reply=True)
break
except:
idx += 1
if idx == 10:
raise Exception('unsubscribe not arrived...')
sleep(1)
idx = 0
while True:
try:
check_mail(f'=?utf-8?q?Vous_avez_=C3=A9t=C3=A9_d=C3=A9sinscrits_de_la_liste_de_diffusion_Test?=', family=True)
break
except:
idx += 1
if idx == 10:
raise Exception('unsubscribe confirmation not arrived...')
sleep(1)

View file

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10"> <rougail version="0.10">
<services> <services>
<service name="mariadbclient" target="multi-user" engine="creole"/> <service name="mariadbclient" target="risotto" engine="creole"/>
</services> </services>
<variables> <variables>
<family name="mariadb" description="MariaDB"> <family name="mariadb" description="MariaDB">

View file

@ -1,6 +1,7 @@
[Unit] [Unit]
Description=Waiting for mariadb server Description=Waiting for mariadb server
Before=network.target After=network-online.target
Before=risotto.target
[Service] [Service]
Type=oneshot Type=oneshot

View file

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Nextcloud management Description=Nextcloud management
After=postgresqlclient.service After=risotto.target
Before=apache.service php-fpm.service Before=apache.service php-fpm.service
[Service] [Service]

View file

@ -13,6 +13,7 @@
<file file_type="variable" source="ca_InternalReverseProxy.crt">revprox_ca_file</file> <file file_type="variable" source="ca_InternalReverseProxy.crt">revprox_ca_file</file>
<file filelist="nginx_default_https" mode="600">/etc/pki/tls/certs/nginx.crt</file> <file filelist="nginx_default_https" mode="600">/etc/pki/tls/certs/nginx.crt</file>
<file filelist="nginx_default_https" mode="600">/etc/pki/tls/private/nginx.key</file> <file filelist="nginx_default_https" mode="600">/etc/pki/tls/private/nginx.key</file>
<file>/tests/nginx-common.yml</file>
</service> </service>
</services> </services>
<variables> <variables>

View file

@ -0,0 +1,13 @@
address: %%ip_eth0
nginx_default_http: %slurp
%if %%getVar('nginx_default_http', False) and not %%getVar('revprox_client_external_domainnames', None)
true
%else
false
%end if
nginx_default_https: %slurp
%if %%getVar('nginx_default_https', False) and not %%getVar('revprox_client_external_domainnames', None)
true
%else
false
%end if

View file

@ -76,14 +76,24 @@ http {
%if %%nginx_default_https %if %%nginx_default_https
server { server {
listen 443 ssl http2; listen 443 ssl http2;
server_name %%domain_name_eth0; %if %%getVar('revprox_client_external_domainnames', None)
%for %%domain in %%revprox_client_external_domainnames
server_name %%domain;
%end for
%else
server_name _;
%end if
root %%nginx_root; root %%nginx_root;
# ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_certificate_key "/etc/pki/nginx/private/server.key";
ssl_certificate /etc/pki/tls/certs/nginx.crt; ssl_certificate /etc/pki/tls/certs/nginx.crt;
ssl_certificate_key /etc/pki/tls/private/nginx.key; ssl_certificate_key /etc/pki/tls/private/nginx.key;
ssl_client_certificate /etc/pki/ca-trust/source/anchors/ca_InternalReverseProxy.crt; %if %%getVar('revprox_client_external_domainnames', None)
ssl_client_certificate %%revprox_ca_file;
%else
ssl_client_certificate /etc/pki/ca-trust/source/anchors/ca_HTTP.crt;
%end if
ssl_session_cache shared:SSL:1m; ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m; ssl_session_timeout 10m;
@ -105,5 +115,7 @@ http {
%else %else
include /etc/nginx/sites-enabled/*; include /etc/nginx/sites-enabled/*;
%end if %end if
%if not %%getVar('revprox_client_external_domainnames', None)
include /etc/nginx/sites-enabled/*;
%end if
} }

View file

@ -0,0 +1,50 @@
from yaml import load, SafeLoader
from os import environ
from pytest import raises
import warnings
import socket
from requests import get
from requests.exceptions import SSLError
def req(url, ip, verify=True):
# Monkey patch to force IPv4 resolution
old_getaddrinfo = socket.getaddrinfo
def new_getaddrinfo(*args, **kwargs):
ret = old_getaddrinfo(*args, **kwargs)
dns = list(ret[0])
dns[-1] = (ip, dns[-1][1])
return [dns]
socket.getaddrinfo = new_getaddrinfo
if not verify:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
ret = get(url, verify=verify)
else:
ret = get(url, verify=verify)
ret_code = ret.status_code
content = ret.content
socket.getaddrinfo = old_getaddrinfo
return ret_code, content.decode()
def test_revprox():
conf_file = f'{environ["MACHINE_TEST_DIR"]}/nginx-common.yml'
with open(conf_file) as yaml:
data = load(yaml, Loader=SafeLoader)
# test unknown domain
url = 'google.fr'
protocols = []
if data['nginx_default_http']:
protocols.append('http')
if data['nginx_default_https']:
protocols.append('https')
# test certificate
with raises(SSLError):
# not certificat problem for https://{url}
req(f'https://{url}', data['address'])
for protocol in protocols:
ret_code, content = req(f'{protocol}://{url}', data['address'], verify=False)
assert ret_code == 200, f'{protocol}://{url} do not returns code 200 but {ret_code}'
assert "<title>Test Page for the HTTP Server on Fedora</title>" in content, f'{protocol}://{url} do not returns default fedora page'

View file

@ -1,22 +1,16 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10"> <rougail version="0.10">
<services>
<service name='nginx'>
<file filelist="nginx_default_risotto">/etc/nginx/default.d/risotto.conf</file>
</service>
</services>
<variables> <variables>
<family name="nginx"> <family name="nginx">
<variable name="nginx_default_https" redefine="True"> <variable name="nginx_default_http" redefine="True" hidden="True">
<value>False</value>
</variable>
<variable name="nginx_default_https" redefine="True" hidden="True">
<value>True</value> <value>True</value>
</variable> </variable>
<variable name="php_fpm_user" redefine="True" exists="True"> <variable name="php_fpm_user" redefine="True" exists="True">
<value>nginx</value> <value>nginx</value>
</variable> </variable>
<variable name="nginx_root_directory" type="filename"/>
<variable name="nginx_locations" type="filename" multi="True" mandatory="True">
<value>/</value>
</variable>
</family> </family>
<family name="redis" description="Redis"> <family name="redis" description="Redis">
<variable name="redis_client_key_owner" redefine="True" exists="True"> <variable name="redis_client_key_owner" redefine="True" exists="True">
@ -29,11 +23,4 @@
</variable> </variable>
</family> </family>
</variables> </variables>
<constraints>
<condition name="disabled_if_in" source="nginx_root_directory">
<param type="nil"/>
<target type="filelist">nginx_default_risotto</target>
<target type="variable">nginx_locations</target>
</condition>
</constraints>
</rougail> </rougail>

View file

@ -0,0 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<services>
<service name='nginx'>
<file>/etc/pki/ca-trust/source/anchors/ca_HTTP.crt</file>
</service>
</services>
</rougail>

View file

@ -4,7 +4,7 @@
<service name='nginx'> <service name='nginx'>
<override engine="creole"/> <override engine="creole"/>
<file source="nginx-options-rp.conf">/etc/nginx/conf.d/options-rp.conf</file> <file source="nginx-options-rp.conf">/etc/nginx/conf.d/options-rp.conf</file>
<file source="revprox-nginx.conf">/etc/nginx/conf.d/risotto.conf</file> <file source="revprox-nginx.conf">/etc/nginx/sites-enabled/risotto.conf</file>
<file source="certificate.crt" file_type="variable" mode="600" variable="nginx.revprox_domainnames">nginx.nginx_certificate_filename</file> <file source="certificate.crt" file_type="variable" mode="600" variable="nginx.revprox_domainnames">nginx.nginx_certificate_filename</file>
<file source="private.key" file_type="variable" mode="600" variable="nginx.revprox_domainnames">nginx.nginx_private_key_filename</file> <file source="private.key" file_type="variable" mode="600" variable="nginx.revprox_domainnames">nginx.nginx_private_key_filename</file>
<file>/tests/reverse-proxy.yml</file> <file>/tests/reverse-proxy.yml</file>
@ -22,6 +22,9 @@
<variable name="nginx_default_http" redefine="True"> <variable name="nginx_default_http" redefine="True">
<value>True</value> <value>True</value>
</variable> </variable>
<variable name="nginx_default_https" redefine="True">
<value>True</value>
</variable>
</family> </family>
</variables> </variables>
</rougail> </rougail>

View file

@ -0,0 +1,3 @@
%for %%idx in %%range(%%len(%%zones_list))
%%get_chain(authority_cn=%%getVar('domain_name_eth' + %%str(%%idx)), authority_name="HTTP", hide=%%hide_secret)
%end for

View file

@ -0,0 +1,2 @@
%%get_certificate(%%nginx_default, authority_cn=%%domain_name_eth0, authority_name='HTTP', type="server", hide=%%hide_secret)
%%get_chain(%%nginx_default, 'HTTP', hide=%%hide_secret)

View file

@ -0,0 +1 @@
%%get_private_key(%%nginx_default, authority_cn=%%domain_name_eth0, authority_name='HTTP', type='server', hide=%%hide_secret)

View file

@ -41,7 +41,7 @@ server {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Destination $dest; proxy_set_header Destination $dest;
%end if %end if
proxy_ssl_trusted_certificate /etc/pki/ca-trust/source/anchors/ca_InternalReverseProxy.crt; proxy_ssl_trusted_certificate %%revprox_ca_file;
proxy_ssl_verify on; proxy_ssl_verify on;
proxy_ssl_verify_depth 2; proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse on; proxy_ssl_session_reuse on;

View file

@ -32,19 +32,8 @@ def test_revprox():
conf_file = f'{environ["MACHINE_TEST_DIR"]}/reverse-proxy.yml' conf_file = f'{environ["MACHINE_TEST_DIR"]}/reverse-proxy.yml'
with open(conf_file) as yaml: with open(conf_file) as yaml:
data = load(yaml, Loader=SafeLoader) data = load(yaml, Loader=SafeLoader)
# test unknown domain
url = 'google.fr'
ret_code, content = req(f'https://{url}', data['address'], verify=False)
assert ret_code == 200, f'https://{url} do not returns code 200 but {ret_code}'
assert "<title>Test Page for the HTTP Server on Fedora</title>" in content, f'https://{url} returns default fedora page'
# test certificate
try:
req(f'https://{url}', data['address'])
raise Exception(f'not certificat problem for https://{url}')
except SSLError:
pass
# test known domains # test known domains
for url in data['urls']: for url in data['urls']:
ret_code, content = req(f'https://{url}', data['address']) ret_code, content = req(f'https://{url}', data['address'])
assert ret_code == 200, f'https://{url} do not returns code 200 but {ret_code}' assert ret_code == 200, f'https://{url} do not returns code 200 but {ret_code}'
assert "<title>Test Page for the HTTP Server on Fedora</title>" not in content, f'https://{url} returns default fedora page' assert "<title>Test Page for the HTTP Server on Fedora</title>" not in content, f'https://{url} do returns default fedora page'

View file

@ -1,2 +1,2 @@
[Unit] [Unit]
After=network.target After=risotto.target

View file

@ -1,5 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10"> <rougail version="0.10">
<services>
<service name="oauth2-client" target="risotto" engine="creole"/>
</services>
<variables> <variables>
<family name="oauth2_client" description="OAuth2 client"> <family name="oauth2_client" description="OAuth2 client">
<variable name="oauth2_client_server_domainname" type="domainname" description="OAuth2 server domain name" mandatory='True' supplier="OAuth2"/> <variable name="oauth2_client_server_domainname" type="domainname" description="OAuth2 server domain name" mandatory='True' supplier="OAuth2"/>

View file

@ -0,0 +1 @@
PKG="$PKG curl"

View file

@ -0,0 +1,7 @@
[Unit]
After=network-online.target
Before=risotto.target
[Service]
Type=oneshot
ExecStart=/usr/bin/timeout 90 bash -c 'while ! [ "$(/usr/bin/curl --write-out '%{http_code}' --silent --output /dev/null https://%%oauth2_client_server_domainname/.well-known/openid-configuration)" = 200 ]; do sleep 1; done;'

View file

@ -7,5 +7,5 @@ depends:
- relay-mail-client - relay-mail-client
- reverse-proxy-client - reverse-proxy-client
- redis-client - redis-client
- nginx-common - nginx-https
- oauth2-client - oauth2-client

View file

@ -6,7 +6,8 @@
<file engine="none" source="sysuser-peertube.conf">/sysusers.d/0peertube.conf</file> <file engine="none" source="sysuser-peertube.conf">/sysusers.d/0peertube.conf</file>
<file engine="none" source="tmpfile-peertube.conf">/tmpfiles.d/0peertube.conf</file> <file engine="none" source="tmpfile-peertube.conf">/tmpfiles.d/0peertube.conf</file>
<file>/etc/peertube/production.yaml</file> <file>/etc/peertube/production.yaml</file>
<file source="nginx.peertube.conf">/etc/nginx/conf.d/peertube.conf</file> <file source="nginx.peertube.conf">/etc/nginx/default.d/peertube.conf</file>
<file source="nginx.peertube.conf.d.conf">/etc/nginx/conf.d/peertube.conf</file>
</service> </service>
</services> </services>
<variables> <variables>
@ -45,6 +46,9 @@
</family> </family>
</family> </family>
<family name="nginx"> <family name="nginx">
<variable name="nginx_root" redefine='True'>
<value>/usr/share/peertube</value>
</variable>
<family name="revprox_client"> <family name="revprox_client">
<variable name="revprox_client_location" redefine="True"> <variable name="revprox_client_location" redefine="True">
<value>/</value> <value>/</value>

View file

@ -16,15 +16,14 @@
# GNUNUX location / { return 301 https://$host$request_uri; } # GNUNUX location / { return 301 https://$host$request_uri; }
# GNUNUX } # GNUNUX }
upstream %%domain_name_eth0 { # GNUNUX upstream %%domain_name_eth0 {
# GNUNUX server ${PEERTUBE_HOST}; # GNUNUX server ${PEERTUBE_HOST};
server localhost:9000; # GNUNUX }
}
server { # GNUNUX server {
listen 443 ssl http2; # GNUNUX listen 443 ssl http2;
listen [::]:443 ssl http2; # GNUNUX listen [::]:443 ssl http2;
server_name %%domain_name_eth0; # GNUNUX server_name %%domain_name_eth0;
# GNUNUX access_log /var/log/nginx/peertube.access.log; # reduce I/0 with buffer=10m flush=5m # GNUNUX access_log /var/log/nginx/peertube.access.log; # reduce I/0 with buffer=10m flush=5m
# GNUNUX error_log /var/log/nginx/peertube.error.log; # GNUNUX error_log /var/log/nginx/peertube.error.log;
@ -35,11 +34,6 @@ server {
## ##
# GNUNUX ssl_certificate /etc/letsencrypt/live/${WEBSERVER_HOST}/fullchain.pem; # GNUNUX ssl_certificate /etc/letsencrypt/live/${WEBSERVER_HOST}/fullchain.pem;
# GNUNUX ssl_certificate_key /etc/letsencrypt/live/${WEBSERVER_HOST}/privkey.pem; # GNUNUX ssl_certificate_key /etc/letsencrypt/live/${WEBSERVER_HOST}/privkey.pem;
#>GNUNUX
ssl_client_certificate %%revprox_ca_file;
ssl_certificate %%revprox_cert_file;
ssl_certificate_key %%revprox_key_file;
#<GNUNUX
# GNUNUX location ^~ '/.well-known/acme-challenge' { # GNUNUX location ^~ '/.well-known/acme-challenge' {
# GNUNUX default_type "text/plain"; # GNUNUX default_type "text/plain";
@ -51,14 +45,14 @@ server {
# based on Mozilla Guideline v5.6 # based on Mozilla Guideline v5.6
## ##
ssl_protocols TLSv1.2 TLSv1.3; # GNUNUX ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on; # GNUNUX ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; # add ECDHE-RSA-AES256-SHA if you want compatibility with Android 4 # GNUNUX ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; # add ECDHE-RSA-AES256-SHA if you want compatibility with Android 4
ssl_session_timeout 1d; # defaults to 5m # GNUNUX ssl_session_timeout 1d; # defaults to 5m
ssl_session_cache shared:SSL:10m; # estimated to 40k sessions # GNUNUX ssl_session_cache shared:SSL:10m; # estimated to 40k sessions
ssl_session_tickets off; # GNUNUX ssl_session_tickets off;
ssl_stapling on; # GNUNUX ssl_stapling on;
ssl_stapling_verify on; # GNUNUX ssl_stapling_verify on;
# HSTS (https://hstspreload.org), requires to be copied in 'location' sections that have add_header directives # HSTS (https://hstspreload.org), requires to be copied in 'location' sections that have add_header directives
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; #add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
@ -145,7 +139,6 @@ server {
## ##
# GNUNUX root /var/www/peertube/storage; # GNUNUX root /var/www/peertube/storage;
root /usr/share/peertube;
# Enable compression for JS/CSS/HTML, for improved client load times. # Enable compression for JS/CSS/HTML, for improved client load times.
# It might be nice to compress JSON/XML as returned by the API, but # It might be nice to compress JSON/XML as returned by the API, but
@ -268,4 +261,4 @@ server {
try_files $uri @api; try_files $uri @api;
} }
} # GNUNUX }

View file

@ -0,0 +1,4 @@
upstream %%domain_name_eth0 {
# GNUNUX server ${PEERTUBE_HOST};
server localhost:9000;
}

View file

@ -7,16 +7,13 @@
<file>/etc/piwigo/database.inc.php</file> <file>/etc/piwigo/database.inc.php</file>
<file mode="755">/sbin/piwigo.sh</file> <file mode="755">/sbin/piwigo.sh</file>
<file engine="none">/etc/php-fpm.d/piwigo.conf</file> <file engine="none">/etc/php-fpm.d/piwigo.conf</file>
<file source="piwigo.nginx.conf">/etc/nginx/default.d/piwigo.conf</file>
</service> </service>
</services> </services>
<variables> <variables>
<variable name="piwigo_admin_email" type="mail" description="Adresse courriel de l'administrateur Piwigo" mandatory="True"/> <variable name="piwigo_admin_email" type="mail" description="Adresse courriel de l'administrateur Piwigo" mandatory="True"/>
<variable name="piwigo_admin_password" type="password" auto_save="False" hidden="True"/> <variable name="piwigo_admin_password" type="password" auto_save="False" hidden="True"/>
<family name="nginx"> <variable name="piwigo_locations" type="filename" multi="True" mandatory="True"/>
<variable name="nginx_root_directory" mandatory="True" redefine="True">
<value>/usr/local/share/piwigo</value>
</variable>
</family>
<variable name="piwigo_title" type="string" description="Titre de l'album" mandatory="True"> <variable name="piwigo_title" type="string" description="Titre de l'album" mandatory="True">
<value>Album photographique</value> <value>Album photographique</value>
</variable> </variable>
@ -53,7 +50,7 @@
</fill> </fill>
<fill name="get_locations"> <fill name="get_locations">
<param name="usernames" type="variable">piwigo_users</param> <param name="usernames" type="variable">piwigo_users</param>
<target>nginx_locations</target> <target>piwigo_locations</target>
</fill> </fill>
</constraints> </constraints>
</rougail> </rougail>

View file

@ -1,3 +1,5 @@
# To allow POST on static pages
error_page 405 =200 $uri;
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options nosniff; add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block"; add_header X-XSS-Protection "1; mode=block";
@ -7,17 +9,14 @@ add_header X-Permitted-Cross-Domain-Policies none;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;'; add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';
add_header Referrer-Policy no-referrer always; add_header Referrer-Policy no-referrer always;
%for %%location in %%nginx_locations %for %%location in %%piwigo_locations
location %%location { location %%location {
%if %%location == '/' %if %%location == '/'
root %slurp root %slurp
%else %else
alias %slurp alias %slurp
%end if %end if
%%nginx_root_directory; /usr/local/share/piwigo;
%if not %%getVar('php_fpm_installed', False)
index index.html;
%else
index index.php; index index.php;
location ~ ^(?<script_name>.+?\.php)(?<path_info>/.*)?$ { location ~ ^(?<script_name>.+?\.php)(?<path_info>/.*)?$ {
fastcgi_pass php-fpm; fastcgi_pass php-fpm;
@ -25,6 +24,5 @@ location %%location {
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params; include fastcgi_params;
} }
%end if
} }
%end for %end for

View file

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Piwigo management Description=Piwigo management
After=mariadbclient.service After=risotto.target
Before=nginx.service php-fpm.service Before=nginx.service php-fpm.service
[Service] [Service]

View file

@ -7,7 +7,7 @@
<file engine="none" source="tmpfile-peertube.conf">/tmpfiles.d/0peertube.conf</file> <file engine="none" source="tmpfile-peertube.conf">/tmpfiles.d/0peertube.conf</file>
<file>/etc/peertube/production.yaml</file> <file>/etc/peertube/production.yaml</file>
<file engine="none">/etc/pam.d/login</file> <file engine="none">/etc/pam.d/login</file>
<file source="nginx.peertube.conf">/etc/nginx/conf.d/peertube.conf</file> <file source="nginx.peertube.conf">/etc/nginx/sites-enabled/peertube.conf</file>
</service> </service>
</services> </services>
<variables> <variables>

View file

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10"> <rougail version="0.10">
<services> <services>
<service name="postgresqlclient" target="multi-user" engine="creole"> <service name="postgresqlclient" target="risotto" engine="creole">
<file mode="400">/secrets/postgresql.pass</file> <file mode="400">/secrets/postgresql.pass</file>
<file>/etc/pki/ca-trust/source/anchors/ca_PostgreSQL.crt</file> <file>/etc/pki/ca-trust/source/anchors/ca_PostgreSQL.crt</file>
<file>/etc/pki/tls/certs/postgresql.crt</file> <file>/etc/pki/tls/certs/postgresql.crt</file>

View file

@ -1,6 +1,7 @@
[Unit] [Unit]
Description=Waiting for postgresql server Description=Waiting for postgresql server
Before=network.target After=network-online.target
Before=risotto.target
[Service] [Service]
Type=oneshot Type=oneshot

1
seed/postgresql/DEBUG.md Normal file
View file

@ -0,0 +1 @@
pg_dumpall --clean > /srv/database.sql

View file

@ -33,7 +33,7 @@ class Authentication:
ret = req.get(url) ret = req.get(url)
code = ret.status_code code = ret.status_code
content = ret.content content = ret.content
assert code == 200 assert code == 200, f"cannot access to lemonldap; {content}"
assert b'<title trspan="authPortal">Authentication portal</title>' in content, f'cannot find LemonLdap title: {content}' assert b'<title trspan="authPortal">Authentication portal</title>' in content, f'cannot find LemonLdap title: {content}'
def auth_lemonldap(self, def auth_lemonldap(self,
@ -62,7 +62,8 @@ class Authentication:
authorize_url = f'{portal_url}authorize' authorize_url = f'{portal_url}authorize'
ret = req.get(authorize_url) ret = req.get(authorize_url)
assert ret.status_code == 200 assert ret.status_code == 200
assert title in ret.content.decode() content = ret.content.decode()
assert title in content, f'cannot find {title} in {content}'
def get(self, def get(self,
url, url,
@ -78,7 +79,8 @@ class Authentication:
def post(self, def post(self,
url, url,
data, data,
headers=None,
): ):
with MookDns(self.ip): with MookDns(self.ip):
ret = post(url, cookies=self.cookies, data=data) ret = post(url, cookies=self.cookies, data=data, headers=headers)
assert ret.status_code == 200, f'return code is {ret.status_code}' assert ret.status_code == 200, f'return code is {ret.status_code}'

View file

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Roundcube database init Description=Roundcube database init
After=postgresqlclient.service After=risotto.target
Before=nginx.service php-fpm.service Before=nginx.service php-fpm.service
[Service] [Service]

View file

@ -29,6 +29,7 @@
<file>/secrets/root.pwd</file> <file>/secrets/root.pwd</file>
<file engine="none">/tmpfiles.d/risotto-volatile.conf</file> <file engine="none">/tmpfiles.d/risotto-volatile.conf</file>
</service> </service>
<service name="risotto" target="multi-user" type="target" engine="none"/>
</services> </services>
<variables> <variables>
<variable name='root_password' type="password" description="Mot de passe de l'administrateur système root" auto_save='False' mandatory="True"/> <variable name='root_password' type="password" description="Mot de passe de l'administrateur système root" auto_save='False' mandatory="True"/>

View file

@ -0,0 +1,5 @@
[Unit]
Description=Waiting for all dependencies
Before=multi-user.target
After=network-online.target
Wants=network-online.target