Merge remote-tracking branch 'origin/dev' into bookworm

This commit is contained in:
Alexandre Aubin 2023-07-04 18:10:25 +02:00
commit bdc296f858
12 changed files with 71 additions and 29 deletions

View file

@ -1,3 +1,3 @@
location / {
return 302 https://$http_host/yunohost/admin;
return 302 https://$host/yunohost/admin;
}

View file

@ -25,7 +25,7 @@ server {
{# Note that this != "False" is meant to be failure-safe, in the case the redrect_to_https would happen to contain empty string or whatever value. We absolutely don't want to disable the HTTPS redirect *except* when it's explicitly being asked to be disabled. #}
{% if redirect_to_https != "False" %}
location / {
return 301 https://$http_host$request_uri;
return 301 https://$host$request_uri;
}
{# The app config snippets are not included in the HTTP conf unless HTTPS redirect is disabled, because app's location may blocks will conflict or bypass/ignore the HTTPS redirection. #}
{% else %}

View file

@ -4,7 +4,7 @@ location /yunohost/api/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header Host $host;
{% if webadmin_allowlist_enabled == "True" %}
{% for ip in webadmin_allowlist.split(',') %}

7
debian/changelog vendored
View file

@ -4,6 +4,13 @@ yunohost (12.0.0) unstable; urgency=low
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 04 May 2023 20:30:19 +0200
yunohost (11.1.21.4) stable; urgency=low
- regenconf: Get rid of previous tmp hack about /dev/null for people that went through the very first 11.1.21, because it's causing issue in unpriviledged LXC or similar context (8242cab7)
- apps: don't attempt to del password key if it doesn't exist (29338f79)
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 14 Jun 2023 15:48:33 +0200
yunohost (11.1.21.3) stable; urgency=low
- Fix again /var/www/.well-known/ynh-diagnosis/ perms which are too broad and could be exploited to serve malicious files x_x (84984ad8)

View file

@ -124,7 +124,7 @@ ynh_remove_apps() {
# Requires YunoHost version 11.0.* or higher, and that the app relies on packaging v2 or higher.
# The spawned shell will have environment variables loaded and environment files sourced
# from the app's service configuration file (defaults to $app.service, overridable by the packager with `service` setting).
# If the app relies on a specific PHP version, then `php` will be aliased that version.
# If the app relies on a specific PHP version, then `php` will be aliased that version. The PHP command will also be appended with the `phpflags` settings.
ynh_spawn_app_shell() {
# Declare an array to define the options of this helper.
local legacy_args=a
@ -176,9 +176,10 @@ ynh_spawn_app_shell() {
# Force `php` to its intended version
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
if [ -n "$phpversion" ]
then
eval "php() { php${phpversion} \"\$@\"; }"
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
export -f php
fi

View file

@ -872,6 +872,8 @@ app:
### app_shell()
shell:
action_help: Open an interactive shell with the app environment already loaded
# Here we set a GET only not to lock the command line. There is no actual API endpoint for app_shell()
api: GET /apps/<app>/shell
arguments:
app:
help: App ID

View file

@ -84,7 +84,7 @@ re_app_instance_name = re.compile(
)
APP_REPO_URL = re.compile(
r"^https://[a-zA-Z0-9-_.]+/[a-zA-Z0-9-_./~]+/[a-zA-Z0-9-_.]+_ynh(/?(-/)?tree/[a-zA-Z0-9-_.]+)?(\.git)?/?$"
r"^https://[a-zA-Z0-9-_.]+/[a-zA-Z0-9-_./~]+/[a-zA-Z0-9-_.]+_ynh(/?(-/)?(tree|src/(branch|tag|commit))/[a-zA-Z0-9-_.]+)?(\.git)?/?$"
)
APP_FILES_TO_COPY = [
@ -1193,7 +1193,8 @@ def app_install(
for question in questions:
# Or should it be more generally question.redact ?
if question.type == "password":
del env_dict_for_logging[f"YNH_APP_ARG_{question.name.upper()}"]
if f"YNH_APP_ARG_{question.name.upper()}" in env_dict_for_logging:
del env_dict_for_logging[f"YNH_APP_ARG_{question.name.upper()}"]
if question.name in env_dict_for_logging:
del env_dict_for_logging[question.name]

View file

@ -182,6 +182,10 @@ class MyDiagnoser(Diagnoser):
if success != "ok":
return None
else:
if type_ == "TXT" and isinstance(answers,list):
for part in answers:
if part.startswith('"v=spf1'):
return part
return answers[0] if len(answers) == 1 else answers
def current_record_match_expected(self, r):

View file

@ -331,7 +331,7 @@ def firewall_reload(skip_upnp=False):
# Refresh port forwarding with UPnP
firewall_upnp(no_refresh=False)
_run_service_command("reload", "fail2ban")
_run_service_command("restart", "fail2ban")
if errors:
logger.warning(m18n.n("firewall_rules_cmd_failed"))

View file

@ -69,8 +69,19 @@ def test_repo_url_definition():
assert _is_app_repo_url("git@github.com:YunoHost-Apps/foobar_ynh.git")
assert _is_app_repo_url("https://git.super.host/~max/foobar_ynh")
### Gitea
assert _is_app_repo_url("https://gitea.instance.tld/user/repo_ynh")
assert _is_app_repo_url("https://gitea.instance.tld/user/repo_ynh/src/branch/branch_name")
assert _is_app_repo_url("https://gitea.instance.tld/user/repo_ynh/src/tag/tag_name")
assert _is_app_repo_url("https://gitea.instance.tld/user/repo_ynh/src/commit/abcd1234")
### Invalid patterns
# no schema
assert not _is_app_repo_url("github.com/YunoHost-Apps/foobar_ynh")
# http
assert not _is_app_repo_url("http://github.com/YunoHost-Apps/foobar_ynh")
# does not end in `_ynh`
assert not _is_app_repo_url("https://github.com/YunoHost-Apps/foobar_wat")
assert not _is_app_repo_url("https://github.com/YunoHost-Apps/foobar_ynh_wat")
assert not _is_app_repo_url("https://github.com/YunoHost-Apps/foobar/tree/testing")

View file

@ -16,6 +16,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import pwd
import re
import os
import subprocess
@ -174,6 +175,12 @@ def tools_postinstall(
raw_msg=True,
)
# Crash early if the username is already a system user, which is
# a common confusion. We don't want to crash later and end up in an half-configured state.
all_existing_usernames = {x.pw_name for x in pwd.getpwall()}
if username in all_existing_usernames:
raise YunohostValidationError("system_username_exists")
if username in ADMIN_ALIASES:
raise YunohostValidationError(
f"Unfortunately, {username} cannot be used as a username", raw_msg=True

View file

@ -22,7 +22,7 @@ import shutil
import random
import tempfile
import subprocess
from typing import Dict, Any, List
from typing import Dict, Any, List, Union
from moulinette import m18n
from moulinette.utils.process import check_output
@ -1011,16 +1011,16 @@ class AptDependenciesAppResource(AppResource):
##### Example
```toml
[resources.apt]
packages = "nyancat, lolcat, sl"
packages = ["nyancat", "lolcat", "sl"]
# (this part is optional and corresponds to the legacy ynh_install_extra_app_dependencies helper)
extras.yarn.repo = "deb https://dl.yarnpkg.com/debian/ stable main"
extras.yarn.key = "https://dl.yarnpkg.com/debian/pubkey.gpg"
extras.yarn.packages = "yarn"
extras.yarn.packages = ["yarn"]
```
##### Properties
- `packages`: Comma-separated list of packages to be installed via `apt`
- `packages`: List of packages to be installed via `apt`
- `packages_from_raw_bash`: A multi-line bash snippet (using triple quotes as open/close) which should echo additional packages to be installed. Meant to be used for packages to be conditionally installed depending on architecture, debian version, install questions, or other logic.
- `extras`: A dict of (repo, key, packages) corresponding to "extra" repositories to fetch dependencies from
@ -1044,20 +1044,14 @@ class AptDependenciesAppResource(AppResource):
packages: List = []
packages_from_raw_bash: str = ""
extras: Dict[str, Dict[str, str]] = {}
extras: Dict[str, Dict[str, Union[str, List]]] = {}
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
for key, values in properties.get("extras", {}).items():
if not all(
isinstance(values.get(k), str) for k in ["repo", "key", "packages"]
):
raise YunohostError(
"In apt resource in the manifest: 'extras' repo should have the keys 'repo', 'key' and 'packages' defined and be strings",
raw_msg=True,
)
super().__init__(properties, *args, **kwargs)
if isinstance(self.packages, str):
self.packages = [value.strip() for value in self.packages.split(",")]
if self.packages_from_raw_bash:
out, err = self.check_output_bash_snippet(self.packages_from_raw_bash)
if err:
@ -1065,17 +1059,32 @@ class AptDependenciesAppResource(AppResource):
"Error while running apt resource packages_from_raw_bash snippet:"
)
logger.error(err)
self.packages += ", " + out.replace("\n", ", ")
self.packages += out.split("\n")
for key, values in self.extras.items():
if isinstance(values.get("packages"), str):
values["packages"] = [value.strip() for value in values["packages"].split(",")] # type: ignore
if not isinstance(values.get("repo"), str) \
or not isinstance(values.get("key"), str) \
or not isinstance(values.get("packages"), list):
raise YunohostError(
"In apt resource in the manifest: 'extras' repo should have the keys 'repo', 'key' defined as strings and 'packages' defined as list",
raw_msg=True,
)
def provision_or_update(self, context: Dict = {}):
script = [f"ynh_install_app_dependencies {self.packages}"]
script = " ".join(["ynh_install_app_dependencies", *self.packages])
for repo, values in self.extras.items():
script += [
f"ynh_install_extra_app_dependencies --repo='{values['repo']}' --key='{values['key']}' --package='{values['packages']}'"
]
script += "\n" + " ".join([
"ynh_install_extra_app_dependencies",
f"--repo='{values['repo']}'",
f"--key='{values['key']}'",
f"--package='{' '.join(values['packages'])}'"
])
# FIXME : we're feeding the raw value of values['packages'] to the helper .. if we want to be consistent, may they should be comma-separated, though in the majority of cases, only a single package is installed from an extra repo..
self._run_script("provision_or_update", "\n".join(script))
self._run_script("provision_or_update", script)
def deprovision(self, context: Dict = {}):
self._run_script("deprovision", "ynh_remove_app_dependencies")
@ -1166,7 +1175,7 @@ class PortsResource(AppResource):
port_value = self.get_setting(setting_name)
if not port_value and name != "main":
# Automigrate from legacy setting foobar_port (instead of port_foobar)
legacy_setting_name = "{name}_port"
legacy_setting_name = f"{name}_port"
port_value = self.get_setting(legacy_setting_name)
if port_value:
self.set_setting(setting_name, port_value)