Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions acapy_agent/tails/indy_tails_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
from typing import Tuple
from urllib.parse import quote

from ..config.injection_context import InjectionContext
from ..ledger.base import BaseLedger
Expand Down Expand Up @@ -70,8 +71,10 @@ async def upload_tails_file(
"tails_server_base_url setting is not set"
)

upload_url = tails_server_upload_url.rstrip("/") + f"/{filename}"
public_url = tails_server_base_url.rstrip("/") + f"/{filename}"
# BUG #1580: encode revocation tag to avoid spaces in tails URLs
encoded_filename = quote(filename, safe=":")
upload_url = tails_server_upload_url.rstrip("/") + f"/{encoded_filename}"
public_url = tails_server_base_url.rstrip("/") + f"/{encoded_filename}"

try:
await put_file(
Expand Down
69 changes: 49 additions & 20 deletions acapy_agent/tails/tests/test_indy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from unittest import IsolatedAsyncioTestCase
from urllib.parse import quote

from ...config.injection_context import InjectionContext
from ...ledger.base import BaseLedger
Expand All @@ -10,6 +11,7 @@
TEST_DID = "55GkHamhTU1ZbTbV2ab9DE"
CRED_DEF_ID = f"{TEST_DID}:3:CL:1234:default"
REV_REG_ID = f"{TEST_DID}:4:{CRED_DEF_ID}:CL_ACCUM:0"
REV_REG_ID_WITH_SPACE = f"{TEST_DID}:4:{CRED_DEF_ID}:CL_ACCUM:tag with space"


class TestIndyTailsServer(IsolatedAsyncioTestCase):
Expand All @@ -18,14 +20,14 @@ async def test_upload_no_tails_upload_url_x(self):
indy_tails = test_module.IndyTailsServer()

with self.assertRaises(test_module.TailsServerNotConfiguredError):
await indy_tails.upload_tails_file(context, REV_REG_ID, "/tmp/dummy/path")
await indy_tails.upload_tails_file(context, REV_REG_ID, "dummy/path")

async def test_upload(self):
context = InjectionContext(
settings={
"ledger.genesis_transactions": "dummy",
"tails_server_base_url": "http://1.2.3.4:8088/tails/",
"tails_server_upload_url": "http://1.2.3.4:8088",
"tails_server_base_url": "https://tails.example/tails/",
"tails_server_upload_url": "https://tails.example",
}
)
indy_tails = test_module.IndyTailsServer()
Expand All @@ -35,21 +37,21 @@ async def test_upload(self):
(ok, text) = await indy_tails.upload_tails_file(
context,
REV_REG_ID,
"/tmp/dummy/path",
"dummy/path",
)
assert ok

# already contains / from config, no need to add it
assert text == context.settings["tails_server_base_url"] + REV_REG_ID
assert (
mock_put.call_args.args[0]
== context.settings["tails_server_upload_url"] + "/" + REV_REG_ID
assert text == context.settings["tails_server_base_url"] + quote(
REV_REG_ID, safe=":"
)
assert mock_put.call_args.args[0] == context.settings[
"tails_server_upload_url"
] + "/" + quote(REV_REG_ID, safe=":")

async def test_upload_indy_vdr(self):
self.profile = await create_test_profile()
self.profile.settings["tails_server_base_url"] = "http://1.2.3.4:8088/tails/"
self.profile.settings["tails_server_upload_url"] = "http://1.2.3.4:8088"
self.profile.settings["tails_server_base_url"] = "https://tails.example/tails/"
self.profile.settings["tails_server_upload_url"] = "https://tails.example"
mock_multi_ledger_manager = mock.MagicMock(
BaseMultipleLedgerManager, autospec=True
)
Expand All @@ -74,23 +76,50 @@ async def test_upload_indy_vdr(self):
(ok, text) = await indy_tails.upload_tails_file(
self.profile.context,
REV_REG_ID,
"/tmp/dummy/path",
"dummy/path",
)
assert ok

# already contains / from config, no need to add it
assert text == self.profile.settings["tails_server_base_url"] + REV_REG_ID
assert (
mock_put.call_args.args[0]
== self.profile.settings["tails_server_upload_url"] + "/" + REV_REG_ID
assert text == self.profile.settings["tails_server_base_url"] + quote(
REV_REG_ID, safe=":"
)
assert mock_put.call_args.args[0] == self.profile.settings[
"tails_server_upload_url"
] + "/" + quote(REV_REG_ID, safe=":")

async def test_upload_with_space_in_revocation_tag(self):
# BUG #1580: ensure revocation tag whitespace is URL-encoded
context = InjectionContext(
settings={
"ledger.genesis_transactions": "dummy",
"tails_server_base_url": "https://tails.example/tails/",
"tails_server_upload_url": "https://tails.example",
}
)
indy_tails = test_module.IndyTailsServer()

with mock.patch.object(test_module, "put_file", mock.CoroutineMock()) as mock_put:
mock_put.return_value = "tails-hash"
(ok, text) = await indy_tails.upload_tails_file(
context,
REV_REG_ID_WITH_SPACE,
"dummy/path",
)
assert ok

assert text == context.settings["tails_server_base_url"] + quote(
REV_REG_ID_WITH_SPACE, safe=":"
)
assert mock_put.call_args.args[0] == context.settings[
"tails_server_upload_url"
] + "/" + quote(REV_REG_ID_WITH_SPACE, safe=":")

async def test_upload_x(self):
context = InjectionContext(
settings={
"ledger.genesis_transactions": "dummy",
"tails_server_base_url": "http://1.2.3.4:8088/tails/",
"tails_server_upload_url": "http://1.2.3.4:8088",
"tails_server_base_url": "https://tails.example/tails/",
"tails_server_upload_url": "https://tails.example",
}
)
indy_tails = test_module.IndyTailsServer()
Expand All @@ -99,7 +128,7 @@ async def test_upload_x(self):
mock_put.side_effect = test_module.PutError("Server down for maintenance")

(ok, text) = await indy_tails.upload_tails_file(
context, REV_REG_ID, "/tmp/dummy/path"
context, REV_REG_ID, "dummy/path"
)
assert not ok
assert text == "Server down for maintenance"
Loading