mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 13:17:07 +00:00
fix(objstore): sign funkwhale's media URLs against the host the browser dials
funkwhale has two S3 surfaces sharing one private bucket. Audio goes out as X-Accel-Redirect and the front nginx fetches it server-side, but attachments (instance logo, avatars, covers) land in the API JSON as absolute URLs the BROWSER dials. AWS_S3_ENDPOINT_URL drives the boto3 client, so with the internal endpoint django-storages signed URLs for http://seaweedfs:8333, a host no browser can reach. Point the client at the new bucket-less public_endpoint key. Measured against the live gateway: a URL signed for seaweedfs:8333 and sent to the public host answers 403 SignatureDoesNotMatch, while one signed for the public host reaches bucket lookup — query-string SigV4 binds the Host, so the signing host and the fetch host must be the same string. AWS_S3_CUSTOM_DOMAIN cannot serve this: storages/backends/s3.py:689 returns UNSIGNED without a CloudFront signer, and the bucket also holds the music library that music/views.py exists to gate. AWS_CA_BUNDLE follows, because the public endpoint is TLS on the local CA and botocore reads its trust store only from that variable (configprovider.py:59) — sys-svc-compose-ca injects SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE and NODE_EXTRA_CA_CERTS, never this one. It takes the bundle rather than the bare root cert, since AWS_CA_BUNDLE replaces the default store. AWS_QUERYSTRING_AUTH=True fixes a pre-existing break: upstream defaults it to `not PROXY_MEDIA`, which produced unsigned URLs against a private bucket. The new front nginx.conf.j2 serves /_protected/media, which the stock template resolves with `alias ${MEDIA_ROOT}/$1;` and therefore 404s for every S3-backed listen. web-svc-seaweedfs keeps no onion vhost. Its tor-contract reason now states the mechanical cause instead of the old claim that the role is never a Tor-browser surface, which decidim and funkwhale have made false: the node hidden service publishes http only while sys-front-tls keys listen/ssl on application_id, so an onion vhost would listen on 443 against a port-80 hidden service. Attachment fetches therefore still fail on an onion pick, and the spec is left to fail there rather than record the miss and pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
40001f0e9a
commit
1e61debad2
10 files changed
+203
-6
No files matched your search
@@ -104,6 +104,7 @@ class ObjstoreLookupTests(unittest.TestCase):
|
||||
self.assertEqual(out["url"], "")
|
||||
self.assertEqual(out["public_domain"], "")
|
||||
self.assertEqual(out["public_bucket"], "")
|
||||
self.assertEqual(out["public_endpoint"], "")
|
||||
self.assertEqual(out["public_url"], "")
|
||||
self.assertEqual(out["reach_host"], "127.0.0.1")
|
||||
|
||||
@@ -139,6 +140,7 @@ class ObjstoreLookupTests(unittest.TestCase):
|
||||
self.assertEqual(out["url"], "http://seaweedfs-central:8334")
|
||||
self.assertEqual(out["public_domain"], "api.seaweedfs.s3.example.com")
|
||||
self.assertEqual(out["public_bucket"], "api.seaweedfs.s3.example.com/foo")
|
||||
self.assertEqual(out["public_endpoint"], "https://api.seaweedfs.s3.example.com")
|
||||
self.assertEqual(out["public_url"], "https://api.seaweedfs.s3.example.com/foo")
|
||||
|
||||
self.assertEqual(
|
||||
@@ -146,6 +148,28 @@ class ObjstoreLookupTests(unittest.TestCase):
|
||||
"http://seaweedfs-central:8334",
|
||||
)
|
||||
|
||||
def test_named_canonical_siblings_do_not_win_over_the_api(self):
|
||||
applications = {
|
||||
"web-app-foo": {
|
||||
"services": {"minio": {"enabled": True, "shared": True}},
|
||||
"secrets": {"credentials": {"objstore_secret_key": "sk"}},
|
||||
},
|
||||
"web-app-minio": {
|
||||
"services": {"minio": {"name": "minio-central"}},
|
||||
"domains": {
|
||||
"canonical": {
|
||||
"console": "console.minio.s3.example.com",
|
||||
"api": "api.minio.s3.example.com",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
out = self._run(["web-app-foo"], applications)[0]
|
||||
|
||||
self.assertEqual(out["public_domain"], "api.minio.s3.example.com")
|
||||
self.assertEqual(out["public_endpoint"], "https://api.minio.s3.example.com")
|
||||
|
||||
def test_credentialed_url_percent_encodes_both_halves(self):
|
||||
applications = {
|
||||
"web-app-foo": {
|
||||
|
||||
Reference in new issue
Block a user