fix: allow S2S consumers with site:readAll to submit authenticated scrape jobs#2853
Draft
aenascut wants to merge 1 commit into
Draft
fix: allow S2S consumers with site:readAll to submit authenticated scrape jobs#2853aenascut wants to merge 1 commit into
aenascut wants to merge 1 commit into
Conversation
…rape jobs POST /tools/scrape/jobs checked hasAccess(site) only — an org-membership check that always fails for cross-tenant S2S principals (their token carries their own org, not the customer's). Every other cross-tenant route (sites, organizations, configuration) already has the hasS2SCapability(CAP_SITE_READ_ALL) fallback; scrapeJob was missed. Fixes SITES-47964 (DRS 403 on twilio.com authenticated scrape path). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
POST /tools/scrape/jobswith asiteId(required whenoptions.enableAuthentication: true) applies a per-site org-membership check (hasAccess(site)) that always fails for cross-tenant S2S principals. A service token carries the principal's own IMS org in its tenants list, not the customer's org — sohasOrganization(customerImsOrgId)is unconditionally false regardless of what capabilities the consumer holds.Every other cross-tenant S2S route in this service (
sites.js,organizations.js,configuration.js) already has thehasS2SCapability(CAP_SITE_READ_ALL)fallback. The scrape job controller was missed.Evidence
Traced via Splunk (
index=dx_aem_engineering sourcetype=dx_aem_sites_mystique_backend_prod) and CloudWatch (SpaceCat prod account640168421876) during incident SITES-47964 (twilio.com, site275d1b4e, org138eaa2a).Scan
c474b9f1— authenticated path, DRS jobdde32831Mystique submits batch at
10:23:41. Six seconds later the poller logs:DRS's S2S principal passed L1 (
scrapeJob:writecapability present, consumer ACTIVE) but hit the org-membership wall at L2 (hasAccess(site)). All 10 sub-job POSTs returned HTTP 403. Fast-fail at 13.9s.Scan
8339a60b— unauthenticated path (no siteId), DRS job870b4218No
siteId→hasAccessnot reached → job accepted (HTTP 200), 10 job IDs019f5b0a-*created, 100 URL messages queued onspacecat-scrape-content-processing-jobs.fifo. The content-scraper Lambda logged zero events for all 10 job IDs across the 4-hour window. DRS backstop tripped at 14400s:Root cause for this path:
spacecat-scrape-queue-1.fifohad ~175k messages backlogged at the time. The 100 twilio messages were enqueued but expired (4-day SQS retention) before the content-scraper reached them. This is a separate scaling issue tracked in SITES-47964.What changed
createScrapeJobinscrapeJob.jsnow mirrors the access-control pattern used by every other cross-tenant S2S route:hasS2SCapabilityre-fetches the Consumer record from the DB on every call (stale token cannot grant access). An S2S consumer withoutsite:readAllstill falls through tohasAccess(site)— existing behaviour for all other consumers is unchanged.Auth flow after this fix
Follow-up required — grant DRS the
site:readAllcapabilityThis code change is necessary but not sufficient. The DRS Consumer record must be updated to include
site:readAllbefore the fix takes effect. Without the data grant,hasS2SCapabilityreturns{ allowed: false, reason: 'missing-capability' }and the 403 persists.DRS is already registered as an S2S consumer with
scrapeJob:write(that is how it passes L1). The update only adds the cross-tenant read capability.Steps (requires
is_s2s_admintoken):clientId:consumerId. Then patch capabilities:Valid capabilities follow
entity:operationformat where operation ∈{ read, write, delete, readAll, create }.site:readAllis the existing capability used by all other cross-tenant S2S routes (e.g.GET /sites,GET /sites/:siteId/identity) — no new capability string is introduced.The
PATCHendpoint is admin-gated (hasS2SAdminAccess()required). It re-validates capabilities on write and logs the change. The update takes effect immediately on the next DRS request — no deploy needed after the data grant.Suggested verification after deploy + data grant:
Re-run a DRS authenticated bundle scan against twilio prod site
275d1b4e. Expect HTTP 200 onPOST /tools/scrape/jobsand SpaceCat job IDs transitioning to COMPLETED within the normal scrape window.Secondary issue (not fixed here)
spacecat-scrape-queue-1.fifohad ~175k messages backlogged at investigation time (2026-07-20).spacecat-scrape-queue-2.fifoexists but has no event source mapping tocontent-scraper. Adding one would double consumer throughput with no infra changes. The DLQ (spacecat-scraper-dlq.fifo) held 277 messages from failed scrapes across multiple customers. Both items tracked in SITES-47964.Related