Skip to content

fix: use execute-api domain for WebSocket Management API#268

Merged
layertwo merged 1 commit intomainlinefrom
fix/channel-apigw-endpoint
Mar 3, 2026
Merged

fix: use execute-api domain for WebSocket Management API#268
layertwo merged 1 commit intomainlinefrom
fix/channel-apigw-endpoint

Conversation

@layertwo
Copy link
Owner

@layertwo layertwo commented Mar 3, 2026

Summary

  • Fix AccessDeniedException on PostToConnection by using the execute-api domain instead of the custom domain for the API Gateway Management API endpoint
  • The custom domain (channel.prod.ffsync.layertwo.dev) doesn't work for the Management API because the IAM policy from grantManageConnections is scoped to the execute-api ARN
  • Derives endpoint from event.requestContext.apiId + session.region_name instead of event.requestContext.domainName

Test plan

  • 976 Python tests pass, 100% coverage
  • Deploy and verify WebSocket pairing creates channels successfully

@github-actions
Copy link

github-actions bot commented Mar 3, 2026

Diff for stage: DefaultStage

Diff for stack: GitHubOidcStack - 0 to add, 1 to update, 0 to destroy 🟡

Details
Resources
[~] Custom::AWSCDKOpenIdConnectProvider GitHubOidcProvider7EBF861F
 ├─ [~] CodeHash
 │   ├─ [-] 62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb
 │   └─ [+] d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50
 └─ [~] RejectUnauthorized
[~] AWS::Lambda::Function CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb.zip
 │       └─ [+] d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb
         └─ [+] asset.d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50

Diff for stack: Service-prod - 0 to add, 0 to update, 0 to destroy

Details
Resources
[~] AWS::Lambda::Function AuthApiHandlerED50ACFA
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf.zip
 │       └─ [+] 5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf
         └─ [+] asset.5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988
[~] AWS::Lambda::Function TokenApiHandler2E66DB25
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf.zip
 │       └─ [+] 5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf
         └─ [+] asset.5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988
[~] AWS::Lambda::Function ProfileApiHandler9B65A298
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf.zip
 │       └─ [+] 5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf
         └─ [+] asset.5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988
[~] AWS::Lambda::Function ApiHandler5E7490E8
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf.zip
 │       └─ [+] 5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.850221aad906011940bd40dd2b8310bd089e61849abe9c6b1b3613b10da31dbf
         └─ [+] asset.5174e8eb39d2a8923c1463ac8268cc0ba8191e0dbc87557af1d142a35d5b5988
[~] AWS::Lambda::Function ChannelApiHandler02759D57
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] e9113cb6dadd0085c2631e8f755dbec103f0a284da11b33a3dfd7659b7ff49ef.zip
 │       └─ [+] 0823488cf4518e58ff22331aa868f9110776de70f7cba2b156f42954b11061e8.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.e9113cb6dadd0085c2631e8f755dbec103f0a284da11b33a3dfd7659b7ff49ef
         └─ [+] asset.0823488cf4518e58ff22331aa868f9110776de70f7cba2b156f42954b11061e8

No Changes for stack: Frontend-prod ✅
No Changes for stack: Monitoring-prod ✅

Generated for commit 6d86105 at 2026-03-03T03:00:30.062Z

The Management API endpoint must use the execute-api domain, not the
custom domain. Using the custom domain causes AccessDeniedException
because the IAM policy from grantManageConnections is scoped to the
execute-api ARN.

Derives the endpoint from event.requestContext.apiId and
session.region_name instead of event.requestContext.domainName.
@layertwo layertwo force-pushed the fix/channel-apigw-endpoint branch from aaeec89 to 6d86105 Compare March 3, 2026 02:57
@github-actions
Copy link

github-actions bot commented Mar 3, 2026

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  lambda/src/services
  channel_service.py
Project Total  

This report was generated by python-coverage-comment-action

@layertwo layertwo merged commit 940df9e into mainline Mar 3, 2026
10 checks passed
@layertwo layertwo deleted the fix/channel-apigw-endpoint branch March 5, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant