Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,4 @@ node_modules/

.ruff_cache/
.env-cdk
config.yaml
34 changes: 34 additions & 0 deletions browser_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = {
catalogUrl: "https://stac.eoapi.dev",
catalogTitle: "eoAPI STAC Browser",
allowExternalAccess: true, // Must be true if catalogUrl is not given
allowedDomains: [],
detectLocaleFromBrowser: true,
storeLocale: true,
locale: "en",
fallbackLocale: "en",
supportedLocales: ["de", "es", "en", "fr", "it", "ro"],
apiCatalogPriority: null,
useTileLayerAsFallback: true,
displayGeoTiffByDefault: false,
buildTileUrlTemplate: ({ href, asset }) =>
"https://raster.eoapi.dev/external/tiles/WebMercatorQuad/{z}/{x}/{y}@2x?url=" +
encodeURIComponent(asset.href.startsWith("/vsi") ? asset.href : href),
stacProxyUrl: null,
pathPrefix: "/",
historyMode: "history",
cardViewMode: "cards",
cardViewSort: "asc",
showThumbnailsAsAssets: false,
stacLint: true,
geoTiffResolution: 128,
redirectLegacyUrls: false,
itemsPerPage: 12,
defaultThumbnailSize: null,
maxPreviewsOnMap: 50,
crossOriginMedia: null,
requestHeaders: {},
requestQueryParameters: {},
preprocessSTAC: null,
authConfig: null,
};
81 changes: 73 additions & 8 deletions infrastructure/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
RemovalPolicy,
Stack,
aws_certificatemanager,
aws_cloudfront,
aws_cloudfront_origins,
aws_ec2,
aws_iam,
aws_lambda,
aws_rds,
aws_route53,
aws_route53_targets,
aws_s3,
)
from aws_cdk.aws_apigateway import DomainNameOptions
Expand Down Expand Up @@ -352,29 +356,90 @@ def __init__(
)

if app_config.stac_browser_version:
if not (
app_config.hosted_zone_id
and app_config.hosted_zone_name
and app_config.stac_browser_custom_domain
and app_config.stac_browser_certificate_arn
):
raise ValueError(
"to deploy STAC browser you must provide config parameters for hosted_zone_id and stac_browser_custom_domain and stac_browser_certificate_arn"
)

stac_browser_bucket = aws_s3.Bucket(
self,
"stac-browser-bucket",
bucket_name=app_config.build_service_name("stac-browser"),
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True,
website_index_document="index.html",
public_read_access=True,
block_public_access=aws_s3.BlockPublicAccess(
block_public_acls=False,
block_public_policy=False,
ignore_public_acls=False,
restrict_public_buckets=False,
block_public_access=aws_s3.BlockPublicAccess.BLOCK_ALL,
enforce_ssl=True,
)

distribution = aws_cloudfront.Distribution(
self,
"stac-browser-distribution",
default_behavior=aws_cloudfront.BehaviorOptions(
origin=aws_cloudfront_origins.S3Origin(stac_browser_bucket),
viewer_protocol_policy=aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
allowed_methods=aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD,
cached_methods=aws_cloudfront.CachedMethods.CACHE_GET_HEAD,
),
object_ownership=aws_s3.ObjectOwnership.OBJECT_WRITER,
default_root_object="index.html",
error_responses=[
aws_cloudfront.ErrorResponse(
http_status=404,
response_http_status=200,
response_page_path="/index.html",
)
],
certificate=aws_certificatemanager.Certificate.from_certificate_arn(
self,
"stac-browser-certificate",
app_config.stac_browser_certificate_arn,
),
domain_names=[app_config.stac_browser_custom_domain],
)

account_id = Stack.of(self).account
distribution_arn = f"arn:aws:cloudfront::${account_id}:distribution/${distribution.distribution_id}"

stac_browser_bucket.add_to_resource_policy(
aws_iam.PolicyStatement(
actions=["s3:GetObject"],
resources=[stac_browser_bucket.arn_for_objects("*")],
principals=[aws_iam.ServicePrincipal("cloudfront.amazonaws.com")],
conditions={"StringEquals": {"AWS:SourceArn": distribution_arn}},
)
)

hosted_zone = aws_route53.HostedZone.from_hosted_zone_attributes(
self,
"stac-browser-hosted-zone",
hosted_zone_id=app_config.hosted_zone_id,
zone_name=app_config.hosted_zone_name,
)

aws_route53.ARecord(
self,
"stac-browser-alias",
zone=hosted_zone,
target=aws_route53.RecordTarget.from_alias(
aws_route53_targets.CloudFrontTarget(distribution)
),
record_name=app_config.stac_browser_custom_domain,
)

StacBrowser(
self,
"stac-browser",
github_repo_tag=app_config.stac_browser_version,
stac_catalog_url=f"https://{app_config.stac_api_custom_domain}",
website_index_document="index.html",
bucket_arn=stac_browser_bucket.bucket_arn,
config_file_path=os.path.join(
os.path.abspath(context_dir), "browser_config.js"
),
)

def _create_data_access_role(self) -> aws_iam.Role:
Expand Down
32 changes: 24 additions & 8 deletions infrastructure/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ class AppConfig(BaseSettings):
as it will be used as a backend.""",
default=None,
)
stac_browser_custom_domain: Optional[str] = Field(
description="Custom domain name for the STAC Browser site",
default=None,
)
stac_browser_certificate_arn: Optional[str] = Field(
description="Arn for the STAC Browser custom domain name (must be in us-east-1)",
default=None,
)
hosted_zone_id: Optional[str] = Field(
description="Hosted Zone ID for custom domains",
default=None,
)
hosted_zone_name: Optional[str] = Field(
description="Hosted Zone Name for custom domains",
default=None,
)

model_config = SettingsConfigDict(
env_file=".env-cdk", yaml_file="config.yaml", extra="allow"
Expand All @@ -137,14 +153,14 @@ def validate_model(self) -> Self:
and therefore `nat_gateway_count` has to be > 0."""
)

if (
self.stac_browser_version is not None
and self.stac_api_custom_domain is None
):
raise ValueError(
"""If a STAC browser version is provided,
a custom domain must be provided for the STAC API"""
)
# if (
# self.stac_browser_version is not None
# and self.stac_api_custom_domain is None
# ):
# raise ValueError(
# """If a STAC browser version is provided,
# a custom domain must be provided for the STAC API"""
# )

if self.acm_certificate_arn is None and any(
[
Expand Down