From 5f099e00d05ffacae1db6bb2ee39fd94dc3fd095 Mon Sep 17 00:00:00 2001 From: Karen Dolan Date: Mon, 1 Apr 2024 14:09:52 -0400 Subject: [PATCH] OPC-982 restrict iFrame embeds to *.harvard.edu, localhost testing, and config whitelist - Update to use Content-Security-Policy: frame-ancestors instead of X-Frame-Options - OPTION requests send origin header which is needed for the special cors headers - Remove old headers - support configurable whitelist --- libraries/default.rb | 5 +++++ recipes/configure-engage-nginx-proxy.rb | 5 ++++- templates/default/engage-nginx-proxy-conf.erb | 10 +++++----- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/default.rb b/libraries/default.rb index e1082222..0e77d886 100644 --- a/libraries/default.rb +++ b/libraries/default.rb @@ -242,6 +242,11 @@ def get_engage_admin_allowed_hosts node.fetch(:vpn_ips, []) + ["127.0.0.1/32"] end + # Default harvard.edu domain and localhosts for iframe embedding + def get_iframe_embed_allowed_hosts + return node.fetch(:iframe_embed_whitelist, []) + ["https://*.harvard.edu", "http://localhost:*", "https://localhost:*", "http://127.0.0.1:*"] + end + # Same subdomain CORS supprt # If special public_engage_hostname_cors config exists, use that for subdomain CORS support # Otherwise, use regular engage hostname for subdomain CORS support diff --git a/recipes/configure-engage-nginx-proxy.rb b/recipes/configure-engage-nginx-proxy.rb index 0dcf6e48..cb6cf69a 100644 --- a/recipes/configure-engage-nginx-proxy.rb +++ b/recipes/configure-engage-nginx-proxy.rb @@ -15,6 +15,8 @@ # Escape the 2 dots to use as literal dot chars in regex engage_domain_cors_regex = public_engage_hostname_cors[/((?=.)(\w+))((?:.)(\w+)){2}\z/].gsub(/\./, "\\.") +iframe_embed_whitelist = get_iframe_embed_allowed_hosts + ssl_info = node.fetch(:ssl, get_dummy_cert) if cert_defined(ssl_info) create_ssl_cert(ssl_info) @@ -47,7 +49,8 @@ opencast_backend_http_port: 8080, certificate_exists: certificate_exists, public_engage_hostname: public_engage_hostname, - engage_domain_cors_regex: engage_domain_cors_regex + engage_domain_cors_regex: engage_domain_cors_regex, + iframe_embed_whitelist: iframe_embed_whitelist.join(" ") }) end diff --git a/templates/default/engage-nginx-proxy-conf.erb b/templates/default/engage-nginx-proxy-conf.erb index 8db55301..aa528b2e 100644 --- a/templates/default/engage-nginx-proxy-conf.erb +++ b/templates/default/engage-nginx-proxy-conf.erb @@ -120,18 +120,19 @@ server { set $cors_origin "*"; set $cors_cred "true"; set $cors_method "GET, OPTIONS"; - # No defaults for these + + # No defaults for these: setting header to empty string causes the header to not be sent set $cors_header ""; - set $cors_xframe_option ""; set $cors_vary ""; set $cors_expose_headers ""; + # Special header permissios for domains in special enage specified domain (IC support) + # OPTION requests send option header containing domain if ($http_origin ~* (https?://.*\.<%= @engage_domain_cors_regex %>(:[0-9]+)?)) { set $cors_origin $http_origin; set $cors_cred true; set $cors_header $http_access_control_request_headers; set $cors_method $http_access_control_request_method; - set $cors_xframe_option 'ALLOW FROM $http_origin'; set $cors_vary 'Origin'; set $cors_expose_headers 'Content-Length,Content-Range'; } @@ -139,9 +140,9 @@ server { add_header Access-Control-Allow-Credentials $cors_cred always; add_header Access-Control-Allow-Headers $cors_header always; add_header Access-Control-Allow-Methods $cors_method always; - add_header X-Frame-Options $cors_xframe_option always; add_header Vary $cors_vary always; add_header Access-Control-Expose-Headers $cors_expose_headers always; + add_header Content-Security-Policy "frame-ancestors 'self' <%= @iframe_embed_whitelist %>;"; # -- End cors specific headers (nginx omits headers with empty value )-- # location /static { @@ -169,7 +170,6 @@ server { add_header Access-Control-Allow-Credentials $cors_cred; add_header Access-Control-Allow-Headers $cors_header; add_header Access-Control-Allow-Methods $cors_method; - add_header X-Frame-Options $cors_xframe_option; add_header Vary $cors_vary; add_header Access-Control-Expose-Headers $cors_expose_headers; # Tell client that this pre-flight info is valid for 20 days.