Skip to content

Commit 3a20ef2

Browse files
authored
feat!: configure cloudfront with origin access control (proposal) (#376)
### Issue No relevant github issue but in MCP, setting a default root object is required which this work helps to address. ### What? - enable logging (this was added in [another merged PR](#375)) - configure cloudfront to use origin access control and delete the origin access identity that gets created - set default root object to `index.html` - use flag to enable/disable feature`VEDA_CLOUDFRONT_OAC` ### Why? - currently, our MCP deployments need to be manually updated in order for the cloudfront distribution to work properly with S3 buckets that block public access ### Testing? - deployed these changes to UAH dev and MCP test ### Other - I opted to not add policy configuration in this PR since there is no way to tell via CDK if a policy on a bucket already exists. In order for this to work, the S3 browser bucket must allow cloudfront to `GetObject` ``` { "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::BUCKET/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::ACCOUNT:distribution/DISTRIBUTION_ID" } } } ] ``` ### Misc In order to properly configure this for our UAH stacks, we will need to update the buckets to block public access, not use static website hosting, and to include the bucket policy like above. These changes are required because our current UAH buckets do use static website hosting and therefore don't have the above policy and allow read access.
2 parents 8863d92 + f4b89c7 commit 3a20ef2

File tree

3 files changed

+80
-17
lines changed

3 files changed

+80
-17
lines changed

.example.env

+1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ STAC_BROWSER_BUCKET=
3131
STAC_URL=
3232
CERT_ARN=
3333
VEDA_CLOUDFRONT=
34+
VEDA_CLOUDFRONT_OAC=[OPTIONAL, CONFIGURES ORIGIN ACCESS CONTROL, DEFAULTS TO TRUE]
3435
VEDA_CUSTOM_HOST=

routes/infrastructure/config.py

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ class vedaRouteSettings(BaseSettings):
1414
description="Boolean if Cloudfront Distribution should be deployed",
1515
)
1616

17+
cloudfront_oac: Optional[bool] = Field(
18+
True,
19+
description="Boolean that configures Cloufront STAC Browser Origin with Origin Access Control",
20+
)
21+
1722
# STAC S3 browser bucket name
1823
stac_browser_bucket: Optional[str] = Field(
1924
None, description="STAC browser S3 bucket name"

routes/infrastructure/construct.py

+74-17
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,81 @@ def __init__(
4242
else None
4343
)
4444

45-
self.distribution = cf.Distribution(
46-
self,
47-
stack_name,
48-
comment=stack_name,
49-
default_behavior=cf.BehaviorOptions(
50-
origin=origins.HttpOrigin(
51-
origin_bucket.bucket_website_domain_name,
52-
protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY,
53-
origin_id="stac-browser",
45+
if veda_route_settings.cloudfront_oac:
46+
# create the origin access control resource
47+
cfn_origin_access_control = cf.CfnOriginAccessControl(
48+
self,
49+
"VedaCfnOriginAccessControl",
50+
origin_access_control_config=cf.CfnOriginAccessControl.OriginAccessControlConfigProperty(
51+
name=f"veda-{stage}-oac",
52+
origin_access_control_origin_type="s3",
53+
signing_behavior="always",
54+
signing_protocol="sigv4",
55+
description="Origin Access Control for STAC Browser",
5456
),
55-
cache_policy=cf.CachePolicy.CACHING_DISABLED,
56-
),
57-
certificate=domain_cert,
58-
enable_logging=True,
59-
domain_names=[f"{stage}.{veda_route_settings.domain_hosted_zone_name}"]
60-
if veda_route_settings.domain_hosted_zone_name
61-
else None,
62-
)
57+
)
58+
59+
self.distribution = cf.Distribution(
60+
self,
61+
stack_name,
62+
comment=stack_name,
63+
default_behavior=cf.BehaviorOptions(
64+
origin=origins.S3Origin(
65+
origin_bucket, origin_id="stac-browser"
66+
),
67+
cache_policy=cf.CachePolicy.CACHING_DISABLED,
68+
origin_request_policy=cf.OriginRequestPolicy.CORS_S3_ORIGIN,
69+
response_headers_policy=cf.ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS,
70+
viewer_protocol_policy=cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
71+
),
72+
certificate=domain_cert,
73+
default_root_object="index.html",
74+
enable_logging=True,
75+
domain_names=[
76+
f"{stage}.{veda_route_settings.domain_hosted_zone_name}"
77+
]
78+
if veda_route_settings.domain_hosted_zone_name
79+
else None,
80+
)
81+
# associate the created OAC with the distribution
82+
distribution_props = self.distribution.node.default_child
83+
if distribution_props is not None:
84+
distribution_props.add_override(
85+
"Properties.DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity",
86+
"",
87+
)
88+
distribution_props.add_property_override(
89+
"DistributionConfig.Origins.0.OriginAccessControlId",
90+
cfn_origin_access_control.ref,
91+
)
92+
93+
# remove the OAI reference from the distribution
94+
all_distribution_props = self.distribution.node.find_all()
95+
for child in all_distribution_props:
96+
if child.node.id == "S3Origin":
97+
child.node.try_remove_child("Resource")
98+
else:
99+
self.distribution = cf.Distribution(
100+
self,
101+
stack_name,
102+
comment=stack_name,
103+
default_behavior=cf.BehaviorOptions(
104+
origin=origins.HttpOrigin(
105+
origin_bucket.bucket_website_domain_name,
106+
protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY,
107+
origin_id="stac-browser",
108+
),
109+
cache_policy=cf.CachePolicy.CACHING_DISABLED,
110+
),
111+
certificate=domain_cert,
112+
default_root_object="index.html",
113+
enable_logging=True,
114+
domain_names=[
115+
f"{stage}.{veda_route_settings.domain_hosted_zone_name}"
116+
]
117+
if veda_route_settings.domain_hosted_zone_name
118+
else None,
119+
)
63120

64121
self.distribution.add_behavior(
65122
path_pattern="/api/stac*",

0 commit comments

Comments
 (0)