Skip to content
Draft
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
56 changes: 56 additions & 0 deletions dispatcher/src/conf.d/available_vhosts/wknd.vhost
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,62 @@ Include conf.d/variables/custom.vars
# Add header breadcrumbs for help in troubleshooting
<IfModule mod_headers.c>
Header add X-Vhost "publish"
SetEnvIfExpr "req_novary('Origin') == ''" CORSType=none CORSProcessing=false
SetEnvIfExpr "req_novary('Origin') != ''" CORSType=cors CORSProcessing=true CORSTrusted=false

SetEnvIfExpr "req_novary('Access-Control-Request-Method') == '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=invalidpreflight CORSProcessing=false
SetEnvIfExpr "req_novary('Access-Control-Request-Method') != '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=preflight CORSProcessing=true CORSTrusted=false
SetEnvIfExpr "req_novary('Origin') -strcmatch 'https://%{HTTP_HOST}*'" CORSType=samedomain CORSProcessing=false


# For requests that require CORS processing, check if the Origin can be trusted. We could use a RewriteMap to lookup, however the variety of URLs is infinite
# So its better to use Regexes. If a RewriteMap is required, split out the FQDN from the Origin prior to checking the RewriteMap.

# Need to extract the http host from envar after processing
# setenvif is late processing, but this needs to be checked
# this seems to be the only way (other than RewriteRule E=) of getting HTTP_HOST into an envar late in the
# request processing cycle.
SetEnvIfExpr "%{HTTP_HOST} =~ /(.*)/ " ParsedHost=$1

# Before this, if CORSProcessing is true, CORSTrusted if false.
# Next check the Origin header to identify request that can be trusted to do Cors, by matching the Origin header.

SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(https://(.*\.)?adobe\.com(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(https://(.*\.)?csb\.app(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(https://cdpn\.io(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(https://(.*\.)?github\.dev(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(https://(.*\.)?vercel\.app(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(http://localhost(:\d+)?$)#" CORSTrusted=true
SetEnvIfExpr "env('CORSProcessing') == 'true' && env('CORSTrusted') != 'true' && req_novary('Origin') =~ m#(http://127\.0\.0\.1(:\d+)?$)#" CORSTrusted=true

# Debugging, comment out for production
# Header always set "X-CORSType" "%{CORSType}e"
# Header always set "X-CORSProcessing" "%{CORSProcessing}e"
# Header always set "X-CORSTrusted" "%{CORSTrusted}e"
# Header always set "X-ParsedHost" "%{ParsedHost}e"

# Extract the Origin header (should probably ensure split request is not possible, by passing the result through a URL encode step)
SetEnvIfNoCase ^Origin$ ^https://(.*)$ CORSTrustedOrigin=https://$1

# Flush If already set
Header unset Access-Control-Allow-Origin
Header unset Access-Control-Allow-Credentials

# Trusted
Header always set Access-Control-Allow-Credentials "true" "expr=reqenv('CORSTrusted') == 'true'"
Header always set Access-Control-Allow-Origin "%{CORSTrustedOrigin}e" "expr=reqenv('CORSTrusted') == 'true'"
Header always set Access-Control-Allow-Methods "GET, HEAD, POST" "expr=reqenv('CORSTrusted') == 'true'"
Header always set Access-Control-Max-Age 1800 "expr=reqenv('CORSTrusted') == 'true'"
Header always set Access-Control-Allow-Headers "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, X-AEM-Vip-Key" "expr=reqenv('CORSTrusted') == 'true'"

# Non-CORS or Not Trusted
Header unset Access-Control-Allow-Credentials "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
Header unset Access-Control-Allow-Origin "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
Header unset Access-Control-Allow-Methods "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
Header unset Access-Control-Max-Age "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"

# Always vary on origin, even if its not there.
Header merge Vary Origin
</IfModule>
<Directory />
<IfModule disp_apache2.c>
Expand Down
4 changes: 4 additions & 0 deletions dispatcher/src/conf.d/rewrites/rewrite.rules
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ RewriteRule ^(.*)$ https://wknd.site%{REQUEST_URI} [R=301,L,E=cdncache]
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule ^(/)$ /us/en.html [R=301,L,E=cdncache]

# CORS - send 204 for CORS requests which are not trusted
RewriteCond expr "reqenv('CORSProcessing') == 'true' && reqenv('CORSTrusted') == 'false'"
RewriteRule "^(.*)" - [R=204,L]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rewrite rule will not work in its current form/position, as conf.d/rewrites/default_rewrite.rules contains rewrite at as a last rule with flag [PT], and that implicitly implies L flag. See PT section on https://httpd.apache.org/docs/2.4/rewrite/flags.html

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jabran, have you tested the PR?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, tested this using a local author-publish-dispatcher setup.

RewriteCond %{REQUEST_URI} !^/apps
RewriteCond %{REQUEST_URI} !^/bin
RewriteCond %{REQUEST_URI} !^/content
Expand Down
10 changes: 0 additions & 10 deletions dispatcher/src/conf.dispatcher.d/available_farms/wknd.farm
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
#
# This file originated as a copy from conf.dispatcher.d/available_farms/default.farm
#
# Modifications to this file include:
# + Added CORS Headers to /cache /headers
#

/publishfarm {
# client headers which should be passed through to the render instances
Expand Down Expand Up @@ -100,20 +97,13 @@
# requests to the cached resource, the stored headers are added to the
# response.
# Note, that file globbing characters are not allowed here.
# CORS HTTP response headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_response_headers
/headers {
"Cache-Control"
"Content-Disposition"
"Content-Type"
"Expires"
"Last-Modified"
"X-Content-Type-Options"
"Access-Control-Allow-Origin"
"Access-Control-Expose-Headers"
"Access-Control-Max-Age"
"Access-Control-Allow-Credentials"
"Access-Control-Allow-Methods"
"Access-Control-Allow-Headers"
}
# A grace period defines the number of seconds a stale, auto-invalidated
# resource may still be served from the cache after the last activation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,4 @@
# By default, it includes the default client headers.
#

# Allowing CORS headers to be passed through to the publish tier to support headless and SPA Editor use cases.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_request_headers

"Origin"
"Access-Control-Request-Method"
"Access-Control-Request-Headers"

$include "./default_clientheaders.any"

This file was deleted.