HDFS-8654. OzoneHandler : Add ACL support. (Contributed by Anu Engineer)
This commit is contained in:
parent
b1fa06aacb
commit
835f872a0a
|
@ -20,3 +20,4 @@
|
|||
HDFS-8644. OzoneHandler : Add volume handler. (Anu Engineer via
|
||||
Arpit Agarwal)
|
||||
|
||||
HDFS-8654. OzoneHandler : Add ACL support. (Anu Engineer via Arpit Agarwal)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue