Skip to content

Commit

Permalink
feat(browser): use eoapi-cdk to build a radiant earth stac browser fo…
Browse files Browse the repository at this point in the history
…r instances with a cloudfront
  • Loading branch information
anayeaye committed Nov 29, 2023
1 parent 7e348cf commit 184382c
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 11 deletions.
11 changes: 11 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from raster_api.infrastructure.construct import RasterApiLambdaConstruct
from routes.infrastructure.construct import CloudfrontDistributionConstruct
from stac_api.infrastructure.construct import StacApiLambdaConstruct
from eoapi_cdk import StacBrowser

app = App()
if veda_app_settings.bootstrap_qualifier:
Expand Down Expand Up @@ -89,6 +90,16 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
region=veda_app_settings.cdk_default_region,
)

# eoapi-cdk stac-browser only supported for stacks with cloudfront distribution
if veda_app_settings.cloudfront:
stac_browser = StacBrowser(
veda_stack,
"stac-browser",
github_repo_tag=veda_app_settings.stac_browser_tag,
stac_catalog_url=veda_routes.stac_catalog_url,
bucket_arn=veda_routes.bucket.bucket_arn,
)

# TODO this conditional supports deploying a second set of APIs to a separate custom domain and should be removed if no longer necessary
if veda_app_settings.alt_domain():
alt_domain = DomainConstruct(
Expand Down
13 changes: 13 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ class vedaAppSettings(BaseSettings):
description="Custom bootstrap qualifier override if not using a default installation of AWS CDK Toolkit to synthesize app.",
)

stac_browser_tag: Optional[str] = Field(
"v3.1.0",
description=(
"Tag of the radiant earth stac-browser repo to use to build the app"
"https://github.com/radiantearth/stac-browser/releases."
),
)

cloudfront: Optional[bool] = Field(
False,
description="Boolean if Cloudfront Distribution should be deployed",
)

def cdk_env(self) -> dict:
"""Load a cdk environment dict for stack"""

Expand Down
14 changes: 12 additions & 2 deletions routes/infrastructure/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ class vedaRouteSettings(BaseSettings):
description="Boolean if Cloudfront Distribution should be deployed",
)

# STAC S#3 browser bucket name
# STAC S3 browser bucket name
stac_browser_bucket: Optional[str] = Field(
"", description="STAC browser S3 bucket name"
None, description="STAC browser S3 bucket name"
)

# API Gateway URLs
Expand All @@ -39,6 +39,16 @@ class vedaRouteSettings(BaseSettings):
description="Certificate’s ARN",
)

custom_host: str = Field(
None,
description="Complete url of custom host including subdomain. Used to infer url of stac-api before app synthesis.",
)

stac_root_path: str = Field(
"",
description="Optional path prefix to add to all api endpoints. Used to infer url of stac-api before app synthesis.",
)

class Config:
"""model config"""

Expand Down
50 changes: 44 additions & 6 deletions routes/infrastructure/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from typing import Optional
from urllib.parse import urlparse

from aws_cdk import CfnOutput, Stack
from aws_cdk import CfnOutput, RemovalPolicy, Stack
from aws_cdk import aws_certificatemanager as certificatemanager
from aws_cdk import aws_cloudfront as cf
from aws_cdk import aws_cloudfront_origins as origins
from aws_cdk import aws_route53, aws_route53_targets
from aws_cdk import aws_s3 as s3
from aws_cdk import aws_iam as iam
from constructs import Construct

from .config import veda_route_settings
Expand All @@ -32,10 +33,29 @@ def __init__(
stack_name = Stack.of(self).stack_name

if veda_route_settings.cloudfront:
s3Bucket = s3.Bucket.from_bucket_name(
self,
"stac-browser-bucket",
bucket_name=veda_route_settings.stac_browser_bucket,

if veda_route_settings.stac_browser_bucket:
self.bucket = s3.Bucket.from_bucket_name(
self,
"stac-browser-bucket",
bucket_name=veda_route_settings.stac_browser_bucket,
)
else:
self.bucket = s3.Bucket(
self,
"stac-browser-bucket",
bucket_name=f"{stack_name}-stac-browser",
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True,
website_index_document="index.html",
public_read_access=True,
block_public_access=s3.BlockPublicAccess(
block_public_acls=False,
block_public_policy=False,
ignore_public_acls=False,
restrict_public_buckets=False,
),
object_ownership=s3.ObjectOwnership.OBJECT_WRITER,
)

# Certificate must be in zone us-east-1
Expand All @@ -53,7 +73,7 @@ def __init__(
comment=stack_name,
default_behavior=cf.BehaviorOptions(
origin=origins.HttpOrigin(
s3Bucket.bucket_website_domain_name,
self.bucket.bucket_website_domain_name,
protocol_policy=cf.OriginProtocolPolicy.HTTP_ONLY,
origin_id="stac-browser",
),
Expand Down Expand Up @@ -110,5 +130,23 @@ def __init__(
),
record_name=stage,
)

# Infer stac url before synthesis for stac-browser deployment and add cloudfront service to bucket resource policy
self.stac_catalog_url = f"https://{veda_route_settings.custom_host}/{veda_route_settings.stac_root_path.lstrip('/')}"
self.distribution_arn = f"arn:aws:cloudfront::{self.distribution.env.account}:distribution/{self.distribution.distribution_id}"
self.bucket.add_to_resource_policy(
permission=iam.PolicyStatement(
actions=["s3:GetObject"],
conditions={
"StringEquals": {
"aws:SourceArn": self.distribution_arn
}
},
effect=iam.Effect("ALLOW"),
principals=[iam.ServicePrincipal("cloudfront.amazonaws.com")],
resources=[self.bucket.arn_for_objects("*")],
sid="AllowCloudFrontServicePrincipal",
)
)

CfnOutput(self, "Endpoint", value=self.distribution.domain_name)
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
extra_reqs = {
"dev": ["pre-commit", "python-dotenv"],
"deploy": [
"aws-cdk-lib<3.0.0,>=2.15.0",
"aws-cdk-lib<3.0.0,>=2.47.0.a0",
"constructs>=10.0.0,<11.0.0",
"aws-cdk.aws_apigatewayv2_alpha~=2.15.0a0",
"aws_cdk.aws_apigatewayv2_integrations_alpha~=2.15.0a0",
"aws-cdk.aws_apigatewayv2_alpha~=2.47.0.a0",
"aws_cdk.aws_apigatewayv2_integrations_alpha~=2.47.0.a0",
"pydantic~=1.0",
"eoapi-cdk==5.4.0",
],
"test": [
"pytest",
Expand Down

0 comments on commit 184382c

Please sign in to comment.