Skip to content

Commit 5b00a8f

Browse files
committed
fix(prod): make direct Tigris playback browser-safe
1 parent 2d78eff commit 5b00a8f

5 files changed

Lines changed: 49 additions & 5 deletions

File tree

apps/site/lib/player-engine.test.mts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,11 @@ test("explicit MSE playback still allows opener startup when requested", () => {
123123
url: "https://ash-1.play.rend.so/v/asset/opener.mp4",
124124
});
125125
});
126+
127+
test("automatic playback starts with the opener until browser HLS support is known", () => {
128+
assert.deepEqual(initialSourceSelection(READY_BOOTSTRAP, "hls", "auto"), {
129+
label: "opener",
130+
artifactPath: "opener.mp4",
131+
url: "https://ash-1.play.rend.so/v/asset/opener.mp4",
132+
});
133+
});

apps/site/lib/player-engine.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ export function initialSourceSelection(
152152
return null;
153153
}
154154

155+
// The server cannot know whether the browser supports native HLS. Start the
156+
// universally playable opener for auto mode, then let the client upgrade to
157+
// native HLS or hls.js without first assigning an unsupported manifest.
158+
if (playbackEngine === "auto" && ready.opener_url) {
159+
return { label: "opener", artifactPath: "opener.mp4", url: ready.opener_url };
160+
}
161+
155162
if (ready.playable_state === "hls_ready" && ready.manifest_url) {
156163
return { label: "native_hls", artifactPath: "hls/master.m3u8", url: ready.manifest_url };
157164
}

infra/aws/platform/analytics.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ resource "aws_s3_object" "clickhouse_schema" {
116116
bucket = aws_s3_bucket.clickhouse_native_backups.id
117117
key = "bootstrap/clickhouse-schema.sql"
118118
content = join("\n", [for schema in sort(fileset("${path.module}/../../../clickhouse", "*.sql")) : file("${path.module}/../../../clickhouse/${schema}")])
119-
source_hash = sha256(join("\n", [for schema in sort(fileset("${path.module}/../../../clickhouse", "*.sql")) : file("${path.module}/../../../clickhouse/${schema}")]))
119+
etag = md5(join("\n", [for schema in sort(fileset("${path.module}/../../../clickhouse", "*.sql")) : file("${path.module}/../../../clickhouse/${schema}")]))
120120
server_side_encryption = "aws:kms"
121121
kms_key_id = aws_kms_key.clickhouse.arn
122122
}

infra/aws/platform/locals.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ locals {
4141
{ name = "REND_PLAYBACK_MODE", value = "tigris" },
4242
{ name = "REND_PLAYBACK_BASE_URL", value = local.playback_base_url },
4343
{ name = "REND_TIGRIS_PLAYBACK_BASE_URL", value = local.playback_base_url },
44-
{ name = "REND_PUBLIC_PLAYBACK_ENABLED", value = "false" },
44+
{ name = "REND_PUBLIC_PLAYBACK_ENABLED", value = "true" },
4545
{ name = "REND_PUBLIC_PLAYBACK_ALIAS_ENABLED", value = "true" },
4646
{ name = "REND_PUBLIC_PLAYBACK_ALIAS_BUCKET", value = var.tigris_media_bucket },
4747
{ name = "REND_PUBLIC_PLAYBACK_ALIAS_PREFIX", value = "v" },

infra/aws/scripts/provision-tigris.sh

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ ensure_bucket() {
130130
local bucket="$1"
131131
local location="$2"
132132
local cors_file="$3"
133+
local allow_public_policy="${4:-false}"
133134
local bucket_info
134135
local expected_location
135136
local actual_location
@@ -160,7 +161,7 @@ ensure_bucket() {
160161
--bucket "$bucket" \
161162
--query 'PolicyStatus.IsPublic' \
162163
--output text)"
163-
if [[ "$public_policy" != "False" && "$public_policy" != "false" ]]; then
164+
if [[ "$allow_public_policy" != "true" && "$public_policy" != "False" && "$public_policy" != "false" ]]; then
164165
echo "Tigris policy is public for bucket $bucket" >&2
165166
exit 1
166167
fi
@@ -183,7 +184,35 @@ ensure_bucket() {
183184
}
184185

185186
ensure_bucket "$TIGRIS_SOURCE_BUCKET" "$TIGRIS_SOURCE_LOCATION" "$work_dir/source-cors.json"
186-
ensure_bucket "$TIGRIS_MEDIA_BUCKET" "$TIGRIS_MEDIA_LOCATION" "$work_dir/media-cors.json"
187+
ensure_bucket "$TIGRIS_MEDIA_BUCKET" "$TIGRIS_MEDIA_LOCATION" "$work_dir/media-cors.json" true
188+
189+
# Only immutable playback aliases are anonymously readable. Canonical media,
190+
# processing attempts, and source objects remain private. Asset identifiers are
191+
# unguessable UUIDs and the public API already grants playback by asset ID, so
192+
# signed cookies add no authorization boundary while preventing credentialed
193+
# browser playback on Tigris's S3-compatible CORS responses.
194+
jq -n --arg bucket "$TIGRIS_MEDIA_BUCKET" '{
195+
Version: "2012-10-17",
196+
Statement: [{
197+
Sid: "PublicReadPlaybackAliases",
198+
Effect: "Allow",
199+
Principal: "*",
200+
Action: ["s3:GetObject"],
201+
Resource: ["arn:aws:s3:::" + $bucket + "/v/*"]
202+
}]
203+
}' >"$work_dir/media-policy.json"
204+
tigris_s3api put-bucket-policy \
205+
--bucket "$TIGRIS_MEDIA_BUCKET" \
206+
--policy "file://$work_dir/media-policy.json" >/dev/null
207+
208+
media_public_policy="$(tigris_s3api get-bucket-policy-status \
209+
--bucket "$TIGRIS_MEDIA_BUCKET" \
210+
--query 'PolicyStatus.IsPublic' \
211+
--output text)"
212+
if [[ "$media_public_policy" != "True" && "$media_public_policy" != "true" ]]; then
213+
echo "Tigris playback alias policy is not public for bucket $TIGRIS_MEDIA_BUCKET" >&2
214+
exit 1
215+
fi
187216

188217
playback_public_key_pem="$(printf '%s' "$TIGRIS_PLAYBACK_PUBLIC_KEY_PEM_B64" | base64 --decode)"
189218
if [[ "$playback_public_key_pem" != "-----BEGIN PUBLIC KEY-----"* ]]; then
@@ -234,4 +263,4 @@ aws ssm put-parameter \
234263
--overwrite \
235264
--no-cli-pager >/dev/null
236265

237-
echo "Tigris source and media bucket contracts, private playback key, and custom playback domain are reconciled."
266+
echo "Tigris private source/canonical media, public playback aliases, and custom playback domain are reconciled."

0 commit comments

Comments
 (0)