Skip to content

Commit

Permalink
Fixes nginxinc#62
Browse files Browse the repository at this point in the history
This commit adds support for CORS response headers.

Signed-off-by: Elijah Zupancic <[email protected]>
  • Loading branch information
dekobon committed Dec 14, 2022
1 parent 41645a0 commit 28824ad
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 4 deletions.
5 changes: 5 additions & 0 deletions Dockerfile.buildkit.plus
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ ENV PROXY_CACHE_VALID_OK "1h"
ENV PROXY_CACHE_VALID_NOTFOUND "1m"
ENV PROXY_CACHE_VALID_FORBIDDEN "30s"

ENV PROXY_CACHE_VALID_OK "1h"
ENV PROXY_CACHE_VALID_NOTFOUND "1m"
ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
ENV CORS_ENABLED 0

COPY plus/usr /usr

# Copy files from the OSS NGINX Docker container such that the container
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.oss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ENV NJS_VERSION 0.7.9
ENV PROXY_CACHE_VALID_OK "1h"
ENV PROXY_CACHE_VALID_NOTFOUND "1m"
ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
ENV CORS_ENABLED 0

# We modify the nginx base image by:
# 1. Adding configuration files needed for proxying private S3 buckets
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.plus
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ENV XSLT_VERSION 28-1
ENV PROXY_CACHE_VALID_OK "1h"
ENV PROXY_CACHE_VALID_NOTFOUND "1m"
ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
ENV CORS_ENABLED 0

COPY plus/etc/ssl /etc/ssl
COPY plus/usr /usr
Expand Down
4 changes: 3 additions & 1 deletion common/docker-entrypoint.d/00-check-for-required-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ set -e
failed=0

required=("S3_BUCKET_NAME" "S3_SERVER" "S3_SERVER_PORT" "S3_SERVER_PROTO"
"S3_REGION" "S3_STYLE" "ALLOW_DIRECTORY_LIST" "AWS_SIGS_VERSION")
"S3_REGION" "S3_STYLE" "ALLOW_DIRECTORY_LIST" "AWS_SIGS_VERSION"
"CORS_ENABLED")

# Require some form of authentication to be configured.

Expand Down Expand Up @@ -107,3 +108,4 @@ echo "Directory Listing Enabled: ${ALLOW_DIRECTORY_LIST}"
echo "Provide Index Pages Enabled: ${PROVIDE_INDEX_PAGE}"
echo "Append slash for directory enabled: ${APPEND_SLASH_FOR_POSSIBLE_DIRECTORY}"
echo "Stripping the following headers from responses: x-amz-;${HEADER_PREFIXES_TO_STRIP}"
echo "CORS Enabled: ${CORS_ENABLED}"
28 changes: 27 additions & 1 deletion common/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env bash
#
# Copyright 2020 F5 Networks
#
Expand All @@ -19,11 +19,37 @@

set -e

parseBoolean() {
case "$1" in
TRUE | true | True | YES | Yes | 1)
echo 1
;;
*)
echo 0
;;
esac
}

# This line is an addition to the NGINX Docker image's entrypoint script.
if [ -z ${DNS_RESOLVERS+x} ]; then
export DNS_RESOLVERS="$(cat /etc/resolv.conf | grep nameserver | cut -d' ' -f2 | xargs)"
fi

# Normalize the CORS_ENABLED environment variable to a numeric value
# so that it can be easily parsed in the nginx configuration.
export CORS_ENABLED="$(parseBoolean "${CORS_ENABLED}")"

# By enabling CORS, we also need to enable the OPTIONS method which
# is not normally used as part of the gateway. The following variable
# defines the set of acceptable headers.
if [ "${CORS_ENABLED}" == "1" ]; then
export LIMIT_METHODS_TO="GET HEAD OPTIONS"
export LIMIT_METHODS_TO_CSV="GET, HEAD, OPTIONS"
else
export LIMIT_METHODS_TO="GET HEAD"
export LIMIT_METHODS_TO_CSV="GET, HEAD"
fi

# Nothing is modified under this line

if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
Expand Down
21 changes: 20 additions & 1 deletion common/etc/nginx/templates/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ server {
}

location / {
# This value is templated in based on the value of $CORS_ENABLED. When
# CORS is enabled, acceptable methods are GET, HEAD, and OPTIONS.
# Otherwise, they are GET and HEAD.
limit_except ${LIMIT_METHODS_TO} {}

# CORS is implemented by returning the appropriate headers as part of
# the response to an OPTIONS request. If you want to customize the
# CORS response, the cors.conf.template file can be overwritten and
# extended to meet one's needs.
include /etc/nginx/conf.d/gateway/cors.conf;

auth_request /aws/credentials/retrieve;

# Redirect to the proper location based on the client request - either
Expand All @@ -86,6 +97,10 @@ server {
# we plan to use.
include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_headers.conf;

# The CORS configuration needs to be imported in several places in order for
# it to be applied within different contexts.
include /etc/nginx/conf.d/gateway/cors.conf;

# Don't allow any headers from the client - we don't want them messing
# with S3 at all.
proxy_pass_request_headers off;
Expand Down Expand Up @@ -128,6 +143,10 @@ server {
# we plan to use.
include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_headers.conf;

# The CORS configuration needs to be imported in several places in order for
# it to be applied within different contexts.
include /etc/nginx/conf.d/gateway/cors.conf;

# Don't allow any headers from the client - we don't want them messing
# with S3 at all.
proxy_pass_request_headers off;
Expand Down Expand Up @@ -193,7 +212,7 @@ server {
# Provide a hint to the client on 405 errors of the acceptable request methods
error_page 405 @error405;
location @error405 {
add_header Allow "GET, HEAD" always;
add_header Allow "${LIMIT_METHODS_TO_CSV}" always;
return 405;
}

Expand Down
31 changes: 31 additions & 0 deletions common/etc/nginx/templates/gateway/cors.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
set $request_cors "${request_method}_${CORS_ENABLED}";

if ($request_cors = "OPTIONS_1") {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}

if ($request_cors = "GET_1") {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}

if ($request_cors = "HEAD_1") {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
9 changes: 8 additions & 1 deletion docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ running as a Container or as a Systemd service.
* `PROXY_CACHE_VALID_NOTFOUND` - Sets caching time for response code 404
* `PROXY_CACHE_VALID_FORBIDDEN` - Sets caching time for response code 403
* `JS_TRUSTED_CERT_PATH` - (optional) Enables the `js_fetch_trusted_certificate` directive when retrieving AWS credentials and sets the path (on the container) to the specified path
* `HEADER_PREFIXES_TO_STRIP` - (optional) a list of HTTP header prefixes that exclude headers client responses. List should be specified in lower-case and a semicolon (;) should be used to as a deliminator between values. For example: `x-goog-;x-something-`
* `HEADER_PREFIXES_TO_STRIP` - (optional) a list of HTTP header prefixes that exclude headers client responses. List should be specified in lower-case and a semicolon (;) should be used to as a deliminator between values. For example: `x-goog-;x-something-`
* `CORS_ENABLED` - Flag (true/false) that enables CORS headers on GET
requests and enables pre-flight OPTIONS requests. If enabled, this will
add CORS headers for "fully open" cross domain requests by default,
meaning all domains are allowed, similar to the settings show in
[this example](https://enable-cors.org/server_nginx.html).
CORS settings can be fine-tuned by overwriting the
[`cors.conf.template`](/common/etc/nginx/templates/gateway/cors.conf.template) file. (default: false)

If you are using [AWS instance profile credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html),
you will need to omit the `S3_ACCESS_KEY_ID` and `S3_SECRET_KEY` variables from
Expand Down

0 comments on commit 28824ad

Please sign in to comment.