HBASE-11438 - [Visibility Controller] Support UTF8 character as Visibility
Labels (ram)
This commit is contained in:
parent
c60cfbc999
commit
c1660a7962
|
@ -36,22 +36,11 @@ public class Authorizations {
|
|||
public Authorizations(String... labels) {
|
||||
this.labels = new ArrayList<String>(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<String> labels) {
|
||||
for (String label : labels) {
|
||||
validateLabel(label);
|
||||
}
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.security.visibility;
|
|||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
/**
|
||||
* This contains a visibility expression which can be associated with a cell. When it is set with a
|
||||
|
@ -46,4 +47,40 @@ public class CellVisibility {
|
|||
public String toString() {
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helps in quoting authentication Strings. Use this if unicode characters to
|
||||
* be used in expression or special characters like '(', ')',
|
||||
* '"','\','&','|','!'
|
||||
*/
|
||||
public static String quote(String auth) {
|
||||
return quote(Bytes.toBytes(auth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helps in quoting authentication Strings. Use this if unicode characters to
|
||||
* be used in expression or special characters like '(', ')',
|
||||
* '"','\','&','|','!'
|
||||
*/
|
||||
public static String quote(byte[] auth) {
|
||||
int escapeChars = 0;
|
||||
|
||||
for (int i = 0; i < auth.length; i++)
|
||||
if (auth[i] == '"' || auth[i] == '\\')
|
||||
escapeChars++;
|
||||
|
||||
byte[] escapedAuth = new byte[auth.length + escapeChars + 2];
|
||||
int index = 1;
|
||||
for (int i = 0; i < auth.length; i++) {
|
||||
if (auth[i] == '"' || auth[i] == '\\') {
|
||||
escapedAuth[index++] = '\\';
|
||||
}
|
||||
escapedAuth[index++] = auth[i];
|
||||
}
|
||||
|
||||
escapedAuth[0] = '"';
|
||||
escapedAuth[escapedAuth.length - 1] = '"';
|
||||
|
||||
return Bytes.toString(escapedAuth);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.security.visibility;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
|
@ -60,7 +59,7 @@ public class VisibilityLabelsValidator {
|
|||
return validAuthChars[0xff & b];
|
||||
}
|
||||
|
||||
static final boolean isValidLabel(byte[] label) {
|
||||
public static final boolean isValidLabel(byte[] label) {
|
||||
for (int i = 0; i < label.length; i++) {
|
||||
if (!isValidAuthChar(label[i])) {
|
||||
return false;
|
||||
|
@ -68,9 +67,4 @@ public class VisibilityLabelsValidator {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final boolean isValidLabel(String label) {
|
||||
Matcher matcher = pattern.matcher(label);
|
||||
return matcher.matches();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,56 +114,21 @@ public class TestScan {
|
|||
@Test
|
||||
public void testSetAuthorizations() {
|
||||
Scan scan = new Scan();
|
||||
scan.setAuthorizations(new Authorizations("A", "B", "0123", "A0", "1A1", "_a"));
|
||||
try {
|
||||
scan.setAuthorizations(new Authorizations("\u002b|\u0029"));
|
||||
scan.setAuthorizations(new Authorizations("A", "B", "0123", "A0", "1A1", "_a"));
|
||||
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");
|
||||
fail("should not throw exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,12 +70,11 @@ 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.ByteStringer;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.apache.hadoop.hbase.util.ByteStringer;
|
||||
import com.sun.jersey.api.json.JSONConfiguration;
|
||||
import com.sun.jersey.api.json.JSONJAXBContext;
|
||||
import com.sun.jersey.api.json.JSONMarshaller;
|
||||
|
@ -527,11 +526,6 @@ public class ScannerModel implements ProtobufMessageHandler, Serializable {
|
|||
if (authorizations != null) {
|
||||
List<String> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.security.visibility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
|
@ -35,49 +37,80 @@ public class ExpressionParser {
|
|||
private static final char AND = '&';
|
||||
private static final char NOT = '!';
|
||||
private static final char SPACE = ' ';
|
||||
|
||||
private static final char DOUBLE_QUOTES = '"';
|
||||
public ExpressionNode parse(String expS) throws ParseException {
|
||||
expS = expS.trim();
|
||||
Stack<ExpressionNode> expStack = new Stack<ExpressionNode>();
|
||||
int index = 0;
|
||||
int endPos = expS.length();
|
||||
byte[] exp = Bytes.toBytes(expS);
|
||||
int endPos = exp.length;
|
||||
while (index < endPos) {
|
||||
byte b = exp[index];
|
||||
switch (b) {
|
||||
case OPEN_PARAN:
|
||||
processOpenParan(expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case CLOSE_PARAN:
|
||||
processCloseParan(expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case AND:
|
||||
case OR:
|
||||
processANDorOROp(getOperator(b), expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case NOT:
|
||||
processNOTOp(expStack, expS, index);
|
||||
break;
|
||||
default:
|
||||
int labelOffset = index;
|
||||
do {
|
||||
if (!VisibilityLabelsValidator.isValidAuthChar(exp[index])) {
|
||||
throw new ParseException("Error parsing expression " + expS + " at column : "
|
||||
+ index);
|
||||
case OPEN_PARAN:
|
||||
processOpenParan(expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case CLOSE_PARAN:
|
||||
processCloseParan(expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case AND:
|
||||
case OR:
|
||||
processANDorOROp(getOperator(b), expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
case NOT:
|
||||
processNOTOp(expStack, expS, index);
|
||||
break;
|
||||
case DOUBLE_QUOTES:
|
||||
int labelOffset = ++index;
|
||||
// We have to rewrite the expression within double quotes as incase of expressions
|
||||
// with escape characters we may have to avoid them as the original expression did
|
||||
// not have them
|
||||
List<Byte> list = new ArrayList<Byte>();
|
||||
while (index < endPos && !endDoubleQuotesFound(exp[index])) {
|
||||
if (exp[index] == '\\') {
|
||||
index++;
|
||||
if (exp[index] != '\\' && exp[index] != '"')
|
||||
throw new ParseException("invalid escaping with quotes " + expS + " at column : "
|
||||
+ index);
|
||||
}
|
||||
list.add(exp[index]);
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
} while (index < endPos && !isEndOfLabel(exp[index]));
|
||||
String leafExp = new String(exp, labelOffset, index - labelOffset).trim();
|
||||
if (leafExp.isEmpty()) {
|
||||
throw new ParseException("Error parsing expression " + expS + " at column : " + index);
|
||||
}
|
||||
processLabelExpNode(new LeafExpressionNode(leafExp), expStack, expS, index);
|
||||
// We already crossed the label node index. So need to reduce 1 here.
|
||||
index--;
|
||||
index = skipSpaces(exp, index);
|
||||
// The expression has come to the end. still no double quotes found
|
||||
if(index == endPos) {
|
||||
throw new ParseException("No terminating quotes " + expS + " at column : " + index);
|
||||
}
|
||||
// This could be costly. but do we have any alternative?
|
||||
// If we don't do this way then we may have to handle while checking the authorizations.
|
||||
// Better to do it here.
|
||||
byte[] array = com.google.common.primitives.Bytes.toArray(list);
|
||||
String leafExp = new String(array).trim();
|
||||
if (leafExp.isEmpty()) {
|
||||
throw new ParseException("Error parsing expression " + expS + " at column : " + index);
|
||||
}
|
||||
processLabelExpNode(new LeafExpressionNode(leafExp), expStack, expS, index);
|
||||
index = skipSpaces(exp, index);
|
||||
break;
|
||||
default:
|
||||
labelOffset = index;
|
||||
do {
|
||||
if (!VisibilityLabelsValidator.isValidAuthChar(exp[index])) {
|
||||
throw new ParseException("Error parsing expression "
|
||||
+ expS + " at column : " + index);
|
||||
}
|
||||
index++;
|
||||
} while (index < endPos && !isEndOfLabel(exp[index]));
|
||||
leafExp = new String(exp, labelOffset, index - labelOffset).trim();
|
||||
if (leafExp.isEmpty()) {
|
||||
throw new ParseException("Error parsing expression " + expS + " at column : " + index);
|
||||
}
|
||||
processLabelExpNode(new LeafExpressionNode(leafExp), expStack, expS, index);
|
||||
// We already crossed the label node index. So need to reduce 1 here.
|
||||
index--;
|
||||
index = skipSpaces(exp, index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
@ -255,8 +288,12 @@ public class ExpressionParser {
|
|||
expStack.push(new NonLeafExpressionNode(Operator.NOT));
|
||||
}
|
||||
|
||||
private static boolean endDoubleQuotesFound(byte b) {
|
||||
return (b == DOUBLE_QUOTES);
|
||||
}
|
||||
private static boolean isEndOfLabel(byte b) {
|
||||
return (b == OPEN_PARAN || b == CLOSE_PARAN || b == OR || b == AND || b == NOT || b == SPACE);
|
||||
return (b == OPEN_PARAN || b == CLOSE_PARAN || b == OR || b == AND ||
|
||||
b == NOT || b == SPACE);
|
||||
}
|
||||
|
||||
private static Operator getOperator(byte op) {
|
||||
|
|
|
@ -53,11 +53,11 @@ import org.apache.hadoop.hbase.HTableDescriptor;
|
|||
import org.apache.hadoop.hbase.KeyValue;
|
||||
import org.apache.hadoop.hbase.KeyValue.Type;
|
||||
import org.apache.hadoop.hbase.KeyValueUtil;
|
||||
import org.apache.hadoop.hbase.MetaTableAccessor;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Tag;
|
||||
import org.apache.hadoop.hbase.MetaTableAccessor;
|
||||
import org.apache.hadoop.hbase.client.Append;
|
||||
import org.apache.hadoop.hbase.client.Delete;
|
||||
import org.apache.hadoop.hbase.client.Get;
|
||||
|
@ -1149,13 +1149,6 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb
|
|||
if (table.isSystemTable() && !table.equals(LABELS_TABLE_NAME)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
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.scanLabelGenerators != null) {
|
||||
|
@ -1310,30 +1303,21 @@ public class VisibilityController extends BaseRegionObserver implements MasterOb
|
|||
for (VisibilityLabel visLabel : labels) {
|
||||
byte[] label = visLabel.getLabel().toByteArray();
|
||||
String labelStr = Bytes.toString(label);
|
||||
if (VisibilityLabelsValidator.isValidLabel(label)) {
|
||||
if (this.visibilityManager.getLabelOrdinal(labelStr) > 0) {
|
||||
RegionActionResult.Builder failureResultBuilder = RegionActionResult.newBuilder();
|
||||
failureResultBuilder.setException(ResponseConverter
|
||||
.buildException(new LabelAlreadyExistsException("Label '" + labelStr
|
||||
+ "' already exists")));
|
||||
response.addResult(failureResultBuilder.build());
|
||||
} else {
|
||||
Put p = new Put(Bytes.toBytes(ordinalCounter));
|
||||
p.addImmutable(
|
||||
LABELS_TABLE_FAMILY, LABEL_QUALIFIER, label, LABELS_TABLE_TAGS);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Adding the label "+labelStr);
|
||||
}
|
||||
puts.add(p);
|
||||
ordinalCounter++;
|
||||
response.addResult(successResult);
|
||||
}
|
||||
} else {
|
||||
if (this.visibilityManager.getLabelOrdinal(labelStr) > 0) {
|
||||
RegionActionResult.Builder failureResultBuilder = RegionActionResult.newBuilder();
|
||||
failureResultBuilder.setException(ResponseConverter
|
||||
.buildException(new InvalidLabelException("Invalid visibility label '" + labelStr
|
||||
+ "'")));
|
||||
.buildException(new LabelAlreadyExistsException("Label '" + labelStr
|
||||
+ "' already exists")));
|
||||
response.addResult(failureResultBuilder.build());
|
||||
} else {
|
||||
Put p = new Put(Bytes.toBytes(ordinalCounter));
|
||||
p.addImmutable(LABELS_TABLE_FAMILY, LABEL_QUALIFIER, label, LABELS_TABLE_TAGS);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Adding the label " + labelStr);
|
||||
}
|
||||
puts.add(p);
|
||||
ordinalCounter++;
|
||||
response.addResult(successResult);
|
||||
}
|
||||
}
|
||||
OperationStatus[] opStatus = this.regionEnv.getRegion().batchMutate(
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
*/
|
||||
package org.apache.hadoop.hbase.security.visibility;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.apache.hadoop.hbase.SmallTests;
|
||||
import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode;
|
||||
|
@ -308,6 +308,99 @@ public class TestExpressionParser {
|
|||
executeNegativeCase("! a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonAsciiCases() throws Exception {
|
||||
ExpressionNode node = parser.parse(CellVisibility.quote("\u0027") + "&"
|
||||
+ CellVisibility.quote("\u002b") + "|" + CellVisibility.quote("\u002d") + "&"
|
||||
+ CellVisibility.quote("\u003f"));
|
||||
assertTrue(node instanceof NonLeafExpressionNode);
|
||||
NonLeafExpressionNode nlNode = (NonLeafExpressionNode) node;
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u003f", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.OR, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u002d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u002b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
|
||||
|
||||
node = parser.parse(CellVisibility.quote("\u0027") + "&" + CellVisibility.quote("\u002b") + "|"
|
||||
+ CellVisibility.quote("\u002d") + "&" + CellVisibility.quote("\u003f"));
|
||||
assertTrue(node instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) node;
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u003f", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.OR, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u002d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u002b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCasesSeperatedByDoubleQuotes() throws Exception {
|
||||
ExpressionNode node = null;
|
||||
try {
|
||||
node = parser.parse("\u0027&\"|\u002b&\u003f");
|
||||
fail("Excpetion must be thrown as there are special characters without quotes");
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
node = parser.parse(CellVisibility.quote("\u0027") + "&" + CellVisibility.quote("\"") + "|"
|
||||
+ CellVisibility.quote("\u002b" + "&" + "\u003f"));
|
||||
assertTrue(node instanceof NonLeafExpressionNode);
|
||||
NonLeafExpressionNode nlNode = (NonLeafExpressionNode) node;
|
||||
assertEquals(Operator.OR, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u002b" + "&" + "\u003f",
|
||||
((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\"", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
|
||||
try {
|
||||
node = parser.parse(CellVisibility.quote("\u0027&\\") + "|"
|
||||
+ CellVisibility.quote("\u002b" + "&" + "\\") + CellVisibility.quote("$$\""));
|
||||
fail("Excpetion must be thrown as there is not operator");
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
node = parser.parse(CellVisibility.quote("\u0027" + "&" + "\\") + "|"
|
||||
+ CellVisibility.quote("\u003f" + "&" + "\\") + "&" + CellVisibility.quote("$$\""));
|
||||
assertTrue(node instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) node;
|
||||
assertEquals(Operator.AND, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("$$\"", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
|
||||
nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
|
||||
assertEquals(Operator.OR, nlNode.getOperator());
|
||||
assertEquals(2, nlNode.getChildExps().size());
|
||||
assertEquals("\u0027" + "&" + "\\",
|
||||
((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
|
||||
assertEquals("\u003f" + "&" + "\\",
|
||||
((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
|
||||
try {
|
||||
node = parser.parse(CellVisibility.quote("\u002b&\\") + "|" + CellVisibility.quote("\u0027&\\") + "&"
|
||||
+ "\"$$");
|
||||
fail("Excpetion must be thrown as there is no end quote");
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private void executeNegativeCase(String exp) {
|
||||
try {
|
||||
parser.parse(exp);
|
||||
|
|
|
@ -83,6 +83,12 @@ public class TestVisibilityLabels {
|
|||
private static final String PRIVATE = "private";
|
||||
private static final String CONFIDENTIAL = "confidential";
|
||||
private static final String SECRET = "secret";
|
||||
private static final String COPYRIGHT = "\u00A9ABC";
|
||||
private static final String ACCENT = "\u0941";
|
||||
private static final String UNICODE_VIS_TAG = COPYRIGHT + "\"" + ACCENT + "\\" + SECRET + "\""
|
||||
+ "\u0027&\\";
|
||||
private static final String UC1 = "\u0027\"\u002b";
|
||||
private static final String UC2 = "\u002d\u003f";
|
||||
public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
|
||||
private static final byte[] row1 = Bytes.toBytes("row1");
|
||||
private static final byte[] row2 = Bytes.toBytes("row2");
|
||||
|
@ -154,6 +160,77 @@ public class TestVisibilityLabels {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleVisibilityLabelsWithUniCodeCharacters() throws Exception {
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
HTable table = createTableAndWriteDataWithLabels(tableName,
|
||||
SECRET + "|" + CellVisibility.quote(COPYRIGHT), "(" + CellVisibility.quote(COPYRIGHT) + "&"
|
||||
+ CellVisibility.quote(ACCENT) + ")|" + CONFIDENTIAL,
|
||||
CellVisibility.quote(UNICODE_VIS_TAG) + "&" + SECRET);
|
||||
try {
|
||||
Scan s = new Scan();
|
||||
s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL, PRIVATE, COPYRIGHT, ACCENT,
|
||||
UNICODE_VIS_TAG));
|
||||
ResultScanner scanner = table.getScanner(s);
|
||||
Result[] next = scanner.next(3);
|
||||
assertTrue(next.length == 3);
|
||||
CellScanner cellScanner = next[0].cellScanner();
|
||||
cellScanner.advance();
|
||||
Cell current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row1, 0, row1.length));
|
||||
cellScanner = next[1].cellScanner();
|
||||
cellScanner.advance();
|
||||
current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row2, 0, row2.length));
|
||||
cellScanner = next[2].cellScanner();
|
||||
cellScanner.advance();
|
||||
current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row3, 0, row3.length));
|
||||
} finally {
|
||||
if (table != null) {
|
||||
table.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthorizationsWithSpecialUnicodeCharacters() throws Exception {
|
||||
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
|
||||
HTable table = createTableAndWriteDataWithLabels(tableName,
|
||||
CellVisibility.quote(UC1) + "|" + CellVisibility.quote(UC2), CellVisibility.quote(UC1),
|
||||
CellVisibility.quote(UNICODE_VIS_TAG));
|
||||
try {
|
||||
Scan s = new Scan();
|
||||
s.setAuthorizations(new Authorizations(UC1, UC2, ACCENT,
|
||||
UNICODE_VIS_TAG));
|
||||
ResultScanner scanner = table.getScanner(s);
|
||||
Result[] next = scanner.next(3);
|
||||
assertTrue(next.length == 3);
|
||||
CellScanner cellScanner = next[0].cellScanner();
|
||||
cellScanner.advance();
|
||||
Cell current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row1, 0, row1.length));
|
||||
cellScanner = next[1].cellScanner();
|
||||
cellScanner.advance();
|
||||
current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row2, 0, row2.length));
|
||||
cellScanner = next[2].cellScanner();
|
||||
cellScanner.advance();
|
||||
current = cellScanner.current();
|
||||
assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
|
||||
current.getRowLength(), row3, 0, row3.length));
|
||||
} finally {
|
||||
if (table != null) {
|
||||
table.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisibilityLabelsWithComplexLabels() throws Exception {
|
||||
|
@ -406,7 +483,7 @@ public class TestVisibilityLabels {
|
|||
}
|
||||
}
|
||||
// One label is the "system" label.
|
||||
Assert.assertEquals("The count should be 8", 8, i);
|
||||
Assert.assertEquals("The count should be 13", 13, i);
|
||||
}
|
||||
|
||||
private void waitForLabelsRegionAvailability(HRegionServer regionServer) {
|
||||
|
@ -466,8 +543,7 @@ public class TestVisibilityLabels {
|
|||
assertEquals("org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException",
|
||||
resultList.get(1).getException().getName());
|
||||
assertTrue(resultList.get(2).getException().getValue().isEmpty());
|
||||
assertEquals("org.apache.hadoop.hbase.security.visibility.InvalidLabelException",
|
||||
resultList.get(3).getException().getName());
|
||||
assertTrue(resultList.get(3).getException().getValue().isEmpty());
|
||||
assertTrue(resultList.get(4).getException().getValue().isEmpty());
|
||||
return null;
|
||||
}
|
||||
|
@ -929,7 +1005,8 @@ public class TestVisibilityLabels {
|
|||
PrivilegedExceptionAction<VisibilityLabelsResponse> action =
|
||||
new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
|
||||
public VisibilityLabelsResponse run() throws Exception {
|
||||
String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE };
|
||||
String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE, COPYRIGHT, ACCENT,
|
||||
UNICODE_VIS_TAG, UC1, UC2 };
|
||||
try {
|
||||
VisibilityClient.addLabels(conf, labels);
|
||||
} catch (Throwable t) {
|
||||
|
|
Loading…
Reference in New Issue