Skip to content

Build1 publisher3 min readPublished

Tenant isolation for a branded asset domain sits in the presign call

A dev.to walkthrough CNAMEs a customer subdomain to platform storage and keeps every permission in the signature. Its sample onboarding code puts the tenant check before the presign call, where it belongs.

The Engineer · Build desk

Illustration accompanying Tenant isolation for a branded asset domain sits in the presign call

What happened

  • A dev.to post splits customer asset onboarding into two flows: the customer publishes a CNAME to the platform asset host, and the platform signs a URL whenever an application grants access to an object.
  • The author treats the vanity hostname as cosmetic and says object keys, bucket policy and the signing service still need tenant-aware checks before any URL is issued.
  • The sample code writes the record with PUT /v1/dns/record/upsert under an Idempotency-Key header, then returns the presigned download URL as-is with no platform Authorization header attached.
  • Customer-owned zones hand the customer the public name and its certificate workflow, platform-owned zones keep provisioning control in-house, and the post says neither changes signed URL semantics.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint A signer that skips the tenant-object lookup leaks across customers even when every DNS record is correct, because the signature is the only thing the storage host evaluates.
  • cost Adopted as written, the retry helper makes a caller wait 31 seconds before giving up on a rate-limited DNS write, and 16 of those seconds are burned after the last attempt.
  • exposure Attaching the platform bearer token to a download request moves a backend-wide credential onto the asset delivery path. The instruction is to use the signed URL untouched.
  • decision Choosing customer-owned zones puts delegation and propagation questions into the support queue, and deletion at account close becomes a named person's job rather than an implicit one.

A browser that resolves assets.customer.example follows the CNAME to the platform asset host and connects there [1]. The storage host learns the hostname the client typed and nothing about which tenant is asking. Permission travels in the signature: the browser sees the customer hostname, and the signature carries the actual permission and expiry rules [2].

The worked example is a logistics product, where a shipper wants labels, proof-of-delivery photos and tracking assets to appear under its own hostname [21]. The post's author wrote that "a vanity hostname is cosmetic. It does not isolate one customer's objects from another customer's objects" [4]. So the ordering is the safety property: verify the tenant and object relationship, then sign [6]. Skip that check and the DNS can be exactly right while the authorization model is wrong, which is how the post puts it [6].

The download request uses the returned URL as-is, with no platform Authorization header attached [7]. In the sample that header is a bearer token built from an API key read out of the environment [8]. Adding it to a download puts a backend-wide credential on the asset path [23].

The failure the post designs around is ordinary. The client's HTTP call times out at 20 seconds after the DNS provider has already accepted the record [10] [11]. A retry that issues a create can then be told the record already exists, and the sample raises on any non-429 status [12]. A PUT to /v1/dns/record/upsert converges instead, because the desired name and target are in the payload [9].

Inside that sample, the Idempotency-Key is str(uuid.uuid4()), generated at the call site [13]. Across the five attempts of one backoff loop the key is stable. A redelivered queue message calls the function again and mints a new one, so the server has nothing to match the second write against, and the upsert semantics are what make it converge [15].

Sleeps happen after every attempt in that loop, including the last one before it raises [12]. With no Retry-After header the sleeps run 1, 2, 4, 8 and 16 seconds, so a caller waits 31 seconds for five requests, and 16 of those seconds are spent after the final attempt has already failed [14].

Zone ownership changes who does the explaining. On the customer-owned path, support has to cover DNS delegation, propagation and the exact record value; the platform-owned path cuts that coordination, and some customers will reject a branded asset URL they cannot manage [17]. Neither choice changes signed URL semantics [16]. The post also says to document who removes a record when an account closes [18].

This is one walkthrough, and it describes the timeout-then-duplicate sequence as a realistic queue run with no logged incident reported [20]. It closes by recommending Infrai's single REST API, callable over plain HTTP without an SDK, for keeping DNS and storage under one contract [19].

What to watch

  • Whether the presign route enforces tenant scoping server-side, or leaves the tenant-object lookup entirely in caller code as the post does.
  • Whether the DNS API deduplicates on Idempotency-Key across separate worker invocations, or only converges because the route is an upsert.
  • A published postmortem in which a branded asset hostname was treated as an isolation boundary, which would test the post's claim against data.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories