Skip to content
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

[BUG] Missing 403 error response for Static Website #69

Closed
bhrutledge opened this issue Jun 28, 2022 · 11 comments · Fixed by #70, #107 or #156
Closed

[BUG] Missing 403 error response for Static Website #69

bhrutledge opened this issue Jun 28, 2022 · 11 comments · Fixed by #70, #107 or #156
Labels
bug Something isn't working

Comments

@bhrutledge
Copy link
Contributor

bhrutledge commented Jun 28, 2022

Describe the bug

The Python static_website construct doesn't route 403 AccessDenied errors to the root object. This is with a Nuxt SPA built via npm run generate prior to running cdk deploy.

Expected Behavior

Getting the Nuxt 404 page when accessing a route that doesn't exist.

Screen Shot 2022-06-28 at 11 46 23 AM

Current Behavior

Getting an AWS error:

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>SD5ACEACKRM2GR8Q</RequestId>
<HostId>X0fWDXEGxlX/fS+eFoBiM/8yI4ZpZi7g5HWrwluVsb8h2Z2NtBbMLqHVdiGiPnsIUkajgARoS9Y=</HostId>
</Error>

Reproduction Steps

Here's the CDK stack that I created:

from pathlib import Path
from typing import Any

from aws_cdk import CfnOutput, Stack
from aws_prototyping_sdk import static_website
from constructs import Construct


class FrontendStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs: Any) -> None:
        super().__init__(scope, construct_id, **kwargs)

        dist_path = Path(__file__).parent / ".." / ".." / "frontend" / "dist"

        website = static_website.StaticWebsite(
            self,
            "Frontend",
            website_content_path=str(dist_path.resolve()),
        )

        CfnOutput(
            self,
            "URL",
            value=f"https://{website.cloud_front_distribution.domain_name}",
        )

Possible Solution

Additional Information/Context

I added a 403 response manually via the CloudFront console, and got the expected behavior (i.e. the Nuxt 404 page).

Screen Shot 2022-06-28 at 11 41 42 AM

I was able to accomplish the same thing by overriding error_responses:

        website = static_website.StaticWebsite(
            self,
            "Frontend",
            website_content_path=str(dist_path.resolve()),
            distribution_props=cloudfront.DistributionProps(
                # HACK: Per the docs, default_behavior.origin is required, but ignored
                default_behavior=cloudfront.BehaviorOptions(
                    origin=static_website.StaticWebsiteOrigin()
                ),
                error_responses=[
                    # HACK: Handle AWS `AccessDenied` errors for missing Nuxt routes
                    cloudfront.ErrorResponse(
                        http_status=403,
                        response_http_status=200,
                        response_page_path="/index.html",
                    ),
                    # Copied from StaticWebsite to add an additional respose
                    cloudfront.ErrorResponse(
                        http_status=404,
                        response_http_status=200,
                        response_page_path="/index.html",
                    ),
                ],
            ),
        )

PDK version used

aws-prototyping-sdk.static-website==0.2.10

What languages are you seeing this issue on?

Python

Environment details (OS name and version, etc.)

macOS 12.4

@bhrutledge bhrutledge added the bug Something isn't working label Jun 28, 2022
bhrutledge added a commit to bhrutledge/aws-prototyping-sdk that referenced this issue Jun 28, 2022
agdimech pushed a commit that referenced this issue Jun 29, 2022
@agdimech
Copy link
Contributor

Great first issue! This has been merged in :)

@agdimech
Copy link
Contributor

@agdimech agdimech reopened this Jul 21, 2022
@agdimech
Copy link
Contributor

I am going to have to revert this change as it can lead to the accidental leakage of information from the index.html page which otherwise would be blocked by WAF. Please re-implement your original workaround if using PDK v > 0.5

