Skip to content

Instantly share code, notes, and snippets.

@crowne
Created November 15, 2024 18:05
Show Gist options
  • Save crowne/3a45fdddaad010486788a868df979dee to your computer and use it in GitHub Desktop.
Save crowne/3a45fdddaad010486788a868df979dee to your computer and use it in GitHub Desktop.
nginx cors headers using maps
log_format lf_app '$remote_addr - $remote_user [$time_local] $status $body_bytes_sent "$request" '
'"$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'<"$obfuscated_request_body" >';
map $request_body $obfuscated_request_body {
~*(.*)(password)(.*) $1$2********;
default $request_body;
}
include includes/security_mappings.inc;
server {
server_name dev.myapp.com;
listen 80;
location / {
return 301 https://dev.myapp.com$request_uri;
}
access_log /var/log/nginx/myapp.com.access.log;
error_log /var/log/nginx/myapp.com.error.log;
}
server {
server_name dev.myapp.com;
listen 443 ssl ;
ssl_certificate /ssl/myapp/tls.crt;
ssl_certificate_key /ssl/myapp/tls.key;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers off;
ssl_ciphers EECDH+CHACHA20:EECDH+AES;
ssl_ecdh_curve X25519:prime256v1:secp521r1:secp384r1;
root /usr/share/nginx/html;
index index.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
access_log /var/log/nginx/myapp.com.access.log lf_app;
access_log /var/log/nginx/access.log lf_app;
error_log /var/log/nginx/myapp.com.error.log debug;
client_max_body_size 32M;
location / {
include includes/security_headers.inc;
try_files /index.html =404;
}
location /assets/ {
include includes/security_headers.inc;
try_files $uri $uri/ =404;
}
location = /50x.html {
root /usr/share/nginx/html;
}
}
# Content-Security-Policy header values
set $SCRIPT "script-src 'self' 'unsafe-inline'";
set $STYLE "style-src 'self' 'unsafe-inline'";
set $STYLE "${STYLE} https://fonts.googleapis.com";
set $IMG "img-src 'self' data:";
set $FONT "font-src 'self' data:";
set $FONT "${FONT} https://fonts.googleapis.com";
set $FONT "${FONT} https://fonts.gstatic.com";
set $DEFAULT "default-src 'self'";
set $CONNECT "connect-src 'self'";
set $CONNECT "${CONNECT} ${api_url}";
set $CONNECT "${CONNECT} $cognito_url";
set $CONNECT "${CONNECT} https://cognito-idp.eu-west-1.amazonaws.com";
set $FRAME "frame-src 'self'";
set $CSP_HEADER_VALUE "${SCRIPT}; ${STYLE}; ${IMG}; ${FONT}; ${DEFAULT}; ${CONNECT}; ${FRAME}";
# cors configuration
# app header
add_header X-app-header-mode "$cors_header_type";
# Security headers
add_header Strict-Transport-Security "max-age=31536000";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
# csp header
add_header Content-Security-Policy "$CSP_HEADER_VALUE";
# cors headers
add_header 'Access-Control-Allow-Origin' "$cors_header_origin";
add_header 'Access-Control-Allow-Credentials' "$cors_header_credentials";
add_header 'Access-Control-Max-Age' $cors_opt_max_age;
add_header 'Access-Control-Allow-Methods' "$cors_opt_methods";
add_header 'Access-Control-Allow-Headers' "$cors_opt_headers";
add_header 'Content-Length' "$cors_opt_content_length";
add_header 'Content-Type' "$cors_opt_content_type";
if ($cors_header_type = 'trueoptions') {
return 204;
}
map $server_name $app_env {
default "prod";
"stg.myapp.com" "stg";
"dev.myapp.com" "dev";
}
map $app_env $api_url {
default "https://api.myapp.com";
"stg" "https://stg-api.myapp.com";
"dev" "https://dev-api.myapp.com";
}
map $app_env $cognito_url {
default "https://prod-myappcom.auth.eu-west-1.amazoncognito.com";
"stg" "https://dev-myappcom.auth.eu-west-1.amazoncognito.com";
"dev" "https://dev-myappcom.auth.eu-west-1.amazoncognito.com";
}
map $http_origin $cors_header {
default "false";
"~^(http(s)?:\/\/([a-z]|\d|-|\.)*(myapp\.com|login\.microsoftonline\.com|\.amazoncognito\.com)(:[0-9]+)?)$" "true";
}
map $cors_header $nocors_header {
"true" "false";
"false" "true";
}
map "$cors_header$request_method" $cors_header_type {
default "other";
"trueget" "trueget";
"truepost" "truepost";
"trueoptions" "trueoptions";
}
map $cors_header_type $cors_header_origin {
default "$http_origin";
"other" "";
}
map $cors_header_type $cors_header_credentials {
default "true";
"other" "";
}
map $cors_header_type $cors_opt_max_age {
default "";
"trueoptions" 1728000; # cache preflight value for 20 days
}
map $cors_header_type $cors_opt_methods {
default "";
"trueoptions" 'GET, POST, OPTIONS';
}
map $cors_header_type $cors_opt_headers {
default "";
"trueoptions" 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
}
map $cors_header_type $cors_opt_content_length {
default "";
"trueoptions" 0;
}
map $cors_header_type $cors_opt_content_type {
default "";
"trueoptions" 'text/plain charset=UTF-8';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment