diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSV4SignatureProcessor.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSSignatureProcessor.java similarity index 92% rename from hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSV4SignatureProcessor.java rename to hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSSignatureProcessor.java index 1ff1a72575b7..0cb82fb77b9e 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSV4SignatureProcessor.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/AWSSignatureProcessor.java @@ -43,6 +43,7 @@ import java.util.regex.Pattern; import org.apache.hadoop.ozone.s3.exception.OS3Exception; +import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV2; import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV4; import org.apache.hadoop.ozone.s3.header.Credential; @@ -54,15 +55,15 @@ import org.slf4j.LoggerFactory; /** - * Parser to process AWS v4 auth request. Creates string to sign and auth + * Parser to process AWS V2 & V4 auth request. Creates string to sign and auth * header. For more details refer to AWS documentation https://docs.aws * .amazon.com/general/latest/gr/sigv4-create-canonical-request.html. **/ @RequestScoped -public class AWSV4SignatureProcessor implements SignatureProcessor { +public class AWSSignatureProcessor implements SignatureProcessor { private final static Logger LOG = - LoggerFactory.getLogger(AWSV4SignatureProcessor.class); + LoggerFactory.getLogger(AWSSignatureProcessor.class); @Context private ContainerRequestContext context; @@ -72,13 +73,12 @@ public class AWSV4SignatureProcessor implements SignatureProcessor { private String uri; private String method; private AuthorizationHeaderV4 v4Header; + private AuthorizationHeaderV2 v2Header; private String stringToSign; @PostConstruct public void init() throws Exception { - LOG.info("Initializing request header parser"); - //header map is MUTABLE. It's better to save it here. (with lower case // keys!!!) this.headers = new LowerCaseKeyStringMap(new HashMap<>()); @@ -107,10 +107,18 @@ public void init() this.uri = context.getUriInfo().getRequestUri().getPath(); this.method = context.getMethod(); - if (v4Header == null) { - v4Header = new AuthorizationHeaderV4(headers.get(AUTHORIZATION_HEADER)); + String authHeader = headers.get(AUTHORIZATION_HEADER); + String[] split = authHeader.split(" "); + if (split[0].equals(AuthorizationHeaderV2.IDENTIFIER)) { + if (v2Header == null) { + v2Header = new AuthorizationHeaderV2(authHeader); + } + } else { + if (v4Header == null) { + v4Header = new AuthorizationHeaderV4(authHeader); + } + parse(); } - parse(); } @@ -320,11 +328,13 @@ public static String hash(String payload) throws NoSuchAlgorithmException { } public String getAwsAccessId() { - return v4Header.getAccessKeyID(); + return (v4Header != null ? v4Header.getAccessKeyID() : + v2Header != null ? v2Header.getAccessKeyID() : ""); } public String getSignature() { - return v4Header.getSignature(); + return (v4Header != null ? v4Header.getSignature() : + v2Header != null ? v2Header.getSignature() : ""); } public String getStringToSign() throws Exception { @@ -342,6 +352,11 @@ public void setV4Header( this.v4Header = v4Header; } + @VisibleForTesting + public void setV2Header(AuthorizationHeaderV2 v2Header) { + this.v2Header = v2Header; + } + /** * A simple map which forces lower case key usage. */ diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java index 3cd7b7c5dc02..a3042c13a3cf 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java @@ -51,7 +51,7 @@ public class OzoneClientProducer { private OzoneClient client; @Inject - private SignatureProcessor v4RequestParser; + private SignatureProcessor signatureParser; @Inject private OzoneConfiguration ozoneConfiguration; @@ -76,7 +76,7 @@ public void destory() throws IOException { private OzoneClient getClient(OzoneConfiguration config) throws IOException { try { - String awsAccessId = v4RequestParser.getAwsAccessId(); + String awsAccessId = signatureParser.getAwsAccessId(); UserGroupInformation remoteUser = UserGroupInformation.createRemoteUser(awsAccessId); if (OzoneSecurityUtil.isSecurityEnabled(config)) { @@ -85,8 +85,8 @@ private OzoneClient getClient(OzoneConfiguration config) throws IOException { OzoneTokenIdentifier identifier = new OzoneTokenIdentifier(); identifier.setTokenType(S3AUTHINFO); - identifier.setStrToSign(v4RequestParser.getStringToSign()); - identifier.setSignature(v4RequestParser.getSignature()); + identifier.setStrToSign(signatureParser.getStringToSign()); + identifier.setSignature(signatureParser.getSignature()); identifier.setAwsAccessId(awsAccessId); identifier.setOwner(new Text(awsAccessId)); if (LOG.isTraceEnabled()) { diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV2.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV2.java index dfafc3a5acad..fe096cee9ff5 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV2.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV2.java @@ -29,7 +29,7 @@ */ public class AuthorizationHeaderV2 { - private final static String IDENTIFIER = "AWS"; + public final static String IDENTIFIER = "AWS"; private String authHeader; private String identifier; private String accessKeyID; diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV4.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV4.java index 0d9f092b8e36..1e48689a86c7 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV4.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthorizationHeaderV4.java @@ -35,8 +35,8 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty; import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.MALFORMED_HEADER; -import static org.apache.hadoop.ozone.s3.AWSV4SignatureProcessor.AWS4_SIGNING_ALGORITHM; -import static org.apache.hadoop.ozone.s3.AWSV4SignatureProcessor.DATE_FORMATTER; +import static org.apache.hadoop.ozone.s3.AWSSignatureProcessor.AWS4_SIGNING_ALGORITHM; +import static org.apache.hadoop.ozone.s3.AWSSignatureProcessor.DATE_FORMATTER; /** * S3 Authorization header. diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSV4SignatureProcessor.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSSignatureProcessor.java similarity index 69% rename from hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSV4SignatureProcessor.java rename to hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSSignatureProcessor.java index 11b3b91724df..239e2857957b 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSV4SignatureProcessor.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestAWSSignatureProcessor.java @@ -24,6 +24,7 @@ import java.net.URI; import org.apache.hadoop.ozone.s3.exception.OS3Exception; +import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV2; import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV4; import org.junit.Assert; @@ -33,10 +34,10 @@ /** * Test the Auth parser. */ -public class TestAWSV4SignatureProcessor { +public class TestAWSSignatureProcessor { @Test - public void testInitialization() throws Exception { + public void testV4Initialization() throws Exception { MultivaluedMap headers = new MultivaluedHashMap<>(); headers.putSingle("Content-Length", "123"); @@ -76,7 +77,7 @@ public void validateDateRange() throws OS3Exception { Mockito.when(mock.getMethod()).thenReturn("GET"); Mockito.when(mock.getUriInfo()).thenReturn(uriInfo); - AWSV4SignatureProcessor parser = new AWSV4SignatureProcessor() { + AWSSignatureProcessor parser = new AWSSignatureProcessor() { @Override void validateSignedHeader(String header, String headerValue) throws OS3Exception { @@ -100,4 +101,41 @@ void validateSignedHeader(String header, String headerValue) "f20d4de80af2271545385e8d4c7df608cae70a791c69b97aab1527ed93a0d665", parser.getStringToSign()); } + + @Test + public void testV2Initialization() throws Exception { + + MultivaluedMap headers = new MultivaluedHashMap<>(); + String authHeader = "AWS root:ixWQAgWvJDuqLUqgDG9o4b2HF7c="; + headers.putSingle("Authorization", authHeader); + + AuthorizationHeaderV2 parserAuthHeader = + new AuthorizationHeaderV2(authHeader); + + MultivaluedMap queryParameters = new MultivaluedHashMap<>(); + + UriInfo uriInfo = Mockito.mock(UriInfo.class); + Mockito.when(uriInfo.getQueryParameters()).thenReturn(queryParameters); + Mockito.when(uriInfo.getRequestUri()) + .thenReturn(new URI("http://localhost/buckets")); + + ContainerRequestContext mock = Mockito.mock(ContainerRequestContext.class); + Mockito.when(mock.getHeaders()).thenReturn(headers); + Mockito.when(mock.getMethod()).thenReturn("GET"); + Mockito.when(mock.getUriInfo()).thenReturn(uriInfo); + + AWSSignatureProcessor parser = new AWSSignatureProcessor() { + @Override + void validateSignedHeader(String header, String headerValue) + throws OS3Exception { + super.validateSignedHeader(header, headerValue); + } + }; + parser.setV2Header(parserAuthHeader); + parser.setContext(mock); + parser.init(); + + Assert.assertEquals("root", parser.getAwsAccessId()); + Assert.assertEquals("ixWQAgWvJDuqLUqgDG9o4b2HF7c=", parser.getSignature()); + } } \ No newline at end of file diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketPut.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketPut.java index 014cb3e5ae8a..b4a21e3ae583 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketPut.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketPut.java @@ -30,7 +30,7 @@ import org.apache.hadoop.ozone.s3.exception.OS3Exception; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; -import static org.apache.hadoop.ozone.s3.AWSV4SignatureProcessor.DATE_FORMATTER; +import static org.apache.hadoop.ozone.s3.AWSSignatureProcessor.DATE_FORMATTER; import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.MALFORMED_HEADER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/header/TestAuthorizationHeaderV4.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/header/TestAuthorizationHeaderV4.java index e5d5562cd1a5..5ca1c4522414 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/header/TestAuthorizationHeaderV4.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/header/TestAuthorizationHeaderV4.java @@ -26,7 +26,7 @@ import java.time.LocalDate; import static java.time.temporal.ChronoUnit.DAYS; -import static org.apache.hadoop.ozone.s3.AWSV4SignatureProcessor.DATE_FORMATTER; +import static org.apache.hadoop.ozone.s3.AWSSignatureProcessor.DATE_FORMATTER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail;