Open DAMSCROW opened 5 days ago
Comprehensive Explanation of the Origin Access Control Circular Dependency Issue
Your Use Case
You have two AWS CloudFormation stacks in your project:
Hosts a React frontend application in an S3 bucket.
Defines an Origin Access Control (OAC) object to secure access to the bucket when used as an origin for CloudFront.
Creates a CloudFront distribution that uses the S3 bucket as an origin.
Requires the bucket and the OAC object from the Frontend Bucket Stack to configure its origin settings.
Your Actual Issue
When deploying the two stacks, a cyclic dependency issue arises. This means:
The Frontend Bucket Stack requires the CloudFront Distribution ID (from the Global CloudFront Stack) to update the bucket policy to allow secure access.
The Global CloudFront Stack needs the bucket and the OAC object (from the Frontend Bucket Stack) to create the CloudFront distribution.
Both stacks depend on information from each other to complete their configuration, creating a deadlock, as neither can fully deploy without the other.
How Origin Access Control (OAC) is Currently Implemented
In your setup:
Creates an S3 bucket for the React app.
Defines an Origin Access Control (OAC) object with sigv4 signing.
Exports the bucket and OAC object for use in other stacks.
Receives the bucket and OAC object as parameters.
Configures the CloudFront distribution's origin using the method S3BucketOrigin.withOriginAccessControl().
The Frontend Bucket Stack exports the bucket and OAC, but it also requires the CloudFront Distribution ID to complete the bucket policy.
The CloudFront Stack cannot finish because it needs the bucket and OAC to configure the origin.
This results in a cyclic dependency.
How the Previous Origin Access Identity (OAI) Setup Worked
Previously, you used Origin Access Identity (OAI) instead of OAC. Here’s how it worked:
The bucket did not need to know which specific CloudFront distribution was accessing it.
The bucket policy was written to allow access to any CloudFront distribution with the OAI.
The Frontend Bucket Stack and the Global CloudFront Stack didn’t need to depend on each other directly.
The two stacks could deploy independently without creating circular dependencies.
Why the Issue Appears with OAC
Unlike OAI, Origin Access Control (OAC) is stricter and more secure. It requires:
The bucket policy to specifically allow access for a specific CloudFront Distribution ID.
Here’s what’s happening:
Needs to include the CloudFront Distribution ID (from the CloudFront Stack) in its bucket policy to enforce OAC-based access control.
Needs the bucket and the OAC object (from the Frontend Bucket Stack) to set up the origin.
This creates a circular dependency:
The Frontend Bucket Stack cannot finish until the CloudFront Distribution ID exists.
The Global CloudFront Stack cannot finish until the bucket and OAC are available.
This was not an issue with OAI because OAI does not require the bucket to reference the specific CloudFront Distribution ID. It acts as a general "access pass."
Understanding the Issue in Layman’s Terms
With OAI: Imagine you’re at a concert, and the security guard at the entrance checks if you have a general “access pass.” It doesn’t matter who you are or which ticket you hold as long as you have the pass. Similarly, the bucket only cared that CloudFront had a valid OAI, so it didn’t need to know the CloudFront’s details.
With OAC: Now, the security is stricter. The guard asks for your specific ticket ID to confirm you’re allowed in. This means the bucket needs to know the exact CloudFront Distribution ID. But here’s the catch: CloudFront also needs the bucket’s details to configure itself properly. Both are waiting for each other, causing a standstill (cyclic dependency).
Understanding the Issue in Technical Terms
OAI is designed to work without coupling the bucket to a specific CloudFront Distribution. The bucket policy allows access for any request carrying a valid OAI, making it flexible and avoiding direct dependencies between stacks.
OAC, on the other hand, ties the bucket to a specific CloudFront Distribution via its ID. This tight coupling ensures higher security but introduces a dependency:
The bucket policy must be updated with the CloudFront Distribution ID.
The CloudFront configuration requires the bucket and OAC details upfront.
This mutual dependency creates the circular reference that CloudFormation cannot resolve.
Possible Solutions
Solution 1: Cross-Stack Outputs
Process:
Deploy the Frontend Bucket Stack first.
Export the bucket name and OAC ID as outputs.
Import these outputs in the Global CloudFront Stack to configure the distribution.
Export the CloudFront Distribution ID from the Global CloudFront Stack.
Update the Frontend Bucket Stack to use the imported Distribution ID for the bucket policy.
Key Point: This requires a two-step deployment because the Distribution ID is only available after the Global CloudFront Stack is deployed.
Solution 2: Custom Resource (Lambda Function)
Process:
Deploy both stacks without updating the bucket policy.
Use a Lambda function as a custom resource to:
Fetch the CloudFront Distribution ID after the Global CloudFront Stack is deployed.
Update the bucket policy with the Distribution ID.
Key Point: This also requires a two-step process, as the Lambda updates the bucket policy asynchronously after both stacks are deployed.
Solution 3: Combine Stacks
Process:
Merge the Frontend Bucket Stack and the Global CloudFront Stack into a single stack.
This way, the bucket, OAC, and CloudFront distribution are all created together, eliminating cross-stack dependencies.
Key Point: This allows for a single-step deployment but reduces modularity and reusability of the stacks.
Recommendation
The best solution depends on your needs:
For modularity: Use Solution 1 (Cross-Stack Outputs).
For automation: Use Solution 2 (Custom Resource).
For simplicity: Use Solution 3 (Combine Stacks).
Both Solution 1 and Solution 2 require a two-step deployment due to the inherent dependency between the bucket policy and CloudFront Distribution ID.
Let me know if you'd like detailed implementation for any of these solutions!
import as cdk from 'aws-cdk-lib'; import as s3 from 'aws-cdk-lib/aws-s3'; import as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import as iam from 'aws-cdk-lib/aws-iam';
// Step 1: Create the S3 bucket (no OAC for now) const bucket = new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, // Customize as needed });
// Step 2: Create the Origin Access Control separately const originAccessControl = new cloudfront.OriginAccessControl(stack, 'MyOAC', { originAccessControlName: 'MyOAC', signingBehavior: cloudfront.OriginAccessControlSigningBehavior.ALWAYS, signingProtocol: cloudfront.OriginAccessControlSigningProtocol.SIGV4, s3CanonicalUserId: bucket.bucketOwnerCanonicalUserId, });
// Step 3: Create CloudFront distribution using the manual S3 origin const distribution = new cloudfront.Distribution(stack, 'MyDistribution', { defaultBehavior: { origin: new cloudfront.origins.S3Origin(bucket, { originAccessControl, }), }, });
// Step 4: Manually update the bucket policy (to allow CloudFront access)
bucket.addToResourcePolicy(new iam.PolicyStatement({
actions: ['s3:GetObject'],
resources: [${bucket.bucketArn}/*
],
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
conditions: {
StringEquals: {
'AWS:SourceArn': arn:aws:cloudfront::${stack.account}:distribution/${distribution.distributionId}
,
},
},
}));
import as cdk from 'aws-cdk-lib'; import as s3 from 'aws-cdk-lib/aws-s3'; import as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import as iam from 'aws-cdk-lib/aws-iam';
// Create the S3 bucket const bucket = new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, // Customize as needed });
// Create the Origin Access Control for CloudFront const originAccessControl = new cloudfront.S3OriginAccessControl(stack, 'MyOAC', { originAccessControlName: 'MyOAC', signingBehavior: cloudfront.OriginAccessControlSigningBehavior.ALWAYS, signingProtocol: cloudfront.OriginAccessControlSigningProtocol.SIGV4, s3CanonicalUserId: bucket.bucketOwnerCanonicalUserId, });
// Create CloudFront distribution with the S3 Origin and OAC const distribution = new cloudfront.Distribution(stack, 'MyDistribution', { defaultBehavior: { origin: new cloudfront.origins.S3Origin(bucket, { originAccessControl, }), }, });
// Add a bucket policy manually
bucket.addToResourcePolicy(new iam.PolicyStatement({
actions: ['s3:GetObject'],
resources: [${bucket.bucketArn}/*
],
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
conditions: {
StringEquals: {
'AWS:SourceArn': arn:aws:cloudfront::${stack.account}:distribution/${distribution.distributionId}
,
},
},
}));
import as cdk from 'aws-cdk-lib'; import as s3 from 'aws-cdk-lib/aws-s3'; import as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import as iam from 'aws-cdk-lib/aws-iam';
// Create the S3 bucket const bucket = new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, // Customize as needed });
// Create the Origin Access Control for CloudFront const originAccessControl = new cloudfront.S3OriginAccessControl(stack, 'MyOAC', { originAccessControlName: 'MyOAC', signingBehavior: cloudfront.OriginAccessControlSigningBehavior.ALWAYS, signingProtocol: cloudfront.OriginAccessControlSigningProtocol.SIGV4, s3CanonicalUserId: bucket.bucketOwnerCanonicalUserId, });
// Create CloudFront distribution with the S3 Origin and OAC const distribution = new cloudfront.Distribution(stack, 'MyDistribution', { defaultBehavior: { origin: new cloudfront.origins.S3Origin(bucket, { originAccessControl, }), }, });
// Add a bucket policy manually
bucket.addToResourcePolicy(new iam.PolicyStatement({
actions: ['s3:GetObject'],
resources: [${bucket.bucketArn}/*
],
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
conditions: {
StringEquals: {
'AWS:SourceArn': arn:aws:cloudfront::${stack.account}:distribution/${distribution.distributionId}
,
},
},
}));
Summary of the Initial Setup, Issue, and Solution
Initial Setup (With Origin Access Identity - OAI)
The Frontend Bucket Stack:
Created an S3 bucket and an Origin Access Identity (OAI).
The bucket policy was automatically updated to allow access to any CloudFront distribution with the OAI.
The Global CloudFront Stack:
Created a CloudFront distribution and used the S3 bucket as the origin.
No specific CloudFront distribution ID was required in the bucket policy because OAI allowed generic access.
Why OAI Did Not Cause a Cyclic Dependency
OAI does not require the bucket policy to reference a specific CloudFront Distribution ID.
The bucket policy allowed access to any CloudFront distribution with the OAI, removing the need for inter-stack dependencies.
Updated Setup (With Origin Access Control - OAC)
The Frontend Bucket Stack:
Created the S3 bucket and the Origin Access Control (OAC).
Exported both the bucket and OAC for the Global CloudFront Stack.
The Global CloudFront Stack:
Used the S3 bucket and OAC to create an S3 origin via S3BucketOrigin.withOriginAccessControl.
Created the CloudFront distribution using the S3 origin.
Issue: Cyclic Dependency
With OAC, the bucket policy must explicitly allow access for a specific CloudFront distribution.
The dependency cycle occurred because:
The Frontend Bucket Stack required the CloudFront Distribution ID to update the bucket policy.
The Global CloudFront Stack needed the S3 bucket and OAC from the Frontend Bucket Stack to create the distribution.
Proposed Solution
Decouple the bucket and OAC creation:
The Frontend Bucket Stack now creates only the S3 bucket and exports it.
The Global CloudFront Stack:
Creates the Origin Access Control (OAC).
Passes the exported bucket and the created OAC to the S3 origin.
Creates the CloudFront distribution.
Explicitly updates the bucket policy using the created CloudFront Distribution ID after the distribution is deployed.
Additional Questions and Explanations
The dependency occurred because the S3BucketOrigin.withOriginAccessControl method attempts to update the bucket policy automatically, requiring the CloudFront Distribution ID, which was not yet created.
The bucket policy update is deferred until the CloudFront distribution is created, explicitly handled in the Global CloudFront Stack.
The Frontend Bucket Stack only creates the bucket, eliminating direct dependencies on the CloudFront distribution.
No, as long as the bucket policy is explicitly updated after the CloudFront distribution creation, the automatic updates do not interfere.
The S3 origin was created in the Global CloudFront Stack using:
new S3BucketOrigin(bucket, { originAccessControl: createdOAC });
The explicit bucket policy update ensured access for the specific distribution.
OAI allowed generic access to any CloudFront distribution, avoiding the need for a distribution ID in the bucket policy and preventing cyclic dependencies.
OAI: Generic access for any CloudFront distribution, no dependency on the distribution ID.
OAC: Requires specific access for a single CloudFront distribution, necessitating its ID in the bucket policy.
Outcome of the Updated Setup
The updated setup avoids cyclic dependencies by:
Separating the creation of the bucket and the OAC.
Explicitly handling the bucket policy update after the distribution is created.
Ensuring no implicit bucket policy updates occur during the S3 origin creation.
This approach ensures modularity, security, and a seamless deployment process.
Summary of the Initial Setup, Issue, and Solution
Initial Setup (With Origin Access Identity - OAI)
The Frontend Bucket Stack:
Created an S3 bucket and an Origin Access Identity (OAI).
The bucket policy was automatically updated to allow access to any CloudFront distribution with the OAI.
The Global CloudFront Stack:
Created a CloudFront distribution and used the S3 bucket as the origin.
No specific CloudFront distribution ID was required in the bucket policy because OAI allowed generic access.
Why OAI Did Not Cause a Cyclic Dependency
OAI does not require the bucket policy to reference a specific CloudFront Distribution ID.
The bucket policy allowed access to any CloudFront distribution with the OAI, removing the need for inter-stack dependencies.
Updated Setup (With Origin Access Control - OAC)
The Frontend Bucket Stack:
Created the S3 bucket and the Origin Access Control (OAC).
Exported both the bucket and OAC for the Global CloudFront Stack.
The Global CloudFront Stack:
Used the S3 bucket and OAC to create an S3 origin via S3BucketOrigin.withOriginAccessControl.
Created the CloudFront distribution using the S3 origin.
Issue: Cyclic Dependency
With OAC, the bucket policy must explicitly allow access for a specific CloudFront distribution.
The dependency cycle occurred because:
The Frontend Bucket Stack required the CloudFront Distribution ID to update the bucket policy.
The Global CloudFront Stack needed the S3 bucket and OAC from the Frontend Bucket Stack to create the distribution.
Proposed Solution
Decouple the bucket and OAC creation:
The Frontend Bucket Stack now creates only the S3 bucket and exports it.
The Global CloudFront Stack:
Creates the Origin Access Control (OAC).
Passes the exported bucket and the created OAC to the S3 origin.
Creates the CloudFront distribution.
Explicitly updates the bucket policy using the created CloudFront Distribution ID after the distribution is deployed.
Additional Questions and Explanations
The dependency occurred because the S3BucketOrigin.withOriginAccessControl method attempts to update the bucket policy automatically, requiring the CloudFront Distribution ID, which was not yet created.
The bucket policy update is deferred until the CloudFront distribution is created, explicitly handled in the Global CloudFront Stack.
The Frontend Bucket Stack only creates the bucket, eliminating direct dependencies on the CloudFront distribution.
No, as long as the bucket policy is explicitly updated after the CloudFront distribution creation, the automatic updates do not interfere.
The S3 origin was created in the Global CloudFront Stack using:
new S3BucketOrigin(bucket, { originAccessControl: createdOAC });
The explicit bucket policy update ensured access for the specific distribution.
OAI allowed generic access to any CloudFront distribution, avoiding the need for a distribution ID in the bucket policy and preventing cyclic dependencies.
OAI: Generic access for any CloudFront distribution, no dependency on the distribution ID.
OAC: Requires specific access for a single CloudFront distribution, necessitating its ID in the bucket policy.
Outcome of the Updated Setup
The updated setup avoids cyclic dependencies by:
Separating the creation of the bucket and the OAC.
Explicitly handling the bucket policy update after the distribution is created.
Ensuring no implicit bucket policy updates occur during the S3 origin creation.
This approach ensures modularity, security, and a seamless deployment process.
S3BucketOrigin.withOriginAccessControl
.S3BucketOrigin.withOriginAccessControl
method attempts to update the bucket policy automatically, requiring the CloudFront Distribution ID, which was not yet created.
new S3BucketOrigin(bucket, {
originAccessControl: createdOAC
});
S3BucketOrigin.withOriginAccessControl
.S3BucketOrigin.withOriginAccessControl
method attempts to update the bucket policy automatically, requiring the CloudFront Distribution ID, which was not yet created.
new S3BucketOrigin(bucket, {
originAccessControl: createdOAC
});
# Handling Cyclic Dependencies in CloudFront and S3 with OAC
## **Initial Setup (With Origin Access Identity - OAI)**
### Frontend Bucket Stack
- Created an **S3 bucket** and an **Origin Access Identity (OAI)**.
- Automatically updated the bucket policy to allow access to **any CloudFront distribution** with the OAI.
### Global CloudFront Stack
- Created a **CloudFront distribution** and used the S3 bucket as the origin.
- Did not require the CloudFront distribution ID in the bucket policy because OAI allowed generic access.
### Why OAI Did Not Cause a Cyclic Dependency
- OAI does not require the bucket policy to reference a specific CloudFront distribution ID.
- The bucket policy allowed access to any CloudFront distribution with the OAI, avoiding inter-stack dependencies.
---
## **Updated Setup (With Origin Access Control - OAC)**
### Frontend Bucket Stack
- Created the **S3 bucket** and **Origin Access Control (OAC)**.
- Exported the bucket and OAC for use in the **Global CloudFront Stack**.
### Global CloudFront Stack
- Used the S3 bucket and OAC to create an S3 origin using `S3BucketOrigin.withOriginAccessControl`.
- Created the CloudFront distribution using the S3 origin.
---
## **Issue: Cyclic Dependency**
- With OAC, the bucket policy must explicitly allow access for a specific CloudFront distribution.
- A dependency cycle occurred because:
1. The **Frontend Bucket Stack** required the **CloudFront Distribution ID** to update the bucket policy.
2. The **Global CloudFront Stack** required the **S3 bucket and OAC** from the Frontend Bucket Stack to create the distribution.
---
## **Proposed Solution**
### Decouple the bucket and OAC creation:
1. The **Frontend Bucket Stack**:
- Creates only the S3 bucket and exports it.
2. The **Global CloudFront Stack**:
- Creates the **Origin Access Control (OAC)**.
- Passes the exported bucket and created OAC to the S3 origin.
- Creates the **CloudFront distribution**.
- Explicitly updates the bucket policy with the CloudFront distribution ID after the distribution is deployed.
---
## **Additional Questions and Explanations**
### 1. Why did the initial setup with OAC cause a cyclic dependency, even without explicitly updating the bucket policy?
- The dependency occurred because the `S3BucketOrigin.withOriginAccessControl` method attempts to update the bucket policy automatically, requiring the **CloudFront Distribution ID**, which was not yet created.
### 2. Why doesn’t the current approach cause cyclic dependencies?
- The bucket policy update is deferred until the CloudFront distribution is created and explicitly handled in the **Global CloudFront Stack**.
- The **Frontend Bucket Stack** only creates the bucket, eliminating direct dependencies on the CloudFront distribution.
### 3. Is it necessary to explicitly prevent automatic bucket policy updates in the current setup?
- No, as long as the bucket policy is explicitly updated after the CloudFront distribution creation, automatic updates do not interfere.
### 4. How was the S3 origin created in the updated setup?
- The S3 origin was created in the **Global CloudFront Stack** using:
```typescript
new S3BucketOrigin(bucket, {
originAccessControl: createdOAC
});
Why did OAI not cause issues in the initial setup?
OAI allowed generic access to any CloudFront distribution, avoiding the need for a distribution ID in the bucket policy and preventing cyclic dependencies.
OAI: Allows generic access for any CloudFront distribution, no dependency on the distribution ID.
OAC: Requires specific access for a single CloudFront distribution, necessitating its ID in the bucket policy.
Outcome of the Updated Setup
The updated setup avoids cyclic dependencies by:
Separating the creation of the bucket and the OAC.
Explicitly handling the bucket policy update after the distribution is created.
Ensuring no implicit bucket policy updates occur during the S3 origin creation.
This approach ensures modularity, security, and a seamless deployment process.
Here’s a summarized version of the issue and the solution:
Issue with the Initial Setup: In my initial setup, I was creating an S3 bucket and an Origin Access Control (OAC) in the frontend bucket stack. This OAC was used in the global CloudFront stack to create a CloudFront distribution. However, this setup caused a cyclic dependency. The reason was that the S3 origin creation required a CloudFront distribution ID for the bucket policy update, but the CloudFront distribution couldn’t be created until the S3 origin and OAC were available, causing a circular dependency.
Why OAI Didn't Cause This Issue: In the initial setup with OAI (Origin Access Identity), the bucket policy was updated to allow any CloudFront distribution to access the S3 bucket, so there was no need for a specific distribution ID. This allowed CloudFront to access the bucket without causing a cyclic dependency.
How I’m Fixing the Issue: To resolve the cyclic dependency, I’ve separated the creation of the bucket and OAC. Now, the frontend bucket stack only creates the S3 bucket, and the global CloudFront stack creates the OAC and CloudFront distribution. The bucket is passed to the CloudFront stack, and the bucket policy is explicitly updated only after the CloudFront distribution is created. This fixes the cyclic dependency issue by ensuring the CloudFront distribution ID is available before the policy update.
This version should take around 2 minutes to read out and provides the necessary context in a concise manner.
Here’s a summarized version of the issue and the solution:
Issue with the Initial Setup: In my initial setup, I was creating an S3 bucket and an Origin Access Control (OAC) in the frontend bucket stack. This OAC was used in the global CloudFront stack to create a CloudFront distribution. However, this setup caused a cyclic dependency. The reason was that the S3 origin creation required a CloudFront distribution ID for the bucket policy update, but the CloudFront distribution couldn’t be created until the S3 origin and OAC were available, causing a circular dependency.
Why OAI Didn't Cause This Issue: In the initial setup with OAI (Origin Access Identity), the bucket policy was updated to allow any CloudFront distribution to access the S3 bucket, so there was no need for a specific distribution ID. This allowed CloudFront to access the bucket without causing a cyclic dependency.
How I’m Fixing the Issue: To resolve the cyclic dependency, I’ve separated the creation of the bucket and OAC. Now, the frontend bucket stack only creates the S3 bucket, and the global CloudFront stack creates the OAC and CloudFront distribution. The bucket is passed to the CloudFront stack, and the bucket policy is explicitly updated only after the CloudFront distribution is created. This fixes the cyclic dependency issue by ensuring the CloudFront distribution ID is available before the policy update.
This version should take around 2 minutes to read out and provides the necessary context in a concise manner.
Here’s a more concise version for your status update:
I’m currently facing a cyclic dependency issue in my setup. The problem arises because I’m creating an S3 bucket and Origin Access Control (OAC) in the frontend bucket stack, and then passing them to the global CloudFront stack. The issue is that the S3 origin needs the CloudFront distribution ID to update the bucket policy, but the distribution can’t be created until the bucket and OAC are available, causing a cycle.
While deploying, I ran into issues in the POC environment. Luckily, Chris advised me not to test in pre-prod and instead work on the POC/dev environment first. If not, I could’ve broken pre-prod. I’m now focused on fixing the POC and deploying the modified code. I’ll give a detailed walkthrough during today’s demo.
This version should fit well for a quick 30-45 second status update.
Here’s a more concise version for your status update:
I’m currently facing a cyclic dependency issue in my setup. The problem arises because I’m creating an S3 bucket and Origin Access Control (OAC) in the frontend bucket stack, and then passing them to the global CloudFront stack. The issue is that the S3 origin needs the CloudFront distribution ID to update the bucket policy, but the distribution can’t be created until the bucket and OAC are available, causing a cycle.
While deploying, I ran into issues in the POC environment. Luckily, Chris advised me not to test in pre-prod and instead work on the POC/dev environment first. If not, I could’ve broken pre-prod. I’m now focused on fixing the POC and deploying the modified code. I’ll give a detailed walkthrough during today’s demo.
This version should fit well for a quick 30-45 second status update.
Update Summary for the Next Call
During our recent discussion with Sam, we had an in-depth conversation about the current testing setup, challenges, and the direction we need to take for improvement. Below is a summary of the key points discussed, decisions made, and the agreed action items:
Key Discussion Points:
Sam emphasised that Jest should not be used for UI/layout testing as it adds little value. Instead, it should focus on testing isolated, functional components and performing snapshot tests for reactivity.
Testing the UI should be handled by Appium for automating user scenarios and validating the application’s behaviour.
Appium is already in use for the Ionic app and is effective for end-to-end testing.
Sam is currently exploring Appium further on his MacBook to prepare it for broader implementation.
The current centralised Jest configuration in the dashboard is problematic. Instead, Jest should be moved to the package/environment level to make it accessible and customisable for all applications in the monorepository.
Decisions Taken:
Jest will remain the default test runner for unit and snapshot testing of components, focusing on isolated and functional units.
Appium will be adopted as the standard tool for end-to-end UI testing to ensure comprehensive scenario-based validation.
Jest configuration will be refactored out of the dashboard and set up at the package/environment level for greater flexibility.
Action Items:
Refactor the Jest configuration to make it available at the package/environment level for use across all applications.
Collaborate with Sam on his Appium exploration and prepare for its adoption in the testing pipeline.
Define clear boundaries for Jest (unit testing) and Appium (UI testing) to avoid redundant efforts and ensure a streamlined testing process.
This approach will ensure a robust and efficient testing framework tailored to the monorepository's needs, aligning with Sam’s recommendations.
Update Summary for the Next Call
During our recent discussion with Sam, we had an in-depth conversation about the current testing setup, challenges, and the direction we need to take for improvement. Below is a summary of the key points discussed, decisions made, and the agreed action items:
Key Discussion Points:
Sam emphasised that Jest should not be used for UI/layout testing as it adds little value. Instead, it should focus on testing isolated, functional components and performing snapshot tests for reactivity.
Testing the UI should be handled by Appium for automating user scenarios and validating the application’s behaviour.
Appium is already in use for the Ionic app and is effective for end-to-end testing.
Sam is currently exploring Appium further on his MacBook to prepare it for broader implementation.
The current centralised Jest configuration in the dashboard is problematic. Instead, Jest should be moved to the package/environment level to make it accessible and customisable for all applications in the monorepository.
Decisions Taken:
Jest will remain the default test runner for unit and snapshot testing of components, focusing on isolated and functional units.
Appium will be adopted as the standard tool for end-to-end UI testing to ensure comprehensive scenario-based validation.
Jest configuration will be refactored out of the dashboard and set up at the package/environment level for greater flexibility.
Action Items:
Refactor the Jest configuration to make it available at the package/environment level for use across all applications.
Collaborate with Sam on his Appium exploration and prepare for its adoption in the testing pipeline.
Define clear boundaries for Jest (unit testing) and Appium (UI testing) to avoid redundant efforts and ensure a streamlined testing process.
This approach will ensure a robust and efficient testing framework tailored to the monorepository's needs, aligning with Sam’s recommendations.
Subject: Request for Review and Approval of Updates
Hi Sam,
As discussed earlier, we have removed the test cases from the layout file and streamlined the configurations that were relevant for testing with Jest at the time but are no longer required. Additionally, we have implemented a new test case for the hook introduced to access the transcript query.
Please review the updates and provide your approval at your earliest convenience.
Best regards, [Your Name]
In a layman’s perspective, let’s break this down with an analogy:
Origin Access Identity (OAI):
Think of this as giving someone a key to your house (S3 bucket). When you use OAI:
You’re telling AWS: “This specific person (CloudFront distribution using OAI) has the key to access my house.”
You can simply say: "Give this person access to my house" using grantRead(). AWS knows who you’re referring to because the person (OAI) is clearly identified.
Origin Access Control (OAC):
Now, with OAC, instead of handing out a physical key, you’re using a secret handshake:
CloudFront doesn’t have a "key" (like OAI) anymore. Instead, it uses a special signed message (SigV4) to prove it is authorized to access your house (S3 bucket).
But here’s the thing: your house's security system (S3 bucket) doesn’t recognize this secret handshake by default. You need to go to the house’s settings (bucket policy) and say: “Hey, if someone does this secret handshake, let them in.”
So, bucket.addToResourcePolicy() is like configuring your house’s security system to recognize and trust the secret handshake (OAC).
Why You Can’t Use grantRead() for OAC
With OAI, you’re dealing with a specific "person" (the OAI) that has an identity. AWS can easily grant permissions to this person.
With OAC, there’s no specific person. Instead, it’s based on a behavior (the signed request from CloudFront). grantRead() doesn’t work here because it’s designed to work with specific people (IAM identities), not behaviors.
Simple Example:
OAI: “Hey AWS, give CloudFront (person with a key) access to the bucket.”
AWS replies: “Sure, I know who CloudFront is. I’ll let them in.”
OAC: “Hey AWS, allow CloudFront (anyone who can perform the secret handshake) to access the bucket.”
AWS replies: “Okay, but you need to explicitly update your house’s security system to trust this handshake. I can’t just assume it’s allowed.”
By using bucket.addToResourcePolicy() for OAC, you’re essentially teaching the system to trust CloudFront's "handshake" requests, allowing it to fetch objects from your S3 bucket.
Does this analogy help clarify things?