diff --git a/hadoop-ozone/dist/src/main/smoketest/s3/bucketlist.robot b/hadoop-ozone/dist/src/main/smoketest/s3/bucketlist.robot index 22e2aced19c2..5e8ed10e9823 100644 --- a/hadoop-ozone/dist/src/main/smoketest/s3/bucketlist.robot +++ b/hadoop-ozone/dist/src/main/smoketest/s3/bucketlist.robot @@ -25,6 +25,7 @@ Suite Setup Setup s3 tests *** Variables *** ${ENDPOINT_URL} http://s3g:9878 ${BUCKET} generated +${DEFAULT_OWNER_ID} bb2bd7ca4a327f84e6cd3979f8fa3828a50a08893c1b68f9d6715352c8d07b93 *** Test Cases *** @@ -33,7 +34,7 @@ List buckets ${bucket_names} = Execute echo '''${result}''' | jq -r '.Buckets[].Name' Should contain ${bucket_names} ${BUCKET} ${ownerId} = Execute echo '''${result}''' | jq -r '.Owner.ID' - Should Not Be Equal ${ownerId} null + Should Be Equal ${ownerId} ${DEFAULT_OWNER_ID} ${ownerDisplayName} = Execute echo '''${result}''' | jq -r '.Owner.DisplayName' Should Not Be Equal ${ownerDisplayName} null diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java index 87776c3499cf..ccb922eb31a8 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java @@ -105,6 +105,7 @@ import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; import org.apache.hadoop.ozone.s3.S3ClientFactory; import org.apache.hadoop.ozone.s3.S3GatewayService; +import org.apache.hadoop.ozone.s3.endpoint.S3Owner; import org.apache.hadoop.security.UserGroupInformation; import org.apache.ozone.test.OzoneTestBase; import org.junit.jupiter.api.MethodOrderer; @@ -270,7 +271,7 @@ public void testListBuckets() throws IOException { Owner s3AccountOwner = s3Client.getS3AccountOwner(); assertThat(s3AccountOwner.getDisplayName()).isEqualTo(expectOwner); - assertThat(s3AccountOwner.getId()).isEqualTo(expectOwner); + assertThat(s3AccountOwner.getId()).isEqualTo(S3Owner.DEFAULT_S3OWNER_ID); } @Test diff --git a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java index 6087787e2dfa..1d1867ae605d 100644 --- a/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java +++ b/hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java @@ -55,6 +55,7 @@ import org.apache.hadoop.ozone.client.io.OzoneOutputStream; import org.apache.hadoop.ozone.s3.S3ClientFactory; import org.apache.hadoop.ozone.s3.S3GatewayService; +import org.apache.hadoop.ozone.s3.endpoint.S3Owner; import org.apache.hadoop.security.UserGroupInformation; import org.apache.ozone.test.OzoneTestBase; import org.junit.jupiter.api.MethodOrderer; @@ -151,7 +152,7 @@ public void listBuckets() throws Exception { assertEquals(1, syncResponse.buckets().size()); assertEquals(bucketName, syncResponse.buckets().get(0).name()); assertEquals(expectedOwner, syncResponse.owner().displayName()); - assertEquals(expectedOwner, syncResponse.owner().id()); + assertEquals(S3Owner.DEFAULT_S3OWNER_ID, syncResponse.owner().id()); } @Test diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java index 118900aa53d0..9eff0c77b5aa 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java @@ -529,7 +529,7 @@ public S3BucketAcl getAcl(String bucketName) OzoneVolume volume = getVolume(); // TODO: use bucket owner instead of volume owner here once bucket owner // TODO: is supported. - S3Owner owner = new S3Owner(volume.getOwner(), volume.getOwner()); + S3Owner owner = S3Owner.of(volume.getOwner()); result.setOwner(owner); // TODO: remove this duplication avoid logic when ACCESS and DEFAULT scope @@ -745,10 +745,8 @@ private void addKey(ListObjectResponse response, OzoneKey next) { keyMetadata.setStorageClass(S3StorageType.STANDARD.toString()); } keyMetadata.setLastModified(next.getModificationTime()); - String ownerName = next.getOwner(); - String displayName = ownerName; - // Use ownerName to fill displayName - keyMetadata.setOwner(new S3Owner(ownerName, displayName)); + String displayName = next.getOwner(); + keyMetadata.setOwner(S3Owner.of(displayName)); response.addKey(keyMetadata); } diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListMultipartUploadsResult.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListMultipartUploadsResult.java index 5b2fabe0e147..98801a520e96 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListMultipartUploadsResult.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListMultipartUploadsResult.java @@ -155,10 +155,10 @@ public static class Upload { private String uploadId; @XmlElement(name = "Owner") - private S3Owner owner = S3Owner.NOT_SUPPORTED_OWNER; + private S3Owner owner = S3Owner.DEFAULT_S3_OWNER; @XmlElement(name = "Initiator") - private S3Owner initiator = S3Owner.NOT_SUPPORTED_OWNER; + private S3Owner initiator = S3Owner.DEFAULT_S3_OWNER; @XmlElement(name = "StorageClass") private String storageClass = "STANDARD"; diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java index d1271d7b7bc5..9ff2e945cda3 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java @@ -55,7 +55,7 @@ public Response get() Iterator bucketIterator; try { bucketIterator = - listS3Buckets(null, volume -> response.setOwner(new S3Owner(volume.getOwner(), volume.getOwner()))); + listS3Buckets(null, volume -> response.setOwner(S3Owner.of(volume.getOwner()))); } catch (Exception e) { getMetrics().updateListS3BucketsFailureStats(startNanos); throw e; diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/S3Owner.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/S3Owner.java index 4d1da87c313e..d332d5824fde 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/S3Owner.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/S3Owner.java @@ -29,8 +29,10 @@ @XmlRootElement(name = "Owner") public class S3Owner { + // The default S3 owner ID, generated by S3Utils.generateCanonicalUserId with input: "ozone" + public static final String DEFAULT_S3OWNER_ID = "bb2bd7ca4a327f84e6cd3979f8fa3828a50a08893c1b68f9d6715352c8d07b93"; public static final S3Owner - NOT_SUPPORTED_OWNER = new S3Owner("NOT-SUPPORTED", "Not Supported"); + DEFAULT_S3_OWNER = new S3Owner(DEFAULT_S3OWNER_ID, "ozone"); @XmlElement(name = "DisplayName") private String displayName; @@ -42,6 +44,10 @@ public S3Owner() { } + public static S3Owner of(String displayName) { + return new S3Owner(DEFAULT_S3OWNER_ID, displayName); + } + public S3Owner(String id, String displayName) { this.id = id; this.displayName = displayName; diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Utils.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Utils.java index a99bfca73721..6355f8cd24f3 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Utils.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Utils.java @@ -32,6 +32,7 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.hadoop.hdds.client.ReplicationConfig; import org.apache.hadoop.hdds.client.ReplicationFactor; import org.apache.hadoop.hdds.client.ReplicationType; @@ -143,4 +144,16 @@ public static boolean hasSignedPayloadHeader(HttpHeaders headers) { signingAlgorithm.equals(STREAMING_AWS4_ECDSA_P256_SHA256_PAYLOAD) || signingAlgorithm.equals(STREAMING_AWS4_ECDSA_P256_SHA256_PAYLOAD_TRAILER); } + + /** + * Generates a Canonical User ID compatible with S3 by returning the + * SHA-256 hexadecimal encoding of the input string. + * + * @param input the input string + * @return the SHA-256 hexadecimal encoded Canonical User ID + */ + public static String generateCanonicalUserId(String input) { + return DigestUtils.sha256Hex(input); + } + } diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestRootList.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestRootList.java index a7d7c5e4d301..915bb8ed3722 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestRootList.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestRootList.java @@ -65,7 +65,7 @@ public void testListBucket() throws Exception { response = (ListBucketResponse) rootEndpoint.get().getEntity(); assertEquals(10, response.getBucketsNum()); assertEquals("root", response.getOwner().getDisplayName()); - assertEquals("root", response.getOwner().getId()); + assertEquals(S3Owner.DEFAULT_S3OWNER_ID, response.getOwner().getId()); } } diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/util/TestS3Utils.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/util/TestS3Utils.java index bc61df82e7cf..b616ea47a88a 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/util/TestS3Utils.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/util/TestS3Utils.java @@ -25,6 +25,7 @@ import org.apache.hadoop.hdds.client.RatisReplicationConfig; import org.apache.hadoop.hdds.client.ReplicationConfig; import org.apache.hadoop.hdds.protocol.proto.HddsProtos; +import org.apache.hadoop.ozone.s3.endpoint.S3Owner; import org.apache.hadoop.ozone.s3.exception.OS3Exception; import org.junit.jupiter.api.Test; @@ -144,4 +145,9 @@ public void testResolveRepConfWhenUserPassedIsInvalid() throws OS3Exception { "INVALID", ratis3ReplicationConfig, ratis1ReplicationConfig)); } + @Test + public void testGenerateCanonicalUserId() { + assertEquals(S3Owner.DEFAULT_S3OWNER_ID, S3Utils.generateCanonicalUserId("ozone")); + } + }