/**
ing ok * 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.blur.thrift;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.blur.thirdparty.thrift_0_9_0.TException;
import org.apache.blur.thrift.generated.Blur.Iface;
import org.apache.blur.thrift.generated.BlurException;
import org.apache.blur.thrift.generated.BlurQuery;
import org.apache.blur.thrift.generated.BlurResult;
import org.apache.blur.thrift.generated.BlurResults;
import org.apache.blur.thrift.generated.Column;
import org.apache.blur.thrift.generated.ColumnDefinition;
import org.apache.blur.thrift.generated.FetchResult;
import org.apache.blur.thrift.generated.FetchRowResult;
import org.apache.blur.thrift.generated.Query;
import org.apache.blur.thrift.generated.Record;
import org.apache.blur.thrift.generated.RecordMutation;
import org.apache.blur.thrift.generated.Row;
import org.apache.blur.thrift.generated.RowMutation;
import org.apache.blur.thrift.generated.RowMutationType;
import org.apache.blur.thrift.generated.Selector;
import org.apache.blur.thrift.generated.TableDescriptor;
import org.apache.blur.thrift.util.BlurThriftHelper;
import org.apache.blur.user.User;
import org.apache.blur.user.UserContext;
import org.apache.blur.utils.BlurConstants;
import org.junit.Test;
public class BlurClusterTestSecurity extends BlurClusterTestBase {
private static final String ACL_DISCOVER = "acl-discover";
private static final String TEST = "test";
private static final String ACL_READ = "acl-read";
private static final String DISCOVER = "discover";
private static final String READ = "read";
@Override
protected void setupTableProperties(TableDescriptor tableDescriptor) {
tableDescriptor.putToTableProperties(BlurConstants.BLUR_RECORD_SECURITY, "true");
}
@Override
protected RowMutation mutate(RowMutation rowMutation) {
List<RecordMutation> mutations = rowMutation.getRecordMutations();
for (RecordMutation mutation : mutations) {
Record record = mutation.getRecord();
record.addToColumns(new Column(ACL_READ, READ));
record.addToColumns(new Column(ACL_DISCOVER, DISCOVER));
}
return rowMutation;
}
@Override
protected void postTableCreate(TableDescriptor tableDescriptor, Iface client) {
String name = tableDescriptor.getName();
try {
client.addColumnDefinition(name, new ColumnDefinition(TEST, ACL_READ, null, false, ACL_READ, null, false));
client
.addColumnDefinition(name, new ColumnDefinition(TEST, ACL_DISCOVER, null, false, ACL_DISCOVER, null, false));
} catch (BlurException e) {
throw new RuntimeException(e);
} catch (TException e) {
throw new RuntimeException(e);
}
}
@Override
protected User getUser() {
return new User("testuser", getUserAttributes());
}
@Override
protected Map<String, String> getUserAttributes() {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(BlurConstants.ACL_READ, READ);
attributes.put(BlurConstants.ACL_DISCOVER, DISCOVER);
return attributes;
}
@Test
public void testSecurityMaskReadRowQuery() throws BlurException, TException, IOException {
String tableName = "testSecurity2";
createTable(tableName);
Iface client = getClient();
{
ColumnDefinition columnDefinition = new ColumnDefinition(TEST, "read_mask", null, false, "read-mask", null, false);
columnDefinition.setMultiValueField(false);
client.addColumnDefinition(tableName, columnDefinition);
}
List<RowMutation> batch = new ArrayList<RowMutation>();
for (int i = 0; i < 50; i++) {
List<RecordMutation> recordMutations = getRecordMutations("a");
RowMutation mutation1 = new RowMutation(tableName, getRowId(), RowMutationType.REPLACE_ROW, recordMutations);
addReadMaskColumn(mutation1);
batch.add(mutation1);
}
client.mutateBatch(batch);
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(BlurConstants.ACL_READ, "a");
User user = new User("testuser", attributes);
UserContext.setUser(user);
BlurQuery blurQuery = new BlurQuery();
blurQuery.setSelector(new Selector());
Query query = new Query();
query.setRowQuery(true);
query.setQuery("*");
blurQuery.setQuery(query);
blurQuery.setFetch(100);
BlurResults results = client.query(tableName, blurQuery);
for (BlurResult result : results.getResults()) {
System.out.println(result.getFetchResult().getRowResult().getRow());
}
List<String> terms = client.terms(tableName, TEST, "test2", "", (short) 1000);
assertTrue(terms.isEmpty());
UserContext.reset();
}
private void addReadMaskColumn(RowMutation mutation) {
List<RecordMutation> recordMutations = mutation.getRecordMutations();
for (RecordMutation recordMutation : recordMutations) {
Record record = recordMutation.getRecord();
record.addToColumns(new Column("test2", UUID.randomUUID().toString()));
record.addToColumns(new Column("read_mask", "test2|MASK"));
}
}
@Test
public void testSecurityReadOnlyRowQuery() throws BlurException, TException, IOException {
String tableName = "testSecurity1";
createTable(tableName);
Iface client = getClient();
String bulkId = UUID.randomUUID().toString();
client.bulkMutateStart(bulkId);
for (int i = 0; i < 1000; i++) {
RowMutation mutation1 = new RowMutation(tableName, getRowId(), RowMutationType.REPLACE_ROW, getRecordMutations(
"a", "a&b", "(a&b)|c"));
RowMutation mutation2 = new RowMutation(tableName, getRowId(), RowMutationType.REPLACE_ROW, getRecordMutations(
"b", "b&c", "a|(b&c)"));
RowMutation mutation3 = new RowMutation(tableName, getRowId(), RowMutationType.REPLACE_ROW, getRecordMutations(
"c", "c&a", "(a&c)|b"));
client.bulkMutateAddMultiple(bulkId, Arrays.asList(mutation1, mutation2, mutation3));
}
client.bulkMutateFinish(bulkId, true, true);
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(BlurConstants.ACL_READ, "a");
User user = new User("testuser", attributes);
UserContext.setUser(user);
BlurQuery blurQuery = new BlurQuery();
Query query = new Query();
query.setRowQuery(true);
query.setQuery("test.test:value");
blurQuery.setQuery(query);
blurQuery.setSelector(new Selector());
BlurResults results = client.query(tableName, blurQuery);
assertEquals(2000, results.getTotalResults());
Set<String> aclChecks = new HashSet<String>();
aclChecks.add("a");
aclChecks.add("a|(b&c)");
for (BlurResult result : results.getResults()) {
FetchResult fetchResult = result.getFetchResult();
assertNotNull(fetchResult);
FetchRowResult rowResult = fetchResult.getRowResult();
assertNotNull(rowResult);
Row row = rowResult.getRow();
assertNotNull(row);
List<Record> records = row.getRecords();
assertEquals(1, records.size());
for (Record record : records) {
Column column = findColumn(record, ACL_READ);
String value = column.getValue();
assertTrue(aclChecks.contains(value));
}
}
UserContext.reset();
}
private Column findColumn(Record record, String name) {
for (Column column : record.getColumns()) {
if (column.getName().equals(name)) {
return column;
}
}
return null;
}
private List<RecordMutation> getRecordMutations(String... readAcls) {
List<RecordMutation> recordMutations = new ArrayList<RecordMutation>();
for (int i = 0; i < readAcls.length; i++) {
String recordId = Integer.toString(i);
RecordMutation recordMutation = BlurThriftHelper.newRecordMutation(TEST, recordId,
BlurThriftHelper.newColumn(TEST, "value"), BlurThriftHelper.newColumn(ACL_READ, readAcls[i]));
recordMutations.add(recordMutation);
}
return recordMutations;
}
private String getRowId() {
return UUID.randomUUID().toString();
}
}