Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Access-Control-Allow-Credentials header #416

Merged
merged 2 commits into from
Sep 26, 2023
Merged
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
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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="" \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/org/gaul/s3proxy/CrossOriginResourceSharing.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -50,16 +51,18 @@ public final class CrossOriginResourceSharing {
private final Set<Pattern> allowedOrigins;
private final Set<String> allowedMethods;
private final Set<String> 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<String> allowedOrigins,
Collection<String> allowedMethods,
Collection<String> allowedHeaders) {
Collection<String> allowedHeaders,
String allowCredentials) {
Set<Pattern> allowedPattern = new HashSet<Pattern>();
boolean anyOriginAllowed = false;

Expand Down Expand Up @@ -92,9 +95,12 @@ public CrossOriginResourceSharing(Collection<String> 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() {
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/org/gaul/s3proxy/S3Proxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/gaul/s3proxy/S3ProxyConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/gaul/s3proxy/S3ProxyHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2990,6 +2990,9 @@ private void addCorsResponseHeader(HttpServletRequest request,
corsRules.getAllowedOrigin(corsOrigin));
response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,
corsRules.getAllowedMethods());
if (corsRules.isAllowCredentials()) {
response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/run-docker-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}" \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
}