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

Creation of Public Buckets #222

Merged
merged 3 commits into from
Mar 2, 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
12 changes: 10 additions & 2 deletions src/main/java/ninja/S3Dispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class S3Dispatcher implements WebDispatcher {

private static final String HTTP_HEADER_NAME_ETAG = "ETag";
private static final String HTTP_HEADER_NAME_CONTENT_TYPE = "Content-Type";
private static final String HTTP_HEADER_NAME_AMAZON_ACL = "x-amz-acl";
private static final String CONTENT_TYPE_XML = "application/xml";
private static final String RESPONSE_DISPLAY_NAME = "DisplayName";
private static final String RESPONSE_BUCKET = "Bucket";
Expand Down Expand Up @@ -472,6 +473,13 @@ private void bucket(WebContext webContext, String bucketName) {
}
} else if (HttpMethod.PUT.equals(method)) {
bucket.create();

// in order to allow creation of public buckets, we support a single canned access control list
String cannedAccessControlList = webContext.getHeader(HTTP_HEADER_NAME_AMAZON_ACL);
if (Strings.areEqual(cannedAccessControlList, "public-read-write")) {
bucket.makePublic();
}

signalObjectSuccess(webContext);
webContext.respondWith().status(HttpResponseStatus.OK);
} else {
Expand Down Expand Up @@ -730,7 +738,7 @@ private Map<String, String> parseUploadProperties(WebContext webContext) {
for (String name : webContext.getRequest().headers().names()) {
String nameLower = name.toLowerCase();
if (nameLower.startsWith("x-amz-meta-") || "content-md5".equals(nameLower) || "content-type".equals(
nameLower) || "x-amz-acl".equals(nameLower)) {
nameLower) || HTTP_HEADER_NAME_AMAZON_ACL.equals(nameLower)) {
properties.put(name, webContext.getHeader(name));
}
}
Expand Down Expand Up @@ -865,7 +873,7 @@ private void startMultipartUpload(WebContext webContext, Bucket bucket, String i
for (String name : webContext.getRequest().headers().names()) {
String nameLower = name.toLowerCase();
if (nameLower.startsWith("x-amz-meta-") || "content-md5".equals(nameLower) || "content-type".equals(
nameLower) || "x-amz-acl".equals(nameLower)) {
nameLower) || HTTP_HEADER_NAME_AMAZON_ACL.equals(nameLower)) {
properties.put(name, webContext.getHeader(name));
response.addHeader(name, webContext.getHeader(name));
}
Expand Down
16 changes: 3 additions & 13 deletions src/test/java/BaseAWSSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import com.amazonaws.HttpMethod
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.Headers
import com.amazonaws.services.s3.model.AmazonS3Exception
import com.amazonaws.services.s3.model.CannedAccessControlList
import com.amazonaws.services.s3.model.CreateBucketRequest
import com.amazonaws.services.s3.model.DeleteObjectsRequest
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest
import com.amazonaws.services.s3.model.ListObjectsV2Request
Expand All @@ -32,18 +34,6 @@ abstract class BaseAWSSpec extends BaseSpecification {

abstract AmazonS3Client getClient()

private void createPubliclyAccessibleBucket(String bucketName) {
def client = getClient()
client.createBucket(bucketName)

// we make the bucket now public via our own endpoint; note that this is not proper S3 code
// where you would use ACLs that we do not support in S3 Ninja
def url = new URL("http://localhost:9999/ui/" + bucketName + "/?make-public")
HttpURLConnection connection = (HttpURLConnection) url.openConnection()
connection.getResponseCode() == 200
connection.disconnect();
}

private void putObjectWithContent(String bucketName, String key, String content) {
def client = getClient()
def data = content.getBytes(StandardCharsets.UTF_8)
Expand Down Expand Up @@ -413,7 +403,7 @@ abstract class BaseAWSSpec extends BaseSpecification {
def content = "I am pointless text content"
def client = getClient()
when:
createPubliclyAccessibleBucket(bucketName)
client.createBucket(new CreateBucketRequest(bucketName).withCannedAcl(CannedAccessControlList.PublicReadWrite))
putObjectWithContent(bucketName, key, content)
then:
def url = new URL("http://localhost:9999/" + bucketName + "/" + key)
Expand Down