diff --git a/plugins/lookup/objstore.py b/plugins/lookup/objstore.py index b35062e495..86fdad854c 100644 --- a/plugins/lookup/objstore.py +++ b/plugins/lookup/objstore.py @@ -1,6 +1,7 @@ from __future__ import annotations from typing import Any +from urllib.parse import quote from ansible.errors import AnsibleError from ansible.plugins.loader import lookup_loader @@ -108,6 +109,7 @@ class LookupModule(LookupBase): "volume": "", "endpoint": "", "url": "", + "credentialed_url": "", "public_domain": "", "public_bucket": "", "public_url": "", @@ -211,6 +213,8 @@ class LookupModule(LookupBase): ) endpoint = f"{host}:{port}" url = f"http://{endpoint}" + userinfo = f"{quote(access_key, safe='')}:{quote(secret_key, safe='')}" + credentialed_url = f"http://{userinfo}@{endpoint}" public_domain = get( applications, @@ -255,6 +259,7 @@ class LookupModule(LookupBase): "volume": volume, "endpoint": endpoint, "url": url, + "credentialed_url": credentialed_url, "public_domain": public_domain, "public_bucket": public_bucket, "public_url": public_url, diff --git a/roles/web-app-zammad/templates/env.j2 b/roles/web-app-zammad/templates/env.j2 index 053b7f4582..eee3174f76 100644 --- a/roles/web-app-zammad/templates/env.j2 +++ b/roles/web-app-zammad/templates/env.j2 @@ -13,8 +13,7 @@ MEMCACHE_SERVERS={{ lookup('engine', 'memcached', application_id, 'host') }}:{{ {% set objstore = lookup('objstore', application_id) %} {% if objstore.enabled | bool %} -{% set objstore_userinfo = (objstore.access_key | urlencode | replace('/', '%2F')) ~ ':' ~ (objstore.secret_key | urlencode | replace('/', '%2F')) %} -S3_URL={{ ((objstore.url | replace('://', '://' ~ objstore_userinfo ~ '@')) ~ '/' ~ objstore.bucket ~ '?region=' ~ objstore.region ~ '&force_path_style=true') | dotenv_quote }} +S3_URL={{ (objstore.credentialed_url ~ '/' ~ objstore.bucket ~ '?region=' ~ objstore.region ~ '&force_path_style=true') | dotenv_quote }} {% endif %} ELASTICSEARCH_HOST={{ ZAMMAD_SEARCH_SERVICE }} diff --git a/tests/unit/python/plugins/lookup/test_objstore.py b/tests/unit/python/plugins/lookup/test_objstore.py index 55eb704d49..24338bb56f 100644 --- a/tests/unit/python/plugins/lookup/test_objstore.py +++ b/tests/unit/python/plugins/lookup/test_objstore.py @@ -148,6 +148,33 @@ class ObjstoreLookupTests(unittest.TestCase): "http://seaweedfs-central:8334", ) + def test_credentialed_url_percent_encodes_both_halves(self): + applications = { + "web-app-foo": { + "services": {"seaweedfs": {"enabled": True, "shared": True}}, + "secrets": {"credentials": {"objstore_secret_key": "a/b+c=d"}}, + }, + "web-svc-seaweedfs": { + "services": { + "seaweedfs": {"name": "seaweedfs-central", "api_port": 8334} + }, + }, + } + + out = self._run(["web-app-foo"], applications)[0] + + self.assertEqual( + out["credentialed_url"], + "http://foo:a%2Fb%2Bc%3Dd@seaweedfs-central:8334", + ) + self.assertEqual(out["url"], "http://seaweedfs-central:8334") + + def test_credentialed_url_is_empty_without_an_engine(self): + applications = {"web-app-foo": {"services": {}}} + self.assertEqual( + self._run(["web-app-foo", "credentialed_url"], applications)[0], "" + ) + def test_public_url_scheme_follows_provider_tls(self): applications = { "web-app-foo": {