You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by ar...@apache.org on 2015/07/07 18:00:01 UTC

hadoop git commit: HDFS-8654. OzoneHandler : Add ACL support. (Contributed by Anu Engineer)

Repository: hadoop
Updated Branches:
  refs/heads/HDFS-7240 6551e11c0 -> 93cebb2e2


HDFS-8654. OzoneHandler : Add ACL support. (Contributed by Anu Engineer)


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

Branch: refs/heads/HDFS-7240
Commit: 93cebb2e286fcb3e2733c4501b64bd3a744d3c43
Parents: 6551e11
Author: Arpit Agarwal <ar...@apache.org>
Authored: Tue Jul 7 08:59:28 2015 -0700
Committer: Arpit Agarwal <ar...@apache.org>
Committed: Tue Jul 7 08:59:28 2015 -0700

----------------------------------------------------------------------
 .../hadoop-hdfs/CHANGES-HDFS-7240.txt           |   2 +
 .../hadoop/ozone/web/request/OzoneAcl.java      | 203 +++++++++++++++++++
 .../hadoop/ozone/web/utils/OzoneConsts.java     |   9 +
 .../apache/hadoop/ozone/web/TestOzoneAcls.java  | 139 +++++++++++++
 4 files changed, 353 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/93cebb2e/hadoop-hdfs-project/hadoop-hdfs/CHANGES-HDFS-7240.txt
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES-HDFS-7240.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES-HDFS-7240.txt
index 123fbc8..bf68394 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES-HDFS-7240.txt
+++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES-HDFS-7240.txt
@@ -26,3 +26,5 @@
     HDFS-8661. DataNode should filter the set of NameSpaceInfos passed to
     Datasets. (Arpit Agarwal)
 
+    HDFS-8654. OzoneHandler : Add ACL support. (Anu Engineer via Arpit Agarwal)
+

http://git-wip-us.apache.org/repos/asf/hadoop/blob/93cebb2e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/request/OzoneAcl.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/request/OzoneAcl.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/request/OzoneAcl.java
new file mode 100644
index 0000000..521c277
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/request/OzoneAcl.java
@@ -0,0 +1,203 @@
+/*
+ * 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.web.request;
+
+import org.apache.hadoop.ozone.web.utils.OzoneConsts;
+
+import java.util.Objects;
+
+/**
+ * OzoneACL classes define bucket ACLs used in OZONE.
+ *
+ * ACLs in Ozone follow this pattern.
+ * • user:name:rw
+ * • group:name:rw
+ * • world::rw
+ */
+public class OzoneAcl {
+  private OzoneACLType type;
+  private String name;
+  private OzoneACLRights rights;
+
+  /**
+   * Constructor for OzoneAcl.
+   *
+   * @param type - Type
+   * @param name - Name of user
+   * @param rights - Rights
+   */
+  public OzoneAcl(OzoneACLType type, String name, OzoneACLRights rights) {
+    this.name = name;
+    this.rights = rights;
+    this.type = type;
+  }
+
+  /**
+   * Parses an ACL string and returns the ACL object.
+   *
+   * @param acl - Acl String , Ex. user:anu:rw
+   *
+   * @return - Ozone ACLs
+   */
+  public static OzoneAcl parseAcl(String acl) throws IllegalArgumentException {
+    if ((acl == null) || acl.isEmpty()) {
+      throw new IllegalArgumentException("ACLs cannot be null or empty");
+    }
+    String[] parts = acl.trim().split(":");
+    if (parts.length < 3) {
+      throw new IllegalArgumentException("ACLs are not in expected format");
+    }
+
+    OzoneACLType aclType = OzoneACLType.valueOf(parts[0].toUpperCase());
+    OzoneACLRights rights = OzoneACLRights.getACLRight(parts[2].toLowerCase());
+
+    if (((aclType == OzoneACLType.USER) || (aclType == OzoneACLType.GROUP))
+        && (parts[1].length() == 0)) {
+      throw new IllegalArgumentException("User or group name is required");
+    }
+
+    if ((aclType == OzoneACLType.WORLD) && (parts[1].length() != 0)) {
+      throw new IllegalArgumentException("Unexpected name part in world type");
+    }
+    // TODO : Support sanitation of these user names by calling into
+    // userAuth Interface.
+    return new OzoneAcl(aclType, parts[1], rights);
+  }
+
+  /**
+   * Returns a hash code value for the object. This method is
+   * supported for the benefit of hash tables.
+   *
+   * @return a hash code value for this object.
+   *
+   * @see Object#equals(Object)
+   * @see System#identityHashCode
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hash(this.getName(), this.getRights().toString(),
+                        this.getType().toString());
+  }
+
+  /**
+   * Returns name.
+   *
+   * @return name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Returns Rights.
+   *
+   * @return - Rights
+   */
+  public OzoneACLRights getRights() {
+    return rights;
+  }
+
+  /**
+   * Returns Type.
+   *
+   * @return type
+   */
+  public OzoneACLType getType() {
+    return type;
+  }
+
+  /**
+   * Indicates whether some other object is "equal to" this one.
+   *
+   * @param obj the reference object with which to compare.
+   *
+   * @return {@code true} if this object is the same as the obj
+   * argument; {@code false} otherwise.
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    OzoneAcl otherAcl = (OzoneAcl) obj;
+    return otherAcl.getName().equals(this.getName()) &&
+        otherAcl.getRights() == this.getRights() &&
+        otherAcl.getType() == this.getType();
+  }
+
+  /**
+   * ACL types.
+   */
+  public enum OzoneACLType {
+    USER(OzoneConsts.OZONE_ACL_USER_TYPE),
+    GROUP(OzoneConsts.OZONE_ACL_GROUP_TYPE),
+    WORLD(OzoneConsts.OZONE_ACL_WORLD_TYPE);
+
+    /**
+     * String value for this Enum.
+     */
+    private final String value;
+
+    /**
+     * Init OzoneACLtypes enum.
+     *
+     * @param val String type for this enum.
+     */
+    OzoneACLType(String val) {
+      value = val;
+    }
+  }
+
+  /**
+   * ACL rights.
+   */
+  public enum OzoneACLRights {
+    READ, WRITE, READ_WRITE;
+
+    /**
+     * Returns the ACL rights based on passed in String.
+     *
+     * @param type ACL right string
+     *
+     * @return OzoneACLRights
+     */
+    public static OzoneACLRights getACLRight(String type) {
+      if (type == null || type.isEmpty()) {
+        throw new IllegalArgumentException("ACL right cannot be empty");
+      }
+
+      switch (type) {
+      case OzoneConsts.OZONE_ACL_READ:
+        return OzoneACLRights.READ;
+      case OzoneConsts.OZONE_ACL_WRITE:
+        return OzoneACLRights.WRITE;
+      case OzoneConsts.OZONE_ACL_READ_WRITE:
+      case OzoneConsts.OZONE_ACL_WRITE_READ:
+        return OzoneACLRights.READ_WRITE;
+      default:
+        throw new IllegalArgumentException("ACL right is not recognized");
+      }
+
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/93cebb2e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneConsts.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneConsts.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneConsts.java
index 56c814e..bdd7b6d 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneConsts.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneConsts.java
@@ -34,6 +34,15 @@ public final class OzoneConsts {
   public static final int OZONE_MIN_BUCKET_NAME_LENGTH = 3;
   public static final int OZONE_MAX_BUCKET_NAME_LENGTH = 63;
 
+  public static final String OZONE_ACL_USER_TYPE = "user";
+  public static final String OZONE_ACL_GROUP_TYPE = "group";
+  public static final String OZONE_ACL_WORLD_TYPE = "world";
+
+  public static final String OZONE_ACL_READ = "r";
+  public static final String OZONE_ACL_WRITE = "w";
+  public static final String OZONE_ACL_READ_WRITE = "rw";
+  public static final String OZONE_ACL_WRITE_READ = "wr";
+
   private OzoneConsts() {
     // Never Constructed
   }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/93cebb2e/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/web/TestOzoneAcls.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/web/TestOzoneAcls.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/web/TestOzoneAcls.java
new file mode 100644
index 0000000..87e0a28
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/web/TestOzoneAcls.java
@@ -0,0 +1,139 @@
+/**
+ * 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.web;
+
+import org.apache.hadoop.ozone.web.request.OzoneAcl;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class TestOzoneAcls {
+
+  @Test
+  public void TestACLParse() {
+    HashMap<String, Boolean> testMatrix;
+    testMatrix = new HashMap<>();
+
+    testMatrix.put("user:bilbo:r", Boolean.TRUE);
+    testMatrix.put("user:bilbo:w", Boolean.TRUE);
+    testMatrix.put("user:bilbo:rw", Boolean.TRUE);
+    testMatrix.put("user:bilbo:wr", Boolean.TRUE);
+    testMatrix.put("    user:bilbo:wr   ", Boolean.TRUE);
+
+
+    // ACLs makes no judgement on the quality of
+    // user names. it is for the userAuth interface
+    // to determine if a user name is really a name
+    testMatrix.put(" user:*:rw", Boolean.TRUE);
+    testMatrix.put(" user:~!:rw", Boolean.TRUE);
+
+
+    testMatrix.put("", Boolean.FALSE);
+    testMatrix.put(null, Boolean.FALSE);
+    testMatrix.put(" user:bilbo:", Boolean.FALSE);
+    testMatrix.put(" user:bilbo:rx", Boolean.FALSE);
+    testMatrix.put(" user:bilbo:mk", Boolean.FALSE);
+    testMatrix.put(" user::rw", Boolean.FALSE);
+    testMatrix.put("user11:bilbo:rw", Boolean.FALSE);
+    testMatrix.put(" user:::rw", Boolean.FALSE);
+
+    testMatrix.put(" group:hobbit:r", Boolean.TRUE);
+    testMatrix.put(" group:hobbit:w", Boolean.TRUE);
+    testMatrix.put(" group:hobbit:rw", Boolean.TRUE);
+    testMatrix.put(" group:hobbit:wr", Boolean.TRUE);
+    testMatrix.put(" group:*:rw", Boolean.TRUE);
+    testMatrix.put(" group:~!:rw", Boolean.TRUE);
+
+    testMatrix.put(" group:hobbit:", Boolean.FALSE);
+    testMatrix.put(" group:hobbit:rx", Boolean.FALSE);
+    testMatrix.put(" group:hobbit:mk", Boolean.FALSE);
+    testMatrix.put(" group::", Boolean.FALSE);
+    testMatrix.put(" group::rw", Boolean.FALSE);
+    testMatrix.put(" group22:hobbit:", Boolean.FALSE);
+    testMatrix.put(" group:::rw", Boolean.FALSE);
+
+    testMatrix.put("JUNK group:hobbit:r", Boolean.FALSE);
+    testMatrix.put("JUNK group:hobbit:w", Boolean.FALSE);
+    testMatrix.put("JUNK group:hobbit:rw", Boolean.FALSE);
+    testMatrix.put("JUNK group:hobbit:wr", Boolean.FALSE);
+    testMatrix.put("JUNK group:*:rw", Boolean.FALSE);
+    testMatrix.put("JUNK group:~!:rw", Boolean.FALSE);
+
+    testMatrix.put(" world::r", Boolean.TRUE);
+    testMatrix.put(" world::w", Boolean.TRUE);
+    testMatrix.put(" world::rw", Boolean.TRUE);
+    testMatrix.put(" world::wr", Boolean.TRUE);
+
+    testMatrix.put(" world:bilbo:w", Boolean.FALSE);
+    testMatrix.put(" world:bilbo:rw", Boolean.FALSE);
+
+    Set<String> keys = testMatrix.keySet();
+    for (String key : keys) {
+      if (testMatrix.get(key)) {
+        OzoneAcl.parseAcl(key);
+      } else {
+        try {
+          OzoneAcl.parseAcl(key);
+          // should never get here since parseAcl will throw
+          fail("An exception was expected but did not happen.");
+        } catch (IllegalArgumentException e) {
+          // nothing to do
+        }
+      }
+    }
+  }
+
+  @Test
+  public void TestACLValues() {
+    OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw");
+    assertEquals(acl.getName(), "bilbo");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.READ_WRITE);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.USER);
+
+    acl = OzoneAcl.parseAcl("user:bilbo:wr");
+    assertEquals(acl.getName(), "bilbo");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.READ_WRITE);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.USER);
+
+    acl = OzoneAcl.parseAcl("user:bilbo:r");
+    assertEquals(acl.getName(), "bilbo");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.READ);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.USER);
+
+    acl = OzoneAcl.parseAcl("user:bilbo:w");
+    assertEquals(acl.getName(), "bilbo");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.WRITE);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.USER);
+
+    acl = OzoneAcl.parseAcl("group:hobbit:wr");
+    assertEquals(acl.getName(), "hobbit");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.READ_WRITE);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.GROUP);
+
+    acl = OzoneAcl.parseAcl("world::wr");
+    assertEquals(acl.getName(), "");
+    assertEquals(acl.getRights(), OzoneAcl.OzoneACLRights.READ_WRITE);
+    assertEquals(acl.getType(), OzoneAcl.OzoneACLType.WORLD);
+  }
+
+}