diff --git a/s3_artifact/action.py b/s3_artifact/action.py index d04ed43..eb1fa52 100644 --- a/s3_artifact/action.py +++ b/s3_artifact/action.py @@ -1,3 +1,4 @@ +import json import os import subprocess from dataclasses import dataclass @@ -70,12 +71,21 @@ def _prepare_cache_control_and_content_type_command(cache_config: S3ArtifactCust def _get_default_cache_control(): return f"--cache-control '{config.default_cache_control}'" if config.default_cache_control else "" + metadata = json.dumps( + { + "X-Frame-Options": "SAMEORIGIN", + "Content-Security-Policy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains", + "X-Content-Type-Options": "nosniff", + }, + ) return ( f"aws s3 sync {config.local_artifacts_path} {target} {_get_default_cache_control()} {S3_SYNC_OPTIONS}", *( _prepare_cache_control_and_content_type_command(custom_metadata) for custom_metadata in config.custom_metadata ), + f"aws s3 cp {target} {target} {S3_CP_OPTIONS} --exclude '*' --include '*.html' --metadata '{metadata}'", ) diff --git a/tests/test_action.py b/tests/test_action.py index a0cba47..31b1270 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -1,3 +1,4 @@ +import json import os from dataclasses import asdict from tempfile import NamedTemporaryFile @@ -29,11 +30,24 @@ def _get_website_config(cache: Sequence[S3ArtifactCustomMetadataConfig] = ()) -> ) -def _get_upload_commands(pattern: str, mime_type: str, max_age: str) -> tuple[str, str]: +def _get_metadata_command(): + return ( + f"aws s3 cp {ARTIFACTS_BUCKET} {ARTIFACTS_BUCKET} --recursive --no-progress --exclude '*' --include '*.html' " + f"--metadata '{json.dumps({ + "X-Frame-Options": "SAMEORIGIN", + "Content-Security-Policy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains", + "X-Content-Type-Options": "nosniff", + })}'" + ) + + +def _get_upload_commands(pattern: str, mime_type: str, max_age: str) -> tuple[str, str, str]: return ( f"aws s3 sync dist/ {ARTIFACTS_BUCKET} --cache-control 'max-age=60' --delete --no-progress", f"aws s3 cp {ARTIFACTS_BUCKET} {ARTIFACTS_BUCKET} --recursive --no-progress --exclude '*' " f"--include {pattern} --metadata-directive REPLACE --content-type '{mime_type}' --cache-control '{max_age}'", + _get_metadata_command(), ) @@ -42,7 +56,10 @@ def test_upload(self): # Test success without special metadata self.assertEqual( first=upload(config=_get_website_config(), target=ARTIFACTS_BUCKET), - second=(f"aws s3 sync dist/ {ARTIFACTS_BUCKET} --cache-control 'max-age=60' --delete --no-progress",), + second=( + f"aws s3 sync dist/ {ARTIFACTS_BUCKET} --cache-control 'max-age=60' --delete --no-progress", + _get_metadata_command(), + ), ) # Test success with special metadata