-
Notifications
You must be signed in to change notification settings - Fork 9
feat(edge): Lambda@Edge Cognito enforcement on CloudFront (split-stack, region-agnostic) #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
30efc6d
docs: Lambda@Edge Cognito enforcement design (v2)
royosherove 28a3f4e
feat(edge): Lambda@Edge Cognito enforcement on CloudFront
royosherove b139e7d
fix(edge): address P0/P1 findings from first review round
royosherove 8a70dc9
fix(edge): address round-2 P0/P1 findings
royosherove 7ecf3c6
fix(edge): address round-3 P1/P2 findings
royosherove 72c5d99
docs+wip: split-stack architecture design (v3) + partial CFN refactor
royosherove caa1269
fix(edge): address v3 design review P0/P1
royosherove c78bd2b
feat(edge): installer 2-phase deploy for split-stack architecture
royosherove 4c554ea
fix(edge): Codex P1 findings on PR #86
royosherove 43f8fbb
fix(edge): override parseAuthPath to match Cognito CallbackURLs
royosherove d3b8380
fix(edge): unblock deployment and protect ALB origin
royosherove cb1a8df
fix(edge): harden auth cookies and refresh config
royosherove 6057bff
fix(edge): secure packaging and add logout support
royosherove File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| AWSTemplateFormatVersion: '2010-09-09' | ||
| Description: > | ||
| Lowkey WebUI Cognito Auth — Lambda@Edge companion stack. | ||
| Deploys the Lambda@Edge function, its version, IAM role, and the two | ||
| Secrets Manager secrets (signing key + merged edge config) in us-east-1 | ||
| because Lambda@Edge sources MUST live in us-east-1 (AWS platform | ||
| requirement). The main Lowkey stack can deploy in any region; the | ||
| installer wires the two together via CFN parameters and cross-region | ||
| Secrets Manager writes. | ||
|
|
||
| Parameters: | ||
| EnvironmentName: | ||
| Type: String | ||
| MinLength: 1 | ||
| Description: "Environment name — matches the main stack's EnvironmentName so secret names align." | ||
|
|
||
| PackName: | ||
| Type: String | ||
| Default: kirocrew | ||
| Description: "Pack that owns this edge Lambda. Used only for tags." | ||
|
|
||
| EdgeLambdaS3Bucket: | ||
| Type: String | ||
| MinLength: 1 | ||
| Description: "S3 bucket (in us-east-1) holding the Lambda@Edge deployment zip." | ||
|
|
||
| EdgeLambdaS3Key: | ||
| Type: String | ||
| MinLength: 1 | ||
| Description: "S3 key of the Lambda@Edge deployment zip." | ||
|
|
||
| EdgeLambdaCodeSha256: | ||
| Type: String | ||
| MinLength: 1 | ||
| Description: "Base64 SHA256 of the deployment zip. Forces a new AWS::Lambda::Version when code changes." | ||
|
|
||
| Rules: | ||
| WebUIEdgeRequiresUsEast1: | ||
| Assertions: | ||
| - Assert: !Equals [!Ref 'AWS::Region', 'us-east-1'] | ||
| AssertDescription: "Lambda@Edge companion stack must be deployed in us-east-1." | ||
|
|
||
| Resources: | ||
| # Raw HMAC signing key. CFN-managed via GenerateSecretString. Never written | ||
| # to by anything else — read once by the main-stack Custom Resource which | ||
| # then merges it into EdgeConfigSecret alongside the Cognito pool/client/domain. | ||
| WebUIEdgeSigningKeySecret: | ||
| Type: AWS::SecretsManager::Secret | ||
| Properties: | ||
| Name: !Sub '/lowkey/${EnvironmentName}/webui-edge-signing-key' | ||
| Description: !Sub 'Raw HMAC signing key for KiroCrew WebUI Lambda@Edge (${EnvironmentName})' | ||
| GenerateSecretString: | ||
| SecretStringTemplate: '{}' | ||
| GenerateStringKey: 'key' | ||
| PasswordLength: 64 | ||
| ExcludePunctuation: true | ||
| Tags: | ||
| - Key: loki:managed | ||
| Value: 'true' | ||
| - Key: loki:pack | ||
| Value: !Ref PackName | ||
| - Key: loki:env | ||
| Value: !Ref EnvironmentName | ||
|
|
||
| # Merged {poolId, clientId, cognitoDomain, signingKey} secret that the | ||
| # Lambda@Edge reads at cold start. Initial SecretString is a placeholder; | ||
| # the main-stack Custom Resource overwrites it once the Cognito pool exists. | ||
| WebUIEdgeConfigSecret: | ||
| Type: AWS::SecretsManager::Secret | ||
| Properties: | ||
| Name: !Sub '/lowkey/${EnvironmentName}/webui-edge-config' | ||
| Description: !Sub 'Merged Cognito config for KiroCrew WebUI Lambda@Edge (${EnvironmentName})' | ||
| SecretString: '{"poolId":"pending","clientId":"pending","cognitoDomain":"pending","signingKey":"pending"}' | ||
| Tags: | ||
| - Key: loki:managed | ||
| Value: 'true' | ||
| - Key: loki:pack | ||
| Value: !Ref PackName | ||
| - Key: loki:env | ||
| Value: !Ref EnvironmentName | ||
|
|
||
| WebUIEdgeLambdaRole: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
| RoleName: !Sub '${EnvironmentName}-webui-edge-role' | ||
| AssumeRolePolicyDocument: | ||
| Version: '2012-10-17' | ||
| Statement: | ||
| - Effect: Allow | ||
| Principal: | ||
| Service: | ||
| - lambda.amazonaws.com | ||
| - edgelambda.amazonaws.com | ||
| Action: sts:AssumeRole | ||
| ManagedPolicyArns: | ||
| - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole | ||
| Policies: | ||
| - PolicyName: FetchEdgeConfig | ||
| PolicyDocument: | ||
| Version: '2012-10-17' | ||
| Statement: | ||
| - Effect: Allow | ||
| Action: | ||
| - secretsmanager:GetSecretValue | ||
| Resource: !Ref WebUIEdgeConfigSecret | ||
|
|
||
| WebUIEdgeLambdaFunction: | ||
| Type: AWS::Lambda::Function | ||
| Properties: | ||
| FunctionName: !Sub '${EnvironmentName}-webui-edge-auth' | ||
| Runtime: nodejs22.x | ||
| Handler: index.handler | ||
| MemorySize: 128 | ||
| Timeout: 5 | ||
| Role: !GetAtt WebUIEdgeLambdaRole.Arn | ||
| Code: | ||
| S3Bucket: !Ref EdgeLambdaS3Bucket | ||
| S3Key: !Ref EdgeLambdaS3Key | ||
|
|
||
| WebUIEdgeLambdaVersion: | ||
| Type: AWS::Lambda::Version | ||
| # Old versions cannot be deleted while CloudFront still references them | ||
| # (Lambda@Edge replicas take ~1hr to GC after CloudFront disassociates). | ||
| # Retain them on stack update/delete so a code refresh doesn't roll back | ||
| # the edge stack. Old versions are free — they accumulate harmlessly. | ||
| DeletionPolicy: Retain | ||
| UpdateReplacePolicy: Retain | ||
| Properties: | ||
| FunctionName: !Ref WebUIEdgeLambdaFunction | ||
| Description: !Sub 'KiroCrew WebUI Cognito auth (${EnvironmentName}) sha256=${EdgeLambdaCodeSha256}' | ||
| CodeSha256: !Ref EdgeLambdaCodeSha256 | ||
|
|
||
| Outputs: | ||
| EdgeLambdaVersionArn: | ||
| Description: "Versioned ARN of the Lambda@Edge function. Pass this to the main stack's WebUIEdgeLambdaVersionArn parameter." | ||
| Value: !Ref WebUIEdgeLambdaVersion | ||
|
|
||
| EdgeLambdaFunctionArn: | ||
| Description: "Unversioned ARN of the Lambda@Edge function." | ||
| Value: !GetAtt WebUIEdgeLambdaFunction.Arn | ||
|
|
||
| EdgeConfigSecretName: | ||
| Description: "Deterministic name of the merged edge config secret. Custom Resource in the main stack uses this via a cross-region Secrets Manager client." | ||
| Value: !Sub '/lowkey/${EnvironmentName}/webui-edge-config' | ||
|
|
||
| EdgeConfigSecretArn: | ||
| Description: "Full ARN of the edge config secret." | ||
| Value: !Ref WebUIEdgeConfigSecret | ||
|
|
||
| SigningKeySecretName: | ||
| Description: "Deterministic name of the raw signing key secret." | ||
| Value: !Sub '/lowkey/${EnvironmentName}/webui-edge-signing-key' | ||
|
|
||
| SigningKeySecretArn: | ||
| Description: "Full ARN of the signing key secret." | ||
| Value: !Ref WebUIEdgeSigningKeySecret | ||
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
EdgeLambdaCodeSha256changes, CloudFormation replaces this version and then attempts to delete the old version while the separately deployed main stack's CloudFront distribution still references it. Lambda rejects deletion of a replicated Lambda@Edge version, so the edge-stack update can fail before the installer gets the new ARN and updates the main stack. Add an update-retention strategy for old versions or otherwise sequence association removal/update before deleting them.Useful? React with 👍 / 👎.