Skip to content
Closed
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
32 changes: 32 additions & 0 deletions frontend/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,41 @@ import type { NextConfig } from 'next'

const forceStandalone = process.env.FORCE_STANDALONE === 'yes'
const isLocal = process.env.NEXT_PUBLIC_ENVIRONMENT === 'local'
const contentSecurityPolicy =
"default-src 'self'; script-src 'self' 'unsafe-inline' https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://www.googletagmanager.com https://*.i.posthog.com https://*.tile.openstreetmap.org; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com; img-src 'self' data: https://authjs.dev https://avatars.githubusercontent.com https://*.tile.openstreetmap.org https://owasp.org https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://raw.githubusercontent.com; font-src 'self' https://cdn.jsdelivr.net; connect-src 'self' https://github-contributions-api.jogruber.de https://*.google-analytics.com https://*.i.posthog.com https://*.sentry.io https://*.tile.openstreetmap.org; object-src 'none'; frame-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';"
const contentSecurityPolicyLocal = contentSecurityPolicy.replace(
"script-src 'self' 'unsafe-inline'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'"
)
const securityHeaders = [
{
key: 'Content-Security-Policy',
value: isLocal ? contentSecurityPolicyLocal : contentSecurityPolicy,
},
{
key: 'Permissions-Policy',
value: 'camera=(), fullscreen=(self), geolocation=(self), microphone=()',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'X-Frame-Options',
value: 'DENY',
},
]

const nextConfig: NextConfig = {
devIndicators: false,
async headers() {
return [
{
headers: securityHeaders,
source: '/(.*)',
},
]
},
images: {
// This is a list of remote patterns that Next.js will use to determine
// if an image is allowed to be loaded from a remote source.
Expand Down
19 changes: 12 additions & 7 deletions infrastructure/modules/alb/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ locals {
"/status",
"/status/*",
]
backend_path_chunks = chunklist(local.backend_paths, 5)
backend_path_chunks = chunklist(local.backend_paths, 5)
content_security_policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://www.googletagmanager.com https://*.i.posthog.com https://*.tile.openstreetmap.org; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com; img-src 'self' data: https://authjs.dev https://avatars.githubusercontent.com https://*.tile.openstreetmap.org https://owasp.org https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://raw.githubusercontent.com; font-src 'self' https://cdn.jsdelivr.net; connect-src 'self' https://github-contributions-api.jogruber.de https://*.google-analytics.com https://*.i.posthog.com https://*.sentry.io https://*.tile.openstreetmap.org; object-src 'none'; frame-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';"
}

data "aws_elb_service_account" "main" {}
Expand Down Expand Up @@ -127,12 +128,16 @@ resource "aws_lb_listener" "http_redirect" {
}

resource "aws_lb_listener" "https" {
certificate_arn = aws_acm_certificate_validation.main.certificate_arn
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
tags = var.common_tags
certificate_arn = aws_acm_certificate_validation.main.certificate_arn
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
routing_http_response_content_security_policy_header_value = local.content_security_policy
routing_http_response_strict_transport_security_header_value = "max-age=31536000; includeSubDomains; preload"
routing_http_response_x_content_type_options_header_value = "nosniff"
routing_http_response_x_frame_options_header_value = "DENY"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
tags = var.common_tags

default_action {
target_group_arn = aws_lb_target_group.frontend.arn
Expand Down
32 changes: 32 additions & 0 deletions infrastructure/modules/alb/tests/alb.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,38 @@ run "test_https_listener_ssl_policy" {
}
}

run "test_https_listener_sets_hsts_header" {
command = plan
assert {
condition = aws_lb_listener.https.routing_http_response_strict_transport_security_header_value == "max-age=31536000; includeSubDomains; preload"
error_message = "HTTPS listener must set HSTS header value."
}
}

run "test_https_listener_sets_x_frame_options_header" {
command = plan
assert {
condition = aws_lb_listener.https.routing_http_response_x_frame_options_header_value == "DENY"
error_message = "HTTPS listener must set X-Frame-Options header value."
}
}

run "test_https_listener_sets_x_content_type_options_header" {
command = plan
assert {
condition = aws_lb_listener.https.routing_http_response_x_content_type_options_header_value == "nosniff"
error_message = "HTTPS listener must set X-Content-Type-Options header value."
}
}

run "test_https_listener_sets_csp_header" {
command = plan
assert {
condition = aws_lb_listener.https.routing_http_response_content_security_policy_header_value == "default-src 'self'; script-src 'self' 'unsafe-inline' https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://www.googletagmanager.com https://*.i.posthog.com https://*.tile.openstreetmap.org; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com; img-src 'self' data: https://authjs.dev https://avatars.githubusercontent.com https://*.tile.openstreetmap.org https://owasp.org https://owasp-nest.s3.amazonaws.com https://owasp-nest-production.s3.amazonaws.com https://raw.githubusercontent.com; font-src 'self' https://cdn.jsdelivr.net; connect-src 'self' https://github-contributions-api.jogruber.de https://*.google-analytics.com https://*.i.posthog.com https://*.sentry.io https://*.tile.openstreetmap.org; object-src 'none'; frame-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';"
error_message = "HTTPS listener must set Content-Security-Policy header value."
}
}

run "test_backend_listener_rules_not_created_when_null" {
command = plan
variables {
Expand Down