From a921384064328add60df002a271dcef1ed1ab7c7 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 18 Apr 2022 14:15:43 +0200 Subject: [PATCH 1/2] add Access-Control-Allow-Credentials header --- src/main/java/org/gaul/s3proxy/S3ProxyHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java index 235ee7b1..ae46cfdb 100644 --- a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java +++ b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java @@ -2990,6 +2990,7 @@ private void addCorsResponseHeader(HttpServletRequest request, corsRules.getAllowedOrigin(corsOrigin)); response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, corsRules.getAllowedMethods()); + response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); } } From 52089997cb216dbf6b7a6d2bc2b64f696df69ca3 Mon Sep 17 00:00:00 2001 From: steve Date: Tue, 27 Sep 2022 09:43:47 +0200 Subject: [PATCH 2/2] add PROPERTY_CORS_ALLOW_CREDENTIAL config property --- Dockerfile | 1 + README.md | 1 + .../gaul/s3proxy/CrossOriginResourceSharing.java | 14 ++++++++++++-- src/main/java/org/gaul/s3proxy/S3Proxy.java | 6 +++++- .../java/org/gaul/s3proxy/S3ProxyConstants.java | 2 ++ src/main/java/org/gaul/s3proxy/S3ProxyHandler.java | 4 +++- src/main/resources/run-docker-container.sh | 1 + .../CrossOriginResourceSharingResponseTest.java | 3 +++ .../CrossOriginResourceSharingRuleTest.java | 11 +++++++++-- 9 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index fffae63c..392ef953 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,7 @@ ENV \ S3PROXY_CORS_ALLOW_ORIGINS="" \ S3PROXY_CORS_ALLOW_METHODS="" \ S3PROXY_CORS_ALLOW_HEADERS="" \ + S3PROXY_CORS_ALLOW_CREDENTIAL="" \ S3PROXY_IGNORE_UNKNOWN_HEADERS="false" \ S3PROXY_ENCRYPTED_BLOBSTORE="" \ S3PROXY_ENCRYPTED_BLOBSTORE_PASSWORD="" \ diff --git a/README.md b/README.md index d06a1f2e..71f48106 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ file (and corresponding ENV variables for Docker): s3proxy.cors-allow-origins=https://example\.com https://.+\.example\.com https://example\.cloud s3proxy.cors-allow-methods=GET PUT s3proxy.cors-allow-headers=Accept Content-Type +s3proxy.cors-allow-credential=true ``` CORS cannot be configured per bucket. `s3proxy.cors-allow-all=true` will accept any origin and header. diff --git a/src/main/java/org/gaul/s3proxy/CrossOriginResourceSharing.java b/src/main/java/org/gaul/s3proxy/CrossOriginResourceSharing.java index 7bbb0d52..b6278e71 100644 --- a/src/main/java/org/gaul/s3proxy/CrossOriginResourceSharing.java +++ b/src/main/java/org/gaul/s3proxy/CrossOriginResourceSharing.java @@ -40,6 +40,7 @@ public final class CrossOriginResourceSharing { private static final String HEADER_VALUE_SEPARATOR = ", "; private static final String ALLOW_ANY_ORIGIN = "*"; private static final String ALLOW_ANY_HEADER = "*"; + private static final String ALLOW_CREDENTIALS = "true"; private static final Logger logger = LoggerFactory.getLogger( CrossOriginResourceSharing.class); @@ -50,16 +51,18 @@ public final class CrossOriginResourceSharing { private final Set allowedOrigins; private final Set allowedMethods; private final Set allowedHeaders; + private final String allowCredentials; public CrossOriginResourceSharing() { // CORS Allow all this(Lists.newArrayList(ALLOW_ANY_ORIGIN), SUPPORTED_METHODS, - Lists.newArrayList(ALLOW_ANY_HEADER)); + Lists.newArrayList(ALLOW_ANY_HEADER), ""); } public CrossOriginResourceSharing(Collection allowedOrigins, Collection allowedMethods, - Collection allowedHeaders) { + Collection allowedHeaders, + String allowCredentials) { Set allowedPattern = new HashSet(); boolean anyOriginAllowed = false; @@ -92,9 +95,12 @@ public CrossOriginResourceSharing(Collection allowedOrigins, this.allowedHeadersRaw = Joiner.on(HEADER_VALUE_SEPARATOR).join( this.allowedHeaders); + this.allowCredentials = allowCredentials; + logger.info("CORS allowed origins: {}", allowedOrigins); logger.info("CORS allowed methods: {}", allowedMethods); logger.info("CORS allowed headers: {}", allowedHeaders); + logger.info("CORS allow credentials: {}", allowCredentials); } public String getAllowedMethods() { @@ -166,6 +172,10 @@ public boolean isEveryHeaderAllowed(String headers) { return result; } + public boolean isAllowCredentials() { + return ALLOW_CREDENTIALS.equals(allowCredentials); + } + @Override public boolean equals(Object object) { if (this == object) { diff --git a/src/main/java/org/gaul/s3proxy/S3Proxy.java b/src/main/java/org/gaul/s3proxy/S3Proxy.java index de4533a8..1ec9d375 100644 --- a/src/main/java/org/gaul/s3proxy/S3Proxy.java +++ b/src/main/java/org/gaul/s3proxy/S3Proxy.java @@ -262,6 +262,9 @@ public static Builder fromProperties(Properties properties) S3ProxyConstants.PROPERTY_CORS_ALLOW_METHODS, ""); String corsAllowHeaders = properties.getProperty( S3ProxyConstants.PROPERTY_CORS_ALLOW_HEADERS, ""); + String allowCredentials = properties.getProperty( + S3ProxyConstants.PROPERTY_CORS_ALLOW_CREDENTIAL, ""); + Splitter splitter = Splitter.on(" ").trimResults() .omitEmptyStrings(); @@ -280,7 +283,8 @@ public static Builder fromProperties(Properties properties) builder.corsRules(new CrossOriginResourceSharing( Lists.newArrayList(splitter.split(corsAllowOrigins)), Lists.newArrayList(splitter.split(corsAllowMethods)), - Lists.newArrayList(splitter.split(corsAllowHeaders)))); + Lists.newArrayList(splitter.split(corsAllowHeaders)), + allowCredentials)); } String jettyMaxThreads = properties.getProperty( diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java b/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java index 9936343a..9e0f71af 100644 --- a/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java +++ b/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java @@ -40,6 +40,8 @@ public final class S3ProxyConstants { "s3proxy.cors-allow-methods"; public static final String PROPERTY_CORS_ALLOW_HEADERS = "s3proxy.cors-allow-headers"; + public static final String PROPERTY_CORS_ALLOW_CREDENTIAL = + "s3proxy.cors-allow-credential"; public static final String PROPERTY_CREDENTIAL = "s3proxy.credential"; public static final String PROPERTY_IGNORE_UNKNOWN_HEADERS = diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java index ae46cfdb..75df2440 100644 --- a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java +++ b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java @@ -2990,7 +2990,9 @@ private void addCorsResponseHeader(HttpServletRequest request, corsRules.getAllowedOrigin(corsOrigin)); response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, corsRules.getAllowedMethods()); - response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); + if (corsRules.isAllowCredentials()) { + response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); + } } } diff --git a/src/main/resources/run-docker-container.sh b/src/main/resources/run-docker-container.sh index 3b3cb718..4347d86d 100755 --- a/src/main/resources/run-docker-container.sh +++ b/src/main/resources/run-docker-container.sh @@ -11,6 +11,7 @@ exec java \ -Ds3proxy.cors-allow-origins="${S3PROXY_CORS_ALLOW_ORIGINS}" \ -Ds3proxy.cors-allow-methods="${S3PROXY_CORS_ALLOW_METHODS}" \ -Ds3proxy.cors-allow-headers="${S3PROXY_CORS_ALLOW_HEADERS}" \ + -Ds3proxy.cors-allow-credential="${S3PROXY_CORS_ALLOW_CREDENTIAL}" \ -Ds3proxy.ignore-unknown-headers="${S3PROXY_IGNORE_UNKNOWN_HEADERS}" \ -Ds3proxy.encrypted-blobstore="${S3PROXY_ENCRYPTED_BLOBSTORE}" \ -Ds3proxy.encrypted-blobstore-password="${S3PROXY_ENCRYPTED_BLOBSTORE_PASSWORD}" \ diff --git a/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingResponseTest.java b/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingResponseTest.java index 1c33f33a..c9d0c83d 100644 --- a/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingResponseTest.java +++ b/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingResponseTest.java @@ -303,6 +303,9 @@ public void testCorsPreflightPublicRead() throws Exception { assertThat(response.getFirstHeader( HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).getValue()) .isEqualTo("Accept, Content-Type"); + assertThat(response.getFirstHeader( + HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)) + .isNull(); } @Test diff --git a/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingRuleTest.java b/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingRuleTest.java index 0fb0ca48..6c147af8 100644 --- a/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingRuleTest.java +++ b/src/test/java/org/gaul/s3proxy/CrossOriginResourceSharingRuleTest.java @@ -38,9 +38,10 @@ public void setUp() throws Exception { "https://.+\\.example\\.com", "https://example\\.cloud"), Lists.newArrayList("GET", "PUT"), - Lists.newArrayList("Accept", "Content-Type")); + Lists.newArrayList("Accept", "Content-Type"), + "true"); // CORS disabled - corsOff = new CrossOriginResourceSharing(null, null, null); + corsOff = new CrossOriginResourceSharing(null, null, null, null); } @Test @@ -174,4 +175,10 @@ public void testCorsCfgHeader() throws Exception { assertThat(corsCfg.isEveryHeaderAllowed(probe)) .as("check '%s' as header", probe).isTrue(); } + + @Test + public void testAllowCredentials() { + assertThat(corsOff.isAllowCredentials()).isFalse(); + assertThat(corsCfg.isAllowCredentials()).isTrue(); + } }