agdimech pushed a commit that referenced this issue Jul 21, 2022
BREAKING CHANGE: Removing default error page for 403 as it can lead to the accidental leakage of information from the index.html page which otherwise would be blocked by WAF.
agdimech added a commit that referenced this issue Jul 21, 2022
BREAKING CHANGE: Removing default error page for 403 as it can lead to the accidental leakage of information from the index.html page which otherwise would be blocked by WAF.
@bhrutledge
Copy link
Contributor Author

I am going to have to revert this change as it can lead to the accidental leakage of information from the index.html page which otherwise would be blocked by WAF. Please re-implement your original workaround if using PDK v > 0.5

@agdimech Thanks for the heads up. Can you elaborate on the accidental leakage of information? Is there a better way to configure CloudFront or S3 to response with a 404 instead of a 403 for an object that doesn't exist?

@agdimech
Copy link
Contributor

agdimech commented Jul 21, 2022

It actually is more of a problem when enabling WAF. For example if I restrict the website to only be accessible via certain CIDRs then WAF will BLOCK all resources from the server. With this said, WAF still interrogates Cloudfront to see if any error responses are defined for a 403 in which case the default root page (index.html) is returned which could potentially contain sensitive information.

By reverting this change, the user takes on the onus of being explicit on how they want to handle these types of error scenarios by either relying on the default error page WAF displays or by configuring a custom error page.

I did a quick google and found this in relation to the 403/404 being returned from
Cloudfront: https://stackoverflow.com/questions/19037664/how-do-i-have-an-s3-bucket-return-404-instead-of-403-for-a-key-that-does-not-e

Are you able to please test to see if adding the ListBucket permission to the OAI changes the behaviour to return a 404 instead of a 403?

@agdimech agdimech reopened this Jul 21, 2022
@bhrutledge
Copy link
Contributor Author

bhrutledge commented Jul 25, 2022

Are you able to please test to see if adding the ListBucket permission to the OAI changes the behaviour to return a 404 instead of a 403?

@agdimech I'd be happy to, but I don't know how to do that in the CDK, esp. with this construct. For context, I had to look up what WAF, CIDR, and OAI refer to. 😅 Can you point me in the right direction?

Here's what I think is the relevant bit from my stack:

dist_path = Path(__file__).parent / ".." / ".." / "frontend" / "dist"

self.website = static_website.StaticWebsite(
    self,
    "StaticWebsite",
    website_content_path=str(dist_path.resolve()),
    distribution_props=cloudfront.DistributionProps(
        # Per the docs, default_behavior.origin is required, but ignored
        default_behavior=cloudfront.BehaviorOptions(
            origin=static_website.StaticWebsiteOrigin()
        ),
        domain_names=[self.domain_name],
        certificate=self.certificate,
    ),
)

self.certificate is a DnsValidatedCertificate in us-east-1.

@agdimech
Copy link
Contributor

agdimech commented Aug 3, 2022

Sorry for the delay.

The permissions will need to be applied to the BucketPolicy of the S3 Bucket hosting your website. So to verify, please manually let me know if adding the s3:ListBucket to the Bucket Policy from the aws console. If it works for you then I can make a code change within this package to enable it by default.

Here is what your updated policy should resemble:

 {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/<Your OAI Here>"
            },
            "Action": ["s3:GetObject", "s3:ListBucket"],
            "Resource": ["arn:aws:s3:::<your-bucket>", "arn:aws:s3:::<your-bucket>/*"]
        }

@agdimech
Copy link
Contributor

agdimech commented Sep 7, 2022

@bhrutledge - any progress on this?

@agdimech
Copy link
Contributor

agdimech commented Sep 8, 2022

I have tested this myself and confirm the s3 permissions change resolves this issue so now routes which do not exist in the bucket are returned as a 404 instead of a 403. Pushing a PR shortly to resolve this issue.

@agdimech
Copy link
Contributor

agdimech commented Sep 8, 2022

This has been resolved. There is no longer to need a custom error responses for 403.

@bhrutledge
Copy link
Contributor Author

Thank you! I haven't been working on the project where I use this, but I will be soon, and I'm looking forward to trying this out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants