diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/Authorizations.java hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/Authorizations.java index ac1ee78..beef1e7 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/Authorizations.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/Authorizations.java @@ -33,15 +33,25 @@ import org.apache.hadoop.classification.InterfaceStability; public class Authorizations { private List labels; - public Authorizations(String... labels) { this.labels = new ArrayList(labels.length); for (String label : labels) { + validateLabel(label); this.labels.add(label); } } + private void validateLabel(String label) { + if (!VisibilityLabelsValidator.isValidLabel(label)) { + throw new IllegalArgumentException("Invalid authorization label : " + label + + ". Authorizations cannot contain '(', ')' ,'&' ,'|', '!'" + " and cannot be empty"); + } + } + public Authorizations(List labels) { + for (String label : labels) { + validateLabel(label); + } this.labels = labels; } diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityLabelsValidator.java hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityLabelsValidator.java index d60c43c..43a927c 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityLabelsValidator.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityLabelsValidator.java @@ -17,6 +17,9 @@ */ package org.apache.hadoop.hbase.security.visibility; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.apache.hadoop.classification.InterfaceAudience; /** @@ -27,6 +30,9 @@ public class VisibilityLabelsValidator { // We follow Accumulo parity for valid visibility labels. private static final boolean[] validAuthChars = new boolean[256]; + public static final String regex = "[A-Za-z_\\-\\:\\/\\.0-9]+"; + public static final Pattern pattern = Pattern.compile(regex); + static { for (int i = 0; i < 256; i++) { validAuthChars[i] = false; @@ -63,4 +69,9 @@ public class VisibilityLabelsValidator { } return true; } + + public static final boolean isValidLabel(String label) { + Matcher matcher = pattern.matcher(label); + return matcher.matches(); + } } diff --git hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java index 9565764..97c5f0f 100644 --- hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java +++ hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java @@ -19,6 +19,8 @@ package org.apache.hadoop.hbase.client; +import static org.junit.Assert.fail; + import java.io.IOException; import java.util.Arrays; import java.util.Set; @@ -26,6 +28,7 @@ import java.util.Set; import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.generated.ClientProtos; +import org.apache.hadoop.hbase.security.visibility.Authorizations; import org.apache.hadoop.hbase.util.Bytes; import org.junit.Assert; import org.junit.Test; @@ -107,5 +110,61 @@ public class TestScan { Set qualifiers = scan.getFamilyMap().get(family); Assert.assertEquals(1, qualifiers.size()); } + + @Test + public void testSetAuthorizations() { + Scan scan = new Scan(); + scan.setAuthorizations(new Authorizations("A", "B", "0123", "A0", "1A1", "_a")); + try { + scan.setAuthorizations(new Authorizations("A|B")); + fail("Should have failed for A|B."); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations("A&B")); + fail("Should have failed for A&B."); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations("!B")); + fail("Should have failed for !B."); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations("A", "(A)")); + fail("Should have failed for (A)."); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations("A", "{A")); + fail("Should have failed for {A."); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations(" ")); + fail("Should have failed for empty"); + } catch (IllegalArgumentException e) { + } + try { + scan.setAuthorizations(new Authorizations(":B")); + } catch (IllegalArgumentException e) { + fail("Should not have failed for :B"); + } + try { + scan.setAuthorizations(new Authorizations("-B")); + } catch (IllegalArgumentException e) { + fail("Should not have failed for -B"); + } + try { + scan.setAuthorizations(new Authorizations(".B")); + } catch (IllegalArgumentException e) { + fail("Should not have failed for .B"); + } + try { + scan.setAuthorizations(new Authorizations("/B")); + } catch (IllegalArgumentException e) { + fail("Should not have failed for /B"); + } + } } diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/rest/model/ScannerModel.java hbase-server/src/main/java/org/apache/hadoop/hbase/rest/model/ScannerModel.java index d0bbbd7..8e0bb73 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/rest/model/ScannerModel.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/rest/model/ScannerModel.java @@ -32,7 +32,6 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import com.google.protobuf.HBaseZeroCopyByteString; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.client.Scan; @@ -71,10 +70,12 @@ import org.apache.hadoop.hbase.filter.WhileMatchFilter; import org.apache.hadoop.hbase.rest.ProtobufMessageHandler; import org.apache.hadoop.hbase.rest.protobuf.generated.ScannerMessage.Scanner; import org.apache.hadoop.hbase.security.visibility.Authorizations; +import org.apache.hadoop.hbase.security.visibility.VisibilityLabelsValidator; import org.apache.hadoop.hbase.util.Base64; import org.apache.hadoop.hbase.util.Bytes; import com.google.protobuf.ByteString; +import com.google.protobuf.HBaseZeroCopyByteString; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.api.json.JSONJAXBContext; import com.sun.jersey.api.json.JSONMarshaller; @@ -525,6 +526,11 @@ public class ScannerModel implements ProtobufMessageHandler, Serializable { if (authorizations != null) { List labels = authorizations.getLabels(); for (String label : labels) { + if (!VisibilityLabelsValidator.isValidLabel(label)) { + throw new IllegalArgumentException("Invalid authorization label : " + label + + ". Authorizations cannot contain '(', ')' ,'&' ,'|', '!'" + " " + + "and cannot be empty"); + } model.addLabel(label); } } diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java index c41d719..85941aa 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java @@ -35,7 +35,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import com.google.protobuf.HBaseZeroCopyByteString; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.classification.InterfaceAudience; @@ -117,6 +116,7 @@ import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; import com.google.protobuf.ByteString; +import com.google.protobuf.HBaseZeroCopyByteString; import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcController; import com.google.protobuf.Service; @@ -980,7 +980,8 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb } } - private Filter createVisibilityLabelFilter(HRegion region, Authorizations authorizations) { + private Filter createVisibilityLabelFilter(HRegion region, Authorizations authorizations) + throws IOException { Map cfVsMaxVersions = new HashMap(); for (HColumnDescriptor hcd : region.getTableDesc().getFamilies()) { cfVsMaxVersions.put(new SimpleByteRange(hcd.getName()), hcd.getMaxVersions()); @@ -996,6 +997,12 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb } return new VisibilityLabelFilter(new BitSet(0), cfVsMaxVersions); } + for (String label : authorizations.getLabels()) { + if (!VisibilityLabelsValidator.isValidLabel(label)) { + throw new IllegalArgumentException("Invalid authorization label : " + label + + ". Authorizations cannot contain '(', ')' ,'&' ,'|', '!'" + " and cannot be empty"); + } + } Filter visibilityLabelFilter = null; if (this.scanLabelGenerator != null) { List labels = null;