Map a subset of XML ACLs to canned ACLs

Fixes #116.
pull/124/head
Andrew Gaul 2016-01-18 12:04:43 -08:00
rodzic 566575e71a
commit 19e2426220
5 zmienionych plików z 130 dodań i 9 usunięć

Wyświetl plik

@ -301,6 +301,11 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>

Wyświetl plik

@ -0,0 +1,64 @@
/*
* Copyright 2014-2016 Andrew Gaul <andrew@gaul.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gaul.s3proxy;
import java.util.Collection;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
/** Represent an Amazon AccessControlPolicy for a container or object. */
// CHECKSTYLE:OFF
final class AccessControlPolicy {
@JacksonXmlProperty(localName = "Owner")
Owner owner;
@JacksonXmlProperty(localName = "AccessControlList")
AccessControlList aclList;
static final class Owner {
@JacksonXmlProperty(localName = "ID")
String id;
@JacksonXmlProperty(localName = "DisplayName")
String displayName;
}
static final class AccessControlList {
@JacksonXmlProperty(localName = "Grant")
@JacksonXmlElementWrapper(useWrapping = false)
Collection<Grant> grants;
static final class Grant {
@JacksonXmlProperty(localName = "Grantee")
Grantee grantee;
@JacksonXmlProperty(localName = "Permission")
String permission;
static final class Grantee {
@JacksonXmlProperty(namespace = "xsi", localName = "type",
isAttribute = true)
String type;
@JacksonXmlProperty(localName = "ID")
String id;
@JacksonXmlProperty(localName = "DisplayName")
String displayName;
@JacksonXmlProperty(localName = "URI")
String uri;
}
}
}
}
// CHECKSTYLE:ON

Wyświetl plik

@ -58,6 +58,7 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
@ -841,15 +842,53 @@ final class S3ProxyHandler extends AbstractHandler {
return;
}
// TODO: how to handle XML ACLs?
int ch = is.read();
PushbackInputStream pis = new PushbackInputStream(is);
int ch = pis.read();
if (ch != -1) {
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
pis.unread(ch);
AccessControlPolicy policy = new XmlMapper().readValue(
pis, AccessControlPolicy.class);
access = mapXmlAclsToCannedPolicy(policy);
}
blobStore.setBlobAccess(containerName, blobName, access);
}
/** Map XML ACLs to a canned policy if an exact tranformation exists. */
private static BlobAccess mapXmlAclsToCannedPolicy(
AccessControlPolicy policy) throws S3Exception {
if (!policy.owner.id.equals(FAKE_OWNER_ID)) {
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
}
boolean ownerFullControl = false;
boolean allUsersRead = false;
for (AccessControlPolicy.AccessControlList.Grant grant :
policy.aclList.grants) {
if (grant.grantee.type.equals("CanonicalUser") &&
grant.grantee.id.equals(FAKE_OWNER_ID) &&
grant.permission.equals("FULL_CONTROL")) {
ownerFullControl = true;
} else if (grant.grantee.type.equals("Group") &&
grant.grantee.uri.equals("http://acs.amazonaws.com/" +
"groups/global/AllUsers") &&
grant.permission.equals("READ")) {
allUsersRead = true;
} else {
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
}
}
if (ownerFullControl) {
if (allUsersRead) {
return BlobAccess.PUBLIC_READ;
}
return BlobAccess.PRIVATE;
} else {
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
}
}
private void handleContainerList(HttpServletResponse response,
BlobStore blobStore) throws IOException {
PageSet<? extends StorageMetadata> buckets = blobStore.list();

Wyświetl plik

@ -9,6 +9,7 @@
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
</module>
<module name="NewlineAtEndOfFile"/>
<module name="SuppressionCommentFilter"/>
<module name="Translation"/>
<module name="TreeWalker">
<property name="cacheFile" value="target/cachefile"/>
@ -37,6 +38,7 @@
<module name="EqualsHashCode"/>
<module name="ExplicitInitialization"/>
<module name="FallThrough"/>
<module name="FileContentsHolder"/>
<module name="FinalClass"/>
<module name="GenericWhitespace"/>
<!--

Wyświetl plik

@ -52,11 +52,12 @@ import com.amazonaws.services.s3.model.CopyPartRequest;
import com.amazonaws.services.s3.model.CopyPartResult;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.GroupGrantee;
import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadResult;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.Owner;
import com.amazonaws.services.s3.model.Permission;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.model.UploadPartRequest;
@ -363,13 +364,23 @@ public final class S3AwsSdkTest {
metadata.setContentLength(BYTE_SOURCE.size());
client.putObject(containerName, blobName, BYTE_SOURCE.openStream(),
metadata);
AccessControlList acl = client.getObjectAcl(containerName, blobName);
AccessControlList acl = new AccessControlList();
Owner owner = new Owner();
owner.setId("id");
owner.setDisplayName("display-name");
acl.setOwner(owner);
acl.grantPermission(GroupGrantee.AllUsers, Permission.Read);
client.setObjectAcl(containerName, blobName, acl);
// TODO: work around unimplemented AccessControlList.equals:
// https://github.com/aws/aws-sdk-java/pull/609
AccessControlList acl2 = client.getObjectAcl(containerName, blobName);
assertThat(acl2.getOwner()).isEqualTo(acl.getOwner());
assertThat(acl2.getGrantsAsList()).isEqualTo(acl.getGrantsAsList());
acl.revokeAllPermissions(GroupGrantee.AllUsers);
client.setObjectAcl(containerName, blobName, acl);
acl2 = client.getObjectAcl(containerName, blobName);
assertThat(acl2.getOwner()).isEqualTo(acl.getOwner());
assertThat(acl2.getGrantsAsList()).isEqualTo(acl.getGrantsAsList());
acl.grantPermission(GroupGrantee.AllUsers, Permission.Write);
try {
client.setObjectAcl(containerName, blobName, acl);
Fail.failBecauseExceptionWasNotThrown(AmazonS3Exception.class);