mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Misc legacy cleanup
This commit is contained in:
parent
3fa96fc91b
commit
1051dbb3cc
20 changed files with 10 additions and 1472 deletions
|
@ -97,9 +97,6 @@ user:
|
||||||
pattern: &pattern_lastname
|
pattern: &pattern_lastname
|
||||||
- !!str ^([^\W\d_]{1,30}[ ,.'-]{0,3})+$
|
- !!str ^([^\W\d_]{1,30}[ ,.'-]{0,3})+$
|
||||||
- "pattern_lastname"
|
- "pattern_lastname"
|
||||||
-m:
|
|
||||||
full: --mail
|
|
||||||
help: (Deprecated, see --domain) Main unique email address
|
|
||||||
-p:
|
-p:
|
||||||
full: --password
|
full: --password
|
||||||
help: User password
|
help: User password
|
||||||
|
@ -596,9 +593,6 @@ app:
|
||||||
app:
|
app:
|
||||||
help: Name, local path or git URL of the app to fetch the manifest of
|
help: Name, local path or git URL of the app to fetch the manifest of
|
||||||
|
|
||||||
fetchlist:
|
|
||||||
deprecated: true
|
|
||||||
|
|
||||||
### app_list()
|
### app_list()
|
||||||
list:
|
list:
|
||||||
action_help: List installed apps
|
action_help: List installed apps
|
||||||
|
@ -770,36 +764,6 @@ app:
|
||||||
new_label:
|
new_label:
|
||||||
help: New app label
|
help: New app label
|
||||||
|
|
||||||
### app_addaccess() TODO: Write help
|
|
||||||
addaccess:
|
|
||||||
action_help: Grant access right to users (everyone by default)
|
|
||||||
deprecated: true
|
|
||||||
arguments:
|
|
||||||
apps:
|
|
||||||
nargs: "+"
|
|
||||||
-u:
|
|
||||||
full: --users
|
|
||||||
nargs: "*"
|
|
||||||
|
|
||||||
### app_removeaccess() TODO: Write help
|
|
||||||
removeaccess:
|
|
||||||
action_help: Revoke access right to users (everyone by default)
|
|
||||||
deprecated: true
|
|
||||||
arguments:
|
|
||||||
apps:
|
|
||||||
nargs: "+"
|
|
||||||
-u:
|
|
||||||
full: --users
|
|
||||||
nargs: "*"
|
|
||||||
|
|
||||||
### app_clearaccess()
|
|
||||||
clearaccess:
|
|
||||||
action_help: Reset access rights for the app
|
|
||||||
deprecated: true
|
|
||||||
arguments:
|
|
||||||
apps:
|
|
||||||
nargs: "+"
|
|
||||||
|
|
||||||
subcategories:
|
subcategories:
|
||||||
|
|
||||||
action:
|
action:
|
||||||
|
@ -1023,13 +987,6 @@ service:
|
||||||
full: --log
|
full: --log
|
||||||
help: Absolute path to log file to display
|
help: Absolute path to log file to display
|
||||||
nargs: "+"
|
nargs: "+"
|
||||||
-t:
|
|
||||||
full: --log_type
|
|
||||||
help: Type of the log (file or systemd)
|
|
||||||
nargs: "+"
|
|
||||||
choices:
|
|
||||||
- file
|
|
||||||
- systemd
|
|
||||||
--test_status:
|
--test_status:
|
||||||
help: Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already.
|
help: Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already.
|
||||||
--test_conf:
|
--test_conf:
|
||||||
|
@ -1043,9 +1000,6 @@ service:
|
||||||
full: --need_lock
|
full: --need_lock
|
||||||
help: Use this option to prevent deadlocks if the service does invoke yunohost commands.
|
help: Use this option to prevent deadlocks if the service does invoke yunohost commands.
|
||||||
action: store_true
|
action: store_true
|
||||||
-s:
|
|
||||||
full: --status
|
|
||||||
help: Deprecated, old option. Does nothing anymore. Possibly check the --test_status option.
|
|
||||||
|
|
||||||
### service_remove()
|
### service_remove()
|
||||||
remove:
|
remove:
|
||||||
|
@ -1147,35 +1101,6 @@ service:
|
||||||
default: 50
|
default: 50
|
||||||
type: int
|
type: int
|
||||||
|
|
||||||
### service_regen_conf()
|
|
||||||
regen-conf:
|
|
||||||
action_help: Regenerate the configuration file(s) for a service
|
|
||||||
deprecated_alias:
|
|
||||||
- regenconf
|
|
||||||
arguments:
|
|
||||||
names:
|
|
||||||
help: Services name to regenerate configuration of
|
|
||||||
nargs: "*"
|
|
||||||
metavar: NAME
|
|
||||||
-d:
|
|
||||||
full: --with-diff
|
|
||||||
help: Show differences in case of configuration changes
|
|
||||||
action: store_true
|
|
||||||
-f:
|
|
||||||
full: --force
|
|
||||||
help: >
|
|
||||||
Override all manual modifications in configuration
|
|
||||||
files
|
|
||||||
action: store_true
|
|
||||||
-n:
|
|
||||||
full: --dry-run
|
|
||||||
help: Show what would have been regenerated
|
|
||||||
action: store_true
|
|
||||||
-p:
|
|
||||||
full: --list-pending
|
|
||||||
help: List pending configuration files and exit
|
|
||||||
action: store_true
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
# Firewall #
|
# Firewall #
|
||||||
#############################
|
#############################
|
||||||
|
@ -1351,14 +1276,6 @@ dyndns:
|
||||||
full: --ipv6
|
full: --ipv6
|
||||||
help: IPv6 address to send
|
help: IPv6 address to send
|
||||||
|
|
||||||
### dyndns_installcron()
|
|
||||||
installcron:
|
|
||||||
deprecated: true
|
|
||||||
|
|
||||||
### dyndns_removecron()
|
|
||||||
removecron:
|
|
||||||
deprecated: true
|
|
||||||
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
# Tools #
|
# Tools #
|
||||||
|
@ -1438,12 +1355,6 @@ tools:
|
||||||
nargs: "?"
|
nargs: "?"
|
||||||
metavar: TARGET
|
metavar: TARGET
|
||||||
default: all
|
default: all
|
||||||
--apps:
|
|
||||||
help: (Deprecated, see first positional arg) Fetch the application list to check which apps can be upgraded
|
|
||||||
action: store_true
|
|
||||||
--system:
|
|
||||||
help: (Deprecated, see first positional arg) Fetch available system packages upgrades (equivalent to apt update)
|
|
||||||
action: store_true
|
|
||||||
|
|
||||||
### tools_upgrade()
|
### tools_upgrade()
|
||||||
upgrade:
|
upgrade:
|
||||||
|
@ -1456,12 +1367,6 @@ tools:
|
||||||
- apps
|
- apps
|
||||||
- system
|
- system
|
||||||
nargs: "?"
|
nargs: "?"
|
||||||
--apps:
|
|
||||||
help: (Deprecated, see first positional arg) Upgrade all applications
|
|
||||||
action: store_true
|
|
||||||
--system:
|
|
||||||
help: (Deprecated, see first positional arg) Upgrade only the system packages
|
|
||||||
action: store_true
|
|
||||||
|
|
||||||
### tools_shell()
|
### tools_shell()
|
||||||
shell:
|
shell:
|
||||||
|
|
|
@ -9,7 +9,6 @@ CAN_BIND=${CAN_BIND:-1}
|
||||||
# | arg: -d, --dest_path= - destination file or directory inside the backup dir
|
# | arg: -d, --dest_path= - destination file or directory inside the backup dir
|
||||||
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
|
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
|
||||||
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
|
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
|
||||||
# | arg: arg - Deprecated arg
|
|
||||||
#
|
#
|
||||||
# This helper can be used both in a system backup hook, and in an app backup script
|
# This helper can be used both in a system backup hook, and in an app backup script
|
||||||
#
|
#
|
||||||
|
@ -303,18 +302,6 @@ ynh_restore_file () {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Deprecated helper since it's a dangerous one!
|
|
||||||
#
|
|
||||||
# [internal]
|
|
||||||
#
|
|
||||||
ynh_bind_or_cp() {
|
|
||||||
local AS_ROOT=${3:-0}
|
|
||||||
local NO_ROOT=0
|
|
||||||
[[ "${AS_ROOT}" = "1" ]] || NO_ROOT=1
|
|
||||||
ynh_print_warn --message="This helper is deprecated, you should use ynh_backup instead"
|
|
||||||
ynh_backup "$1" "$2" 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Calculate and store a file checksum into the app settings
|
# Calculate and store a file checksum into the app settings
|
||||||
#
|
#
|
||||||
# usage: ynh_store_file_checksum --file=file
|
# usage: ynh_store_file_checksum --file=file
|
||||||
|
|
|
@ -503,26 +503,6 @@ ynh_get_debian_release () {
|
||||||
echo $(lsb_release --codename --short)
|
echo $(lsb_release --codename --short)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a directory under /tmp
|
|
||||||
#
|
|
||||||
# [internal]
|
|
||||||
#
|
|
||||||
# Deprecated helper
|
|
||||||
#
|
|
||||||
# usage: ynh_mkdir_tmp
|
|
||||||
# | ret: the created directory path
|
|
||||||
ynh_mkdir_tmp() {
|
|
||||||
ynh_print_warn --message="The helper ynh_mkdir_tmp is deprecated."
|
|
||||||
ynh_print_warn --message="You should use 'mktemp -d' instead and manage permissions \
|
|
||||||
properly with chmod/chown."
|
|
||||||
local TMP_DIR=$(mktemp --directory)
|
|
||||||
|
|
||||||
# Give rights to other users could be a security risk.
|
|
||||||
# But for retrocompatibility we need it. (This helpers is deprecated)
|
|
||||||
chmod 755 $TMP_DIR
|
|
||||||
echo $TMP_DIR
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove a file or a directory securely
|
# Remove a file or a directory securely
|
||||||
#
|
#
|
||||||
# usage: ynh_secure_remove --file=path_to_remove
|
# usage: ynh_secure_remove --file=path_to_remove
|
||||||
|
@ -565,38 +545,6 @@ ynh_secure_remove () {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Extract a key from a plain command output
|
|
||||||
#
|
|
||||||
# [internal]
|
|
||||||
#
|
|
||||||
# (Deprecated, use --output-as json and jq instead)
|
|
||||||
ynh_get_plain_key() {
|
|
||||||
local prefix="#"
|
|
||||||
local founded=0
|
|
||||||
# We call this key_ so that it's not caught as
|
|
||||||
# an info to be redacted by the core
|
|
||||||
local key_=$1
|
|
||||||
shift
|
|
||||||
while read line
|
|
||||||
do
|
|
||||||
if [[ "$founded" == "1" ]]
|
|
||||||
then
|
|
||||||
[[ "$line" =~ ^${prefix}[^#] ]] && return
|
|
||||||
echo $line
|
|
||||||
elif [[ "$line" =~ ^${prefix}${key_}$ ]]
|
|
||||||
then
|
|
||||||
if [[ -n "${1:-}" ]]
|
|
||||||
then
|
|
||||||
prefix+="#"
|
|
||||||
key_=$1
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
founded=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Read the value of a key in a ynh manifest file
|
# Read the value of a key in a ynh manifest file
|
||||||
#
|
#
|
||||||
# usage: ynh_read_manifest --manifest="manifest.json" --key="key"
|
# usage: ynh_read_manifest --manifest="manifest.json" --key="key"
|
||||||
|
|
|
@ -113,11 +113,6 @@ SHELL=/bin/bash
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# legacy stuff to avoid yunohost reporting etckeeper as manually modified
|
|
||||||
# (this make sure that the hash is null / file is flagged as to-delete)
|
|
||||||
mkdir -p $pending_dir/etc/etckeeper
|
|
||||||
touch $pending_dir/etc/etckeeper/etckeeper.conf
|
|
||||||
|
|
||||||
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
|
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
|
||||||
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
|
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
|
||||||
echo "
|
echo "
|
||||||
|
@ -242,13 +237,6 @@ for service, conf in new_services.items():
|
||||||
if conffiles:
|
if conffiles:
|
||||||
services[service]['conffiles'] = conffiles
|
services[service]['conffiles'] = conffiles
|
||||||
|
|
||||||
# Remove legacy /var/log/daemon.log and /var/log/syslog from log entries
|
|
||||||
# because they are too general. Instead, now the journalctl log is
|
|
||||||
# returned by default which is more relevant.
|
|
||||||
if "log" in services[service]:
|
|
||||||
if services[service]["log"] in ["/var/log/syslog", "/var/log/daemon.log"]:
|
|
||||||
del services[service]["log"]
|
|
||||||
|
|
||||||
if updated:
|
if updated:
|
||||||
with open('/etc/yunohost/services.yml-new', 'w') as f:
|
with open('/etc/yunohost/services.yml-new', 'w') as f:
|
||||||
yaml.safe_dump(services, f, default_flow_style=False)
|
yaml.safe_dump(services, f, default_flow_style=False)
|
||||||
|
|
|
@ -7,10 +7,6 @@ set -e
|
||||||
do_pre_regen() {
|
do_pre_regen() {
|
||||||
pending_dir=$1
|
pending_dir=$1
|
||||||
|
|
||||||
# If the (legacy) 'from_script' flag is here,
|
|
||||||
# we won't touch anything in the ssh config.
|
|
||||||
[[ ! -f /etc/yunohost/from_script ]] || return 0
|
|
||||||
|
|
||||||
cd /usr/share/yunohost/templates/ssh
|
cd /usr/share/yunohost/templates/ssh
|
||||||
|
|
||||||
# do not listen to IPv6 if unavailable
|
# do not listen to IPv6 if unavailable
|
||||||
|
@ -34,10 +30,6 @@ do_pre_regen() {
|
||||||
do_post_regen() {
|
do_post_regen() {
|
||||||
regen_conf_files=$1
|
regen_conf_files=$1
|
||||||
|
|
||||||
# If the (legacy) 'from_script' flag is here,
|
|
||||||
# we won't touch anything in the ssh config.
|
|
||||||
[[ ! -f /etc/yunohost/from_script ]] || return 0
|
|
||||||
|
|
||||||
# If no file changed, there's nothing to do
|
# If no file changed, there's nothing to do
|
||||||
[[ -n "$regen_conf_files" ]] || return 0
|
[[ -n "$regen_conf_files" ]] || return 0
|
||||||
|
|
||||||
|
|
|
@ -110,11 +110,6 @@ do_pre_regen() {
|
||||||
schema_dir="${ldap_dir}/schema"
|
schema_dir="${ldap_dir}/schema"
|
||||||
mkdir -p "$ldap_dir" "$schema_dir"
|
mkdir -p "$ldap_dir" "$schema_dir"
|
||||||
|
|
||||||
# remove legacy configuration file
|
|
||||||
[ ! -f /etc/ldap/slapd-yuno.conf ] || touch "${ldap_dir}/slapd-yuno.conf"
|
|
||||||
[ ! -f /etc/ldap/slapd.conf ] || touch "${ldap_dir}/slapd.conf"
|
|
||||||
[ ! -f /etc/ldap/schema/yunohost.schema ] || touch "${schema_dir}/yunohost.schema"
|
|
||||||
|
|
||||||
cd /usr/share/yunohost/templates/slapd
|
cd /usr/share/yunohost/templates/slapd
|
||||||
|
|
||||||
# copy configuration files
|
# copy configuration files
|
||||||
|
|
|
@ -119,20 +119,6 @@ do_post_regen() {
|
||||||
mkdir -p "/etc/nginx/conf.d/${domain}.d"
|
mkdir -p "/etc/nginx/conf.d/${domain}.d"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Get rid of legacy lets encrypt snippets
|
|
||||||
for domain in $YNH_DOMAINS; do
|
|
||||||
# If the legacy letsencrypt / acme-challenge domain-specific snippet is still there
|
|
||||||
if [ -e /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf ]
|
|
||||||
then
|
|
||||||
# And if we're effectively including the new domain-independant snippet now
|
|
||||||
if grep -q "include /etc/nginx/conf.d/acme-challenge.conf.inc;" /etc/nginx/conf.d/${domain}.conf
|
|
||||||
then
|
|
||||||
# Delete the old domain-specific snippet
|
|
||||||
rm /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Reload nginx if conf looks good, otherwise display error and exit unhappy
|
# Reload nginx if conf looks good, otherwise display error and exit unhappy
|
||||||
nginx -t 2>/dev/null || { nginx -t; exit 1; }
|
nginx -t 2>/dev/null || { nginx -t; exit 1; }
|
||||||
pgrep nginx && systemctl reload nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
|
pgrep nginx && systemctl reload nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
|
||||||
|
|
|
@ -30,29 +30,6 @@ do_post_regen() {
|
||||||
echo "" | mysql && echo "Can't connect to mysql using unix_socket auth ... something went wrong during initial configuration of mysql !?" >&2
|
echo "" | mysql && echo "Can't connect to mysql using unix_socket auth ... something went wrong during initial configuration of mysql !?" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Legacy code to get rid of /etc/yunohost/mysql ...
|
|
||||||
# Nowadays, we can simply run mysql while being run as root of unix_socket/auth_socket is enabled...
|
|
||||||
if [ -f /etc/yunohost/mysql ]; then
|
|
||||||
|
|
||||||
# This is a trick to check if we're able to use mysql without password
|
|
||||||
# Expect instances installed in stretch to already have unix_socket
|
|
||||||
#configured, but not old instances from the jessie/wheezy era
|
|
||||||
if ! echo "" | mysql 2>/dev/null
|
|
||||||
then
|
|
||||||
password="$(cat /etc/yunohost/mysql)"
|
|
||||||
# Enable plugin unix_socket for root on localhost
|
|
||||||
mysql -u root -p"$password" <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED WITH unix_socket WITH GRANT OPTION;"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If now we're able to login without password, drop the mysql password
|
|
||||||
if echo "" | mysql 2>/dev/null
|
|
||||||
then
|
|
||||||
rm /etc/yunohost/mysql
|
|
||||||
else
|
|
||||||
echo "Can't connect to mysql using unix_socket auth ... something went wrong while trying to get rid of mysql password !?" >&2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# mysql is supposed to be an alias to mariadb... but in some weird case is not
|
# mysql is supposed to be an alias to mariadb... but in some weird case is not
|
||||||
# c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661
|
# c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661
|
||||||
# Playing with enable/disable allows to recreate the proper symlinks.
|
# Playing with enable/disable allows to recreate the proper symlinks.
|
||||||
|
|
|
@ -137,40 +137,13 @@ def app_search(string):
|
||||||
return catalog_of_apps
|
return catalog_of_apps
|
||||||
|
|
||||||
|
|
||||||
# Old legacy function...
|
def app_list(full=False):
|
||||||
def app_fetchlist():
|
|
||||||
logger.warning(
|
|
||||||
"'yunohost app fetchlist' is deprecated. Please use 'yunohost tools update --apps' instead"
|
|
||||||
)
|
|
||||||
from yunohost.tools import tools_update
|
|
||||||
|
|
||||||
tools_update(target="apps")
|
|
||||||
|
|
||||||
|
|
||||||
def app_list(full=False, installed=False, filter=None):
|
|
||||||
"""
|
"""
|
||||||
List installed apps
|
List installed apps
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Old legacy argument ... app_list was a combination of app_list and
|
|
||||||
# app_catalog before 3.8 ...
|
|
||||||
if installed:
|
|
||||||
logger.warning(
|
|
||||||
"Argument --installed ain't needed anymore when using 'yunohost app list'. It directly returns the list of installed apps.."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Filter is a deprecated option...
|
|
||||||
if filter:
|
|
||||||
logger.warning(
|
|
||||||
"Using -f $appname in 'yunohost app list' is deprecated. Just use 'yunohost app list | grep -q 'id: $appname' to check a specific app is installed"
|
|
||||||
)
|
|
||||||
|
|
||||||
out = []
|
out = []
|
||||||
for app_id in sorted(_installed_apps()):
|
for app_id in sorted(_installed_apps()):
|
||||||
|
|
||||||
if filter and not app_id.startswith(filter):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
app_info_dict = app_info(app_id, full=full)
|
app_info_dict = app_info(app_id, full=full)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -1258,64 +1231,6 @@ def app_remove(operation_logger, app):
|
||||||
_assert_system_is_sane_for_app(manifest, "post")
|
_assert_system_is_sane_for_app(manifest, "post")
|
||||||
|
|
||||||
|
|
||||||
def app_addaccess(apps, users=[]):
|
|
||||||
"""
|
|
||||||
Grant access right to users (everyone by default)
|
|
||||||
|
|
||||||
Keyword argument:
|
|
||||||
users
|
|
||||||
apps
|
|
||||||
|
|
||||||
"""
|
|
||||||
from yunohost.permission import user_permission_update
|
|
||||||
|
|
||||||
output = {}
|
|
||||||
for app in apps:
|
|
||||||
permission = user_permission_update(
|
|
||||||
app + ".main", add=users, remove="all_users"
|
|
||||||
)
|
|
||||||
output[app] = permission["corresponding_users"]
|
|
||||||
|
|
||||||
return {"allowed_users": output}
|
|
||||||
|
|
||||||
|
|
||||||
def app_removeaccess(apps, users=[]):
|
|
||||||
"""
|
|
||||||
Revoke access right to users (everyone by default)
|
|
||||||
|
|
||||||
Keyword argument:
|
|
||||||
users
|
|
||||||
apps
|
|
||||||
|
|
||||||
"""
|
|
||||||
from yunohost.permission import user_permission_update
|
|
||||||
|
|
||||||
output = {}
|
|
||||||
for app in apps:
|
|
||||||
permission = user_permission_update(app + ".main", remove=users)
|
|
||||||
output[app] = permission["corresponding_users"]
|
|
||||||
|
|
||||||
return {"allowed_users": output}
|
|
||||||
|
|
||||||
|
|
||||||
def app_clearaccess(apps):
|
|
||||||
"""
|
|
||||||
Reset access rights for the app
|
|
||||||
|
|
||||||
Keyword argument:
|
|
||||||
apps
|
|
||||||
|
|
||||||
"""
|
|
||||||
from yunohost.permission import user_permission_reset
|
|
||||||
|
|
||||||
output = {}
|
|
||||||
for app in apps:
|
|
||||||
permission = user_permission_reset(app + ".main")
|
|
||||||
output[app] = permission["corresponding_users"]
|
|
||||||
|
|
||||||
return {"allowed_users": output}
|
|
||||||
|
|
||||||
|
|
||||||
@is_unit_operation()
|
@is_unit_operation()
|
||||||
def app_makedefault(operation_logger, app, domain=None):
|
def app_makedefault(operation_logger, app, domain=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1643,10 +1558,6 @@ def app_ssowatconf():
|
||||||
|
|
||||||
write_to_json("/etc/ssowat/conf.json", conf_dict, sort_keys=True, indent=4)
|
write_to_json("/etc/ssowat/conf.json", conf_dict, sort_keys=True, indent=4)
|
||||||
|
|
||||||
from .utils.legacy import translate_legacy_rules_in_ssowant_conf_json_persistent
|
|
||||||
|
|
||||||
translate_legacy_rules_in_ssowant_conf_json_persistent()
|
|
||||||
|
|
||||||
logger.debug(m18n.n("ssowat_conf_generated"))
|
logger.debug(m18n.n("ssowat_conf_generated"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -3542,36 +3453,10 @@ def _patch_legacy_helpers(app_folder):
|
||||||
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
|
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
|
||||||
|
|
||||||
stuff_to_replace = {
|
stuff_to_replace = {
|
||||||
# Replace
|
"yunohost app initdb": {"important": True},
|
||||||
# sudo yunohost app initdb $db_user -p $db_pwd
|
"yunohost app checkport": {"important": True},
|
||||||
# by
|
|
||||||
# ynh_mysql_setup_db --db_user=$db_user --db_name=$db_user --db_pwd=$db_pwd
|
|
||||||
"yunohost app initdb": {
|
|
||||||
"pattern": r"(sudo )?yunohost app initdb \"?(\$\{?\w+\}?)\"?\s+-p\s\"?(\$\{?\w+\}?)\"?",
|
|
||||||
"replace": r"ynh_mysql_setup_db --db_user=\2 --db_name=\2 --db_pwd=\3",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# Replace
|
|
||||||
# sudo yunohost app checkport whaterver
|
|
||||||
# by
|
|
||||||
# ynh_port_available whatever
|
|
||||||
"yunohost app checkport": {
|
|
||||||
"pattern": r"(sudo )?yunohost app checkport",
|
|
||||||
"replace": r"ynh_port_available",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# We can't migrate easily port-available
|
|
||||||
# .. but at the time of writing this code, only two non-working apps are using it.
|
|
||||||
"yunohost tools port-available": {"important": True},
|
"yunohost tools port-available": {"important": True},
|
||||||
# Replace
|
"yunohost app checkurl": {"important": True},
|
||||||
# yunohost app checkurl "${domain}${path_url}" -a "${app}"
|
|
||||||
# by
|
|
||||||
# ynh_webpath_register --app=${app} --domain=${domain} --path_url=${path_url}
|
|
||||||
"yunohost app checkurl": {
|
|
||||||
"pattern": r"(sudo )?yunohost app checkurl \"?(\$\{?\w+\}?)\/?(\$\{?\w+\}?)\"?\s+-a\s\"?(\$\{?\w+\}?)\"?",
|
|
||||||
"replace": r"ynh_webpath_register --app=\4 --domain=\2 --path_url=\3",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# Remove
|
# Remove
|
||||||
# Automatic diagnosis data from YunoHost
|
# Automatic diagnosis data from YunoHost
|
||||||
# __PRE_TAG1__$(yunohost tools diagnosis | ...)__PRE_TAG2__"
|
# __PRE_TAG1__$(yunohost tools diagnosis | ...)__PRE_TAG2__"
|
||||||
|
@ -3582,26 +3467,11 @@ def _patch_legacy_helpers(app_folder):
|
||||||
"important": False,
|
"important": False,
|
||||||
},
|
},
|
||||||
# Old $1, $2 in backup/restore scripts...
|
# Old $1, $2 in backup/restore scripts...
|
||||||
"app=$2": {
|
"app=$2": {"only_for": ["scripts/backup", "scripts/restore"], "important": True},
|
||||||
"only_for": ["scripts/backup", "scripts/restore"],
|
|
||||||
"pattern": r"app=\$2",
|
|
||||||
"replace": r"app=$YNH_APP_INSTANCE_NAME",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# Old $1, $2 in backup/restore scripts...
|
# Old $1, $2 in backup/restore scripts...
|
||||||
"backup_dir=$1": {
|
"backup_dir=$1": {"only_for": ["scripts/backup", "scripts/restore"], "important": True},
|
||||||
"only_for": ["scripts/backup", "scripts/restore"],
|
|
||||||
"pattern": r"backup_dir=\$1",
|
|
||||||
"replace": r"backup_dir=.",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# Old $1, $2 in backup/restore scripts...
|
# Old $1, $2 in backup/restore scripts...
|
||||||
"restore_dir=$1": {
|
"restore_dir=$1": {"only_for": ["scripts/restore"], "important": True},
|
||||||
"only_for": ["scripts/restore"],
|
|
||||||
"pattern": r"restore_dir=\$1",
|
|
||||||
"replace": r"restore_dir=.",
|
|
||||||
"important": True,
|
|
||||||
},
|
|
||||||
# Old $1, $2 in install scripts...
|
# Old $1, $2 in install scripts...
|
||||||
# We ain't patching that shit because it ain't trivial to patch all args...
|
# We ain't patching that shit because it ain't trivial to patch all args...
|
||||||
"domain=$1": {"only_for": ["scripts/install"], "important": True},
|
"domain=$1": {"only_for": ["scripts/install"], "important": True},
|
||||||
|
|
|
@ -1,291 +0,0 @@
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from yunohost.utils.error import YunohostError
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
from moulinette.utils.process import check_output, call_async_output
|
|
||||||
from moulinette.utils.filesystem import read_file
|
|
||||||
|
|
||||||
from yunohost.tools import Migration, tools_update, tools_upgrade
|
|
||||||
from yunohost.app import unstable_apps
|
|
||||||
from yunohost.regenconf import manually_modified_files
|
|
||||||
from yunohost.utils.filesystem import free_space_in_directory
|
|
||||||
from yunohost.utils.packages import (
|
|
||||||
get_ynh_package_version,
|
|
||||||
_list_upgradable_apt_packages,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
|
|
||||||
"Upgrade the system to Debian Buster and Yunohost 4.x"
|
|
||||||
|
|
||||||
mode = "manual"
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
self.check_assertions()
|
|
||||||
|
|
||||||
logger.info(m18n.n("migration_0015_start"))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Make sure certificates do not use weak signature hash algorithms (md5, sha1)
|
|
||||||
# otherwise nginx will later refuse to start which result in
|
|
||||||
# catastrophic situation
|
|
||||||
#
|
|
||||||
self.validate_and_upgrade_cert_if_necessary()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Patch sources.list
|
|
||||||
#
|
|
||||||
logger.info(m18n.n("migration_0015_patching_sources_list"))
|
|
||||||
self.patch_apt_sources_list()
|
|
||||||
tools_update(target="system")
|
|
||||||
|
|
||||||
# Tell libc6 it's okay to restart system stuff during the upgrade
|
|
||||||
os.system(
|
|
||||||
"echo 'libc6 libraries/restart-without-asking boolean true' | debconf-set-selections"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Don't send an email to root about the postgresql migration. It should be handled automatically after.
|
|
||||||
os.system(
|
|
||||||
"echo 'postgresql-common postgresql-common/obsolete-major seen true' | debconf-set-selections"
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Specific packages upgrades
|
|
||||||
#
|
|
||||||
logger.info(m18n.n("migration_0015_specific_upgrade"))
|
|
||||||
|
|
||||||
# Update unscd independently, was 0.53-1+yunohost on stretch (custom build of ours) but now it's 0.53-1+b1 on vanilla buster,
|
|
||||||
# which for apt appears as a lower version (hence the --allow-downgrades and the hardcoded version number)
|
|
||||||
unscd_version = check_output(
|
|
||||||
'dpkg -s unscd | grep "^Version: " | cut -d " " -f 2'
|
|
||||||
)
|
|
||||||
if "yunohost" in unscd_version:
|
|
||||||
new_version = check_output(
|
|
||||||
"LC_ALL=C apt policy unscd 2>/dev/null | grep -v '\\*\\*\\*' | grep http -B1 | head -n 1 | awk '{print $1}'"
|
|
||||||
).strip()
|
|
||||||
if new_version:
|
|
||||||
self.apt_install("unscd=%s --allow-downgrades" % new_version)
|
|
||||||
else:
|
|
||||||
logger.warning("Could not identify which version of unscd to install")
|
|
||||||
|
|
||||||
# Upgrade libpam-modules independently, small issue related to willing to overwrite a file previously provided by Yunohost
|
|
||||||
libpammodules_version = check_output(
|
|
||||||
'dpkg -s libpam-modules | grep "^Version: " | cut -d " " -f 2'
|
|
||||||
)
|
|
||||||
if not libpammodules_version.startswith("1.3"):
|
|
||||||
self.apt_install('libpam-modules -o Dpkg::Options::="--force-overwrite"')
|
|
||||||
|
|
||||||
#
|
|
||||||
# Main upgrade
|
|
||||||
#
|
|
||||||
logger.info(m18n.n("migration_0015_main_upgrade"))
|
|
||||||
|
|
||||||
apps_packages = self.get_apps_equivs_packages()
|
|
||||||
self.hold(apps_packages)
|
|
||||||
tools_upgrade(target="system", allow_yunohost_upgrade=False)
|
|
||||||
|
|
||||||
if self.debian_major_version() == 9:
|
|
||||||
raise YunohostError("migration_0015_still_on_stretch_after_main_upgrade")
|
|
||||||
|
|
||||||
# Clean the mess
|
|
||||||
logger.info(m18n.n("migration_0015_cleaning_up"))
|
|
||||||
os.system("apt autoremove --assume-yes")
|
|
||||||
os.system("apt clean --assume-yes")
|
|
||||||
|
|
||||||
#
|
|
||||||
# Yunohost upgrade
|
|
||||||
#
|
|
||||||
logger.info(m18n.n("migration_0015_yunohost_upgrade"))
|
|
||||||
self.unhold(apps_packages)
|
|
||||||
tools_upgrade(target="system")
|
|
||||||
|
|
||||||
def debian_major_version(self):
|
|
||||||
# The python module "platform" and lsb_release are not reliable because
|
|
||||||
# on some setup, they may still return Release=9 even after upgrading to
|
|
||||||
# buster ... (Apparently this is related to OVH overriding some stuff
|
|
||||||
# with /etc/lsb-release for instance -_-)
|
|
||||||
# Instead, we rely on /etc/os-release which should be the raw info from
|
|
||||||
# the distribution...
|
|
||||||
return int(
|
|
||||||
check_output(
|
|
||||||
"grep VERSION_ID /etc/os-release | head -n 1 | tr '\"' ' ' | cut -d ' ' -f2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def yunohost_major_version(self):
|
|
||||||
return int(get_ynh_package_version("yunohost")["version"].split(".")[0])
|
|
||||||
|
|
||||||
def check_assertions(self):
|
|
||||||
|
|
||||||
# Be on stretch (9.x) and yunohost 3.x
|
|
||||||
# NB : we do both check to cover situations where the upgrade crashed
|
|
||||||
# in the middle and debian version could be > 9.x but yunohost package
|
|
||||||
# would still be in 3.x...
|
|
||||||
if (
|
|
||||||
not self.debian_major_version() == 9
|
|
||||||
and not self.yunohost_major_version() == 3
|
|
||||||
):
|
|
||||||
raise YunohostError("migration_0015_not_stretch")
|
|
||||||
|
|
||||||
# Have > 1 Go free space on /var/ ?
|
|
||||||
if free_space_in_directory("/var/") / (1024 ** 3) < 1.0:
|
|
||||||
raise YunohostError("migration_0015_not_enough_free_space")
|
|
||||||
|
|
||||||
# Check system is up to date
|
|
||||||
# (but we don't if 'stretch' is already in the sources.list ...
|
|
||||||
# which means maybe a previous upgrade crashed and we're re-running it)
|
|
||||||
if " buster " not in read_file("/etc/apt/sources.list"):
|
|
||||||
tools_update(target="system")
|
|
||||||
upgradable_system_packages = list(_list_upgradable_apt_packages())
|
|
||||||
if upgradable_system_packages:
|
|
||||||
raise YunohostError("migration_0015_system_not_fully_up_to_date")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def disclaimer(self):
|
|
||||||
|
|
||||||
# Avoid having a super long disclaimer + uncessary check if we ain't
|
|
||||||
# on stretch / yunohost 3.x anymore
|
|
||||||
# NB : we do both check to cover situations where the upgrade crashed
|
|
||||||
# in the middle and debian version could be >= 10.x but yunohost package
|
|
||||||
# would still be in 3.x...
|
|
||||||
if (
|
|
||||||
not self.debian_major_version() == 9
|
|
||||||
and not self.yunohost_major_version() == 3
|
|
||||||
):
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Get list of problematic apps ? I.e. not official or community+working
|
|
||||||
problematic_apps = unstable_apps()
|
|
||||||
problematic_apps = "".join(["\n - " + app for app in problematic_apps])
|
|
||||||
|
|
||||||
# Manually modified files ? (c.f. yunohost service regen-conf)
|
|
||||||
modified_files = manually_modified_files()
|
|
||||||
modified_files = "".join(["\n - " + f for f in modified_files])
|
|
||||||
|
|
||||||
message = m18n.n("migration_0015_general_warning")
|
|
||||||
|
|
||||||
message = (
|
|
||||||
"N.B.: This migration has been tested by the community over the last few months but has only been declared stable recently. If your server hosts critical services and if you are not too confident with debugging possible issues, we recommend you to wait a little bit more while we gather more feedback and polish things up. If on the other hand you are relatively confident with debugging small issues that may arise, you are encouraged to run this migration ;)! You can read about remaining known issues and feedback from the community here: https://forum.yunohost.org/t/12195\n\n"
|
|
||||||
+ message
|
|
||||||
)
|
|
||||||
|
|
||||||
if problematic_apps:
|
|
||||||
message += "\n\n" + m18n.n(
|
|
||||||
"migration_0015_problematic_apps_warning",
|
|
||||||
problematic_apps=problematic_apps,
|
|
||||||
)
|
|
||||||
|
|
||||||
if modified_files:
|
|
||||||
message += "\n\n" + m18n.n(
|
|
||||||
"migration_0015_modified_files", manually_modified_files=modified_files
|
|
||||||
)
|
|
||||||
|
|
||||||
return message
|
|
||||||
|
|
||||||
def patch_apt_sources_list(self):
|
|
||||||
|
|
||||||
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
|
|
||||||
sources_list.append("/etc/apt/sources.list")
|
|
||||||
|
|
||||||
# This :
|
|
||||||
# - replace single 'stretch' occurence by 'buster'
|
|
||||||
# - comments lines containing "backports"
|
|
||||||
# - replace 'stretch/updates' by 'strech/updates' (or same with -)
|
|
||||||
for f in sources_list:
|
|
||||||
command = (
|
|
||||||
"sed -i -e 's@ stretch @ buster @g' "
|
|
||||||
"-e '/backports/ s@^#*@#@' "
|
|
||||||
"-e 's@ stretch/updates @ buster/updates @g' "
|
|
||||||
"-e 's@ stretch-@ buster-@g' "
|
|
||||||
"{}".format(f)
|
|
||||||
)
|
|
||||||
os.system(command)
|
|
||||||
|
|
||||||
def get_apps_equivs_packages(self):
|
|
||||||
|
|
||||||
command = (
|
|
||||||
"dpkg --get-selections"
|
|
||||||
" | grep -v deinstall"
|
|
||||||
" | awk '{print $1}'"
|
|
||||||
" | { grep 'ynh-deps$' || true; }"
|
|
||||||
)
|
|
||||||
|
|
||||||
output = check_output(command)
|
|
||||||
|
|
||||||
return output.split("\n") if output else []
|
|
||||||
|
|
||||||
def hold(self, packages):
|
|
||||||
for package in packages:
|
|
||||||
os.system("apt-mark hold {}".format(package))
|
|
||||||
|
|
||||||
def unhold(self, packages):
|
|
||||||
for package in packages:
|
|
||||||
os.system("apt-mark unhold {}".format(package))
|
|
||||||
|
|
||||||
def apt_install(self, cmd):
|
|
||||||
def is_relevant(line):
|
|
||||||
return "Reading database ..." not in line.rstrip()
|
|
||||||
|
|
||||||
callbacks = (
|
|
||||||
lambda l: logger.info("+ " + l.rstrip() + "\r")
|
|
||||||
if is_relevant(l)
|
|
||||||
else logger.debug(l.rstrip() + "\r"),
|
|
||||||
lambda l: logger.warning(l.rstrip()),
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd = (
|
|
||||||
"LC_ALL=C DEBIAN_FRONTEND=noninteractive APT_LISTCHANGES_FRONTEND=none apt install --quiet -o=Dpkg::Use-Pty=0 --fix-broken --assume-yes "
|
|
||||||
+ cmd
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug("Running: %s" % cmd)
|
|
||||||
|
|
||||||
call_async_output(cmd, callbacks, shell=True)
|
|
||||||
|
|
||||||
def validate_and_upgrade_cert_if_necessary(self):
|
|
||||||
|
|
||||||
active_certs = set(
|
|
||||||
check_output("grep -roh '/.*crt.pem' /etc/nginx/").split("\n")
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd = "LC_ALL=C openssl x509 -in %s -text -noout | grep -i 'Signature Algorithm:' | awk '{print $3}' | uniq"
|
|
||||||
|
|
||||||
default_crt = "/etc/yunohost/certs/yunohost.org/crt.pem"
|
|
||||||
default_key = "/etc/yunohost/certs/yunohost.org/key.pem"
|
|
||||||
default_signature = (
|
|
||||||
check_output(cmd % default_crt) if default_crt in active_certs else None
|
|
||||||
)
|
|
||||||
if default_signature is not None and (
|
|
||||||
default_signature.startswith("md5") or default_signature.startswith("sha1")
|
|
||||||
):
|
|
||||||
logger.warning(
|
|
||||||
"%s is using a pretty old certificate incompatible with newer versions of nginx ... attempting to regenerate a fresh one"
|
|
||||||
% default_crt
|
|
||||||
)
|
|
||||||
|
|
||||||
os.system("mv %s %s.old" % (default_crt, default_crt))
|
|
||||||
os.system("mv %s %s.old" % (default_key, default_key))
|
|
||||||
ret = os.system("/usr/share/yunohost/hooks/conf_regen/02-ssl init")
|
|
||||||
|
|
||||||
if ret != 0 or not os.path.exists(default_crt):
|
|
||||||
logger.error("Upgrading the certificate failed ... reverting")
|
|
||||||
os.system("mv %s.old %s" % (default_crt, default_crt))
|
|
||||||
os.system("mv %s.old %s" % (default_key, default_key))
|
|
||||||
|
|
||||||
signatures = {cert: check_output(cmd % cert) for cert in active_certs}
|
|
||||||
|
|
||||||
def cert_is_weak(cert):
|
|
||||||
sig = signatures[cert]
|
|
||||||
return sig.startswith("md5") or sig.startswith("sha1")
|
|
||||||
|
|
||||||
weak_certs = [cert for cert in signatures.keys() if cert_is_weak(cert)]
|
|
||||||
if weak_certs:
|
|
||||||
raise YunohostError(
|
|
||||||
"migration_0015_weak_certs", certs=", ".join(weak_certs)
|
|
||||||
)
|
|
|
@ -1,83 +0,0 @@
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
from shutil import copy2
|
|
||||||
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
|
|
||||||
from yunohost.app import _is_installed, _patch_legacy_php_versions_in_settings
|
|
||||||
from yunohost.tools import Migration
|
|
||||||
from yunohost.service import _run_service_command
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
PHP70_POOLS = "/etc/php/7.0/fpm/pool.d"
|
|
||||||
PHP73_POOLS = "/etc/php/7.3/fpm/pool.d"
|
|
||||||
|
|
||||||
PHP70_SOCKETS_PREFIX = "/run/php/php7.0-fpm"
|
|
||||||
PHP73_SOCKETS_PREFIX = "/run/php/php7.3-fpm"
|
|
||||||
|
|
||||||
MIGRATION_COMMENT = (
|
|
||||||
"; YunoHost note : this file was automatically moved from {}".format(PHP70_POOLS)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
|
|
||||||
"Migrate php7.0-fpm 'pool' conf files to php7.3"
|
|
||||||
|
|
||||||
dependencies = ["migrate_to_buster"]
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
# Get list of php7.0 pool files
|
|
||||||
php70_pool_files = glob.glob("{}/*.conf".format(PHP70_POOLS))
|
|
||||||
|
|
||||||
# Keep only basenames
|
|
||||||
php70_pool_files = [os.path.basename(f) for f in php70_pool_files]
|
|
||||||
|
|
||||||
# Ignore the "www.conf" (default stuff, probably don't want to touch it ?)
|
|
||||||
php70_pool_files = [f for f in php70_pool_files if f != "www.conf"]
|
|
||||||
|
|
||||||
for f in php70_pool_files:
|
|
||||||
|
|
||||||
# Copy the files to the php7.3 pool
|
|
||||||
src = "{}/{}".format(PHP70_POOLS, f)
|
|
||||||
dest = "{}/{}".format(PHP73_POOLS, f)
|
|
||||||
copy2(src, dest)
|
|
||||||
|
|
||||||
# Replace the socket prefix if it's found
|
|
||||||
c = "sed -i -e 's@{}@{}@g' {}".format(
|
|
||||||
PHP70_SOCKETS_PREFIX, PHP73_SOCKETS_PREFIX, dest
|
|
||||||
)
|
|
||||||
os.system(c)
|
|
||||||
|
|
||||||
# Also add a comment that it was automatically moved from php7.0
|
|
||||||
# (for human traceability and backward migration)
|
|
||||||
c = "sed -i '1i {}' {}".format(MIGRATION_COMMENT, dest)
|
|
||||||
os.system(c)
|
|
||||||
|
|
||||||
app_id = os.path.basename(f)[: -len(".conf")]
|
|
||||||
if _is_installed(app_id):
|
|
||||||
_patch_legacy_php_versions_in_settings(
|
|
||||||
"/etc/yunohost/apps/%s/" % app_id
|
|
||||||
)
|
|
||||||
|
|
||||||
nginx_conf_files = glob.glob("/etc/nginx/conf.d/*.d/%s.conf" % app_id)
|
|
||||||
for f in nginx_conf_files:
|
|
||||||
# Replace the socket prefix if it's found
|
|
||||||
c = "sed -i -e 's@{}@{}@g' {}".format(
|
|
||||||
PHP70_SOCKETS_PREFIX, PHP73_SOCKETS_PREFIX, f
|
|
||||||
)
|
|
||||||
os.system(c)
|
|
||||||
|
|
||||||
os.system(
|
|
||||||
"rm /etc/logrotate.d/php7.0-fpm"
|
|
||||||
) # We remove this otherwise the logrotate cron will be unhappy
|
|
||||||
|
|
||||||
# Reload/restart the php pools
|
|
||||||
_run_service_command("restart", "php7.3-fpm")
|
|
||||||
_run_service_command("enable", "php7.3-fpm")
|
|
||||||
os.system("systemctl stop php7.0-fpm")
|
|
||||||
os.system("systemctl disable php7.0-fpm")
|
|
||||||
|
|
||||||
# Reload nginx
|
|
||||||
_run_service_command("reload", "nginx")
|
|
|
@ -1,82 +0,0 @@
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
|
|
||||||
from yunohost.tools import Migration
|
|
||||||
from yunohost.utils.filesystem import free_space_in_directory, space_used_by_directory
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
|
|
||||||
"Migrate DBs from Postgresql 9.6 to 11 after migrating to Buster"
|
|
||||||
|
|
||||||
dependencies = ["migrate_to_buster"]
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
if not self.package_is_installed("postgresql-9.6"):
|
|
||||||
logger.warning(m18n.n("migration_0017_postgresql_96_not_installed"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self.package_is_installed("postgresql-11"):
|
|
||||||
raise YunohostValidationError("migration_0017_postgresql_11_not_installed")
|
|
||||||
|
|
||||||
# Make sure there's a 9.6 cluster
|
|
||||||
try:
|
|
||||||
self.runcmd("pg_lsclusters | grep -q '^9.6 '")
|
|
||||||
except Exception:
|
|
||||||
logger.warning(
|
|
||||||
"It looks like there's not active 9.6 cluster, so probably don't need to run this migration"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if not space_used_by_directory(
|
|
||||||
"/var/lib/postgresql/9.6"
|
|
||||||
) > free_space_in_directory("/var/lib/postgresql"):
|
|
||||||
raise YunohostValidationError(
|
|
||||||
"migration_0017_not_enough_space", path="/var/lib/postgresql/"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.runcmd("systemctl stop postgresql")
|
|
||||||
self.runcmd(
|
|
||||||
"LC_ALL=C pg_dropcluster --stop 11 main || true"
|
|
||||||
) # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster)
|
|
||||||
self.runcmd("LC_ALL=C pg_upgradecluster -m upgrade 9.6 main")
|
|
||||||
self.runcmd("LC_ALL=C pg_dropcluster --stop 9.6 main")
|
|
||||||
self.runcmd("systemctl start postgresql")
|
|
||||||
|
|
||||||
def package_is_installed(self, package_name):
|
|
||||||
|
|
||||||
(returncode, out, err) = self.runcmd(
|
|
||||||
"dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name),
|
|
||||||
raise_on_errors=False,
|
|
||||||
)
|
|
||||||
return returncode == 0
|
|
||||||
|
|
||||||
def runcmd(self, cmd, raise_on_errors=True):
|
|
||||||
|
|
||||||
logger.debug("Running command: " + cmd)
|
|
||||||
|
|
||||||
p = subprocess.Popen(
|
|
||||||
cmd,
|
|
||||||
shell=True,
|
|
||||||
executable="/bin/bash",
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
|
|
||||||
out, err = p.communicate()
|
|
||||||
returncode = p.returncode
|
|
||||||
if raise_on_errors and returncode != 0:
|
|
||||||
raise YunohostError(
|
|
||||||
"Failed to run command '{}'.\nreturncode: {}\nstdout:\n{}\nstderr:\n{}\n".format(
|
|
||||||
cmd, returncode, out, err
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
out = out.strip().split("\n")
|
|
||||||
return (returncode, out, err)
|
|
|
@ -1,126 +0,0 @@
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from yunohost.utils.error import YunohostError
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
|
|
||||||
from yunohost.firewall import firewall_reload
|
|
||||||
from yunohost.service import service_restart
|
|
||||||
from yunohost.tools import Migration
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
|
|
||||||
"Migrate legacy iptables rules from stretch that relied on xtable and should now rely on nftable"
|
|
||||||
|
|
||||||
dependencies = ["migrate_to_buster"]
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
self.do_ipv4 = os.system("iptables -w -L >/dev/null") == 0
|
|
||||||
self.do_ipv6 = os.system("ip6tables -w -L >/dev/null") == 0
|
|
||||||
|
|
||||||
if not self.do_ipv4:
|
|
||||||
logger.warning(m18n.n("iptables_unavailable"))
|
|
||||||
if not self.do_ipv6:
|
|
||||||
logger.warning(m18n.n("ip6tables_unavailable"))
|
|
||||||
|
|
||||||
backup_folder = "/home/yunohost.backup/premigration/xtable_to_nftable/"
|
|
||||||
if not os.path.exists(backup_folder):
|
|
||||||
os.makedirs(backup_folder, 0o750)
|
|
||||||
self.backup_rules_ipv4 = os.path.join(backup_folder, "legacy_rules_ipv4")
|
|
||||||
self.backup_rules_ipv6 = os.path.join(backup_folder, "legacy_rules_ipv6")
|
|
||||||
|
|
||||||
# Backup existing legacy rules to be able to rollback
|
|
||||||
if self.do_ipv4 and not os.path.exists(self.backup_rules_ipv4):
|
|
||||||
self.runcmd(
|
|
||||||
"iptables-legacy -L >/dev/null"
|
|
||||||
) # For some reason if we don't do this, iptables-legacy-save is empty ?
|
|
||||||
self.runcmd("iptables-legacy-save > %s" % self.backup_rules_ipv4)
|
|
||||||
assert (
|
|
||||||
open(self.backup_rules_ipv4).read().strip()
|
|
||||||
), "Uhoh backup of legacy ipv4 rules is empty !?"
|
|
||||||
if self.do_ipv6 and not os.path.exists(self.backup_rules_ipv6):
|
|
||||||
self.runcmd(
|
|
||||||
"ip6tables-legacy -L >/dev/null"
|
|
||||||
) # For some reason if we don't do this, iptables-legacy-save is empty ?
|
|
||||||
self.runcmd("ip6tables-legacy-save > %s" % self.backup_rules_ipv6)
|
|
||||||
assert (
|
|
||||||
open(self.backup_rules_ipv6).read().strip()
|
|
||||||
), "Uhoh backup of legacy ipv6 rules is empty !?"
|
|
||||||
|
|
||||||
# We inject the legacy rules (iptables-legacy) into the new iptable (just "iptables")
|
|
||||||
try:
|
|
||||||
if self.do_ipv4:
|
|
||||||
self.runcmd("iptables-legacy-save | iptables-restore")
|
|
||||||
if self.do_ipv6:
|
|
||||||
self.runcmd("ip6tables-legacy-save | ip6tables-restore")
|
|
||||||
except Exception as e:
|
|
||||||
self.rollback()
|
|
||||||
raise YunohostError(
|
|
||||||
"migration_0018_failed_to_migrate_iptables_rules", error=e
|
|
||||||
)
|
|
||||||
|
|
||||||
# Reset everything in iptables-legacy
|
|
||||||
# Stolen from https://serverfault.com/a/200642
|
|
||||||
try:
|
|
||||||
if self.do_ipv4:
|
|
||||||
self.runcmd(
|
|
||||||
"iptables-legacy-save | awk '/^[*]/ { print $1 }" # Keep lines like *raw, *filter and *nat
|
|
||||||
' /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }' # Turn all policies to accept
|
|
||||||
" /COMMIT/ { print $0; }'" # Keep the line COMMIT
|
|
||||||
" | iptables-legacy-restore"
|
|
||||||
)
|
|
||||||
if self.do_ipv6:
|
|
||||||
self.runcmd(
|
|
||||||
"ip6tables-legacy-save | awk '/^[*]/ { print $1 }" # Keep lines like *raw, *filter and *nat
|
|
||||||
' /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }' # Turn all policies to accept
|
|
||||||
" /COMMIT/ { print $0; }'" # Keep the line COMMIT
|
|
||||||
" | ip6tables-legacy-restore"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self.rollback()
|
|
||||||
raise YunohostError("migration_0018_failed_to_reset_legacy_rules", error=e)
|
|
||||||
|
|
||||||
# You might be wondering "uh but is it really useful to
|
|
||||||
# iptables-legacy-save | iptables-restore considering firewall_reload()
|
|
||||||
# flush/resets everything anyway ?"
|
|
||||||
# But the answer is : firewall_reload() only resets the *filter table.
|
|
||||||
# On more complex setups (e.g. internet cube or docker) you will also
|
|
||||||
# have rules in the *nat (or maybe *raw?) sections of iptables.
|
|
||||||
firewall_reload()
|
|
||||||
service_restart("fail2ban")
|
|
||||||
|
|
||||||
def rollback(self):
|
|
||||||
|
|
||||||
if self.do_ipv4:
|
|
||||||
self.runcmd("iptables-legacy-restore < %s" % self.backup_rules_ipv4)
|
|
||||||
if self.do_ipv6:
|
|
||||||
self.runcmd("iptables-legacy-restore < %s" % self.backup_rules_ipv6)
|
|
||||||
|
|
||||||
def runcmd(self, cmd, raise_on_errors=True):
|
|
||||||
|
|
||||||
logger.debug("Running command: " + cmd)
|
|
||||||
|
|
||||||
p = subprocess.Popen(
|
|
||||||
cmd,
|
|
||||||
shell=True,
|
|
||||||
executable="/bin/bash",
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
|
|
||||||
out, err = p.communicate()
|
|
||||||
returncode = p.returncode
|
|
||||||
if raise_on_errors and returncode != 0:
|
|
||||||
raise YunohostError(
|
|
||||||
"Failed to run command '{}'.\nreturncode: {}\nstdout:\n{}\nstderr:\n{}\n".format(
|
|
||||||
cmd, returncode, out, err
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
out = out.strip().split(b"\n")
|
|
||||||
return (returncode, out, err)
|
|
|
@ -1,107 +0,0 @@
|
||||||
from moulinette import m18n
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
|
|
||||||
from yunohost.tools import Migration
|
|
||||||
from yunohost.permission import user_permission_list
|
|
||||||
from yunohost.utils.legacy import migrate_legacy_permission_settings
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
"""
|
|
||||||
Add protected attribute in LDAP permission
|
|
||||||
"""
|
|
||||||
|
|
||||||
@Migration.ldap_migration
|
|
||||||
def run(self, backup_folder):
|
|
||||||
|
|
||||||
# Update LDAP database
|
|
||||||
self.add_new_ldap_attributes()
|
|
||||||
|
|
||||||
# Migrate old settings
|
|
||||||
migrate_legacy_permission_settings()
|
|
||||||
|
|
||||||
def add_new_ldap_attributes(self):
|
|
||||||
|
|
||||||
from yunohost.utils.ldap import _get_ldap_interface
|
|
||||||
from yunohost.regenconf import regen_conf, BACKUP_CONF_DIR
|
|
||||||
|
|
||||||
# Check if the migration can be processed
|
|
||||||
ldap_regen_conf_status = regen_conf(names=["slapd"], dry_run=True)
|
|
||||||
# By this we check if the have been customized
|
|
||||||
if ldap_regen_conf_status and ldap_regen_conf_status["slapd"]["pending"]:
|
|
||||||
logger.warning(
|
|
||||||
m18n.n(
|
|
||||||
"migration_0019_slapd_config_will_be_overwritten",
|
|
||||||
conf_backup_folder=BACKUP_CONF_DIR,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update LDAP schema restart slapd
|
|
||||||
logger.info(m18n.n("migration_update_LDAP_schema"))
|
|
||||||
regen_conf(names=["slapd"], force=True)
|
|
||||||
|
|
||||||
logger.info(m18n.n("migration_0019_add_new_attributes_in_ldap"))
|
|
||||||
ldap = _get_ldap_interface()
|
|
||||||
permission_list = user_permission_list(full=True)["permissions"]
|
|
||||||
|
|
||||||
for permission in permission_list:
|
|
||||||
system_perms = {
|
|
||||||
"mail": "E-mail",
|
|
||||||
"xmpp": "XMPP",
|
|
||||||
"ssh": "SSH",
|
|
||||||
"sftp": "STFP",
|
|
||||||
}
|
|
||||||
if permission.split(".")[0] in system_perms:
|
|
||||||
update = {
|
|
||||||
"authHeader": ["FALSE"],
|
|
||||||
"label": [system_perms[permission.split(".")[0]]],
|
|
||||||
"showTile": ["FALSE"],
|
|
||||||
"isProtected": ["TRUE"],
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
app, subperm_name = permission.split(".")
|
|
||||||
if permission.endswith(".main"):
|
|
||||||
update = {
|
|
||||||
"authHeader": ["TRUE"],
|
|
||||||
"label": [
|
|
||||||
app
|
|
||||||
], # Note that this is later re-changed during the call to migrate_legacy_permission_settings() if a 'label' setting exists
|
|
||||||
"showTile": ["TRUE"],
|
|
||||||
"isProtected": ["FALSE"],
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
update = {
|
|
||||||
"authHeader": ["TRUE"],
|
|
||||||
"label": [subperm_name.title()],
|
|
||||||
"showTile": ["FALSE"],
|
|
||||||
"isProtected": ["TRUE"],
|
|
||||||
}
|
|
||||||
|
|
||||||
ldap.update("cn=%s,ou=permission" % permission, update)
|
|
||||||
|
|
||||||
introduced_in_version = "4.1"
|
|
||||||
|
|
||||||
def run_after_system_restore(self):
|
|
||||||
# Update LDAP database
|
|
||||||
self.add_new_ldap_attributes()
|
|
||||||
|
|
||||||
def run_before_app_restore(self, app_id):
|
|
||||||
from yunohost.app import app_setting
|
|
||||||
from yunohost.utils.legacy import migrate_legacy_permission_settings
|
|
||||||
|
|
||||||
# Migrate old settings
|
|
||||||
legacy_permission_settings = [
|
|
||||||
"skipped_uris",
|
|
||||||
"unprotected_uris",
|
|
||||||
"protected_uris",
|
|
||||||
"skipped_regex",
|
|
||||||
"unprotected_regex",
|
|
||||||
"protected_regex",
|
|
||||||
]
|
|
||||||
if any(
|
|
||||||
app_setting(app_id, setting) is not None
|
|
||||||
for setting in legacy_permission_settings
|
|
||||||
):
|
|
||||||
migrate_legacy_permission_settings(app=app_id)
|
|
|
@ -1,100 +0,0 @@
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
|
|
||||||
from yunohost.tools import Migration
|
|
||||||
from yunohost.permission import user_permission_update, permission_sync_to_user
|
|
||||||
from yunohost.regenconf import manually_modified_files
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.migration")
|
|
||||||
|
|
||||||
###################################################
|
|
||||||
# Tools used also for restoration
|
|
||||||
###################################################
|
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
|
||||||
"""
|
|
||||||
Add new permissions around SSH/SFTP features
|
|
||||||
"""
|
|
||||||
|
|
||||||
introduced_in_version = "4.2.2"
|
|
||||||
dependencies = ["extend_permissions_features"]
|
|
||||||
|
|
||||||
@Migration.ldap_migration
|
|
||||||
def run(self, *args):
|
|
||||||
|
|
||||||
from yunohost.utils.ldap import _get_ldap_interface
|
|
||||||
|
|
||||||
ldap = _get_ldap_interface()
|
|
||||||
|
|
||||||
existing_perms_raw = ldap.search(
|
|
||||||
"ou=permission,dc=yunohost,dc=org", "(objectclass=permissionYnh)", ["cn"]
|
|
||||||
)
|
|
||||||
existing_perms = [perm["cn"][0] for perm in existing_perms_raw]
|
|
||||||
|
|
||||||
# Add SSH and SFTP permissions
|
|
||||||
if "sftp.main" not in existing_perms:
|
|
||||||
ldap.add(
|
|
||||||
"cn=sftp.main,ou=permission",
|
|
||||||
{
|
|
||||||
"cn": "sftp.main",
|
|
||||||
"gidNumber": "5004",
|
|
||||||
"objectClass": ["posixGroup", "permissionYnh"],
|
|
||||||
"groupPermission": [],
|
|
||||||
"authHeader": "FALSE",
|
|
||||||
"label": "SFTP",
|
|
||||||
"showTile": "FALSE",
|
|
||||||
"isProtected": "TRUE",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if "ssh.main" not in existing_perms:
|
|
||||||
ldap.add(
|
|
||||||
"cn=ssh.main,ou=permission",
|
|
||||||
{
|
|
||||||
"cn": "ssh.main",
|
|
||||||
"gidNumber": "5003",
|
|
||||||
"objectClass": ["posixGroup", "permissionYnh"],
|
|
||||||
"groupPermission": [],
|
|
||||||
"authHeader": "FALSE",
|
|
||||||
"label": "SSH",
|
|
||||||
"showTile": "FALSE",
|
|
||||||
"isProtected": "TRUE",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add a bash terminal to each users
|
|
||||||
users = ldap.search(
|
|
||||||
"ou=users,dc=yunohost,dc=org",
|
|
||||||
filter="(loginShell=*)",
|
|
||||||
attrs=["dn", "uid", "loginShell"],
|
|
||||||
)
|
|
||||||
for user in users:
|
|
||||||
if user["loginShell"][0] == "/bin/false":
|
|
||||||
dn = user["dn"][0].replace(",dc=yunohost,dc=org", "")
|
|
||||||
ldap.update(dn, {"loginShell": ["/bin/bash"]})
|
|
||||||
else:
|
|
||||||
user_permission_update(
|
|
||||||
"ssh.main", add=user["uid"][0], sync_perm=False
|
|
||||||
)
|
|
||||||
|
|
||||||
permission_sync_to_user()
|
|
||||||
|
|
||||||
# Somehow this is needed otherwise the PAM thing doesn't forget about the
|
|
||||||
# old loginShell value ?
|
|
||||||
subprocess.call(["nscd", "-i", "passwd"])
|
|
||||||
|
|
||||||
if (
|
|
||||||
"/etc/ssh/sshd_config" in manually_modified_files()
|
|
||||||
and os.system(
|
|
||||||
"grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
|
|
||||||
)
|
|
||||||
!= 0
|
|
||||||
):
|
|
||||||
logger.error(m18n.n("diagnosis_sshd_config_insecure"))
|
|
||||||
|
|
||||||
def run_after_system_restore(self):
|
|
||||||
self.run()
|
|
|
@ -375,18 +375,6 @@ def dyndns_update(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def dyndns_installcron():
|
|
||||||
logger.warning(
|
|
||||||
"This command is deprecated. The dyndns cron job should automatically be added/removed by the regenconf depending if there's a private key in /etc/yunohost/dyndns. You can run the regenconf yourself with 'yunohost tools regen-conf yunohost'."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def dyndns_removecron():
|
|
||||||
logger.warning(
|
|
||||||
"This command is deprecated. The dyndns cron job should automatically be added/removed by the regenconf depending if there's a private key in /etc/yunohost/dyndns. You can run the regenconf yourself with 'yunohost tools regen-conf yunohost'."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _guess_current_dyndns_domain(dyn_host):
|
def _guess_current_dyndns_domain(dyn_host):
|
||||||
"""
|
"""
|
||||||
This function tries to guess which domain should be updated by
|
This function tries to guess which domain should be updated by
|
||||||
|
|
|
@ -48,12 +48,10 @@ def service_add(
|
||||||
name,
|
name,
|
||||||
description=None,
|
description=None,
|
||||||
log=None,
|
log=None,
|
||||||
log_type=None,
|
|
||||||
test_status=None,
|
test_status=None,
|
||||||
test_conf=None,
|
test_conf=None,
|
||||||
needs_exposed_ports=None,
|
needs_exposed_ports=None,
|
||||||
need_lock=False,
|
need_lock=False,
|
||||||
status=None,
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Add a custom service
|
Add a custom service
|
||||||
|
@ -62,12 +60,10 @@ def service_add(
|
||||||
name -- Service name to add
|
name -- Service name to add
|
||||||
description -- description of the service
|
description -- description of the service
|
||||||
log -- Absolute path to log file to display
|
log -- Absolute path to log file to display
|
||||||
log_type -- (deprecated) Specify if the corresponding log is a file or a systemd log
|
|
||||||
test_status -- Specify a custom bash command to check the status of the service. N.B. : it only makes sense to specify this if the corresponding systemd service does not return the proper information.
|
test_status -- Specify a custom bash command to check the status of the service. N.B. : it only makes sense to specify this if the corresponding systemd service does not return the proper information.
|
||||||
test_conf -- Specify a custom bash command to check if the configuration of the service is valid or broken, similar to nginx -t.
|
test_conf -- Specify a custom bash command to check if the configuration of the service is valid or broken, similar to nginx -t.
|
||||||
needs_exposed_ports -- A list of ports that needs to be publicly exposed for the service to work as intended.
|
needs_exposed_ports -- A list of ports that needs to be publicly exposed for the service to work as intended.
|
||||||
need_lock -- Use this option to prevent deadlocks if the service does invoke yunohost commands.
|
need_lock -- Use this option to prevent deadlocks if the service does invoke yunohost commands.
|
||||||
status -- Deprecated, doesn't do anything anymore. Use test_status instead.
|
|
||||||
"""
|
"""
|
||||||
services = _get_services()
|
services = _get_services()
|
||||||
|
|
||||||
|
@ -77,15 +73,6 @@ def service_add(
|
||||||
if not isinstance(log, list):
|
if not isinstance(log, list):
|
||||||
log = [log]
|
log = [log]
|
||||||
|
|
||||||
# Deprecated log_type stuff
|
|
||||||
if log_type is not None:
|
|
||||||
logger.warning(
|
|
||||||
"/!\\ Packagers! --log_type is deprecated. You do not need to specify --log_type systemd anymore ... Yunohost now automatically fetch the journalctl of the systemd service by default."
|
|
||||||
)
|
|
||||||
# Usually when adding such a service, the service name will be provided so we remove it as it's not a log file path
|
|
||||||
if name in log:
|
|
||||||
log.remove(name)
|
|
||||||
|
|
||||||
service["log"] = log
|
service["log"] = log
|
||||||
|
|
||||||
if not description:
|
if not description:
|
||||||
|
@ -535,29 +522,6 @@ def service_log(name, number=50):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def service_regen_conf(
|
|
||||||
names=[], with_diff=False, force=False, dry_run=False, list_pending=False
|
|
||||||
):
|
|
||||||
|
|
||||||
services = _get_services()
|
|
||||||
|
|
||||||
if isinstance(names, str):
|
|
||||||
names = [names]
|
|
||||||
|
|
||||||
for name in names:
|
|
||||||
if name not in services.keys():
|
|
||||||
raise YunohostValidationError("service_unknown", service=name)
|
|
||||||
|
|
||||||
if names is []:
|
|
||||||
names = list(services.keys())
|
|
||||||
|
|
||||||
logger.warning(m18n.n("service_regen_conf_is_deprecated"))
|
|
||||||
|
|
||||||
from yunohost.regenconf import regen_conf
|
|
||||||
|
|
||||||
return regen_conf(names, with_diff, force, dry_run, list_pending)
|
|
||||||
|
|
||||||
|
|
||||||
def _run_service_command(action, service):
|
def _run_service_command(action, service):
|
||||||
"""
|
"""
|
||||||
Run services management command (start, stop, enable, disable, restart, reload)
|
Run services management command (start, stop, enable, disable, restart, reload)
|
||||||
|
|
|
@ -329,24 +329,12 @@ def tools_regen_conf(
|
||||||
return regen_conf(names, with_diff, force, dry_run, list_pending)
|
return regen_conf(names, with_diff, force, dry_run, list_pending)
|
||||||
|
|
||||||
|
|
||||||
def tools_update(target=None, apps=False, system=False):
|
def tools_update(target=None):
|
||||||
"""
|
"""
|
||||||
Update apps & system package cache
|
Update apps & system package cache
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Legacy options (--system, --apps)
|
if not target:
|
||||||
if apps or system:
|
|
||||||
logger.warning(
|
|
||||||
"Using 'yunohost tools update' with --apps / --system is deprecated, just write 'yunohost tools update apps system' (no -- prefix anymore)"
|
|
||||||
)
|
|
||||||
if apps and system:
|
|
||||||
target = "all"
|
|
||||||
elif apps:
|
|
||||||
target = "apps"
|
|
||||||
else:
|
|
||||||
target = "system"
|
|
||||||
|
|
||||||
elif not target:
|
|
||||||
target = "all"
|
target = "all"
|
||||||
|
|
||||||
if target not in ["system", "apps", "all"]:
|
if target not in ["system", "apps", "all"]:
|
||||||
|
@ -455,7 +443,7 @@ def _list_upgradable_apps():
|
||||||
|
|
||||||
@is_unit_operation()
|
@is_unit_operation()
|
||||||
def tools_upgrade(
|
def tools_upgrade(
|
||||||
operation_logger, target=None, apps=False, system=False, allow_yunohost_upgrade=True
|
operation_logger, target=None, allow_yunohost_upgrade=True
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Update apps & package cache, then display changelog
|
Update apps & package cache, then display changelog
|
||||||
|
@ -473,21 +461,6 @@ def tools_upgrade(
|
||||||
if not packages.dpkg_lock_available():
|
if not packages.dpkg_lock_available():
|
||||||
raise YunohostValidationError("dpkg_lock_not_available")
|
raise YunohostValidationError("dpkg_lock_not_available")
|
||||||
|
|
||||||
# Legacy options management (--system, --apps)
|
|
||||||
if target is None:
|
|
||||||
|
|
||||||
logger.warning(
|
|
||||||
"Using 'yunohost tools upgrade' with --apps / --system is deprecated, just write 'yunohost tools upgrade apps' or 'system' (no -- prefix anymore)"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (system, apps) == (True, True):
|
|
||||||
raise YunohostValidationError("tools_upgrade_cant_both")
|
|
||||||
|
|
||||||
if (system, apps) == (False, False):
|
|
||||||
raise YunohostValidationError("tools_upgrade_at_least_one")
|
|
||||||
|
|
||||||
target = "apps" if apps else "system"
|
|
||||||
|
|
||||||
if target not in ["apps", "system"]:
|
if target not in ["apps", "system"]:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Uhoh ?! tools_upgrade should have 'apps' or 'system' value for argument target"
|
"Uhoh ?! tools_upgrade should have 'apps' or 'system' value for argument target"
|
||||||
|
|
|
@ -98,7 +98,6 @@ def user_create(
|
||||||
domain,
|
domain,
|
||||||
password,
|
password,
|
||||||
mailbox_quota="0",
|
mailbox_quota="0",
|
||||||
mail=None,
|
|
||||||
):
|
):
|
||||||
|
|
||||||
from yunohost.domain import domain_list, _get_maindomain
|
from yunohost.domain import domain_list, _get_maindomain
|
||||||
|
@ -109,12 +108,6 @@ def user_create(
|
||||||
# Ensure sufficiently complex password
|
# Ensure sufficiently complex password
|
||||||
assert_password_is_strong_enough("user", password)
|
assert_password_is_strong_enough("user", password)
|
||||||
|
|
||||||
if mail is not None:
|
|
||||||
logger.warning(
|
|
||||||
"Packagers ! Using --mail in 'yunohost user create' is deprecated ... please use --domain instead."
|
|
||||||
)
|
|
||||||
domain = mail.split("@")[-1]
|
|
||||||
|
|
||||||
# Validate domain used for email address/xmpp account
|
# Validate domain used for email address/xmpp account
|
||||||
if domain is None:
|
if domain is None:
|
||||||
if msettings.get("interface") == "api":
|
if msettings.get("interface") == "api":
|
||||||
|
|
|
@ -1,239 +0,0 @@
|
||||||
import os
|
|
||||||
from moulinette import m18n
|
|
||||||
from moulinette.utils.log import getActionLogger
|
|
||||||
from moulinette.utils.filesystem import write_to_json, read_yaml
|
|
||||||
|
|
||||||
from yunohost.user import user_list
|
|
||||||
from yunohost.app import (
|
|
||||||
_installed_apps,
|
|
||||||
_get_app_settings,
|
|
||||||
_set_app_settings,
|
|
||||||
)
|
|
||||||
from yunohost.permission import (
|
|
||||||
permission_create,
|
|
||||||
user_permission_update,
|
|
||||||
permission_sync_to_user,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = getActionLogger("yunohost.legacy")
|
|
||||||
|
|
||||||
LEGACY_PERMISSION_LABEL = {
|
|
||||||
("nextcloud", "skipped"): "api", # .well-known
|
|
||||||
("libreto", "skipped"): "pad access", # /[^/]+
|
|
||||||
("leed", "skipped"): "api", # /action.php, for cron task ...
|
|
||||||
("mailman", "protected"): "admin", # /admin
|
|
||||||
("prettynoemiecms", "protected"): "admin", # /admin
|
|
||||||
("etherpad_mypads", "skipped"): "admin", # /admin
|
|
||||||
("baikal", "protected"): "admin", # /admin/
|
|
||||||
("couchpotato", "unprotected"): "api", # /api
|
|
||||||
("freshrss", "skipped"): "api", # /api/,
|
|
||||||
("portainer", "skipped"): "api", # /api/webhooks/
|
|
||||||
("jeedom", "unprotected"): "api", # /core/api/jeeApi.php
|
|
||||||
("bozon", "protected"): "user interface", # /index.php
|
|
||||||
(
|
|
||||||
"limesurvey",
|
|
||||||
"protected",
|
|
||||||
): "admin", # /index.php?r=admin,/index.php?r=plugins,/scripts
|
|
||||||
("kanboard", "unprotected"): "api", # /jsonrpc.php
|
|
||||||
("seafile", "unprotected"): "medias", # /media
|
|
||||||
("ttrss", "skipped"): "api", # /public.php,/api,/opml.php?op=publish
|
|
||||||
("libreerp", "protected"): "admin", # /web/database/manager
|
|
||||||
("z-push", "skipped"): "api", # $domain/[Aa]uto[Dd]iscover/.*
|
|
||||||
("radicale", "skipped"): "?", # $domain$path_url
|
|
||||||
(
|
|
||||||
"jirafeau",
|
|
||||||
"protected",
|
|
||||||
): "user interface", # $domain$path_url/$","$domain$path_url/admin.php.*$
|
|
||||||
("opensondage", "protected"): "admin", # $domain$path_url/admin/
|
|
||||||
(
|
|
||||||
"lstu",
|
|
||||||
"protected",
|
|
||||||
): "user interface", # $domain$path_url/login$","$domain$path_url/logout$","$domain$path_url/api$","$domain$path_url/extensions$","$domain$path_url/stats$","$domain$path_url/d/.*$","$domain$path_url/a$","$domain$path_url/$
|
|
||||||
(
|
|
||||||
"lutim",
|
|
||||||
"protected",
|
|
||||||
): "user interface", # $domain$path_url/stats/?$","$domain$path_url/manifest.webapp/?$","$domain$path_url/?$","$domain$path_url/[d-m]/.*$
|
|
||||||
(
|
|
||||||
"lufi",
|
|
||||||
"protected",
|
|
||||||
): "user interface", # $domain$path_url/stats$","$domain$path_url/manifest.webapp$","$domain$path_url/$","$domain$path_url/d/.*$","$domain$path_url/m/.*$
|
|
||||||
(
|
|
||||||
"gogs",
|
|
||||||
"skipped",
|
|
||||||
): "api", # $excaped_domain$excaped_path/[%w-.]*/[%w-.]*/git%-receive%-pack,$excaped_domain$excaped_path/[%w-.]*/[%w-.]*/git%-upload%-pack,$excaped_domain$excaped_path/[%w-.]*/[%w-.]*/info/refs
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def legacy_permission_label(app, permission_type):
|
|
||||||
return LEGACY_PERMISSION_LABEL.get(
|
|
||||||
(app, permission_type), "Legacy %s urls" % permission_type
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_legacy_permission_settings(app=None):
|
|
||||||
|
|
||||||
logger.info(m18n.n("migrating_legacy_permission_settings"))
|
|
||||||
apps = _installed_apps()
|
|
||||||
|
|
||||||
if app:
|
|
||||||
if app not in apps:
|
|
||||||
logger.error(
|
|
||||||
"Can't migrate permission for app %s because it ain't installed..."
|
|
||||||
% app
|
|
||||||
)
|
|
||||||
apps = []
|
|
||||||
else:
|
|
||||||
apps = [app]
|
|
||||||
|
|
||||||
for app in apps:
|
|
||||||
|
|
||||||
settings = _get_app_settings(app) or {}
|
|
||||||
if settings.get("label"):
|
|
||||||
user_permission_update(
|
|
||||||
app + ".main", label=settings["label"], sync_perm=False
|
|
||||||
)
|
|
||||||
del settings["label"]
|
|
||||||
|
|
||||||
def _setting(name):
|
|
||||||
s = settings.get(name)
|
|
||||||
return s.split(",") if s else []
|
|
||||||
|
|
||||||
skipped_urls = [uri for uri in _setting("skipped_uris") if uri != "/"]
|
|
||||||
skipped_urls += ["re:" + regex for regex in _setting("skipped_regex")]
|
|
||||||
unprotected_urls = [uri for uri in _setting("unprotected_uris") if uri != "/"]
|
|
||||||
unprotected_urls += ["re:" + regex for regex in _setting("unprotected_regex")]
|
|
||||||
protected_urls = [uri for uri in _setting("protected_uris") if uri != "/"]
|
|
||||||
protected_urls += ["re:" + regex for regex in _setting("protected_regex")]
|
|
||||||
|
|
||||||
if skipped_urls != []:
|
|
||||||
permission_create(
|
|
||||||
app + ".legacy_skipped_uris",
|
|
||||||
additional_urls=skipped_urls,
|
|
||||||
auth_header=False,
|
|
||||||
label=legacy_permission_label(app, "skipped"),
|
|
||||||
show_tile=False,
|
|
||||||
allowed="visitors",
|
|
||||||
protected=True,
|
|
||||||
sync_perm=False,
|
|
||||||
)
|
|
||||||
if unprotected_urls != []:
|
|
||||||
permission_create(
|
|
||||||
app + ".legacy_unprotected_uris",
|
|
||||||
additional_urls=unprotected_urls,
|
|
||||||
auth_header=True,
|
|
||||||
label=legacy_permission_label(app, "unprotected"),
|
|
||||||
show_tile=False,
|
|
||||||
allowed="visitors",
|
|
||||||
protected=True,
|
|
||||||
sync_perm=False,
|
|
||||||
)
|
|
||||||
if protected_urls != []:
|
|
||||||
permission_create(
|
|
||||||
app + ".legacy_protected_uris",
|
|
||||||
additional_urls=protected_urls,
|
|
||||||
auth_header=True,
|
|
||||||
label=legacy_permission_label(app, "protected"),
|
|
||||||
show_tile=False,
|
|
||||||
allowed=[],
|
|
||||||
protected=True,
|
|
||||||
sync_perm=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
legacy_permission_settings = [
|
|
||||||
"skipped_uris",
|
|
||||||
"unprotected_uris",
|
|
||||||
"protected_uris",
|
|
||||||
"skipped_regex",
|
|
||||||
"unprotected_regex",
|
|
||||||
"protected_regex",
|
|
||||||
]
|
|
||||||
for key in legacy_permission_settings:
|
|
||||||
if key in settings:
|
|
||||||
del settings[key]
|
|
||||||
|
|
||||||
_set_app_settings(app, settings)
|
|
||||||
|
|
||||||
permission_sync_to_user()
|
|
||||||
|
|
||||||
|
|
||||||
def translate_legacy_rules_in_ssowant_conf_json_persistent():
|
|
||||||
|
|
||||||
persistent_file_name = "/etc/ssowat/conf.json.persistent"
|
|
||||||
if not os.path.exists(persistent_file_name):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Ugly hack because for some reason so many people have tabs in their conf.json.persistent ...
|
|
||||||
os.system(r"sed -i 's/\t/ /g' /etc/ssowat/conf.json.persistent")
|
|
||||||
|
|
||||||
# Ugly hack to try not to misarably fail migration
|
|
||||||
persistent = read_yaml(persistent_file_name)
|
|
||||||
|
|
||||||
legacy_rules = [
|
|
||||||
"skipped_urls",
|
|
||||||
"unprotected_urls",
|
|
||||||
"protected_urls",
|
|
||||||
"skipped_regex",
|
|
||||||
"unprotected_regex",
|
|
||||||
"protected_regex",
|
|
||||||
]
|
|
||||||
|
|
||||||
if not any(legacy_rule in persistent for legacy_rule in legacy_rules):
|
|
||||||
return
|
|
||||||
|
|
||||||
if not isinstance(persistent.get("permissions"), dict):
|
|
||||||
persistent["permissions"] = {}
|
|
||||||
|
|
||||||
skipped_urls = persistent.get("skipped_urls", []) + [
|
|
||||||
"re:" + r for r in persistent.get("skipped_regex", [])
|
|
||||||
]
|
|
||||||
protected_urls = persistent.get("protected_urls", []) + [
|
|
||||||
"re:" + r for r in persistent.get("protected_regex", [])
|
|
||||||
]
|
|
||||||
unprotected_urls = persistent.get("unprotected_urls", []) + [
|
|
||||||
"re:" + r for r in persistent.get("unprotected_regex", [])
|
|
||||||
]
|
|
||||||
|
|
||||||
known_users = list(user_list()["users"].keys())
|
|
||||||
|
|
||||||
for legacy_rule in legacy_rules:
|
|
||||||
if legacy_rule in persistent:
|
|
||||||
del persistent[legacy_rule]
|
|
||||||
|
|
||||||
if skipped_urls:
|
|
||||||
persistent["permissions"]["custom_skipped"] = {
|
|
||||||
"users": [],
|
|
||||||
"label": "Custom permissions - skipped",
|
|
||||||
"show_tile": False,
|
|
||||||
"auth_header": False,
|
|
||||||
"public": True,
|
|
||||||
"uris": skipped_urls
|
|
||||||
+ persistent["permissions"].get("custom_skipped", {}).get("uris", []),
|
|
||||||
}
|
|
||||||
|
|
||||||
if unprotected_urls:
|
|
||||||
persistent["permissions"]["custom_unprotected"] = {
|
|
||||||
"users": [],
|
|
||||||
"label": "Custom permissions - unprotected",
|
|
||||||
"show_tile": False,
|
|
||||||
"auth_header": True,
|
|
||||||
"public": True,
|
|
||||||
"uris": unprotected_urls
|
|
||||||
+ persistent["permissions"].get("custom_unprotected", {}).get("uris", []),
|
|
||||||
}
|
|
||||||
|
|
||||||
if protected_urls:
|
|
||||||
persistent["permissions"]["custom_protected"] = {
|
|
||||||
"users": known_users,
|
|
||||||
"label": "Custom permissions - protected",
|
|
||||||
"show_tile": False,
|
|
||||||
"auth_header": True,
|
|
||||||
"public": False,
|
|
||||||
"uris": protected_urls
|
|
||||||
+ persistent["permissions"].get("custom_protected", {}).get("uris", []),
|
|
||||||
}
|
|
||||||
|
|
||||||
write_to_json(persistent_file_name, persistent, sort_keys=True, indent=4)
|
|
||||||
|
|
||||||
logger.warning(
|
|
||||||
"YunoHost automatically translated some legacy rules in /etc/ssowat/conf.json.persistent to match the new permission system"
|
|
||||||
)
|
|
Loading…
Add table
Reference in a new issue