You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ct...@apache.org on 2013/12/05 00:58:52 UTC
[11/50] [abbrv] git commit: ACCUMULO-1479 finished initial
implementation of table namespace permissions, including tests
ACCUMULO-1479 finished initial implementation of table namespace permissions, including tests
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/14fb2571
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/14fb2571
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/14fb2571
Branch: refs/heads/master
Commit: 14fb257126810965c637ae234b1ba9623c2b5855
Parents: ad9abf4
Author: Sean Hickey <ta...@gmail.com>
Authored: Fri Aug 2 13:32:42 2013 -0400
Committer: Christopher Tubbs <ct...@apache.org>
Committed: Wed Dec 4 18:46:10 2013 -0500
----------------------------------------------------------------------
.../accumulo/core/client/mock/MockTable.java | 2 +-
.../core/client/mock/MockTableNamespace.java | 4 -
.../core/security/TableNamespacePermission.java | 5 +-
.../apache/accumulo/core/util/shell/Shell.java | 3 +-
.../commands/NamespacePermissionsCommand.java | 44 +++++
.../shell/commands/UserPermissionsCommand.java | 22 +--
.../client/mock/MockTableNamespacesTest.java | 180 ++++++++++++-------
.../server/conf/TableParentConfiguration.java | 41 +++++
.../security/AuditedSecurityOperation.java | 2 +-
.../server/security/SecurityOperation.java | 48 ++++-
.../server/security/handler/ZKPermHandler.java | 19 ++
.../java/org/apache/accumulo/master/Master.java | 30 +++-
.../master/tableOps/CloneTableNamespace.java | 25 ++-
.../master/tableOps/CreateTableNamespace.java | 24 ++-
.../master/tableOps/DeleteTableNamespace.java | 14 +-
.../server/conf/TableParentConfiguration.java | 41 -----
.../org/apache/accumulo/test/ShellServerIT.java | 5 +
.../apache/accumulo/test/TableNamespacesIT.java | 144 ++++++++++++---
18 files changed, 466 insertions(+), 187 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/client/mock/MockTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTable.java b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTable.java
index 0e71414..5c4cb36 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTable.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTable.java
@@ -105,7 +105,7 @@ public class MockTable {
MockTable(MockTableNamespace namespace, boolean limitVersion, TimeType timeType) {
this(limitVersion, timeType);
- Set<Entry<String,String>> set = namespace.getSettings().entrySet();
+ Set<Entry<String,String>> set = namespace.settings.entrySet();
Iterator<Entry<String,String>> entries = set.iterator();
while (entries.hasNext()) {
Entry<String,String> entry = entries.next();
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespace.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespace.java b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespace.java
index beec4db..1798dd1 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespace.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/mock/MockTableNamespace.java
@@ -43,10 +43,6 @@ public class MockTableNamespace {
}
}
- public Map<String,String> getSettings() {
- return settings;
- }
-
public List<String> getTables(MockAccumulo acu) {
List<String> l = new LinkedList<String>();
for (String t : acu.tables.keySet()) {
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/security/TableNamespacePermission.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/security/TableNamespacePermission.java b/core/src/main/java/org/apache/accumulo/core/security/TableNamespacePermission.java
index 565a81a..9354b02 100644
--- a/core/src/main/java/org/apache/accumulo/core/security/TableNamespacePermission.java
+++ b/core/src/main/java/org/apache/accumulo/core/security/TableNamespacePermission.java
@@ -23,12 +23,11 @@ public enum TableNamespacePermission {
// One can add new permissions, with new numbers, but please don't change or use numbers previously assigned
READ((byte) 0),
WRITE((byte) 1),
- ALTER_TABLE_NAMESPACE((byte) 2),
+ ALTER_NAMESPACE((byte) 2),
GRANT((byte) 3),
ALTER_TABLE((byte) 4),
CREATE_TABLE((byte) 5),
- DROP_TABLE((byte) 6),
- BULK_IMPORT((byte) 7);
+ DROP_TABLE((byte) 6);
final private byte permID;
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
index debca0b..c19e84a 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
@@ -122,6 +122,7 @@ import org.apache.accumulo.core.util.shell.commands.ListScansCommand;
import org.apache.accumulo.core.util.shell.commands.ListShellIterCommand;
import org.apache.accumulo.core.util.shell.commands.MaxRowCommand;
import org.apache.accumulo.core.util.shell.commands.MergeCommand;
+import org.apache.accumulo.core.util.shell.commands.NamespacePermissionsCommand;
import org.apache.accumulo.core.util.shell.commands.NamespacesCommand;
import org.apache.accumulo.core.util.shell.commands.NoTableCommand;
import org.apache.accumulo.core.util.shell.commands.OfflineCommand;
@@ -354,7 +355,7 @@ public class Shell extends ShellOptions {
new SetShellIterCommand(), new ListShellIterCommand(), new DeleteShellIterCommand()};
Command[] otherCommands = {new HiddenCommand()};
Command[] permissionsCommands = {new GrantCommand(), new RevokeCommand(), new SystemPermissionsCommand(), new TablePermissionsCommand(),
- new UserPermissionsCommand()};
+ new UserPermissionsCommand(), new NamespacePermissionsCommand()};
Command[] stateCommands = {new AuthenticateCommand(), new ClsCommand(), new ClearCommand(), new FateCommand(), new NoTableCommand(), new SleepCommand(),
new TableCommand(), new UserCommand(), new WhoAmICommand()};
Command[] tableCommands = {new CloneTableCommand(), new ConfigCommand(), new CreateTableCommand(), new DeleteTableCommand(), new DropTableCommand(),
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacePermissionsCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacePermissionsCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacePermissionsCommand.java
new file mode 100644
index 0000000..822522e
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/NamespacePermissionsCommand.java
@@ -0,0 +1,44 @@
+/*
+ * 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.accumulo.core.util.shell.commands;
+
+import java.io.IOException;
+
+import org.apache.accumulo.core.security.TableNamespacePermission;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.apache.accumulo.core.util.shell.Shell.Command;
+import org.apache.commons.cli.CommandLine;
+
+public class NamespacePermissionsCommand extends Command {
+ @Override
+ public int execute(final String fullCommand, final CommandLine cl, final Shell shellState) throws IOException {
+ for (String p : TableNamespacePermission.printableValues()) {
+ shellState.getReader().println(p);
+ }
+ return 0;
+ }
+
+ @Override
+ public String description() {
+ return "displays a list of valid table namespace permissions";
+ }
+
+ @Override
+ public int numArgs() {
+ return 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/main/java/org/apache/accumulo/core/util/shell/commands/UserPermissionsCommand.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/UserPermissionsCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/UserPermissionsCommand.java
index 25d9d54..1b6377a 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/UserPermissionsCommand.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/UserPermissionsCommand.java
@@ -47,34 +47,34 @@ public class UserPermissionsCommand extends Command {
}
shellState.getReader().println();
- for (String t : shellState.getConnector().tableOperations().list()) {
+ for (String n : shellState.getConnector().tableNamespaceOperations().list()) {
delim = "";
- for (TablePermission p : TablePermission.values()) {
- if (shellState.getConnector().securityOperations().hasTablePermission(user, t, p) && p != null) {
+ for (TableNamespacePermission p : TableNamespacePermission.values()) {
+ if (p != null && shellState.getConnector().securityOperations().hasTableNamespacePermission(user, n, p)) {
if (runOnce == 0) {
- shellState.getReader().print("\nTable permissions (" + t + "): ");
+ shellState.getReader().print("\nTable Namespace permissions (" + n + "): ");
runOnce++;
}
- shellState.getReader().print(delim + "Table." + p.name());
+ shellState.getReader().print(delim + "Namespace." + p.name());
delim = ", ";
}
-
}
runOnce = 0;
}
shellState.getReader().println();
- for (String n : shellState.getConnector().tableNamespaceOperations().list()) {
+ for (String t : shellState.getConnector().tableOperations().list()) {
delim = "";
- for (TableNamespacePermission p : TableNamespacePermission.values()) {
- if (p != null && shellState.getConnector().securityOperations().hasTableNamespacePermission(user, n, p)) {
+ for (TablePermission p : TablePermission.values()) {
+ if (shellState.getConnector().securityOperations().hasTablePermission(user, t, p) && p != null) {
if (runOnce == 0) {
- shellState.getReader().print("\nTable Namespace permissions (" + n + "): ");
+ shellState.getReader().print("\nTable permissions (" + t + "): ");
runOnce++;
}
- shellState.getReader().print(delim + "Namespace." + p.name());
+ shellState.getReader().print(delim + "Table." + p.name());
delim = ", ";
}
+
}
runOnce = 0;
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java b/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
index d15b3e5..2ba1006 100644
--- a/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/mock/MockTableNamespacesTest.java
@@ -21,14 +21,29 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Map.Entry;
+import java.util.EnumSet;
+import java.util.HashSet;
import java.util.Random;
import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.BatchWriterConfig;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.client.TableNamespaceNotEmptyException;
+import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
+import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.iterators.Filter;
+import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
+import org.apache.accumulo.core.security.Authorizations;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -54,9 +69,9 @@ public class MockTableNamespacesTest {
}
/**
- * This test creates a new namespace "testing" and a table "testing.table1" which puts "table1" into the "testing" namespace.
- * Then we create "testing.table2" which creates "table2" and puts it into "testing" as well.
- * Then we make sure that you can't delete a namespace with tables in it, and then we delete the tables and delete the namespace.
+ * This test creates a new namespace "testing" and a table "testing.table1" which puts "table1" into the "testing" namespace. Then we create "testing.table2"
+ * which creates "table2" and puts it into "testing" as well. Then we make sure that you can't delete a namespace with tables in it, and then we delete the
+ * tables and delete the namespace.
*
* @throws Exception
*/
@@ -93,7 +108,7 @@ public class MockTableNamespacesTest {
c.tableOperations().delete(tableName2);
assertTrue(!c.tableOperations().exists(tableName2));
assertTrue(c.tableNamespaceOperations().exists(namespace));
-
+
c.tableOperations().delete(tableName1);
assertTrue(!c.tableOperations().exists(tableName1));
c.tableNamespaceOperations().delete(namespace);
@@ -128,37 +143,15 @@ public class MockTableNamespacesTest {
c.tableNamespaceOperations().setProperty(namespace, propKey, propVal);
// check the namespace has the property
- boolean itWorked = false;
- for (Entry<String,String> prop : c.tableNamespaceOperations().getProperties(namespace)) {
- if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
- itWorked = true;
- break;
- }
- }
-
- assertTrue(itWorked);
+ assertTrue(checkTableNamespaceHasProp(c, namespace, propKey, propVal));
// check that the table gets it from the namespace
- itWorked = false;
- for (Entry<String,String> prop : c.tableOperations().getProperties(tableName1)) {
- if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
- itWorked = true;
- break;
- }
- }
- assertTrue(itWorked);
+ assertTrue(checkTableHasProp(c, tableName1, propKey, propVal));
// test a second table to be sure the first wasn't magical
- // (also, changed the order, the namespace already exists with the property)
- itWorked = false;
+ // (also, changed the order, the namespace has the property already)
c.tableOperations().create(tableName2);
- for (Entry<String,String> prop : c.tableOperations().getProperties(tableName2)) {
- if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
- itWorked = true;
- break;
- }
- }
- assertTrue(itWorked);
+ assertTrue(checkTableHasProp(c, tableName2, propKey, propVal));
// test that table properties override namespace properties
String propKey2 = Property.TABLE_FILE_MAX.getKey();
@@ -168,47 +161,38 @@ public class MockTableNamespacesTest {
c.tableOperations().setProperty(tableName2, propKey2, tablePropVal);
c.tableNamespaceOperations().setProperty("propchange", propKey2, propVal2);
- itWorked = false;
- for (Entry<String,String> prop : c.tableOperations().getProperties(tableName2)) {
- if (prop.getKey().equals(propKey2) && prop.getValue().equals(tablePropVal)) {
- itWorked = true;
- break;
- }
- }
- assertTrue(itWorked);
+ assertTrue(checkTableHasProp(c, tableName2, propKey2, tablePropVal));
// now check that you can change the default namespace's properties
propVal = "13K";
- propVal2 = "44";
String tableName = "some_table";
c.tableOperations().create(tableName);
c.tableNamespaceOperations().setProperty(Constants.DEFAULT_TABLE_NAMESPACE, propKey, propVal);
- itWorked = false;
- for (Entry<String,String> prop : c.tableOperations().getProperties(tableName)) {
- if (prop.getKey().equals(propKey) && prop.getValue().equals(propVal)) {
- itWorked = true;
- break;
- }
- }
- assertTrue(itWorked);
- }
-
- /**
- * This test creates a new user and a namespace. It checks to make sure the user can't modify anything in the namespace at first, then it grants the user
- * permissions and makes sure that they can modify the namespace. Then it also checks if the user has the correct permissions on tables both already existing
- * in the namespace and ones they create.
- *
- * @throws Exception
- */
- @Test
- public void testNamespacePermissions() throws Exception {
- // TODO make the test once namespace-level permissions are implemented. (ACCUMULO-1479)
+ assertTrue(checkTableHasProp(c, tableName, propKey, propVal));
+
+ // test the properties server-side by configuring an iterator.
+ // should not show anything with column-family = 'a'
+ String tableName3 = namespace + ".table3";
+ c.tableOperations().create(tableName3);
+
+ IteratorSetting setting = new IteratorSetting(250, "thing", SimpleFilter.class.getName());
+ c.tableNamespaceOperations().attachIterator(namespace, setting);
+
+ BatchWriter bw = c.createBatchWriter(tableName3, new BatchWriterConfig());
+ Mutation m = new Mutation("r");
+ m.put("a", "b", new Value("abcde".getBytes()));
+ bw.addMutation(m);
+ bw.flush();
+ bw.close();
+
+ // Scanner s = c.createScanner(tableName3, Authorizations.EMPTY);
+ // do scanners work correctly in mock?
+ // assertTrue(!s.iterator().hasNext());
}
/**
- * This test renames and clones two separate table into different namespaces.
- * different namespace.
+ * This test renames and clones two separate table into different namespaces. different namespace.
*
* @throws Exception
*/
@@ -218,11 +202,11 @@ public class MockTableNamespacesTest {
String namespace2 = "cloned";
String tableName = "table";
String tableName1 = "renamed.table1";
- //String tableName2 = "cloned.table2";
+ // String tableName2 = "cloned.table2";
Instance instance = new MockInstance("renameclone");
Connector c = instance.getConnector("user", new PasswordToken("pass"));
-
+
c.tableOperations().create(tableName);
c.tableNamespaceOperations().create(namespace1);
c.tableNamespaceOperations().create(namespace2);
@@ -233,10 +217,11 @@ public class MockTableNamespacesTest {
assertTrue(!c.tableOperations().exists(tableName));
// TODO implement clone in mock
- /*c.tableOperations().clone(tableName1, tableName2, false, null, null);
-
- assertTrue(c.tableOperations().exists(tableName1));
- assertTrue(c.tableOperations().exists(tableName2));*/
+ /*
+ * c.tableOperations().clone(tableName1, tableName2, false, null, null);
+ *
+ * assertTrue(c.tableOperations().exists(tableName1)); assertTrue(c.tableOperations().exists(tableName2));
+ */
return;
}
@@ -262,4 +247,65 @@ public class MockTableNamespacesTest {
assertTrue(!c.tableOperations().exists(namespace1 + "." + table));
assertTrue(c.tableOperations().exists(namespace2 + "." + table));
}
+
+ /**
+ * This tests adding iterators to a namespace, listing them, and removing them
+ */
+ @Test
+ public void testNamespaceIterators() throws Exception {
+ Instance instance = new MockInstance("Iterators");
+ Connector c = instance.getConnector("user", new PasswordToken("pass"));
+
+ String namespace = "iterator";
+ String tableName = namespace + ".table";
+ String iter = "thing";
+
+ c.tableNamespaceOperations().create(namespace);
+ c.tableOperations().create(tableName);
+
+ IteratorSetting setting = new IteratorSetting(250, iter, SimpleFilter.class.getName());
+ HashSet<IteratorScope> scope = new HashSet<IteratorScope>();
+ scope.add(IteratorScope.scan);
+ c.tableNamespaceOperations().attachIterator(namespace, setting, EnumSet.copyOf(scope));
+
+ BatchWriter bw = c.createBatchWriter(tableName, new BatchWriterConfig());
+ Mutation m = new Mutation("r");
+ m.put("a", "b", new Value("abcde".getBytes(Constants.UTF8)));
+ bw.addMutation(m);
+ bw.flush();
+
+ Scanner s = c.createScanner(tableName, Authorizations.EMPTY);
+ System.out.println(s.iterator().next());
+ // do scanners work correctly in mock?
+ // assertTrue(!s.iterator().hasNext());
+
+ assertTrue(c.tableNamespaceOperations().listIterators(namespace).containsKey(iter));
+ c.tableNamespaceOperations().removeIterator(namespace, iter, EnumSet.copyOf(scope));
+ }
+
+ private boolean checkTableHasProp(Connector c, String t, String propKey, String propVal) throws AccumuloException, TableNotFoundException {
+ for (Entry<String,String> e : c.tableOperations().getProperties(t)) {
+ if (e.getKey().equals(propKey) && e.getValue().equals(propVal)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkTableNamespaceHasProp(Connector c, String n, String propKey, String propVal) throws AccumuloException, TableNamespaceNotFoundException {
+ for (Entry<String,String> e : c.tableNamespaceOperations().getProperties(n)) {
+ if (e.getKey().equals(propKey) && e.getValue().equals(propVal)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static class SimpleFilter extends Filter {
+ public boolean accept(Key k, Value v) {
+ if (k.getColumnFamily().toString().equals("a"))
+ return false;
+ return true;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/base/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java b/server/base/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
new file mode 100644
index 0000000..7590d76
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * 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.accumulo.server.conf;
+
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+
+
+/**
+ * Used by TableConfiguration to dynamically get the TableNamespaceConfiguration if the namespace changes
+ */
+public class TableParentConfiguration extends TableNamespaceConfiguration {
+
+ private String tableId;
+
+ public TableParentConfiguration(String tableId, AccumuloConfiguration parent) {
+ super(null, parent);
+ this.tableId = tableId;
+ this.namespaceId = getNamespaceId();
+ }
+
+ @Override
+ protected String getNamespaceId() {
+ this.namespaceId = Tables.getNamespace(inst, tableId);
+ return this.namespaceId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/base/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java b/server/base/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java
index 7148556..7ec9fd2 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/security/AuditedSecurityOperation.java
@@ -235,7 +235,7 @@ public class AuditedSecurityOperation extends SecurityOperation {
@Override
public boolean canCreateTable(TCredentials c, String tableName) throws ThriftSecurityException {
try {
- boolean result = super.canCreateTable(c);
+ boolean result = super.canCreateTable(c, tableName);
audit(c, result, CAN_CREATE_TABLE_AUDIT_TEMPLATE, tableName);
return result;
} catch (ThriftSecurityException ex) {
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/base/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java b/server/base/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java
index 6dcaf9d..7e7dde9 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/security/SecurityOperation.java
@@ -343,7 +343,7 @@ public class SecurityOperation {
String namespace = TableNamespaces.getNamespaceId(HdfsZooInstance.getInstance(), tableNamespace);
return hasTableNamespacePermission(credentials, namespace, permission, useCached);
} catch (TableNamespaceNotFoundException e) {
- return false;
+ throw new ThriftSecurityException(credentials.getPrincipal(), SecurityErrorCode.TABLE_NAMESPACE_DOESNT_EXIST);
}
}
@@ -451,7 +451,8 @@ public class SecurityOperation {
}
public boolean canCreateTable(TCredentials c, String tableName) throws ThriftSecurityException {
- return canCreateTable(c) || hasTableNamespacePermissionForTableName(c, tableName, TableNamespacePermission.CREATE_TABLE, false);
+ authenticate(c);
+ return hasTableNamespacePermissionForTableName(c, tableName, TableNamespacePermission.CREATE_TABLE, false) || canCreateTable(c);
}
public boolean canCreateTable(TCredentials c) throws ThriftSecurityException {
@@ -469,7 +470,8 @@ public class SecurityOperation {
authenticate(c);
return (hasSystemPermission(c, SystemPermission.CREATE_TABLE, false) || hasTableNamespacePermissionForTableName(c, tableName,
TableNamespacePermission.CREATE_TABLE, false))
- && (hasTablePermission(c, tableId, TablePermission.READ, false) || hasTableNamespacePermissionForTableId(c, tableId, TableNamespacePermission.READ, false));
+ && (hasTablePermission(c, tableId, TablePermission.READ, false) || hasTableNamespacePermissionForTableId(c, tableId, TableNamespacePermission.READ,
+ false));
}
public boolean canDeleteTable(TCredentials c, String tableId) throws ThriftSecurityException {
@@ -504,8 +506,7 @@ public class SecurityOperation {
public boolean canBulkImport(TCredentials c, String tableId) throws ThriftSecurityException {
authenticate(c);
- return hasTablePermission(c, tableId, TablePermission.BULK_IMPORT, false)
- || hasTableNamespacePermissionForTableId(c, tableId, TableNamespacePermission.BULK_IMPORT, false);
+ return hasTablePermission(c, tableId, TablePermission.BULK_IMPORT, false);
}
public boolean canCompact(TCredentials c, String tableId) throws ThriftSecurityException {
@@ -579,7 +580,7 @@ public class SecurityOperation {
public boolean canRevokeTableNamespace(TCredentials c, String user, String tableNamespace) throws ThriftSecurityException {
authenticate(c);
- return hasSystemPermission(c, SystemPermission.ALTER_NAMESPACE, false) || hasTablePermission(c, tableNamespace, TablePermission.GRANT, false);
+ return hasSystemPermission(c, SystemPermission.ALTER_NAMESPACE, false) || hasTableNamespacePermission(c, tableNamespace, TableNamespacePermission.GRANT, false);
}
public void changeAuthorizations(TCredentials credentials, String user, Authorizations authorizations) throws ThriftSecurityException {
@@ -778,7 +779,7 @@ public class SecurityOperation {
}
public void deleteTableNamespace(TCredentials credentials, String tableNamespace) throws ThriftSecurityException {
- if (!canDeleteTable(credentials, tableNamespace))
+ if (!canDeleteNamespace(credentials, tableNamespace))
throw new ThriftSecurityException(credentials.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
try {
permHandle.cleanTableNamespacePermissions(tableNamespace);
@@ -801,4 +802,37 @@ public class SecurityOperation {
return hasSystemPermission(credentials, SystemPermission.CREATE_TABLE, false)
|| hasTableNamespacePermissionForTableName(credentials, tableName, TableNamespacePermission.CREATE_TABLE, false);
}
+
+ public boolean canAlterNamespace(TCredentials credentials, String namespaceId) throws ThriftSecurityException {
+ authenticate(credentials);
+ return hasTableNamespacePermission(credentials, namespaceId, TableNamespacePermission.ALTER_NAMESPACE, false)
+ || hasSystemPermission(credentials, SystemPermission.ALTER_NAMESPACE, false);
+ }
+
+ public boolean canCreateNamespace(TCredentials credentials, String namespace) throws ThriftSecurityException {
+ authenticate(credentials);
+ return canCreateNamespace(credentials);
+ }
+
+ public boolean canCreateNamespace(TCredentials credentials) throws ThriftSecurityException {
+ authenticate(credentials);
+ return hasSystemPermission(credentials, SystemPermission.CREATE_NAMESPACE, false);
+ }
+
+ public boolean canDeleteNamespace(TCredentials credentials, String namespaceId) throws ThriftSecurityException {
+ authenticate(credentials);
+ return hasSystemPermission(credentials, SystemPermission.DROP_NAMESPACE, false);
+ }
+
+ public boolean canRenameNamespace(TCredentials credentials, String namespaceId, String oldName, String newName) throws ThriftSecurityException {
+ authenticate(credentials);
+ return hasTableNamespacePermission(credentials, namespaceId, TableNamespacePermission.ALTER_NAMESPACE, false)
+ || hasSystemPermission(credentials, SystemPermission.ALTER_NAMESPACE, false);
+ }
+
+ public boolean canCloneNamespace(TCredentials credentials, String namespaceId, String namespace) throws ThriftSecurityException {
+ authenticate(credentials);
+ return hasTableNamespacePermission(credentials, namespaceId, TableNamespacePermission.READ, false)
+ && hasSystemPermission(credentials, SystemPermission.CREATE_NAMESPACE, false);
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/base/src/main/java/org/apache/accumulo/server/security/handler/ZKPermHandler.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/security/handler/ZKPermHandler.java b/server/base/src/main/java/org/apache/accumulo/server/security/handler/ZKPermHandler.java
index 78b79a1..6f6304a 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/security/handler/ZKPermHandler.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/security/handler/ZKPermHandler.java
@@ -23,6 +23,7 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
+import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.TableNamespaceNotFoundException;
import org.apache.accumulo.core.client.TableNotFoundException;
@@ -382,6 +383,10 @@ public class ZKPermHandler implements PermissionHandler {
// Allow the root user to flush the system tables
tablePerms.put(RootTable.ID, Collections.singleton(TablePermission.ALTER_TABLE));
tablePerms.put(MetadataTable.ID, Collections.singleton(TablePermission.ALTER_TABLE));
+ // essentially the same but on the system namespace, the ALTER_TABLE permission is now redundant
+ Map<String,Set<TableNamespacePermission>> tableNamespacePerms = new HashMap<String,Set<TableNamespacePermission>>();
+ tableNamespacePerms.put(Constants.SYSTEM_TABLE_NAMESPACE_ID, Collections.singleton(TableNamespacePermission.ALTER_NAMESPACE));
+ tableNamespacePerms.put(Constants.SYSTEM_TABLE_NAMESPACE_ID, Collections.singleton(TableNamespacePermission.ALTER_TABLE));
try {
// prep parent node of users with root username
@@ -392,6 +397,8 @@ public class ZKPermHandler implements PermissionHandler {
zoo.putPersistentData(ZKUserPath + "/" + rootuser + ZKUserSysPerms, ZKSecurityTool.convertSystemPermissions(rootPerms), NodeExistsPolicy.FAIL);
for (Entry<String,Set<TablePermission>> entry : tablePerms.entrySet())
createTablePerm(rootuser, entry.getKey(), entry.getValue());
+ for (Entry<String,Set<TableNamespacePermission>> entry : tableNamespacePerms.entrySet())
+ createTableNamespacePerm(rootuser, entry.getKey(), entry.getValue());
} catch (KeeperException e) {
log.error(e, e);
throw new RuntimeException(e);
@@ -432,6 +439,17 @@ public class ZKPermHandler implements PermissionHandler {
}
}
+ /**
+ * Sets up a new table namespace configuration for the provided user/table. No checking for existence is done here, it should be done before calling.
+ */
+ private void createTableNamespacePerm(String user, String namespace, Set<TableNamespacePermission> perms) throws KeeperException, InterruptedException {
+ synchronized (zooCache) {
+ zooCache.clear();
+ ZooReaderWriter.getRetryingInstance().putPersistentData(ZKUserPath + "/" + user + ZKUserNamespacePerms + "/" + namespace,
+ ZKSecurityTool.convertTableNamespacePermissions(perms), NodeExistsPolicy.FAIL);
+ }
+ }
+
@Override
public void cleanUser(String user) throws AccumuloSecurityException {
try {
@@ -439,6 +457,7 @@ public class ZKPermHandler implements PermissionHandler {
IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
zoo.recursiveDelete(ZKUserPath + "/" + user + ZKUserSysPerms, NodeMissingPolicy.SKIP);
zoo.recursiveDelete(ZKUserPath + "/" + user + ZKUserTablePerms, NodeMissingPolicy.SKIP);
+ zoo.recursiveDelete(ZKUserPath + "/" + user + ZKUserNamespacePerms, NodeMissingPolicy.SKIP);
zooCache.clear(ZKUserPath + "/" + user);
}
} catch (InterruptedException e) {
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/master/src/main/java/org/apache/accumulo/master/Master.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/Master.java b/server/master/src/main/java/org/apache/accumulo/master/Master.java
index d3f22e6..293dbc9 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/Master.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/Master.java
@@ -43,9 +43,9 @@ import org.apache.accumulo.core.client.IteratorSetting;
import org.apache.accumulo.core.client.RowIterator;
import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.admin.TableOperationsImpl;
import org.apache.accumulo.core.client.admin.TimeType;
import org.apache.accumulo.core.client.impl.TableNamespaces;
-import org.apache.accumulo.core.client.admin.TableOperationsImpl;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.client.impl.ThriftTransportPool;
import org.apache.accumulo.core.client.impl.thrift.SecurityErrorCode;
@@ -743,14 +743,22 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
throws ThriftSecurityException, ThriftTableOperationException {
String namespaceId = null;
+ namespaceId = checkNamespaceId(namespace, op);
+
+ if (!security.canAlterNamespace(c, namespaceId))
+ throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
+
try {
- namespaceId = TableNamespaces.getNamespaceId(instance, namespace);
- // TODO insert a permission check here once namespace-level permissions exist. (ACCUMULO-1479)
if (value == null) {
NamespacePropUtil.removeNamespaceProperty(namespaceId, property);
} else {
NamespacePropUtil.setNamespaceProperty(namespaceId, property, value);
}
+ } catch (KeeperException.NoNodeException e) {
+ // race condition... table namespace no longer exists? This call will throw an exception if the table namespace was deleted:
+ checkNamespaceId(namespaceId, op);
+ log.info("Error altering table namespace property", e);
+ throw new ThriftTableOperationException(namespaceId, namespace, op, TableOperationExceptionType.OTHER, "Problem altering table namespaceproperty");
} catch (Exception e) {
log.error("Problem altering table namespace property", e);
throw new ThriftTableOperationException(namespaceId, namespace, op, TableOperationExceptionType.OTHER, "Problem altering table namespace property");
@@ -1125,7 +1133,9 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
switch (op) {
case CREATE: {
String namespace = ByteBufferUtil.toString(arguments.get(0));
- // TODO security check once namespace permissions exist (ACCUMULO-1479)
+ if (!security.canCreateNamespace(c, namespace))
+ throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
+
checkNotSystemNamespace(namespace, TableOperation.CREATE);
checkTableNamespaceName(namespace, TableOperation.CREATE);
fate.seedTransaction(opid, new TraceRepo<Master>(new CreateTableNamespace(c.getPrincipal(), namespace, options)), autoCleanup);
@@ -1135,11 +1145,14 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
String oldName = ByteBufferUtil.toString(arguments.get(0));
String newName = ByteBufferUtil.toString(arguments.get(1));
- // TODO security check (ACCUMULO-1479)
String namespaceId = checkNamespaceId(oldName, TableOperation.RENAME);
+
checkNotSystemNamespace(oldName, TableOperation.RENAME);
checkNotSystemNamespace(newName, TableOperation.RENAME);
checkTableNamespaceName(newName, TableOperation.RENAME);
+ if (!security.canRenameNamespace(c, namespaceId, oldName, newName))
+ throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
+
fate.seedTransaction(opid, new TraceRepo<Master>(new RenameTableNamespace(namespaceId, oldName, newName)), autoCleanup);
break;
}
@@ -1147,7 +1160,9 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
String namespace = ByteBufferUtil.toString(arguments.get(0));
checkNotSystemNamespace(namespace, TableOperation.DELETE);
String namespaceId = checkNamespaceId(namespace, TableOperation.DELETE);
- // TODO security check (ACCUMULO-1479)
+ if (!security.canDeleteNamespace(c, namespaceId))
+ throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
+
fate.seedTransaction(opid, new TraceRepo<Master>(new DeleteTableNamespace(namespaceId)), autoCleanup);
break;
}
@@ -1156,7 +1171,8 @@ public class Master implements LiveTServerSet.Listener, TableObserver, CurrentSt
String namespace = ByteBufferUtil.toString(arguments.get(1));
checkNotSystemNamespace(namespace, TableOperation.CLONE);
checkTableNamespaceName(namespace, TableOperation.CLONE);
- // TODO security check (ACCUMULO-1479)
+ if (!security.canCloneNamespace(c, namespaceId, namespace))
+ throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
Map<String,String> propertiesToSet = new HashMap<String,String>();
Set<String> propertiesToExclude = new HashSet<String>();
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTableNamespace.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTableNamespace.java
index 9b661f2..ffa1448 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTableNamespace.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CloneTableNamespace.java
@@ -23,10 +23,14 @@ import java.util.Set;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.client.impl.thrift.TableOperation;
+import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
+import org.apache.accumulo.core.security.TableNamespacePermission;
import org.apache.accumulo.fate.Repo;
import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
import org.apache.accumulo.master.Master;
import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.security.AuditedSecurityOperation;
+import org.apache.accumulo.server.security.SystemCredentials;
import org.apache.accumulo.server.tables.TableManager;
import org.apache.log4j.Logger;
@@ -134,15 +138,18 @@ class CloneNamespacePermissions extends MasterRepo {
@Override
public Repo<Master> call(long tid, Master environment) throws Exception {
- // TODO add table namespace permissions (ACCUMULO-1479)
- // give all table permissions to the creator
- /*
- * for (TablePermission permission : TablePermission.values()) { try {
- * AuditedSecurityOperation.getInstance().grantTablePermission(SecurityConstants.getSystemCredentials(), cloneInfo.user, cloneInfo.newId, permission); }
- * catch (ThriftSecurityException e) { Logger.getLogger(FinishCloneTableNamespace.class).error(e.getMessage(), e); throw e; } }
- */
-
- // setup permissions in zookeeper before table info in zookeeper
+ // give all table namespace permissions to the creator
+ for (TableNamespacePermission permission : TableNamespacePermission.values()) {
+ try {
+ AuditedSecurityOperation.getInstance().grantTableNamespacePermission(SystemCredentials.get().toThrift(environment.getInstance()), cloneInfo.user,
+ cloneInfo.newId, permission);
+ } catch (ThriftSecurityException e) {
+ Logger.getLogger(FinishCloneTableNamespace.class).error(e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ // setup permissions in zookeeper before table namespace info in zookeeper
// this way concurrent users will not get a spurious pemission denied
// error
return new CloneNamespaceZookeeper(cloneInfo);
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
index d6c6fc4..247ae56 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CreateTableNamespace.java
@@ -23,9 +23,14 @@ import java.util.Map.Entry;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.client.impl.thrift.TableOperation;
+import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
+import org.apache.accumulo.core.security.TableNamespacePermission;
import org.apache.accumulo.fate.Repo;
import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.security.AuditedSecurityOperation;
+import org.apache.accumulo.server.security.SecurityOperation;
+import org.apache.accumulo.server.security.SystemCredentials;
import org.apache.accumulo.server.tables.TableManager;
import org.apache.accumulo.server.util.NamespacePropUtil;
import org.apache.log4j.Logger;
@@ -135,14 +140,17 @@ class SetupNamespacePermissions extends MasterRepo {
@Override
public Repo<Master> call(long tid, Master env) throws Exception {
- // TODO implement once namespace permissions exist (ACCUMULO-1479)
-
- // give all table permissions to the creator
- /*
- * SecurityOperation security = AuditedSecurityOperation.getInstance(); for (TableNamespacePermission permission : TableNamespacePermission.values()) { try
- * { security.grantTableNamespacePermission(SecurityConstants.getSystemCredentials(), tableNamespaceInfo.user, tableNamespaceInfo.tableId, permission); }
- * catch (ThriftSecurityException e) { Logger.getLogger(FinishCreateTableNamespace.class).error(e.getMessage(), e); throw e; } }
- */
+ // give all table namespace permissions to the creator
+ SecurityOperation security = AuditedSecurityOperation.getInstance();
+ for (TableNamespacePermission permission : TableNamespacePermission.values()) {
+ try {
+ security.grantTableNamespacePermission(SystemCredentials.get().toThrift(env.getInstance()), tableNamespaceInfo.user, tableNamespaceInfo.namespaceId,
+ permission);
+ } catch (ThriftSecurityException e) {
+ Logger.getLogger(FinishCreateTableNamespace.class).error(e.getMessage(), e);
+ throw e;
+ }
+ }
// setup permissions in zookeeper before table info in zookeeper
// this way concurrent users will not get a spurious permission denied
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
index 5013a2f..bd8e5c3 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/DeleteTableNamespace.java
@@ -18,8 +18,11 @@ package org.apache.accumulo.master.tableOps;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.client.impl.thrift.TableOperation;
+import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
import org.apache.accumulo.fate.Repo;
import org.apache.accumulo.master.Master;
+import org.apache.accumulo.server.security.AuditedSecurityOperation;
+import org.apache.accumulo.server.security.SystemCredentials;
import org.apache.accumulo.server.tables.TableManager;
import org.apache.log4j.Logger;
@@ -51,11 +54,12 @@ class NamespaceCleanUp extends MasterRepo {
}
Tables.clearCache(master.getInstance());
- // TODO remove any permissions associated with this once they exist (ACCUMULO-1479)
- /*
- * try { AuditedSecurityOperation.getInstance().deleteTable(SecurityConstants.getSystemCredentials(), namespaceName); } catch (ThriftSecurityException e) {
- * log.error(e.getMessage(), e); }
- */
+ // remove any permissions associated with this table namespace
+ try {
+ AuditedSecurityOperation.getInstance().deleteTableNamespace(SystemCredentials.get().toThrift(master.getInstance()), namespaceId);
+ } catch (ThriftSecurityException e) {
+ log.error(e.getMessage(), e);
+ }
Utils.unreserveTableNamespace(namespaceId, id, true);
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/server/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java b/server/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
deleted file mode 100644
index 7590d76..0000000
--- a/server/src/main/java/org/apache/accumulo/server/conf/TableParentConfiguration.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.accumulo.server.conf;
-
-import org.apache.accumulo.core.client.impl.Tables;
-import org.apache.accumulo.core.conf.AccumuloConfiguration;
-
-
-/**
- * Used by TableConfiguration to dynamically get the TableNamespaceConfiguration if the namespace changes
- */
-public class TableParentConfiguration extends TableNamespaceConfiguration {
-
- private String tableId;
-
- public TableParentConfiguration(String tableId, AccumuloConfiguration parent) {
- super(null, parent);
- this.tableId = tableId;
- this.namespaceId = getNamespaceId();
- }
-
- @Override
- protected String getNamespaceId() {
- this.namespaceId = Tables.getNamespace(inst, tableId);
- return this.namespaceId;
- }
-}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java b/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
index 663fa44..792ba3e 100644
--- a/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
+++ b/test/src/test/java/org/apache/accumulo/test/ShellServerIT.java
@@ -873,6 +873,11 @@ public class ShellServerIT extends SimpleMacIT {
exec("setiter -tn thing2 -scan -class org.apache.accumulo.core.iterators.user.SummingCombiner -p 10 -n name", true);
exec("listiter -tn thing2 -scan", true, "Summing", true);
exec("deleteiter -tn thing2 -n name -scan", true);
+ exec("createuser dude");
+ exec("pass");
+ exec("pass");
+ exec("grant Namespace.CREATE_TABLE -tn thing2 -u dude", true);
+ exec("revoke Namespace.CREATE_TABLE -tn thing2 -u dude", true);
// properties override and such
exec("config -tn thing2 -s table.file.max=44444", true);
http://git-wip-us.apache.org/repos/asf/accumulo/blob/14fb2571/test/src/test/java/org/apache/accumulo/test/TableNamespacesIT.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/TableNamespacesIT.java b/test/src/test/java/org/apache/accumulo/test/TableNamespacesIT.java
index b779152..1a52f72 100644
--- a/test/src/test/java/org/apache/accumulo/test/TableNamespacesIT.java
+++ b/test/src/test/java/org/apache/accumulo/test/TableNamespacesIT.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.fail;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
@@ -51,6 +52,7 @@ import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.Filter;
import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.core.security.SystemPermission;
import org.apache.accumulo.core.security.TableNamespacePermission;
import org.apache.accumulo.core.util.UtilWaitThread;
import org.apache.accumulo.examples.simple.constraints.NumericValueConstraint;
@@ -82,8 +84,6 @@ public class TableNamespacesIT {
/**
* This test creates a table without specifying a namespace. In this case, it puts the table into the default namespace.
- *
- * @throws Exception
*/
@Test
public void testDefaultNamespace() throws Exception {
@@ -99,8 +99,6 @@ public class TableNamespacesIT {
* This test creates a new namespace "testing" and a table "testing.table1" which puts "table1" into the "testing" namespace. Then we create "testing.table2"
* which creates "table2" and puts it into "testing" as well. Then we make sure that you can't delete a namespace with tables in it, and then we delete the
* tables and delete the namespace.
- *
- * @throws Exception
*/
@Test
public void testCreateAndDeleteNamespace() throws Exception {
@@ -148,8 +146,6 @@ public class TableNamespacesIT {
* Checks to make sure namespace-level properties are overridden by table-level properties.
*
* Checks to see if the default namespace's properties work as well.
- *
- * @throws Exception
*/
@Test
@@ -216,21 +212,8 @@ public class TableNamespacesIT {
}
/**
- * This test creates a new user and a namespace. It checks to make sure the user can't modify anything in the namespace at first, then it grants the user
- * permissions and makes sure that they can modify the namespace. Then it also checks if the user has the correct permissions on tables both already existing
- * in the namespace and ones they create.
- *
- * @throws Exception
- */
- @Test
- public void testNamespacePermissions() throws Exception {
- // TODO make the test once namespace-level permissions are implemented. (ACCUMULO-1479)
- }
-
- /**
* This test renames and clones two separate table into different namespaces. different namespace.
*
- * @throws Exception
*/
@Test
public void testRenameAndCloneTableToNewNamespace() throws Exception {
@@ -413,6 +396,7 @@ public class TableNamespacesIT {
/**
<<<<<<< HEAD
+<<<<<<< HEAD
* Tests that when a table moves to a new namespace that it's properties inherit from the new namespace and not the old one
*/
@Test
@@ -452,6 +436,10 @@ public class TableNamespacesIT {
}
/**
* Tests new Namespace permissions as well as modifications to Table permissions because of namespaces
+=======
+ * Tests new Namespace permissions as well as modifications to Table permissions because of namespaces. Checks each permission to first make sure the user
+ * doesn't have permission to perform the action, then root grants them the permission and we check to make sure they could perform the action.
+>>>>>>> ACCUMULO-1479 finished initial implementation of table namespace permissions, including tests
*/
@Test
public void testPermissions() throws Exception {
@@ -460,9 +448,9 @@ public class TableNamespacesIT {
PasswordToken pass = new PasswordToken(secret);
String n1 = "namespace1";
-
+
String user1 = "dude";
-
+
c.tableNamespaceOperations().create(n1);
c.tableOperations().create(n1 + ".table1");
@@ -478,9 +466,121 @@ public class TableNamespacesIT {
}
c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.CREATE_TABLE);
-
user1Con.tableOperations().create(n1 + ".table2");
assertTrue(c.tableOperations().list().contains(n1 + ".table2"));
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.CREATE_TABLE);
+
+ try {
+ user1Con.tableOperations().delete(n1 + ".table1");
+ fail();
+ } catch (AccumuloSecurityException e) {
+ // should happen
+ }
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.DROP_TABLE);
+ user1Con.tableOperations().delete(n1 + ".table1");
+ assertTrue(!c.tableOperations().list().contains(n1 + ".table1"));
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.DROP_TABLE);
+
+ c.tableOperations().create(n1 + ".t");
+ BatchWriter bw = c.createBatchWriter(n1 + ".t", null);
+ Mutation m = new Mutation("row");
+ m.put("cf", "cq", "value");
+ bw.addMutation(m);
+ bw.close();
+
+ Iterator<Entry<Key,Value>> i = user1Con.createScanner(n1 + ".t", new Authorizations()).iterator();
+ try {
+ i.next();
+ fail();
+ } catch (RuntimeException e) {
+ // yup
+ }
+
+ m = new Mutation("user1");
+ m.put("cf", "cq", "turtles");
+ bw = user1Con.createBatchWriter(n1 + ".t", null);
+ try {
+ bw.addMutation(m);
+ bw.close();
+ fail();
+ } catch (MutationsRejectedException e) {
+ // good
+ }
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.READ);
+ i = user1Con.createScanner(n1 + ".t", new Authorizations()).iterator();
+ assertTrue(i.hasNext());
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.READ);
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.WRITE);
+ m = new Mutation("user1");
+ m.put("cf", "cq", "turtles");
+ bw = user1Con.createBatchWriter(n1 + ".t", null);
+ bw.addMutation(m);
+ bw.close();
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.WRITE);
+
+ try {
+ user1Con.tableOperations().setProperty(n1 + ".t", Property.TABLE_FILE_MAX.getKey(), "42");
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.ALTER_TABLE);
+ user1Con.tableOperations().setProperty(n1 + ".t", Property.TABLE_FILE_MAX.getKey(), "42");
+ user1Con.tableOperations().removeProperty(n1 + ".t", Property.TABLE_FILE_MAX.getKey());
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.ALTER_TABLE);
+
+ try {
+ user1Con.tableNamespaceOperations().setProperty(n1, Property.TABLE_FILE_MAX.getKey(), "55");
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.ALTER_NAMESPACE);
+ user1Con.tableNamespaceOperations().setProperty(n1, Property.TABLE_FILE_MAX.getKey(), "42");
+ user1Con.tableNamespaceOperations().removeProperty(n1, Property.TABLE_FILE_MAX.getKey());
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.ALTER_NAMESPACE);
+
+ String user2 = "guy";
+ c.securityOperations().createLocalUser(user2, pass);
+ try {
+ user1Con.securityOperations().grantTableNamespacePermission(user2, n1, TableNamespacePermission.ALTER_NAMESPACE);
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantTableNamespacePermission(user1, n1, TableNamespacePermission.GRANT);
+ user1Con.securityOperations().grantTableNamespacePermission(user2, n1, TableNamespacePermission.ALTER_NAMESPACE);
+ user1Con.securityOperations().revokeTableNamespacePermission(user2, n1, TableNamespacePermission.ALTER_NAMESPACE);
+ c.securityOperations().revokeTableNamespacePermission(user1, n1, TableNamespacePermission.GRANT);
+
+ String n2 = "namespace2";
+ try {
+ user1Con.tableNamespaceOperations().create(n2);
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantSystemPermission(user1, SystemPermission.CREATE_NAMESPACE);
+ user1Con.tableNamespaceOperations().create(n2);
+ c.securityOperations().revokeSystemPermission(user1, SystemPermission.CREATE_NAMESPACE);
+
+ try {
+ user1Con.tableNamespaceOperations().delete(n2);
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantSystemPermission(user1, SystemPermission.DROP_NAMESPACE);
+ user1Con.tableNamespaceOperations().delete(n2);
+ c.securityOperations().revokeSystemPermission(user1, SystemPermission.DROP_NAMESPACE);
+
+ try {
+ user1Con.tableNamespaceOperations().setProperty(n1, Property.TABLE_FILE_MAX.getKey(), "33");
+ fail();
+ } catch (AccumuloSecurityException e) {}
+
+ c.securityOperations().grantSystemPermission(user1, SystemPermission.ALTER_NAMESPACE);
+ user1Con.tableNamespaceOperations().setProperty(n1, Property.TABLE_FILE_MAX.getKey(), "33");
+ user1Con.tableNamespaceOperations().removeProperty(n1, Property.TABLE_FILE_MAX.getKey());
+ c.securityOperations().revokeSystemPermission(user1, SystemPermission.ALTER_NAMESPACE);
}
private boolean checkTableHasProp(Connector c, String t, String propKey, String propVal) throws AccumuloException, TableNotFoundException {