HDDS-643. Parse Authorization header in a separate filter. Contributed by 
Bharat Viswanadham.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/639cb6b5
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/639cb6b5
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/639cb6b5

Branch: refs/heads/HDFS-13891
Commit: 639cb6b529b187cb070d4d85163ddb2c8dda0658
Parents: eb25263
Author: Márton Elek <e...@apache.org>
Authored: Thu Oct 25 12:45:53 2018 +0200
Committer: Brahma Reddy Battula <bra...@apache.org>
Committed: Tue Oct 30 11:31:17 2018 +0530

----------------------------------------------------------------------
 .../hadoop/ozone/s3/VirtualHostStyleFilter.java | 13 +++++
 .../ozone/s3/endpoint/BucketEndpoint.java       |  3 +-
 .../hadoop/ozone/s3/endpoint/EndpointBase.java  | 46 ++++-----------
 .../hadoop/ozone/s3/endpoint/RootEndpoint.java  |  6 +-
 .../s3/header/AuthenticationHeaderParser.java   | 61 ++++++++++++++++++++
 .../ozone/s3/TestVirtualHostStyleFilter.java    | 16 +++++
 .../hadoop/ozone/s3/endpoint/TestRootList.java  | 22 +++----
 7 files changed, 115 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java
index f1d52a6..d4e7547 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java
@@ -34,6 +34,7 @@ import java.util.Arrays;
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.fs.InvalidRequestException;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.s3.header.AuthenticationHeaderParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,11 +53,18 @@ public class VirtualHostStyleFilter implements 
ContainerRequestFilter {
 
   @Inject
   private OzoneConfiguration conf;
+
+  @Inject
+  private AuthenticationHeaderParser authenticationHeaderParser;
+
   private String[] domains;
 
   @Override
   public void filter(ContainerRequestContext requestContext) throws
       IOException {
+
+    authenticationHeaderParser.setAuthHeader(requestContext.getHeaderString(
+        HttpHeaders.AUTHORIZATION));
     domains = conf.getTrimmedStrings(OZONE_S3G_DOMAIN_NAME);
 
     if (domains.length == 0) {
@@ -140,4 +148,9 @@ public class VirtualHostStyleFilter implements 
ContainerRequestFilter {
     return match;
   }
 
+  @VisibleForTesting
+  public void setAuthenticationHeaderParser(AuthenticationHeaderParser parser) 
{
+    this.authenticationHeaderParser = parser;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
----------------------------------------------------------------------
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 453cecc..fca251d 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
@@ -36,7 +36,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.time.Instant;
 import java.util.Iterator;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response.ResponseBuilder;
 
 import org.apache.hadoop.ozone.client.OzoneBucket;
@@ -151,7 +150,7 @@ public class BucketEndpoint extends EndpointBase {
   public Response put(@PathParam("bucket") String bucketName, @Context
       HttpHeaders httpHeaders) throws IOException, OS3Exception {
 
-    String userName = parseUsername(httpHeaders);
+    String userName = getAuthenticationHeaderParser().getAccessKeyID();
 
     String location = createS3Bucket(userName, bucketName);
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
index 148bf69..a5af7f1 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
@@ -19,8 +19,6 @@ package org.apache.hadoop.ozone.s3.endpoint;
 
 import javax.inject.Inject;
 import javax.ws.rs.NotFoundException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
 import java.io.IOException;
 
 import org.apache.hadoop.ozone.client.OzoneBucket;
@@ -28,8 +26,7 @@ import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneVolume;
 import org.apache.hadoop.ozone.s3.exception.OS3Exception;
 import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
-import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV2;
-import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV4;
+import org.apache.hadoop.ozone.s3.header.AuthenticationHeaderParser;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.slf4j.Logger;
@@ -46,6 +43,9 @@ public class EndpointBase {
   @Inject
   private OzoneClient client;
 
+  @Inject
+  private AuthenticationHeaderParser authenticationHeaderParser;
+
   protected OzoneBucket getBucket(String volumeName, String bucketName)
       throws IOException {
     return getVolume(volumeName).getBucket(bucketName);
@@ -172,43 +172,17 @@ public class EndpointBase {
     return client.getObjectStore().getOzoneBucketName(s3BucketName);
   }
 
-  /**
-   * Retrieve the username based on the authorization header.
-   *
-   * @param httpHeaders
-   * @return Identified username
-   * @throws OS3Exception
-   */
-  public String parseUsername(
-      @Context HttpHeaders httpHeaders) throws OS3Exception {
-    String auth = httpHeaders.getHeaderString("Authorization");
-    LOG.info("Auth header string {}", auth);
-
-    if (auth == null) {
-      // In this case, adding resource as Authorization, need to revisit in
-      // future if it needs to be changed.
-      throw S3ErrorTable
-          .newError(S3ErrorTable.MALFORMED_HEADER, "Authorization");
-    }
+  public AuthenticationHeaderParser getAuthenticationHeaderParser() {
+    return authenticationHeaderParser;
+  }
 
-    String userName;
-    if (auth.startsWith("AWS4")) {
-      LOG.info("V4 Header {}", auth);
-      AuthorizationHeaderV4 authorizationHeader = new AuthorizationHeaderV4(
-          auth);
-      userName = authorizationHeader.getAccessKeyID().toLowerCase();
-    } else {
-      LOG.info("V2 Header {}", auth);
-      AuthorizationHeaderV2 authorizationHeader = new AuthorizationHeaderV2(
-          auth);
-      userName = authorizationHeader.getAccessKeyID().toLowerCase();
-    }
-    return userName;
+  @VisibleForTesting
+  public void setAuthenticationHeaderParser(AuthenticationHeaderParser parser) 
{
+    this.authenticationHeaderParser = parser;
   }
 
   @VisibleForTesting
   public void setClient(OzoneClient ozoneClient) {
     this.client = ozoneClient;
   }
-
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java
----------------------------------------------------------------------
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 4de26f3..1b0e876 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
@@ -20,8 +20,6 @@ package org.apache.hadoop.ozone.s3.endpoint;
 import javax.ws.rs.GET;
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.Path;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Iterator;
@@ -50,12 +48,12 @@ public class RootEndpoint extends EndpointBase {
    * for more details.
    */
   @GET
-  public ListBucketResponse get(@Context HttpHeaders headers)
+  public ListBucketResponse get()
       throws OS3Exception, IOException {
     OzoneVolume volume;
     ListBucketResponse response = new ListBucketResponse();
 
-    String volumeName = "s3" + parseUsername(headers).toLowerCase();
+    String volumeName = "s3" + 
getAuthenticationHeaderParser().getAccessKeyID();
     try {
       //TODO: we need a specific s3bucketlist endpoint instead
       // of reimplement the naming convention here

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthenticationHeaderParser.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthenticationHeaderParser.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthenticationHeaderParser.java
new file mode 100644
index 0000000..1ca50cb
--- /dev/null
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/header/AuthenticationHeaderParser.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.hadoop.ozone.s3.header;
+
+import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Authentication Header parser to parse HttpHeader Authentication.
+ */
+@RequestScoped
+public class AuthenticationHeaderParser {
+
+  private final static Logger LOG = LoggerFactory.getLogger(
+      AuthenticationHeaderParser.class);
+
+  private String authHeader;
+  private String accessKeyID;
+
+  public void parse() throws OS3Exception {
+    if (authHeader.startsWith("AWS4")) {
+      LOG.debug("V4 Header {}", authHeader);
+      AuthorizationHeaderV4 authorizationHeader = new AuthorizationHeaderV4(
+          authHeader);
+      accessKeyID = authorizationHeader.getAccessKeyID().toLowerCase();
+    } else {
+      LOG.debug("V2 Header {}", authHeader);
+      AuthorizationHeaderV2 authorizationHeader = new AuthorizationHeaderV2(
+          authHeader);
+      accessKeyID = authorizationHeader.getAccessKeyID().toLowerCase();
+    }
+  }
+
+  public String getAccessKeyID() throws OS3Exception {
+    parse();
+    return accessKeyID;
+  }
+
+  public void setAuthHeader(String header) {
+    this.authHeader = header;
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java
index 3fe6e1a..1b706da 100644
--- 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java
@@ -19,6 +19,7 @@ package org.apache.hadoop.ozone.s3;
 
 import org.apache.hadoop.fs.InvalidRequestException;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.s3.header.AuthenticationHeaderParser;
 import org.apache.hadoop.test.GenericTestUtils;
 import org.glassfish.jersey.internal.PropertiesDelegate;
 import org.glassfish.jersey.server.ContainerRequest;
@@ -41,6 +42,7 @@ public class TestVirtualHostStyleFilter {
 
   private static OzoneConfiguration conf;
   private static String s3HttpAddr;
+  private AuthenticationHeaderParser authenticationHeaderParser;
 
   @Before
   public void setup() {
@@ -48,6 +50,8 @@ public class TestVirtualHostStyleFilter {
     s3HttpAddr = "localhost:9878";
     conf.set(S3GatewayConfigKeys.OZONE_S3G_HTTP_ADDRESS_KEY, s3HttpAddr);
     conf.set(S3GatewayConfigKeys.OZONE_S3G_DOMAIN_NAME, s3HttpAddr);
+    authenticationHeaderParser = new AuthenticationHeaderParser();
+    authenticationHeaderParser.setAuthHeader("AWS ozone:scret");
   }
 
   /**
@@ -99,6 +103,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest("mybucket" +
             ".localhost:9878", "/myfile", null, true);
@@ -114,6 +120,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest(s3HttpAddr,
         "/mybucket/myfile", null, false);
@@ -130,6 +138,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest("mybucket" +
         ".localhost:9878", null, null, true);
@@ -145,6 +155,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest("mybucket" +
         ".localhost:9878", null, "?prefix=bh", true);
@@ -169,6 +181,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest("mybucket" +
         ".localhost:9999", null, null, true);
@@ -187,6 +201,8 @@ public class TestVirtualHostStyleFilter {
     VirtualHostStyleFilter virtualHostStyleFilter =
         new VirtualHostStyleFilter();
     virtualHostStyleFilter.setConfiguration(conf);
+    virtualHostStyleFilter.setAuthenticationHeaderParser(
+        authenticationHeaderParser);
 
     ContainerRequest containerRequest = createContainerRequest("mybucket" +
         "localhost:9878", null, null, true);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/639cb6b5/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestRootList.java
----------------------------------------------------------------------
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 65fdf4e..80cad3a 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
@@ -20,7 +20,6 @@
 
 package org.apache.hadoop.ozone.s3.endpoint;
 
-import javax.ws.rs.core.HttpHeaders;
 
 import org.apache.hadoop.ozone.client.ObjectStore;
 import org.apache.hadoop.ozone.client.OzoneClientStub;
@@ -28,21 +27,21 @@ import org.apache.hadoop.ozone.client.OzoneVolume;
 
 import org.apache.commons.lang3.RandomStringUtils;
 import static org.junit.Assert.assertEquals;
+
+import org.apache.hadoop.ozone.s3.header.AuthenticationHeaderParser;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Mockito;
-import static org.mockito.Mockito.when;
 
 /**
  * This class test HeadBucket functionality.
  */
 public class TestRootList {
 
-  private String volumeName = "vol1";
   private OzoneClientStub clientStub;
   private ObjectStore objectStoreStub;
   private OzoneVolume volumeStub;
   private RootEndpoint rootEndpoint;
+  private String userName = "ozone";
 
   @Before
   public void setup() throws Exception {
@@ -50,21 +49,24 @@ public class TestRootList {
     //Create client stub and object store stub.
     clientStub = new OzoneClientStub();
     objectStoreStub = clientStub.getObjectStore();
-    objectStoreStub.createVolume("s3key");
-    volumeStub = objectStoreStub.getVolume("s3key");
+    String volumeName = "s3" + userName;
+    objectStoreStub.createVolume(volumeName);
+    volumeStub = objectStoreStub.getVolume(volumeName);
 
     // Create HeadBucket and setClient to OzoneClientStub
     rootEndpoint = new RootEndpoint();
     rootEndpoint.setClient(clientStub);
+
+    AuthenticationHeaderParser parser = new AuthenticationHeaderParser();
+    parser.setAuthHeader("AWS " + userName +":secret");
+    rootEndpoint.setAuthenticationHeaderParser(parser);
   }
 
   @Test
   public void testListBucket() throws Exception {
-    HttpHeaders headers = Mockito.mock(HttpHeaders.class);
-    when(headers.getHeaderString("Authorization")).thenReturn("AWS 
key:secret");
 
     // List operation should success even there is no bucket.
-    ListBucketResponse response = rootEndpoint.get(headers);
+    ListBucketResponse response = rootEndpoint.get();
     assertEquals(0, response.getBucketsNum());
 
     String bucketBaseName = "bucket-";
@@ -72,7 +74,7 @@ public class TestRootList {
       volumeStub.createBucket(
           bucketBaseName + RandomStringUtils.randomNumeric(3));
     }
-    response = rootEndpoint.get(headers);
+    response = rootEndpoint.get();
     assertEquals(10, response.getBucketsNum());
   }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to