From e631a1dffcca0a256337f05b44a73932b39bf9af Mon Sep 17 00:00:00 2001 From: Jean-Philippe Pialasse Date: Thu, 13 Feb 2025 01:05:14 -0500 Subject: [PATCH] * Wed Feb 12 2025 Jean-Philippe Pialasse 11.0-2.sme - move smanager panel in package [SME: 12916] - add Requires - add templates from smeserver-letsencrypt - use /var/www/html/.well-known/acme-challenge --- createlinks | 65 +- .../dehydrated.action | 1 + .../defaults/letsencrypt/configure | 1 + .../defaults/letsencrypt/hookScript | 1 + .../configuration/defaults/letsencrypt/status | 1 + .../configuration/defaults/letsencrypt/type | 1 + .../events/actions/letsencrypt-setdomains | 4 +- .../templates.metadata/etc/cron.d/dehydrated | 1 + .../templates.metadata/usr/bin/hook-script.sh | 1 + .../etc/cron.d/dehydrated/10dehydrated | 20 + .../templates/etc/dehydrated/config/01notice | 13 + .../etc/dehydrated/config/02variables | 5 + .../etc/dehydrated/config/05usergroup | 6 + .../templates/etc/dehydrated/config/10Default | 90 +++ .../etc/dehydrated/config/10IPVersion | 5 + .../templates/etc/dehydrated/config/15CA | 36 ++ .../templates/etc/dehydrated/config/16OLDCA | 7 + .../etc/dehydrated/config/20ACCEPT_TERMS | 11 + .../etc/dehydrated/config/20challenge | 3 + .../etc/dehydrated/config/25directories | 29 + .../templates/etc/dehydrated/config/30KEYSIZE | 3 + .../etc/dehydrated/config/30KEY_ALGO | 3 + .../templates/etc/dehydrated/config/35days | 3 + .../templates/etc/dehydrated/config/36openssl | 8 + .../etc/dehydrated/config/40curlextra | 3 + .../etc/dehydrated/config/42PrivateKey | 6 + .../etc/dehydrated/config/45Algorithm | 3 + .../templates/etc/dehydrated/config/47hook | 15 + .../templates/etc/dehydrated/config/50email | 3 + .../etc/dehydrated/config/60lockfile | 3 + .../templates/etc/dehydrated/config/65OCSP | 9 + .../templates/etc/dehydrated/config/70chain | 3 + .../templates/etc/dehydrated/config/75cleanup | 3 + .../templates/etc/dehydrated/config/80API | 3 + .../etc/dehydrated/config/85ACCEPT_TERMS | 5 + .../etc/dehydrated/config/template-begin | 0 .../etc/dehydrated/domains.txt/10Domains | 133 ++++ .../etc/dehydrated/domains.txt/template-begin | 0 .../80-koozali-dehydrated-timer.preset | 12 + .../usr/bin/hook-script.sh/10deploy_cert | 54 ++ .../usr/bin/hook-script.sh/20challenges | 76 +++ .../usr/bin/hook-script.sh/template-begin | 17 + .../SrvMngr/Controller/Letsencrypt-Custom.pm | 566 ++++++++++++++++++ .../lib/SrvMngr/Controller/Letsencrypt.pm | 448 ++++++++++++++ .../SrvMngr/I18N/Modules/Letsencrypt/en.pm | 72 +++ .../Modules/Letsencrypt/letsencrypt_en.lex | 55 ++ .../themes/default/public/css/letsencrypt.css | 90 +++ .../default/templates/letsencrypt.html.ep | 69 +++ .../partials/_lets_CHECKALLDOMAINS.html.ep | 45 ++ .../_lets_CHECKALLENABLEDDOMAINS.html.ep | 45 ++ .../partials/_lets_CHECKONEDOMAIN.html.ep | 52 ++ .../templates/partials/_lets_LIST.html.ep | 126 ++++ .../templates/partials/_lets_PARAMS.html.ep | 97 +++ smeserver-certificates.spec | 16 +- 54 files changed, 2327 insertions(+), 20 deletions(-) create mode 100644 root/etc/dnf/plugins/post-transaction-actions.d/dehydrated.action create mode 100644 root/etc/e-smith/db/configuration/defaults/letsencrypt/configure create mode 100644 root/etc/e-smith/db/configuration/defaults/letsencrypt/hookScript create mode 100644 root/etc/e-smith/db/configuration/defaults/letsencrypt/status create mode 100644 root/etc/e-smith/db/configuration/defaults/letsencrypt/type create mode 100644 root/etc/e-smith/templates.metadata/etc/cron.d/dehydrated create mode 100644 root/etc/e-smith/templates.metadata/usr/bin/hook-script.sh create mode 100644 root/etc/e-smith/templates/etc/cron.d/dehydrated/10dehydrated create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/01notice create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/02variables create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/05usergroup create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/10Default create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/10IPVersion create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/15CA create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/16OLDCA create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/20ACCEPT_TERMS create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/20challenge create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/25directories create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/30KEYSIZE create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/30KEY_ALGO create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/35days create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/36openssl create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/40curlextra create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/42PrivateKey create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/45Algorithm create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/47hook create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/50email create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/60lockfile create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/65OCSP create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/70chain create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/75cleanup create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/80API create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/85ACCEPT_TERMS create mode 100644 root/etc/e-smith/templates/etc/dehydrated/config/template-begin create mode 100644 root/etc/e-smith/templates/etc/dehydrated/domains.txt/10Domains create mode 100644 root/etc/e-smith/templates/etc/dehydrated/domains.txt/template-begin create mode 100644 root/etc/e-smith/templates/etc/systemd/system-preset/49-koozali.preset/80-koozali-dehydrated-timer.preset create mode 100644 root/etc/e-smith/templates/usr/bin/hook-script.sh/10deploy_cert create mode 100644 root/etc/e-smith/templates/usr/bin/hook-script.sh/20challenges create mode 100644 root/etc/e-smith/templates/usr/bin/hook-script.sh/template-begin create mode 100644 root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm create mode 100644 root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm create mode 100644 root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm create mode 100644 root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex create mode 100644 root/usr/share/smanager/themes/default/public/css/letsencrypt.css create mode 100644 root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep create mode 100644 root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep create mode 100644 root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep create mode 100644 root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep create mode 100644 root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep create mode 100644 root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep diff --git a/createlinks b/createlinks index eea87ee..e1ab9c3 100644 --- a/createlinks +++ b/createlinks @@ -2,9 +2,47 @@ use esmith::Build::CreateLinks qw(:all); use esmith::Build::Backup qw(:all); - # our event specific for updating with yum without reboot -$event = 'smeserver-certificates-update'; +my $event = 'smeserver-certificates-update'; + + +foreach (qw( + /etc/dehydrated/domains.txt + /etc/dehydrated/config + /usr/bin/hook-script.sh + )) +{ + templates2events("$_", qw( + post-upgrade + bootstrap-console-save + console-save + domain-create + domain-delete + domain-modify + host-create + host-delete + host-modify + smeserver-certificates-update + letsencrypt-config + )); +} + +foreach (qw( + /etc/cron.d/dehydrated + )) +{ + templates2events("$_", qw( + post-upgrade + bootstrap-console-save + console-save + http-proxy-update + smeserver-certificates-update + letsencrypt-config + )); +} +event_link("letsencrypt-kill-dehydrated-timer", $event, "91"); + + #add here the path to your templates needed to expand #see the /etc/systemd/system-preset/49-koozali.preset should be present for systemd integration on all you yum update event @@ -21,22 +59,15 @@ foreach my $file (qw( event_link('systemd-default', $event, '10'); event_link('systemd-reload', $event, '50'); -#services we might need to restart -#event_services($event, 'xxxx' => 'restart', 'yyyy' => 'restart'); - -#Backup contrib files -# backup_includes("smeserver-certificates", qw( - # files(s) to be backed up -#)); - -#Other possible entries: -#Server manager entry -#panel_link("smeserver-certificates", 'manager'); -#Events to smeserver-certificates -#$event = 'smeserver-certificates-smeserver-certificates'; -# safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/smeserver-certificates"); -# templates2events("/etc/smeserver-certificates/smeserver-certificates.conf", $event); +use esmith::Build::Backup qw(:all); +backup_includes("smeserver-certificates", qw( +/etc/dehydrated/ +)); +backup_excludes("smeserver-certificates", qw( +/etc/dehydrated/config +/etc/dehydrated/domains.txt +)); diff --git a/root/etc/dnf/plugins/post-transaction-actions.d/dehydrated.action b/root/etc/dnf/plugins/post-transaction-actions.d/dehydrated.action new file mode 100644 index 0000000..799f245 --- /dev/null +++ b/root/etc/dnf/plugins/post-transaction-actions.d/dehydrated.action @@ -0,0 +1 @@ +dehydrated:any:/sbin/e-smith/signal-event smeserver-certificates-update diff --git a/root/etc/e-smith/db/configuration/defaults/letsencrypt/configure b/root/etc/e-smith/db/configuration/defaults/letsencrypt/configure new file mode 100644 index 0000000..c86c3f3 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/letsencrypt/configure @@ -0,0 +1 @@ +none \ No newline at end of file diff --git a/root/etc/e-smith/db/configuration/defaults/letsencrypt/hookScript b/root/etc/e-smith/db/configuration/defaults/letsencrypt/hookScript new file mode 100644 index 0000000..7a68b11 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/letsencrypt/hookScript @@ -0,0 +1 @@ +disabled diff --git a/root/etc/e-smith/db/configuration/defaults/letsencrypt/status b/root/etc/e-smith/db/configuration/defaults/letsencrypt/status new file mode 100644 index 0000000..7a68b11 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/letsencrypt/status @@ -0,0 +1 @@ +disabled diff --git a/root/etc/e-smith/db/configuration/defaults/letsencrypt/type b/root/etc/e-smith/db/configuration/defaults/letsencrypt/type new file mode 100644 index 0000000..24e1098 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/letsencrypt/type @@ -0,0 +1 @@ +service diff --git a/root/etc/e-smith/events/actions/letsencrypt-setdomains b/root/etc/e-smith/events/actions/letsencrypt-setdomains index 7465ea1..dd12e30 100644 --- a/root/etc/e-smith/events/actions/letsencrypt-setdomains +++ b/root/etc/e-smith/events/actions/letsencrypt-setdomains @@ -135,7 +135,9 @@ for DOMAIN in $domainlist /sbin/e-smith/db $TYPE delprop $DOMAIN letsencryptMYIP continue fi - THISDOMIP=$(/usr/bin/q A @$mydns $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null || /usr/bin/q A @$LOCALIP $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null ) + # q output has changed + #THISDOMIP=$(/usr/bin/q A @$mydns $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null || /usr/bin/q A @$LOCALIP $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null) + THISDOMIP=$(/usr/bin/q @$mydns A $DOMAIN -f json |jq -r 'first(.[].replies[].answer[].a | select( . != null )) // null' 2>/dev/null || /usr/bin/q @$LOCALIP A $DOMAIN -f json |jq -r 'first(.[].replies[].answer[].a | select( . != null )) // null' 2>/dev/null ) previous=$(/sbin/e-smith/db $TYPE getprop $DOMAIN letsencryptSSLcert||echo 'undefined'); # if it does not resolve, next if [[ "$THISDOMIP" == "" ]] diff --git a/root/etc/e-smith/templates.metadata/etc/cron.d/dehydrated b/root/etc/e-smith/templates.metadata/etc/cron.d/dehydrated new file mode 100644 index 0000000..3709f0b --- /dev/null +++ b/root/etc/e-smith/templates.metadata/etc/cron.d/dehydrated @@ -0,0 +1 @@ +PERMS=0644 diff --git a/root/etc/e-smith/templates.metadata/usr/bin/hook-script.sh b/root/etc/e-smith/templates.metadata/usr/bin/hook-script.sh new file mode 100644 index 0000000..5531d85 --- /dev/null +++ b/root/etc/e-smith/templates.metadata/usr/bin/hook-script.sh @@ -0,0 +1 @@ +PERMS=0755 \ No newline at end of file diff --git a/root/etc/e-smith/templates/etc/cron.d/dehydrated/10dehydrated b/root/etc/e-smith/templates/etc/cron.d/dehydrated/10dehydrated new file mode 100644 index 0000000..ce3d0f1 --- /dev/null +++ b/root/etc/e-smith/templates/etc/cron.d/dehydrated/10dehydrated @@ -0,0 +1,20 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) || 'disabled'; + + if ( $letsencryptStatus eq 'enabled' ) { + + $OUT .= "#!/bin/sh\n\n"; + $OUT .= "32 3 * * 5 root test -s /etc/dehydrated/domains.txt && /usr/bin/dehydrated --cron"; + } + + else { + $OUT .= "# letsencrypt is disabled\n"; + } +} + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/01notice b/root/etc/e-smith/templates/etc/dehydrated/config/01notice new file mode 100644 index 0000000..61c2ff4 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/01notice @@ -0,0 +1,13 @@ +#!/bin/bash +######################################################## +# This is the main config file for dehydrated # +# # +# This file is looked for in the following locations: # +# $SCRIPTDIR/config (next to this script) # +# /usr/local/etc/dehydrated/config # +# /etc/dehydrated/config # +# ${PWD}/config (in current working-directory) # +# # +# Default values of this config are in comments # +######################################################## + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/02variables b/root/etc/e-smith/templates/etc/dehydrated/config/02variables new file mode 100644 index 0000000..80d1844 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/02variables @@ -0,0 +1,5 @@ +{ + $letsencryptStatus = $letsencrypt{'status'} || 'disabled'; + $letsencryptAPI = $letsencrypt{'API'} || 'auto'; +""; +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/05usergroup b/root/etc/e-smith/templates/etc/dehydrated/config/05usergroup new file mode 100644 index 0000000..092e3d4 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/05usergroup @@ -0,0 +1,6 @@ +# Which user should dehydrated run as? This will be implictly enforced when running as root +#DEHYDRATED_USER= + +# Which group should dehydrated run as? This will be implictly enforced when running as root +#DEHYDRATED_GROUP= + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/10Default b/root/etc/e-smith/templates/etc/dehydrated/config/10Default new file mode 100644 index 0000000..f3bbbe7 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/10Default @@ -0,0 +1,90 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) + || 'disabled'; + + # Default to v2 as v1 no longer supported for new certs. At the moment (Oct 2020) v1 still supported for renewing certs. + + my $letsencryptAPI = $configDB->get_prop( 'letsencrypt', 'API' ) + || '2'; + + $OUT .= "#!/bin/bash\n"; + + if ( $letsencryptStatus eq 'disabled' ) { + $OUT .= "letsencrypt is disabled"; + } + else { + # We should only be here if we are not disabled + if ( $letsencryptStatus eq 'test' ) { + + # Use staging directory for testing + # Once you are sure you have the settings right then change + + # If it's v1 then use v1, if v2 or auto then use v2 staging + if ( $letsencryptAPI eq '1' ) { + $OUT .= "CA=\"https://acme-staging.api.letsencrypt.org/directory\"\n"; + } + elsif ( ( $letsencryptAPI eq '2' ) || ( $letsencryptAPI eq 'auto' ) ) { + $OUT .= "CA=\"https://acme-staging-v02.api.letsencrypt.org/directory\"\n"; + } + } + + elsif ( $letsencryptStatus ne 'test' ) { + + # Real server - default settings are in the the main dehydrated file + # Only use this once you are sure things are OK or you will hit a rate limit. + + # If it's v1 then use v1, if v2 then v2, if auto accept the defaults in the main file + if ( $letsencryptAPI eq '1' ) { + $OUT .= "CA=\"https://acme-v01.api.letsencrypt.org/directory\"\n"; + } + elsif ( $letsencryptAPI eq '2' ) { + $OUT .= "CA=\"https://acme-v02.api.letsencrypt.org/directory\"\n"; + } + } + + $OUT .= "WELLKNOWN=\"/var/www/html/.well-known/acme-challenge\"\n"; + + # Hook Script always enabled + $OUT .= "HOOK=\"/usr/bin/hook-script.sh\"\n"; + + # Base directory for account key, generated certificates and list of domains (default: $SCRIPTDIR -- uses config directory if undefined) + #BASEDIR=$SCRIPTDIR + + $OUT .= "BASEDIR=\"/etc/dehydrated\"\n"; + + # Location of private account key (default: $BASEDIR/private_key.pem) + #PRIVATE_KEY="${BASEDIR}/private_key.pem" + + my $letsencryptKeysize = $configDB->get_prop( 'letsencrypt', 'keysize' ) + || ''; + if ( $letsencryptKeysize ne '' ) { + + # Default keysize for private keys (default: 4096) + $OUT .= "KEYSIZE=\"4096\"\n"; + } + + my $letsencryptEmail = $configDB->get_prop( 'letsencrypt', 'email' ) || ''; + if ( $letsencryptEmail ne '' ) { + + # E-mail to use during the registration (default: ) + $OUT .= "CONTACT_EMAIL=$letsencryptEmail\n"; + } + + # API version - auto | 1 | 2 + if ( $letsencryptAPI eq '1' ) { + $OUT .= "API=\"1\"\n"; + } + elsif ( $letsencryptAPI eq '2' ) { + $OUT .= "API=\"2\"\n"; + } + else { + $OUT .= "API=\"auto\"\n"; + } + } +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/10IPVersion b/root/etc/e-smith/templates/etc/dehydrated/config/10IPVersion new file mode 100644 index 0000000..281e6eb --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/10IPVersion @@ -0,0 +1,5 @@ +# Resolve names to addresses of IP version only. (curl) +# supported values: 4, 6 +# default: +IP_VERSION=4 + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/15CA b/root/etc/e-smith/templates/etc/dehydrated/config/15CA new file mode 100644 index 0000000..df9ab29 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/15CA @@ -0,0 +1,36 @@ +# Path to certificate authority (default: https://acme-v02.api.letsencrypt.org/directory) +{ + + if ( $letsencryptStatus eq 'test' ) { + + # Use staging directory for testing + # Once you are sure you have the settings right then change + + # If it's v1 then use v1, if v2 or auto then use v2 staging + if ( $letsencryptAPI eq '1' ) { + $OUT .= "CA=\"https://acme-staging.api.letsencrypt.org/directory\"\n"; + } + elsif ( ( $letsencryptAPI eq '2' ) || ( $letsencryptAPI eq 'auto' ) ) { + $OUT .= "CA=\"https://acme-staging-v02.api.letsencrypt.org/directory\"\n"; + } + } + + elsif ( $letsencryptStatus ne 'test' ) { + + # Real server - default settings are in the the main dehydrated file + # Only use this once you are sure things are OK or you will hit a rate limit. + + # If it's v1 then use v1, if v2 then v2, if auto accept the defaults in the main file + if ( $letsencryptAPI eq '1' ) { + $OUT .= "CA=\"https://acme-v01.api.letsencrypt.org/directory\"\n"; + } + elsif ( $letsencryptAPI eq '2' ) { + $OUT .= "CA=\"https://acme-v02.api.letsencrypt.org/directory\"\n"; + } + else { + $OUT .= "#CA=\"https://acme-v02.api.letsencrypt.org/directory\"\n"; + } + } + + +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/16OLDCA b/root/etc/e-smith/templates/etc/dehydrated/config/16OLDCA new file mode 100644 index 0000000..c217a29 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/16OLDCA @@ -0,0 +1,7 @@ +# Path to old certificate authority +# Set this value to your old CA value when upgrading from ACMEv1 to ACMEv2 under a different endpoint. +# If dehydrated detects an account-key for the old CA it will automatically reuse that key +# instead of registering a new one. +# default: https://acme-v01.api.letsencrypt.org/directory +#OLDCA="https://acme-v01.api.letsencrypt.org/directory" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/20ACCEPT_TERMS b/root/etc/e-smith/templates/etc/dehydrated/config/20ACCEPT_TERMS new file mode 100644 index 0000000..09c331d --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/20ACCEPT_TERMS @@ -0,0 +1,11 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + my $ACCEPT_TERMS = $configDB->get_prop( 'letsencrypt', 'ACCEPT_TERMS' ) + || 'no'; + $OUT .= "PARAM_ACCEPT_TERMS=\"yes\"\n" if $ACCEPT_TERMS eq 'yes'; + $OUT .= "# letsencrypt property ACCEPT_TERMS not set to yes\n" unless $ACCEPT_TERMS eq 'yes'; +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/20challenge b/root/etc/e-smith/templates/etc/dehydrated/config/20challenge new file mode 100644 index 0000000..bd382cb --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/20challenge @@ -0,0 +1,3 @@ +# Which challenge should be used? Currently http-01, dns-01 and tls-alpn-01 are supported +#CHALLENGETYPE="http-01" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/25directories b/root/etc/e-smith/templates/etc/dehydrated/config/25directories new file mode 100644 index 0000000..0a9dcde --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/25directories @@ -0,0 +1,29 @@ +# Path to a directory containing additional config files, allowing to override +# the defaults found in the main configuration file. Additional config files +# in this directory needs to be named with a '.sh' ending. +# default: +#CONFIG_D= + +# Directory for per-domain configuration files. +# If not set, per-domain configurations are sourced from each certificates output directory. +# default: +#DOMAINS_D= + +# Base directory for account key, generated certificates and list of domains (default: $SCRIPTDIR -- uses config directory if undefined) +BASEDIR=$SCRIPTDIR + +# File containing the list of domains to request certificates for (default: $BASEDIR/domains.txt) +DOMAINS_TXT="${BASEDIR}/domains.txt" + +# Output directory for generated certificates +CERTDIR="${BASEDIR}/certs" + +# Output directory for alpn verification certificates +ALPNCERTDIR="${BASEDIR}/alpn-certs" + +# Directory for account keys and registration information +ACCOUNTDIR="${BASEDIR}/accounts" + +# Output directory for challenge-tokens to be served by webserver or deployed in HOOK (default: /var/www/dehydrated) +WELLKNOWN="/var/www/dehydrated" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/30KEYSIZE b/root/etc/e-smith/templates/etc/dehydrated/config/30KEYSIZE new file mode 100644 index 0000000..2986f5e --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/30KEYSIZE @@ -0,0 +1,3 @@ +# Default keysize for private keys (default: 4096) +KEYSIZE="{$letsencrypt{KeySize}||$modSSL{KeySize}||4096}" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/30KEY_ALGO b/root/etc/e-smith/templates/etc/dehydrated/config/30KEY_ALGO new file mode 100644 index 0000000..a315ed2 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/30KEY_ALGO @@ -0,0 +1,3 @@ +# SME Server does not support yet elliptic curve (qpsmtpd and perl-IO-SOcket-SSL < 1.95) +KEY_ALGO=rsa + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/35days b/root/etc/e-smith/templates/etc/dehydrated/config/35days new file mode 100644 index 0000000..e98f9e4 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/35days @@ -0,0 +1,3 @@ +# Minimum days before expiration to automatically renew certificate (default: 30) +RENEW_DAYS="{$letsencrypt{DAYS} || 30}" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/36openssl b/root/etc/e-smith/templates/etc/dehydrated/config/36openssl new file mode 100644 index 0000000..a0c9abf --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/36openssl @@ -0,0 +1,8 @@ +# Path to openssl config file (default: - tries to figure out system default) +#OPENSSL_CNF= + +# Path to OpenSSL binary (default: "openssl") +OPENSSL="{ return "/usr/bin/openssl11" if ( -f "/usr/bin/openssl11" ); +"/usr/bin/openssl" +}" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/40curlextra b/root/etc/e-smith/templates/etc/dehydrated/config/40curlextra new file mode 100644 index 0000000..f1efb14 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/40curlextra @@ -0,0 +1,3 @@ +# Extra options passed to the curl binary (default: ) +#CURL_OPTS= + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/42PrivateKey b/root/etc/e-smith/templates/etc/dehydrated/config/42PrivateKey new file mode 100644 index 0000000..901f6e2 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/42PrivateKey @@ -0,0 +1,6 @@ +# Regenerate private keys instead of just signing new certificates on renewal (default: yes) +#PRIVATE_KEY_RENEW="yes" + +# Create an extra private key for rollover (default: no) +#PRIVATE_KEY_ROLLOVER="no" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/45Algorithm b/root/etc/e-smith/templates/etc/dehydrated/config/45Algorithm new file mode 100644 index 0000000..6835fa9 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/45Algorithm @@ -0,0 +1,3 @@ +# Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1 +#KEY_ALGO=rsa + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/47hook b/root/etc/e-smith/templates/etc/dehydrated/config/47hook new file mode 100644 index 0000000..5f772b5 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/47hook @@ -0,0 +1,15 @@ +# Program or function called in certain situations +# +# After generating the challenge-response, or after failed challenge (in this case altname is empty) +# Given arguments: clean_challenge|deploy_challenge altname token-filename token-content +# +# After successfully signing certificate +# Given arguments: deploy_cert domain path/to/privkey.pem path/to/cert.pem path/to/fullchain.pem +# +# BASEDIR and WELLKNOWN variables are exported and can be used in an external program +# default: +HOOK= /usr/bin/hook-script.sh + +# Chain clean_challenge|deploy_challenge arguments together into one hook call per certificate (default: no) +#HOOK_CHAIN="no" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/50email b/root/etc/e-smith/templates/etc/dehydrated/config/50email new file mode 100644 index 0000000..0a88d20 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/50email @@ -0,0 +1,3 @@ +# E-mail to use during the registration (default: ) +CONTACT_EMAIL="{$letsencrypt{'email'}||''}" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/60lockfile b/root/etc/e-smith/templates/etc/dehydrated/config/60lockfile new file mode 100644 index 0000000..b93824a --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/60lockfile @@ -0,0 +1,3 @@ +# Lockfile location, to prevent concurrent access (default: $BASEDIR/lock) +LOCKFILE="${BASEDIR}/lock" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/65OCSP b/root/etc/e-smith/templates/etc/dehydrated/config/65OCSP new file mode 100644 index 0000000..182c427 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/65OCSP @@ -0,0 +1,9 @@ +# Option to add CSR-flag indicating OCSP stapling to be mandatory (default: no) +#OCSP_MUST_STAPLE="no" + +# Fetch OCSP responses (default: no) +#OCSP_FETCH="no" + +# OCSP refresh interval (default: 5 days) +#OCSP_DAYS=5 + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/70chain b/root/etc/e-smith/templates/etc/dehydrated/config/70chain new file mode 100644 index 0000000..c958732 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/70chain @@ -0,0 +1,3 @@ +# Issuer chain cache directory (default: $BASEDIR/chains) +#CHAINCACHE="${BASEDIR}/chains" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/75cleanup b/root/etc/e-smith/templates/etc/dehydrated/config/75cleanup new file mode 100644 index 0000000..ac871a0 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/75cleanup @@ -0,0 +1,3 @@ +# Automatic cleanup (default: no) +#AUTO_CLEANUP="no" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/80API b/root/etc/e-smith/templates/etc/dehydrated/config/80API new file mode 100644 index 0000000..908187d --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/80API @@ -0,0 +1,3 @@ +# ACME API version (default: auto) +API="{$letsencryptAPI||'auto'}" + diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/85ACCEPT_TERMS b/root/etc/e-smith/templates/etc/dehydrated/config/85ACCEPT_TERMS new file mode 100644 index 0000000..fc22d70 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/config/85ACCEPT_TERMS @@ -0,0 +1,5 @@ +{ + my $ACCEPT_TERMS = $letsencrypt{'ACCEPT_TERMS'} || 'no'; + return "PARAM_ACCEPT_TERMS=\"yes\"\n" if $ACCEPT_TERMS eq 'yes'; + $OUT .= "# letsencrypt property ACCEPT_TERMS not set to yes\n" unless $ACCEPT_TERMS eq 'yes'; +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/config/template-begin b/root/etc/e-smith/templates/etc/dehydrated/config/template-begin new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/e-smith/templates/etc/dehydrated/domains.txt/10Domains b/root/etc/e-smith/templates/etc/dehydrated/domains.txt/10Domains new file mode 100644 index 0000000..39a9ea4 --- /dev/null +++ b/root/etc/e-smith/templates/etc/dehydrated/domains.txt/10Domains @@ -0,0 +1,133 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + my $domainsDB = esmith::ConfigDB->open_ro('domains') + or die("can't connect to domains database"); + my $hostsDB = esmith::ConfigDB->open_ro('hosts') + or die("can't connect to hosts database"); + + # my $dbKey = 'domain'; + + # my $systemMode = $configDB->get("SystemMode")->value; + + # if ( $systemMode ne 'servergateway' ) { + # $OUT .= "# System not in Server Gateway mode\n"; + # } + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) + || 'disabled'; + + if ( $letsencryptStatus ne 'disabled' ) { + + # This should get all the connections in an array + + my @domains = $domainsDB->keys; + my @hosts = $hostsDB->keys; + + # print "@domains\n"; + + # Need to check here if we want ALL set + # all, domains, hosts, both, none + my $letsencryptConfig = $configDB->get_prop( 'letsencrypt', 'configure' ) || 'none'; + + # First get all the domains + # We could do this BUT only once as the array drops $vars + + # my $dom = shift @domains; + + # Patch from JPP + # Put Primary domain at top + my $DomainName = $configDB->get('DomainName')->value; + my $mainDomainStatus = $domainsDB->get_prop( "$DomainName", 'letsencryptSSLcert' ) + || 'disabled'; + $OUT .= "$DomainName " unless $mainDomainStatus eq 'disabled'; + + foreach my $domain (@domains) { + + # If we are all or domains then lets do all regardless + if ( $letsencryptConfig eq 'all' || $letsencryptConfig eq 'domains' ) { + + # Check for self + #my $domainStatus = + # $domainsDB->get_prop( "Nameservers", 'HostType' ) || ''; + # + #if ( $domainStatus eq 'Localhost' ) { + $OUT .= "$domain "; + + #} + } + + else { + my $domainEnabled = $domainsDB->get_prop( "$domain", 'letsencryptSSLcert' ) + || 'disabled'; + + if ( $domainEnabled eq 'enabled' ) { + $OUT .= "$domain " unless $DomainName eq $domain; + } + } + + # Now check for hosts + + # Buggered if I remember why we check that + # the host has a domain name in domains ! + # Must have been a reason + + foreach my $fqdn (@hosts) { + + # If we are set to all or hosts just do it + if ( $letsencryptConfig eq 'all' || $letsencryptConfig eq 'hosts' ) { + $OUT .= "$fqdn " unless $DomainName eq $fqdn; + } + + # Just do selected entries + else { + # Lets get the hostname + my $hostname = $fqdn; + $hostname =~ s/\..*//; + + # print "$hostname\n"; + + # Lets get the domain name + my $domainname = $fqdn; + $domainname =~ s/.*?\.//; + + # print "$domainname\n"; + + # is the domain name from the hosts file + # the same as that in the domains file ? + my $hostEnabled = $hostsDB->get_prop( "$fqdn", 'letsencryptSSLcert' ) + || 'disabled'; + + if ( $domainname eq $domain && $hostEnabled eq 'enabled' ) { + + # Are we self ? + my $type = $hostsDB->get_prop( "$fqdn", 'HostType' ); + my $hostOverride = $configDB->get_prop( 'letsencrypt', 'hostOverride' ) + || 'disabled'; + + # print "Override $hostOverride"; + + if ( $hostOverride eq 'yes' ) { + $OUT .= "$fqdn " unless $DomainName eq $fqdn; + } + + elsif ( $type eq 'Self' ) { + + # print "Here: $fqdn $type\n"; + $OUT .= "$fqdn " unless $DomainName eq $fqdn; + } + + } + } + } + } + + } + + else { + $OUT .= "# letsencrypt is disabled\n"; + } +} diff --git a/root/etc/e-smith/templates/etc/dehydrated/domains.txt/template-begin b/root/etc/e-smith/templates/etc/dehydrated/domains.txt/template-begin new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/e-smith/templates/etc/systemd/system-preset/49-koozali.preset/80-koozali-dehydrated-timer.preset b/root/etc/e-smith/templates/etc/systemd/system-preset/49-koozali.preset/80-koozali-dehydrated-timer.preset new file mode 100644 index 0000000..051f475 --- /dev/null +++ b/root/etc/e-smith/templates/etc/systemd/system-preset/49-koozali.preset/80-koozali-dehydrated-timer.preset @@ -0,0 +1,12 @@ +# dehydrated.timer preset +{ +# depending on letsencrypt status +#$status = $letsencrypt{status} || 'disabled'; +#$status = ($status eq "enabled") ? "enable" : "disable"; +#$OUT .= "$status dehydrated.timer\n"; + +# or always disabled +$OUT .= "disable dehydrated.timer\n"; +} + + diff --git a/root/etc/e-smith/templates/usr/bin/hook-script.sh/10deploy_cert b/root/etc/e-smith/templates/usr/bin/hook-script.sh/10deploy_cert new file mode 100644 index 0000000..c88513b --- /dev/null +++ b/root/etc/e-smith/templates/usr/bin/hook-script.sh/10deploy_cert @@ -0,0 +1,54 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) || 'disabled'; + + my $version = $configDB->get_prop( 'sysconfig', 'ReleaseVersion' ); + + $version = substr( $version, 0, 1 ); + + if ( $letsencryptStatus ne 'disabled' ) { + + if ( $version == 8 ) { + $OUT .= <<'_EOF'; + + if [ $1 = "deploy_cert" ]; then + KEY=$3 + CERT=$4 + CHAIN=$6 + echo "Set up modSSL db keys" + /sbin/e-smith/db configuration setprop modSSL key $KEY + /sbin/e-smith/db configuration setprop modSSL crt $CERT + /sbin/e-smith/db configuration setprop modSSL CertificateChainFile $CHAIN + echo "Signal events" + /sbin/e-smith/signal-event domain-modify + /sbin/e-smith/signal-event email-update + /sbin/e-smith/signal-event ibay-modify + echo "All complete" + fi +_EOF + } + else { + + $OUT .= <<'_EOF'; + + if [ $1 = "deploy_cert" ]; then + KEY=$3 + CERT=$4 + CHAIN=$6 + echo "Set up modSSL db keys" + /sbin/e-smith/db configuration setprop modSSL key $KEY + /sbin/e-smith/db configuration setprop modSSL crt $CERT + /sbin/e-smith/db configuration setprop modSSL CertificateChainFile $CHAIN + echo "Signal events" + /sbin/e-smith/signal-event ssl-update + echo "All complete" + fi +_EOF + } + } +} diff --git a/root/etc/e-smith/templates/usr/bin/hook-script.sh/20challenges b/root/etc/e-smith/templates/usr/bin/hook-script.sh/20challenges new file mode 100644 index 0000000..8425bf6 --- /dev/null +++ b/root/etc/e-smith/templates/usr/bin/hook-script.sh/20challenges @@ -0,0 +1,76 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) || 'disabled'; + my $hookscript = $configDB->get_prop( 'letsencrypt', 'hookScript' ) || 'disabled'; + my $host = $configDB->get_prop( 'letsencrypt', 'host' ) || ''; + my $user = $configDB->get_prop( 'letsencrypt', 'user' ) || ''; + my $path = $configDB->get_prop( 'letsencrypt', 'path' ) || ''; + + if ( $letsencryptStatus ne 'disabled' && $hookscript eq 'enabled' && $host ne '' && $user ne '' && $path ne '' ) { + + $OUT .= "if [ \$1 = \"deploy_challenge\" ]; then\n"; + $OUT .= " CHALLENGE_FILE=\$3\n"; + $OUT .= " CHALLENGE_CONTENT=\$4\n"; + $OUT .= " HOST=\"$host\" # FQDN or IP of public-facing server\n"; + $OUT .= " USER=\"$user\" # username on public-facing server\n"; + $OUT .= " REMOTE_PATH=\"$path\"\n"; + $OUT .= " if scp \$WELLKNOWN/\$CHALLENGE_FILE \$USER@\$HOST:\$REMOTE_PATH/\$CHALLENGE_FILE; then\n"; + $OUT .= " exit 0\n"; + $OUT .= " else\n"; + $OUT .= " echo \" Failed to deploy challenge !\" \n "; + $OUT .= " exit 1 \n "; + $OUT .= " fi \n "; + $OUT .= "fi \n "; + $OUT .= "\n"; + $OUT .= " if [ \$1 = \"clean_challenge\" ]; then\n"; + $OUT .= " CHALLENGE_FILE=\$3\n"; + $OUT .= " HOST=\"$host\" # FQDN or IP of public-facing server\n"; + $OUT .= " USER=\"$user\" # username on public-facing server\n"; + $OUT .= " REMOTE_PATH=\"$path\"\n"; + $OUT .= " if ssh \$USER\@\$HOST \"rm \$REMOTE_PATH/\$CHALLENGE_FILE\"; then\n"; + $OUT .= " exit 0\n"; + $OUT .= " else\n"; + $OUT .= " echo \" Failed to clean challenge !\" \n "; + $OUT .= " exit 1 \n "; + $OUT .= " fi \n "; + $OUT .= "fi \n "; + } + else { + $OUT .= "# The following all have to be set to enable deploy/clean challenges\n"; + $OUT .= "# \n"; + if ( $hookscript ne '' ) { + $OUT .= "# hookScript: $hookscript\n"; + } + else { + $OUT .= "# hookScript: Not Set\n"; + } + + if ( $host ne '' ) { + $OUT .= "# host: $host\n"; + } + else { + $OUT .= "# host: Not Set\n"; + } + + if ( $user ne '' ) { + $OUT .= "# user: $user\n"; + } + else { + $OUT .= "# user: Not Set\n"; + } + + if ( $path ne '' ) { + $OUT .= "# path: $path\n"; + } + else { + $OUT .= "# path: Not Set\n"; + } + + } + +} diff --git a/root/etc/e-smith/templates/usr/bin/hook-script.sh/template-begin b/root/etc/e-smith/templates/usr/bin/hook-script.sh/template-begin new file mode 100644 index 0000000..0cdc33a --- /dev/null +++ b/root/etc/e-smith/templates/usr/bin/hook-script.sh/template-begin @@ -0,0 +1,17 @@ +{ + use strict; + use warnings; + use esmith::ConfigDB; + + my $configDB = esmith::ConfigDB->open_ro or die("can't open Config DB"); + + my $letsencryptStatus = $configDB->get_prop( 'letsencrypt', 'status' ) || 'disabled'; + + if ( $letsencryptStatus ne 'disabled' ) { + + $OUT .= "#!/bin/bash\n"; + $OUT .= "# deploy_cert hook will set config database entries for the cert files\n"; + $OUT .= "# and restart appropriate services\n"; + $OUT .= "#\n"; + } +} diff --git a/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm new file mode 100644 index 0000000..ca68016 --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm @@ -0,0 +1,566 @@ +# +# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-11-16 10:30:16 +# +# +# Routines to be edited by the developer to provide content and validation for parameters +# and provison of the control data for table(s) +# +use esmith::util; +use esmith::util::network; +use esmith::ConfigDB; +use esmith::HostsDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::DomainsDB; +use constant FALSE => 0; +use constant TRUE => 1; + +#The most common ones +our $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); +our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); +our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); +our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); +our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + +# Validation routines - parameters for each panel +sub validate_LIST { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (!TRUE) #validate $c->param('InternalIP') + { + $ret .= 'Validation for InternalIP failed'; + } + + if (!TRUE) #validate $c->param('ExternalIP') + { + $ret .= 'Validation for ExternalIP failed'; + } + + if (!TRUE) #validate $c->param('InternetIP') + { + $ret .= 'Validation for InternetIP failed'; + } + + if (!TRUE) #validate $c->param('Issuer') + { + $ret .= 'Validation for Issuer failed'; + } + + if (!TRUE) #validate $c->param('Expiry') + { + $ret .= 'Validation for Expiry failed'; + } + + if (!TRUE) #validate $c->param('NotBefore') + { + $ret .= 'Validation for NotBefore failed'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub validate_LIST + +sub validate_PARAMS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (!TRUE) #validate $c->param('status') + { + $ret .= 'Validation for status failed'; + } + + if (!TRUE) #validate $c->param('hookScript') + { + $ret .= 'Validation for hookScript failed'; + } + + if (!TRUE) #validate $c->param('hostOverride') + { + $ret .= 'Validation for hostOverride failed'; + } + + if (!TRUE) #validate $c->param('ACCEPT_TERMS') + { + $ret .= 'Validation for ACCEPT_TERMS failed'; + } + + if (!TRUE) #validate $c->param('API') + { + $ret .= 'Validation for API failed'; + } + + if (!TRUE) #validate $c->param('keysize') + { + $ret .= 'Validation for keysize failed'; + } + + if (!TRUE) #validate $c->param('configure') + { + $ret .= 'Validation for configure failed'; + } + + if (!TRUE) #validate $c->param('Email') + { + $ret .= 'Validation for Email failed'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub validate_PARAMS + +sub validate_CHECKALLDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (!TRUE) #validate $c->param('AllDomainsCheck') + { + $ret .= 'Validation for AllDomainsCheck failed'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub validate_CHECKALLDOMAINS + +sub validate_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (!TRUE) #validate $c->param('EnabledDomainsCheck') + { + $ret .= 'Validation for EnabledDomainsCheck failed'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub validate_CHECKALLENABLEDDOMAINS + +sub validate_CHECKONEDOMAIN { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (!TRUE) #validate $c->param('OneDomainToCheck') + { + $ret .= 'Validation for OneDomainToCheck failed'; + } + + if (!TRUE) #validate $c->param('OneDomainsCheck') + { + $ret .= 'Validation for OneDomainsCheck failed'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub validate_CHECKONEDOMAIN + +# Get singleton data for each panel +sub get_data_for_panel_LIST { + + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + + # my ($reply, $err, $server_cert) = Net::SSLeay::sslcat('localhost', 443, '/'); + # my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert)); + # my $before = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($server_cert)); + # my $expiry = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($server_cert)); + my %ret = ( + 'Data1' => 'Data for LIST', #Example + # fields from Inputs in LIST $fields['LIST'] + 'InternalIP' => $cdb->get_prop('InternalInterface', 'IPAddress'), + 'ExternalIP' => $cdb->get_prop('ExternalInterface', 'IPAddress'), + 'InternetIP' => $c->get_my_ip(), + 'Issuer' => '$issuer', + 'Expiry' => '$expiry', + 'NotBefore' => '$before', + ); + return %ret; +} ## end sub get_data_for_panel_LIST + +sub get_data_for_panel_PARAMS { + + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1' => 'Data for PARAMS', #Example + # fields from Inputs in PARAMS $fields['PARAMS'] + 'status' => $cdb->get_prop('letsencrypt', 'status', 'disabled'), + 'hookScript' => $cdb->get_prop('letsencrypt', 'hookScript', 'disabled'), + 'hostOverride' => $cdb->get_prop('letsencrypt', 'hostOverride', 'disabled'), + 'ACCEPT_TERMS' => $cdb->get_prop('letsencrypt', 'ACCEPT_TERMS', ''), + 'API' => $cdb->get_prop('letsencrypt', 'API', '2'), + 'keysize' => $cdb->get_prop('letsencrypt', 'keysize', '4096'), + 'configure' => $cdb->get_prop('letsencrypt', 'configure', 'none'), + 'email' => $cdb->get_prop('letsencrypt', 'email') + ); + return %ret; +} ## end sub get_data_for_panel_PARAMS + +sub get_data_for_panel_CHECKALLDOMAINS { + + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1' => 'Data for CHECKALLDOMAINS', #Example + # fields from Inputs in CHECKALLDOMAINS $fields['CHECKALLDOMAINS'] + 'AllDomainsCheck' => $c->update_all_domains(), + ); + return %ret; +} ## end sub get_data_for_panel_CHECKALLDOMAINS + +sub get_data_for_panel_CHECKALLENABLEDDOMAINS { + + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1' => 'Data for CHECKALLENABLEDDOMAINS', #Example + # fields from Inputs in CHECKALLENABLEDDOMAINS $fields['CHECKALLENABLEDDOMAINS'] + 'EnabledDomainsCheck' => $c->update_enabled_domains(), + ); + return %ret; +} ## end sub get_data_for_panel_CHECKALLENABLEDDOMAINS + +sub get_data_for_panel_CHECKONEDOMAIN { + + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1' => 'Data for CHECKONEDOMAIN', #Example + # fields from Inputs in CHECKONEDOMAIN $fields['CHECKONEDOMAIN'] + 'OneDomainToCheck' => $c->param("CHECKONEDOMAIN"), + 'OneDomainsCheck' => $c->update_one_domain($c->param("CHECKONEDOMAIN")) + ); + return %ret; +} ## end sub get_data_for_panel_CHECKONEDOMAIN + +# Get control data for table(s) +# Define a constant hash for field name mapping +use constant DomainList_FIELD_MAPPING => ( + 'Table1-Domain name / HOSTNAME' => 'Domain', + 'Table1-Brief description' => 'Description', + 'Table1-Content' => 'Content', + 'Table1-LABEL_NAMESERVERS' => 'Nameservers', + 'Table1-LABEL_POINT' => 'Source-for-Table1-LABEL_POINT', + 'Table1-LABEL_LECERT' => 'letsencryptSSLcert', + 'Table1-IS_IN_CERT' => 'isincert', + 'Table1-CHECK' => 'Check' + + #'target_field2' => 'source_field2', + # Add more mappings as needed +); +use constant TEST_DOMAIN_LIST => ( + { "domain" => "Domain1", "fred" => "fred1", "description" => "Description1" }, + { "domain" => "Domain2", "fred" => "fred2", "description" => "Description2" }, + { "domain" => "Domain3", "fred" => "fred3", "description" => "Description3" }, + + # Add more test entries as needed +); + +sub actual_DomainList { + my $c = shift; + + # Actual code for extracting DomainList + my @list = (); + + # my @rv = Net::SSLeay::X509_get_subjectAltNames($server_cert); + # foreach my $element (@rv) { + # next if $element =~ /^\d+$/; ; + # #print $element . "\n"; + # push @list, $element; + # } + my @data = (); + my $check = $c->l('Check Domain'); + + for ($ddb->domains) { + my $ns = $_->prop('Nameservers') || 'internet'; + my $le = $_->prop('letsencryptSSLcert') || 'disabled'; #letsencrypt configure all + my $dname = $_->key; + my $isincert = "N"; + my $link = $c->create_link("letsencryptd", "CHECKONEDOMAIN", ""); + my $checklink = "" . $check . ""; + + #my $checklink = "check"; + $isincert = "Y" if ($dname ~~ @list); + + # domain + push @data, + { + Domain => $_->key, + $_->props, + letsencryptSSLcert => $le, + isincert => $isincert, + Check => $checklink, + Nameservers => $ns, + }; + + #and hosts + for my $h ($hdb->get_hosts_by_domain($dname)) { + next if $ddb->get($h->key); + next unless ($h->prop('HostType') eq "Self" || $h->prop('HostType') eq "Local"); + $le = $h->prop('letsencryptSSLcert') || 'disabled'; #letsencrypt configure all + $isincert = "N"; + $isincert = "Y" if ($h->key ~~ @list); + push @data, { + Domain => "--> " . $h->key, + $h->props, + Description => $h->prop('ExternalIP') || $h->prop('InternalIP') || "", + Content => $h->prop('HostType'), + isincert => $isincert, + Check => "", #$checklink + Nameservers => $c->l($ns), + }; + } ## end for my $h ($hdb->get_hosts_by_domain...) + } ## end for ($ddb->domains) + return @data; +} ## end sub actual_DomainList + +sub get_DomainList { + + # Return an array of hashes of the contents for each row and column for DomainList + my $c = shift; + my @source_records + = $c->actual_DomainList(); #TEST_DOMAIN_LIST #Replace by code or call to produce contents of table; + my @transformed_records; + my %Field_Mapping = DomainList_FIELD_MAPPING; + + # Iterate over each record in the source array + for my $source_record (@source_records) { + my %transformed_record; + + # Iterate over each key-value pair in the $Field_Mapping constant + while (my ($target, $source) = each %Field_Mapping) { + + # Check if the source field exists in the source record + if (exists $source_record->{$source}) { + + # Assign the source field value to the target field in the transformed record + $transformed_record{$target} = $source_record->{$source}; + } + } ## end while (my ($target, $source...)) + + # Add transformed record to the array if it's not empty + push @transformed_records, \%transformed_record if %transformed_record; + } ## end for my $source_record (...) + return \@transformed_records; +} ## end sub get_DomainList + +# Return hash with values from row in which link clicked on table +sub get_selected_LIST { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return %ret; +} ## end sub get_selected_LIST + +sub get_selected_PARAMS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return %ret; +} ## end sub get_selected_PARAMS + +sub get_selected_CHECKALLDOMAINS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return %ret; +} ## end sub get_selected_CHECKALLDOMAINS + +sub get_selected_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return %ret; +} ## end sub get_selected_CHECKALLENABLEDDOMAINS + +sub get_selected_CHECKONEDOMAIN { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return %ret; +} ## end sub get_selected_CHECKONEDOMAIN + +#after sucessful modify or create or whatever and submit then perfom (if the params validate) +sub perform_LIST { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (!TRUE + ) #copy or perform with value: InternalIP e.g. $db->set_prop($dbkey,'InternalIP',$c->param('InternalIP'),type=>'service')) + { + $ret .= 'Perform/save failed for InternalIP'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: ExternalIP e.g. $db->set_prop($dbkey,'ExternalIP',$c->param('ExternalIP'),type=>'service')) + { + $ret .= 'Perform/save failed for ExternalIP'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: InternetIP e.g. $db->set_prop($dbkey,'InternetIP',$c->param('InternetIP'),type=>'service')) + { + $ret .= 'Perform/save failed for InternetIP'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: Issuer e.g. $db->set_prop($dbkey,'Issuer',$c->param('Issuer'),type=>'service')) + { + $ret .= 'Perform/save failed for Issuer'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: Expiry e.g. $db->set_prop($dbkey,'Expiry',$c->param('Expiry'),type=>'service')) + { + $ret .= 'Perform/save failed for Expiry'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: NotBefore e.g. $db->set_prop($dbkey,'NotBefore',$c->param('NotBefore'),type=>'service')) + { + $ret .= 'Perform/save failed for NotBefore'; + } ## end if (!TRUE) + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub perform_LIST + +sub perform_PARAMS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'letsencrypt'; + +# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g." + if (!$db->set_prop($dbkey, 'status', $c->param('status'), type => 'service')) { + $ret .= 'Perform/save failed for status'; + } + + if (!$db->set_prop($dbkey, 'hookScript', $c->param('hookScript'), type => 'service')) { + $ret .= 'Perform/save failed for hookScript'; + } + + if (!$db->set_prop($dbkey, 'hostOverride', $c->param('hostOverride'), type => 'service')) { + $ret .= 'Perform/save failed for hostOverride'; + } + + if (!$db->set_prop($dbkey, 'ACCEPT_TERMS', $c->param('ACCEPT_TERMS'), type => 'service')) { + $ret .= 'Perform/save failed for ACCEPT_TERMS'; + } + if (!$db->set_prop($dbkey, 'API', $c->param('API'), type => 'service')) { $ret .= 'Perform/save failed for API'; } + + if (!$db->set_prop($dbkey, 'keysize', $c->param('keysize'), type => 'service')) { + $ret .= 'Perform/save failed for keysize'; + } + + if (!$db->set_prop($dbkey, 'configure', $c->param('configure'), type => 'service')) { + $ret .= 'Perform/save failed for configure'; + } + + if (!$db->set_prop($dbkey, 'email', $c->param('email'), type => 'service')) { + $ret .= 'Perform/save failed for email'; + } + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub perform_PARAMS + +sub perform_CHECKALLDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (!TRUE + ) #copy or perform with value: AllDomainsCheck e.g. $db->set_prop($dbkey,'AllDomainsCheck',$c->param('AllDomainsCheck'),type=>'service')) + { + $ret .= 'Perform/save failed for AllDomainsCheck'; + } ## end if (!TRUE) + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub perform_CHECKALLDOMAINS + +sub perform_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (!TRUE + ) #copy or perform with value: EnabledDomainsCheck e.g. $db->set_prop($dbkey,'EnabledDomainsCheck',$c->param('EnabledDomainsCheck'),type=>'service')) + { + $ret .= 'Perform/save failed for EnabledDomainsCheck'; + } ## end if (!TRUE) + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub perform_CHECKALLENABLEDDOMAINS + +sub perform_CHECKONEDOMAIN { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (!TRUE + ) #copy or perform with value: OneDomainToCheck e.g. $db->set_prop($dbkey,'OneDomainToCheck',$c->param('OneDomainToCheck'),type=>'service')) + { + $ret .= 'Perform/save failed for OneDomainToCheck'; + } ## end if (!TRUE) + + if (!TRUE + ) #copy or perform with value: OneDomainsCheck e.g. $db->set_prop($dbkey,'OneDomainsCheck',$c->param('OneDomainsCheck'),type=>'service')) + { + $ret .= 'Perform/save failed for OneDomainsCheck'; + } ## end if (!TRUE) + if ($ret eq "") { $ret = 'ok'; } + return $ret; +} ## end sub perform_CHECKONEDOMAIN + +sub create_link { + + # WIP + my ($c, $route, $panel, $index) = @_; + my $link = "$route?trt=$panel&Selected=$index"; + return $link; +} ## end sub create_link + +sub get_my_ip { + my ($self, $item, $prop, $default) = @_; + my $output = `/usr/sbin/e-smith/getmyip`; + return $output || "IP"; +} ## end sub get_my_ip + +sub update_one_domain { + my ($self, $domain) = @_; + return "$domain not domain" unless ($ddb->get($domain) || $hdb->get($domain)); + ($domain) = ($domain =~ /([\w\p{L}.]+)/); + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains " " $domain `; + return $output || "-empty-"; +} ## end sub update_one_domain + +sub update_all_domains { + my $self = shift; + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" all `; + return $output || "-empty-"; +} ## end sub update_all_domains + +sub update_enabled_domains { + my $self = shift; + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" enabled `; + return $output || "-empty-"; +} ## end sub update_enabled_domains +1; \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm new file mode 100644 index 0000000..6e700e7 --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm @@ -0,0 +1,448 @@ +package SrvMngr::Controller::Letsencrypt; +# +# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# +#---------------------------------------------------------------------- +# heading : Network +# description : Letsencrypt certificate +# navigation : 6000 6600 +# +# name : letsencrypt, method : get, url : /letsencrypt, ctlact : Letsencrypt#main +# name : letsencryptu, method : post, url : /letsencryptu, ctlact : Letsencrypt#do_update +# name : letsencryptd, method : get, url : /letsencryptd, ctlact : Letsencrypt#do_display +# +# routes : end +# +# Documentation: https://wiki.contribs.org/Letsencrypt +#---------------------------------------------------------------------- +# +# Scheme of things: +# +# TBA!! +use strict; +use warnings; +use Mojo::Base 'Mojolicious::Controller'; +use constant FALSE => 0; +use constant TRUE => 1; +use Locale::gettext; +use SrvMngr::I18N; +use SrvMngr qw(theme_list init_session); +use Data::Dumper; +use esmith::util; +use esmith::util::network; +use esmith::ConfigDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::HostsDB; +use esmith::DomainsDB; +require + '/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm'; #The code that is to be added by the developer + +sub main { + # + # Initial entry - route is "/" + # + #set initial panel + #for initial panel: + #Specifiy panel to enter + #load up _data hash with DB fields + #load up stash with pointer(s) to control fields hash(= get-)) + #and a pointer to the prefix_data hash + #render initial panel + my $c = shift; + $c->app->log->info($c->log_req); + + #The most common ones + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + my $modul = ''; + $lets_data{'trt'} = 'LIST'; + + #Load any DB entries into the _data area so as they are preset in the form + # which DB - this only really works if the initial panel is a PARAMS type panel and not a TABLE + my $db = $cdb; #pickup local or global db or Default to config + $c->do_display($lets_data{'trt'}); +} ## end sub main + +# Post request with params - submit from the form +sub do_update { + # + # Return after submit pushed on panel (this is a post) - route is "/u" + # parameters in the params hash. + # + #load up all params into prefix_data hash: + #By panel (series of if statements - only one executed): + #call validate-PANEL() - return ret = ok or error message + #if validation not ok: + #render back to current panel with error message in stash + #otherwise: + #By panel (series of if statements - only one executed): + #do whatever is required: call perform-PANEL() - return "ok" or Error Message + #call signal-event for any global actions specified (check it exists - error and continue?) + #if action smeserver--update exists + #signal_event smeserver--update + #call signal-event for any specific actions for thids panel (check it exists first - error and continue) + #set success in stash + #if no "nextpanel" entry: + #set firstpanel + #else + #set nextpanel + #call render + my $c = shift; + $c->app->log->info($c->log_req); + my $modul = ''; + + #The most common ones - you might want to comment out any not used. + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + + # Accessing all POST parameters + my %params = $c->req->params->to_hash; + + # Get number of POST parameters + my $num_params = keys %params; + + #Params are available in the hash "params" - copy to the prefix_data hash + #while (my ($key, $value) = each %{$c->req->params->to_hash}) { + # $lets_data{$key} = $value; + #} + # the value of trt will tell you which panel has returned + my $trt = $c->param('trt') || 'LIST'; #hidden control on every form. + my $ret = 'ok'; + + #Validate the parameters in a custom sub one for each panel (although only one of these will be executed) + my $thispanel; + + if ($trt eq 'LIST') { + + #Validate form parameters for panel LIST + $ret = $c->validate_LIST(\%lets_data); + $thispanel = 'LIST'; + } ## end if ($trt eq 'LIST') + + if ($trt eq 'PARAMS') { + + #Validate form parameters for panel PARAMS + $ret = $c->validate_PARAMS(\%lets_data); + $thispanel = 'PARAMS'; + } ## end if ($trt eq 'PARAMS') + + if ($trt eq 'CHECKALLDOMAINS') { + + #Validate form parameters for panel CHECKALLDOMAINS + $ret = $c->validate_CHECKALLDOMAINS(\%lets_data); + $thispanel = 'CHECKALLDOMAINS'; + } ## end if ($trt eq 'CHECKALLDOMAINS') + + if ($trt eq 'CHECKALLENABLEDDOMAINS') { + + #Validate form parameters for panel CHECKALLENABLEDDOMAINS + $ret = $c->validate_CHECKALLENABLEDDOMAINS(\%lets_data); + $thispanel = 'CHECKALLENABLEDDOMAINS'; + } ## end if ($trt eq 'CHECKALLENABLEDDOMAINS') + + if ($trt eq 'CHECKONEDOMAIN') { + + #Validate form parameters for panel CHECKONEDOMAIN + $ret = $c->validate_CHECKONEDOMAIN(\%lets_data); + $thispanel = 'CHECKONEDOMAIN'; + } ## end if ($trt eq 'CHECKONEDOMAIN') + + if ($ret ne "ok") { + $c->do_display($thispanel); + } else { + + #Do whatever is needed, including writing values to the DB + if ($trt eq 'LIST') { + + #do whatever is required ... + $ret = $c->perform_LIST(\%lets_data); + + if ($ret ne "ok") { + + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash(success => $c->l('lets_LIST_panel_action_was_successful')) + ; #A bit bland - edit it in the lex file + } + } ## end if ($trt eq 'LIST') + + if ($trt eq 'PARAMS') { + + #do whatever is required ... + $ret = $c->perform_PARAMS(\%lets_data); + + if ($ret ne "ok") { + + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash(success => $c->l('lets_PARAMS_panel_action_was_successful')) + ; #A bit bland - edit it in the lex file + } + } ## end if ($trt eq 'PARAMS') + + if ($trt eq 'CHECKALLDOMAINS') { + + #do whatever is required ... + $ret = $c->perform_CHECKALLDOMAINS(\%lets_data); + + if ($ret ne "ok") { + + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash(success => $c->l('lets_CHECKALLDOMAINS_panel_action_was_successful')) + ; #A bit bland - edit it in the lex file + } + } ## end if ($trt eq 'CHECKALLDOMAINS') + + if ($trt eq 'CHECKALLENABLEDDOMAINS') { + + #do whatever is required ... + $ret = $c->perform_CHECKALLENABLEDDOMAINS(\%lets_data); + + if ($ret ne "ok") { + + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash(success => $c->l('lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful')) + ; #A bit bland - edit it in the lex file + } + } ## end if ($trt eq 'CHECKALLENABLEDDOMAINS') + + if ($trt eq 'CHECKONEDOMAIN') { + + #do whatever is required ... + $ret = $c->perform_CHECKONEDOMAIN(\%lets_data); + + if ($ret ne "ok") { + + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash(success => $c->l('lets_CHECKONEDOMAIN_panel_action_was_successful')) + ; #A bit bland - edit it in the lex file + } + } ## end if ($trt eq 'CHECKONEDOMAIN') + + # and call any signal-events needed + #TBD + # Setup shared data and call panel + if ('none' eq 'none') { + $lets_data{'trt'} = 'LIST'; + } else { + $lets_data{'trt'} = 'none'; + } + $c->do_display($lets_data{'trt'}); + } ## end else [ if ($ret ne "ok") ] +} ## end sub do_update + +sub do_display { + # + # Return after link clicked in table (this is a get) - route is "/d" + # Expects ?trt=PANEL&selected="TableRowName" plus any other required + # + # OR it maybe a post from the main panel to add a new record + # + #load up all supplied params into prefix_data hash + #call get-selected-PANEL() - returns hash of all relevent parameters + #load up returned hash into prefix_data + #render - to called panel + my ($c, $trt) = @_; + $c->app->log->info($c->log_req); + + #The most common ones - you might want to comment out any not used. + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + my $modul = ""; + + # Accessing all parameters + my $params = $c->req->params->to_hash; + + # Get number of parameters + my $num_params = scalar keys %$params; + + #Tag as Post or Get (ie. create new entry or edit existing one + my $is_new_record = ($c->req->method() eq 'POST'); + + #Params are available in the hash "params" - copy to the prefix_data hash + #while (my ($key, $value) = each %{$c->req->params->to_hash}) { + # $lets_data{$key} = $value; + #} + # the value of trt will tell you which panel has returned + if (!$trt) { + $trt = $c->param('trt') || 'LIST'; #Indicates where to go now + } + + # Now add in the params from the selected row from the table + my %selectedrow; + + if ($trt eq 'LIST') { + + #Validate Get selected row (if applicable) LIST + %selectedrow = $c->get_selected_LIST($lets_data{'Selected'}, $is_new_record); + } ## end if ($trt eq 'LIST') + + if ($trt eq 'PARAMS') { + + #Validate Get selected row (if applicable) PARAMS + %selectedrow = $c->get_selected_PARAMS($lets_data{'Selected'}, $is_new_record); + } ## end if ($trt eq 'PARAMS') + + if ($trt eq 'CHECKALLDOMAINS') { + + #Validate Get selected row (if applicable) CHECKALLDOMAINS + %selectedrow = $c->get_selected_CHECKALLDOMAINS($lets_data{'Selected'}, $is_new_record); + } ## end if ($trt eq 'CHECKALLDOMAINS') + + if ($trt eq 'CHECKALLENABLEDDOMAINS') { + + #Validate Get selected row (if applicable) CHECKALLENABLEDDOMAINS + %selectedrow = $c->get_selected_CHECKALLENABLEDDOMAINS($lets_data{'Selected'}, $is_new_record); + } ## end if ($trt eq 'CHECKALLENABLEDDOMAINS') + + if ($trt eq 'CHECKONEDOMAIN') { + + #Validate Get selected row (if applicable) CHECKONEDOMAIN + %selectedrow = $c->get_selected_CHECKONEDOMAIN($lets_data{'Selected'}, $is_new_record); + } ## end if ($trt eq 'CHECKONEDOMAIN') + + #Copy in the selected row params to the prefix_data hash to pass to the panel + while (my ($key, $value) = each %selectedrow) { + $lets_data{$key} = $value; + } + + # Where to go now + $lets_data{'trt'} = $trt; + + # Set up other shared data according to the panel to go to + if ($trt eq 'LIST') { + + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_LIST(); + + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } ## end if ($trt eq 'LIST') + + if ($trt eq 'PARAMS') { + + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_PARAMS(); + + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } ## end if ($trt eq 'PARAMS') + + if ($trt eq 'CHECKALLDOMAINS') { + + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKALLDOMAINS(); + + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } ## end if ($trt eq 'CHECKALLDOMAINS') + + if ($trt eq 'CHECKALLENABLEDDOMAINS') { + + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKALLENABLEDDOMAINS(); + + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } ## end if ($trt eq 'CHECKALLENABLEDDOMAINS') + + if ($trt eq 'CHECKONEDOMAIN') { + + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKONEDOMAIN(); + + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } ## end if ($trt eq 'CHECKONEDOMAIN') + + # and table control fields + $c->stash(DomainList => $c->get_DomainList()); + + # Data for panel + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); +} ## end sub do_display +1; \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm new file mode 100644 index 0000000..d4bacec --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm @@ -0,0 +1,72 @@ +package SrvMngr::I18N::Modules::Letsencrypt::en; +use strict; +use warnings; +use utf8; +use Mojo::Base 'SrvMngr::I18N'; + +use SrvMngr::I18N::Modules::General::en; + +my %lexicon = ( +# +# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# +'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', +'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', +'lets_SERVICE_STATUS' => 'Service Status', +'lets_EMAIL' => 'Email', +'lets_Back' => 'Back', +'lets_Internal_IP' => 'Internal IP', +'lets_Save' => 'Save', +'lets_Issuer' => 'Issuer', +'lets_IS_IN_CERT' => 'Is In cart', +'lets_For_this_Server' => 'For this Server', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', +'lets_Check_just_one_domain' => 'Check just one domain', +'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', +'lets_Check_all_domains' => 'Check all domains', +'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful', +'lets_Status_Report' => 'Status Report', +'lets_LABEL_NAMESERVERS' => 'Label timeservers', +'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', +'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', +'lets_Error_Status_Report' => 'Error Status Report', +'lets_Not_Before' => 'Not Before', +'lets_Content' => 'Content', +'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt', +'lets_API_STATUS' => 'ape Status', +'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', +'lets_Check_all_enabled_domains' => 'Check all enabled domains', +'lets_All_domains_check_result' => 'All domains check result', +'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful', +'lets_Domains_name' => 'Domains name', +'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', +'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', +'lets_Brief_description' => 'Brief description', +'lets_KEYSIZE_STATUS' => 'Keysize Status', +'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', +'lets_Enabled_domains_check_result' => 'Enabled domains check result', +'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful', +'lets_Internet_IP' => 'Internet IP', +'lets_Expiry' => 'Expiry', +'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', +'lets_LABEL_POINT' => 'Label Point', +'lets_CHECK' => 'Check', +'lets_CONFIG' => 'Config', +'lets_Current_certificate_details' => 'Current certificate details', +'lets_LABEL_LECERT' => 'Label secret', +'lets_One_domain_check_result' => 'One domain check result', +'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful', +'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status', +'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', +'lets_External_Interface_IP' => 'External Interface IP', +'lets_APPLY' => 'Apply', +); + +our %Lexicon = ( + %{ SrvMngr::I18N::Modules::General::en::Lexicon }, + %lexicon +); + + +1; diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex new file mode 100644 index 0000000..965eac8 --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex @@ -0,0 +1,55 @@ +# +# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# edited by bjr 09Jan2025 +# +'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', +'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', +'lets_SERVICE_STATUS' => 'Service Status', +'lets_EMAIL' => 'Email', +'lets_Back' => 'Back', +'lets_Internal_IP' => 'Internal IP', +'lets_Save' => 'Save', +'lets_Issuer' => 'Issuer', +'lets_IS_IN_CERT' => 'Is in certificate', +'lets_For_this_Server' => 'For this Server', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', +'lets_Check_just_one_domain' => 'Check just one domain', +'lets_PARAMS_panel_action_was_successful' => 'Parameter panel action was successful', +'lets_Check_all_domains' => 'Check all domains', +'lets_LIST_panel_action_was_successful' => 'List panel action was successful', +'lets_Status_Report' => 'Status Report', +'lets_LABEL_NAMESERVERS' => 'Label timeservers', +'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', +'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', +'lets_Error_Status_Report' => 'Error Status Report', +'lets_Not_Before' => 'Not Before', +'lets_Content' => 'Content', +'lets_CONFIG_LETSENCRYPT' => 'Configure Letsencrypt', +'lets_API_STATUS' => 'API Status', +'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', +'lets_Check_all_enabled_domains' => 'Check all enabled domains', +'lets_All_domains_check_result' => 'All domains check result', +'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'Check all domains panel action was successful', +'lets_Domains_name' => 'Domains name', +'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', +'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', +'lets_Brief_description' => 'Brief description', +'lets_KEYSIZE_STATUS' => 'Keysize Status', +'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', +'lets_Enabled_domains_check_result' => 'Enabled domains check result', +'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'Check all enabled domains panel action was successful', +'lets_Internet_IP' => 'Internet IP', +'lets_Expiry' => 'Expiry', +'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', +'lets_LABEL_POINT' => 'Label Point', +'lets_CHECK' => 'Check', +'lets_CONFIG' => 'Config', +'lets_Current_certificate_details' => 'Current certificate details', +'lets_LABEL_LECERT' => 'Label secret', +'lets_One_domain_check_result' => 'One domain check result', +'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'Check one domain panel action was successful', +'lets_CONFIGUREMODE_STATUS' => 'Configure mode Status', +'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', +'lets_External_Interface_IP' => 'External Interface IP', +'lets_APPLY' => 'Apply', \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/public/css/letsencrypt.css b/root/usr/share/smanager/themes/default/public/css/letsencrypt.css new file mode 100644 index 0000000..3d2f1ba --- /dev/null +++ b/root/usr/share/smanager/themes/default/public/css/letsencrypt.css @@ -0,0 +1,90 @@ +/* +Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +*/ +.Letsencrypt-panel {} +.name {} +.rout {} +.grou {} +.link2 {} +.link3 {} +.link4 {} +.endg {} +.subh2 {} +.read4 {} +.read5 {} +.read6 {} +.subh3 {} +.read1 {} +.read2 {} +.read3 {} +.subh4 {} +.tabl1 {} +thead .tabl1 {} +tbody .tabl1 {} +.name {} +.rout {} +.subh {} +.para1 {} +.sele1 {} +.sele2 {} +.sele3 {} +.sele4 {} +.sele5 {} +.sele6 {} +.sele7 {} +.emai8 {} +.subm9 {} +.name {} +.rout {} +.head {} +.subh {} +.text1 {} +.back2 {} +.name {} +.rout {} +.head {} +.subh {} +.text1 {} +.back2 {} +.name {} +.rout {} +.head {} +.subh {} +.read1 {} +.text2 {} +.back3 {} + .inline-buttons { + display: flex; /* Use flexbox to arrange items horizontally */ + gap: 10px; /* Optional: Add space between buttons */ + } + + .inline-buttons .link { + /* Additional styling can be added here if needed */ + } + + + .inline-buttons .link { + display: inline-block; /* Keep links as inline-block for button shape */ + padding: 7px 14px; /* Adjusted padding to approximate 70% of the original */ + margin: 0; /* Remove margin */ + background-color: #efefef; /* Light gray background color */ + color: black; /* Text color */ + text-decoration: none; /* Remove underline */ + border: 2px solid #bbb; /* Thin, light gray border */ + border-radius: 3px; /* Slightly rounded corners */ + font-size: 11.2px; /* Adjusted font size to approximate 70% of the original */ + text-align: center; /* Center the text */ + cursor: pointer; /* Pointer cursor on hover */ } + + /* Hover and active effects for better interaction */ + .inline-buttons .link:hover { + background-color: #d9d9d9; /* Darker shade on hover */ + } + + .inline-buttons .link:active { + background-color: #c0c0c0; /* Even darker shade on click */ + } + + span .label { + padding-top:13em; + } diff --git a/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep b/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep new file mode 100644 index 0000000..5224ada --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep @@ -0,0 +1,69 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +% layout 'default', title => "Sme server 2 - Letsencrypt certificate", share_dir => './'; +%# css specific to this panel: +% content_for 'module' => begin +%= stylesheet '/css/letsencrypt.css' +
+ + % if (config->{debug} == 1) { +
+		%= dumper $c->current_route
+		%= dumper $lets_data->{trt}
+	
+ % } + +

<%=$title%>

+ + % if ( stash('modul')) { + %= $c->render_to_string(inline => stash('modul') ); + % } + + %if ($c->stash('first')) { +

+ %=$c->render_to_string(inline =>$c->l($c->stash('first'))) +

+ + %} elsif ($c->stash('success')) { +
+

<%=$c->l('lets_Status_Report') %>

+ %= $c->l($c->stash('success')); +

+
+ + %} elsif ($c->stash('error')) { +
+

<%=$c->l('lets_Error_Status_Report') %>

+ %= $c->l($c->stash('error')); +

+
+ %} + + %#Routing to partials according to trt parameter. + %#This ought to be cascading if/then/elsif, but is easier to just stack the if/then's rather like a case statement' + + % if ($lets_data->{trt} eq "LIST") { + %= include 'partials/_lets_LIST' + %} + + % if ($lets_data->{trt} eq "PARAMS") { + %= include 'partials/_lets_PARAMS' + %} + + % if ($lets_data->{trt} eq "CHECKALLDOMAINS") { + %= include 'partials/_lets_CHECKALLDOMAINS' + %} + + % if ($lets_data->{trt} eq "CHECKALLENABLEDDOMAINS") { + %= include 'partials/_lets_CHECKALLENABLEDDOMAINS' + %} + + % if ($lets_data->{trt} eq "CHECKONEDOMAIN") { + %= include 'partials/_lets_CHECKONEDOMAIN' + %} + + + +
+%end \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep new file mode 100644 index 0000000..69f6508 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep @@ -0,0 +1,45 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if (config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_all_domains')%>

+ +

<%=l('lets_Loop_through_checking_the_letsencrypt')%>

+ + + %=l('lets_All_domains_check_result') + + % param 'AllDomainsCheck' => $lets_data->{AllDomainsCheck} unless param 'AllDomainsCheck'; + %= text_area 'AllDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %my $back_text = l('lets_Back'); # Localized text + %my $actionBack = qq{ + % + % + % + %}; + <%= $c->render_to_string(inline => $actionBack) %> + + + + %# Probably finally by a submit. + %end +
diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep new file mode 100644 index 0000000..2b9f24d --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep @@ -0,0 +1,45 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if (config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_all_enabled_domains')%>

+ +

<%=l('lets_Loop_through_checking_the_letsencrypt')%>

+ + + %=l('lets_Enabled_domains_check_result') + + % param 'EnabledDomainsCheck' => $lets_data->{EnabledDomainsCheck} unless param 'EnabledDomainsCheck'; + %= text_area 'EnabledDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %my $back_text = l('lets_Back'); # Localized text + %my $actionBack = qq{ + % + % + % + %}; + <%= $c->render_to_string(inline => $actionBack) %> + + + + %# Probably finally by a submit. + %end +
diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep new file mode 100644 index 0000000..c578ea4 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep @@ -0,0 +1,52 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if (config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_just_one_domain')%>

+ +

<%=l('lets_Loop_through_and_check_the')%>

+ +

+ %=l('lets_Domains_name') + + % param 'OneDomainToCheck' => $lets_data->{OneDomainToCheck} unless param 'OneDomainToCheck'; + %= text_field 'OneDomainToCheck', size => '50', class => 'textinput OneDomainToCheck' , pattern=>'.*' , placeholder=>'OneDomainToCheck', Readonly=>'true' +

+ + + %=l('lets_One_domain_check_result') + + % param 'OneDomainsCheck' => $lets_data->{OneDomainsCheck} unless param 'OneDomainsCheck'; + %= text_area 'OneDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %my $back_text = l('lets_Back'); # Localized text + %my $actionBack = qq{ + % + % + % + %}; + <%= $c->render_to_string(inline => $actionBack) %> + + + + %# Probably finally by a submit. + %end +
diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep new file mode 100644 index 0000000..9ebcbaa --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep @@ -0,0 +1,126 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if (config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +
+ + + + %= l('lets_CONFIG') + + %#= link_to l('lets_CONFIG'), 'letsencryptd?trt=PARAMS' , class=>'link link2' + + + + %= l('lets_CHECK_ALL_DOMAINS') + + %#= link_to l('lets_CHECK_ALL_DOMAINS'), 'letsencryptd?trt=CHECKALLDOMAINS' , class=>'link link3' + + + + %= l('lets_CHECK_ALL_ENABLED_DOMAINS') + + %#= link_to l('lets_CHECK_ALL_ENABLED_DOMAINS'), 'letsencryptd?trt=CHECKALLENABLEDDOMAINS' , class=>'link link4' + + +
+ + +

<%=l('lets_For_this_Server')%>

+ +

+ %=l('lets_Internal_IP') + + % param 'InternalIP' => $lets_data->{InternalIP} unless param 'InternalIP'; + %= text_field 'InternalIP', size => '50', class => 'textinput InternalIP' , pattern=>'.*' , placeholder=>'InternalIP', Readonly=>'true' +

+ +

+ %=l('lets_External_Interface_IP') + + % param 'ExternalIP' => $lets_data->{ExternalIP} unless param 'ExternalIP'; + %= text_field 'ExternalIP', size => '50', class => 'textinput ExternalIP' , pattern=>'.*' , placeholder=>'ExternalIP', Readonly=>'true' +

+ +

+ %=l('lets_Internet_IP') + + % param 'InternetIP' => $lets_data->{InternetIP} unless param 'InternetIP'; + %= text_field 'InternetIP', size => '50', class => 'textinput InternetIP' , pattern=>'.*' , placeholder=>'InternetIP', Readonly=>'true' +

+ +

<%=l('lets_Current_certificate_details')%>

+ +

+ %=l('lets_Issuer') + + % param 'Issuer' => $lets_data->{Issuer} unless param 'Issuer'; + %= text_field 'Issuer', size => '50', class => 'textinput Issuer' , pattern=>'.*' , placeholder=>'Issuer', Readonly=>'true' +

+ +

+ %=l('lets_Expiry') + + % param 'Expiry' => $lets_data->{Expiry} unless param 'Expiry'; + %= text_field 'Expiry', size => '50', class => 'textinput Expiry' , pattern=>'.*' , placeholder=>'Expiry', Readonly=>'true' +

+ +

+ %=l('lets_Not_Before') + + % param 'NotBefore' => $lets_data->{NotBefore} unless param 'NotBefore'; + %= text_field 'NotBefore', size => '50', class => 'textinput NotBefore' , pattern=>'.*' , placeholder=>'NotBefore', Readonly=>'true' +

+ +

<%=l('lets_List_of_Domains_and_Hosts')%>

+ +
+ + + + + + + + + + + + + + % my $control_data = $c->stash('DomainList'); + % foreach my $row (@$control_data) { + + + + + + + + + + + %} + +
<%=l('lets_Domain_name_/_HOSTNAME')%><%=l('lets_Brief_description')%><%=l('lets_Content')%><%=l('lets_LABEL_NAMESERVERS')%><%=l('lets_LABEL_POINT')%><%=l('lets_LABEL_LECERT')%><%=l('lets_IS_IN_CERT')%><%=l('lets_CHECK')%>
<%=$c->render_to_string(inline=>$row->{'Table1-Domain name / HOSTNAME'})%><%=$c->render_to_string(inline=>$row->{'Table1-Brief description'})%><%=$c->render_to_string(inline=>$row->{'Table1-Content'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_NAMESERVERS'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_POINT'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_LECERT'})%><%=$c->render_to_string(inline=>$row->{'Table1-IS_IN_CERT'})%><%=$c->render_to_string(inline=>$row->{'Table1-CHECK'})%>
+ + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep new file mode 100644 index 0000000..7950547 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep @@ -0,0 +1,97 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if (config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Manage_letsencrypt-config_settings:')%>

+ +

+ %=l('lets_CONFIG_LETSENCRYPT') +

+ +

+ %=l('lets_SERVICE_STATUS') + + % my @status_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled'], ['TEST' => 'test']]; + % param 'status' => $lets_data->{status} unless param 'status'; + %= select_field 'status' => @status_options, class => 'input' +

+ +

+ %=l('lets_HOOKSCRIPT_STATUS') + + % my @hookScript_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled']]; + % param 'hookScript' => $lets_data->{hookScript} unless param 'hookScript'; + %= select_field 'hookScript' => @hookScript_options, class => 'input' +

+ +

+ %=l('lets_HOSTOVERRIDE_STATUS') + + % my @hostOverride_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; + % param 'hostOverride' => $lets_data->{hostOverride} unless param 'hostOverride'; + %= select_field 'hostOverride' => @hostOverride_options, class => 'input' +

+ +

+ %=l('lets_ACCEPT_TERMS_STATUS') + + % my @ACCEPT_TERMS_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; + % param 'ACCEPT_TERMS' => $lets_data->{ACCEPT_TERMS} unless param 'ACCEPT_TERMS'; + %= select_field 'ACCEPT_TERMS' => @ACCEPT_TERMS_options, class => 'input' +

+ +

+ %=l('lets_API_STATUS') + + % my @API_options = [['2' => '2']]; + % param 'API' => $lets_data->{API} unless param 'API'; + %= select_field 'API' => @API_options, class => 'input' +

+ +

+ %=l('lets_KEYSIZE_STATUS') + + % my @keysize_options = [['2048' => '2048'], ['3072' => '3072'], ['4096' => '4096']]; + % param 'keysize' => $lets_data->{keysize} unless param 'keysize'; + %= select_field 'keysize' => @keysize_options, class => 'input' +

+ +

+ %=l('lets_CONFIGUREMODE_STATUS') + + % my @configure_options = [['ALL' => 'all'], ['Domains' => 'domains'], ['HOSTS' => 'hosts'], ['NONE' => 'none']]; + % param 'configure' => $lets_data->{configure} unless param 'configure'; + %= select_field 'configure' => @configure_options, class => 'input' +

+ +

+ %=l('lets_EMAIL') + + % param 'email' => $lets_data->{email} unless param 'email'; + %=email_field 'email', class => 'emai8' +

+ + + + %= submit_button l('lets_Save'), class => 'action subm9' + + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/smeserver-certificates.spec b/smeserver-certificates.spec index 886c154..016610c 100644 --- a/smeserver-certificates.spec +++ b/smeserver-certificates.spec @@ -1,6 +1,6 @@ %define name smeserver-certificates %define version 11.0 -%define release 1 +%define release 2 Summary: This is what smeserver-certificates does. Name: %{name} Version: %{version} @@ -12,15 +12,27 @@ BuildRoot: %{_tmppath}/%{name}-buildroot Prefix: %{_prefix} BuildArchitectures: noarch BuildRequires: smeserver-devtools +Provides: smeserver-letsencrypt +Obsoletes: smeserver-letsencrypt < %{version} Requires: smeserver-release >= 11.0 +Requires: q +Requires: jq +Requires: dehydrated >= 0.6.5 +Requires: smeserver-manager >= 11.0.0-52 AutoReqProv: no %description %changelog +* Wed Feb 12 2025 Jean-Philippe Pialasse 11.0-2.sme +- move smanager panel in package [SME: 12916] +- add Requires +- add templates from smeserver-letsencrypt +- use /var/www/html/.well-known/acme-challenge + * Thu Dec 12 2024 11.0-1.sme -- Initial code - create RPM [SME:12810] +- Initial code - create RPM [SME: 12810] %prep