You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2016/04/22 08:28:27 UTC

[07/13] sentry git commit: SENTRY-999: Refactor the sentry to integrate with external components quickly (Colin Ma, reviewed by Dapeng Sun)

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HivePrivilegeModel.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HivePrivilegeModel.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HivePrivilegeModel.java
new file mode 100644
index 0000000..231acca
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HivePrivilegeModel.java
@@ -0,0 +1,68 @@
+/*
+ * 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.sentry.core.model.db;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.db.validator.DatabaseMustMatch;
+import org.apache.sentry.core.model.db.validator.DatabaseRequiredInPrivilege;
+import org.apache.sentry.core.model.db.validator.ServerNameMustMatch;
+import org.apache.sentry.core.model.db.validator.ServersAllIsInvalid;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.sentry.core.model.db.DBModelAuthorizable.AuthorizableType;
+
+public class HivePrivilegeModel implements Model {
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+  private static HivePrivilegeModel hivePrivilegeModel = new HivePrivilegeModel();
+
+  private HivePrivilegeModel() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = new HiveActionFactory();
+
+    implyMethodMap.put(AuthorizableType.Server.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(AuthorizableType.Db.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(AuthorizableType.Table.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(AuthorizableType.Column.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(AuthorizableType.URI.name().toLowerCase(), ImplyMethodType.URL);
+  }
+
+  @Override
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  @Override
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static HivePrivilegeModel getInstance() {
+    return hivePrivilegeModel;
+  }
+
+  public ImmutableList<PrivilegeValidator> getPrivilegeValidators(String serverName) {
+    return ImmutableList.<PrivilegeValidator>of(new ServersAllIsInvalid(), new DatabaseMustMatch(),
+            new DatabaseRequiredInPrivilege(), new ServerNameMustMatch(serverName));
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/AbstractDBPrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/AbstractDBPrivilegeValidator.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/AbstractDBPrivilegeValidator.java
new file mode 100644
index 0000000..fa28716
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/AbstractDBPrivilegeValidator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.sentry.core.model.db.validator;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.core.common.utils.SentryConstants.PRIVILEGE_PREFIX;
+
+import java.util.List;
+
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.db.DBModelAuthorizables;
+import org.apache.shiro.config.ConfigurationException;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+public abstract class AbstractDBPrivilegeValidator implements PrivilegeValidator {
+
+  @VisibleForTesting
+  public static Iterable<DBModelAuthorizable> parsePrivilege(String string) {
+    List<DBModelAuthorizable> result = Lists.newArrayList();
+    for(String section : AUTHORIZABLE_SPLITTER.split(string)) {
+      // XXX this ugly hack is because action is not an authorizeable
+      if(!section.toLowerCase().startsWith(PRIVILEGE_PREFIX)) {
+        DBModelAuthorizable authorizable = DBModelAuthorizables.from(section);
+        if(authorizable == null) {
+          String msg = "No authorizable found for " + section;
+          throw new ConfigurationException(msg);
+        }
+        result.add(authorizable);
+      }
+    }
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseMustMatch.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseMustMatch.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseMustMatch.java
new file mode 100644
index 0000000..4276667
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseMustMatch.java
@@ -0,0 +1,46 @@
+/*
+ * 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.sentry.core.model.db.validator;
+
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.core.model.db.Database;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.shiro.config.ConfigurationException;
+
+public class DatabaseMustMatch extends AbstractDBPrivilegeValidator {
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws ConfigurationException {
+    String database = context.getDatabase();
+    String privilege = context.getPrivilege();
+    /*
+     *  Rule only applies to rules in per database policy file
+     */
+    if(database != null) {
+      Iterable<DBModelAuthorizable> authorizables = parsePrivilege(privilege);
+      for(DBModelAuthorizable authorizable : authorizables) {
+        if(authorizable instanceof Database &&
+            !database.equalsIgnoreCase(authorizable.getName())) {
+          String msg = "Privilege " + privilege + " references db " +
+              authorizable.getName() + ", but is only allowed to reference "
+              + database;
+          throw new ConfigurationException(msg);
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseRequiredInPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseRequiredInPrivilege.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseRequiredInPrivilege.java
new file mode 100644
index 0000000..fed3038
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/DatabaseRequiredInPrivilege.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sentry.core.model.db.validator;
+
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.db.AccessURI;
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.core.model.db.Database;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.shiro.config.ConfigurationException;
+
+public class DatabaseRequiredInPrivilege extends AbstractDBPrivilegeValidator {
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws ConfigurationException {
+    String database = context.getDatabase();
+    String privilege = context.getPrivilege();
+    /*
+     *  Rule only applies to rules in per database policy file
+     */
+    if(database != null) {
+      Iterable<DBModelAuthorizable> authorizables = parsePrivilege(privilege);
+      /*
+       * Each permission in a non-global file must have a database
+       * object except for URIs.
+       *
+       * We allow URIs to be specified in the per DB policy file for
+       * ease of mangeability. URIs will contain to remain server scope
+       * objects.
+       */
+      boolean foundDatabaseInAuthorizables = false;
+      boolean foundURIInAuthorizables = false;
+      boolean allowURIInAuthorizables = false;
+
+      if ("true".equalsIgnoreCase(
+          System.getProperty(SentryConstants.ACCESS_ALLOW_URI_PER_DB_POLICYFILE))) {
+        allowURIInAuthorizables = true;
+      }
+
+      for(DBModelAuthorizable authorizable : authorizables) {
+        if(authorizable instanceof Database) {
+          foundDatabaseInAuthorizables = true;
+        }
+        if (authorizable instanceof AccessURI) {
+          if (foundDatabaseInAuthorizables) {
+            String msg = "URI object is specified at DB scope in " + privilege;
+            throw new ConfigurationException(msg);
+          }
+          foundURIInAuthorizables = true;
+        }
+      }
+      if(!foundDatabaseInAuthorizables && !(foundURIInAuthorizables && allowURIInAuthorizables)) {
+        String msg = "Missing database object in " + privilege;
+        throw new ConfigurationException(msg);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServerNameMustMatch.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServerNameMustMatch.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServerNameMustMatch.java
new file mode 100644
index 0000000..c79a8bf
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServerNameMustMatch.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sentry.core.model.db.validator;
+
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.core.model.db.Server;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.shiro.config.ConfigurationException;
+
+public class ServerNameMustMatch extends AbstractDBPrivilegeValidator {
+
+  private final String serverName;
+  public ServerNameMustMatch(String serverName) {
+    this.serverName = serverName;
+  }
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws ConfigurationException {
+    String privilege = context.getPrivilege();
+    Iterable<DBModelAuthorizable> authorizables = parsePrivilege(privilege);
+    for(DBModelAuthorizable authorizable : authorizables) {
+      if(authorizable instanceof Server && !serverName.equalsIgnoreCase(authorizable.getName())) {
+        String msg = "Server name " + authorizable.getName() + " in "
+            + privilege + " is invalid. Expected " + serverName;
+        throw new ConfigurationException(msg);
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServersAllIsInvalid.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServersAllIsInvalid.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServersAllIsInvalid.java
new file mode 100644
index 0000000..e3f5a3a
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/validator/ServersAllIsInvalid.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sentry.core.model.db.validator;
+
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.core.model.db.Server;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.shiro.config.ConfigurationException;
+
+public class ServersAllIsInvalid extends AbstractDBPrivilegeValidator {
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws ConfigurationException {
+    String privilege = context.getPrivilege();
+    Iterable<DBModelAuthorizable> authorizables = parsePrivilege(privilege);
+    for(DBModelAuthorizable authorizable : authorizables) {
+      if(authorizable instanceof Server &&
+          authorizable.getName().equals(Server.ALL.getName())) {
+        String msg = "Invalid value for " + authorizable.getAuthzType() + " in " + privilege;
+        throw new ConfigurationException(msg);
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerModelAuthorizables.java b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerModelAuthorizables.java
new file mode 100644
index 0000000..d15e911
--- /dev/null
+++ b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerModelAuthorizables.java
@@ -0,0 +1,46 @@
+/*
+ * 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.sentry.core.model.indexer;
+
+import org.apache.sentry.core.model.indexer.IndexerModelAuthorizable.AuthorizableType;
+import org.apache.sentry.core.common.utils.KeyValue;
+
+public class IndexerModelAuthorizables {
+
+  public static IndexerModelAuthorizable from(KeyValue keyValue) {
+    String prefix = keyValue.getKey().toLowerCase();
+    String name = keyValue.getValue().toLowerCase();
+    for(AuthorizableType type : AuthorizableType.values()) {
+      if(prefix.equalsIgnoreCase(type.name())) {
+        return from(type, name);
+      }
+    }
+    return null;
+  }
+  public static IndexerModelAuthorizable from(String s) {
+    return from(new KeyValue(s));
+  }
+
+  private static IndexerModelAuthorizable from(AuthorizableType type, String name) {
+    switch (type) {
+    case Indexer:
+      return new Indexer(name);
+    default:
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerPrivilegeModel.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerPrivilegeModel.java b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerPrivilegeModel.java
new file mode 100644
index 0000000..6951513
--- /dev/null
+++ b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/IndexerPrivilegeModel.java
@@ -0,0 +1,59 @@
+/*
+ * 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.sentry.core.model.indexer;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.indexer.validator.IndexerRequiredInPrivilege;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class IndexerPrivilegeModel implements Model {
+
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+  private static IndexerPrivilegeModel indexerPrivilegeModel = new IndexerPrivilegeModel();;
+
+  private IndexerPrivilegeModel() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = new IndexerActionFactory();
+
+    implyMethodMap.put(IndexerModelAuthorizable.AuthorizableType.Indexer.name().toLowerCase(), ImplyMethodType.STRING);
+  }
+
+  @Override
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  @Override
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static IndexerPrivilegeModel getInstance() {
+    return indexerPrivilegeModel;
+  }
+
+  public ImmutableList<PrivilegeValidator> getPrivilegeValidators() {
+    return ImmutableList.<PrivilegeValidator>of(new IndexerRequiredInPrivilege());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/AbstractIndexerPrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/AbstractIndexerPrivilegeValidator.java b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/AbstractIndexerPrivilegeValidator.java
new file mode 100644
index 0000000..c73fc3c
--- /dev/null
+++ b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/AbstractIndexerPrivilegeValidator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.sentry.core.model.indexer.validator;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.core.common.utils.SentryConstants.PRIVILEGE_PREFIX;
+
+import java.util.List;
+
+import org.apache.sentry.core.model.indexer.IndexerModelAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.indexer.IndexerModelAuthorizables;
+import org.apache.shiro.config.ConfigurationException;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+public abstract class AbstractIndexerPrivilegeValidator implements PrivilegeValidator {
+
+  @VisibleForTesting
+  public static Iterable<IndexerModelAuthorizable> parsePrivilege(String string) {
+    List<IndexerModelAuthorizable> result = Lists.newArrayList();
+    for(String section : AUTHORIZABLE_SPLITTER.split(string)) {
+      // XXX this ugly hack is because action is not an authorizable
+      if(!section.toLowerCase().startsWith(PRIVILEGE_PREFIX)) {
+        IndexerModelAuthorizable authorizable = IndexerModelAuthorizables.from(section);
+        if(authorizable == null) {
+          String msg = "No authorizable found for " + section;
+          throw new ConfigurationException(msg);
+        }
+        result.add(authorizable);
+      }
+    }
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/IndexerRequiredInPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/IndexerRequiredInPrivilege.java b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/IndexerRequiredInPrivilege.java
new file mode 100644
index 0000000..82bc25d
--- /dev/null
+++ b/sentry-core/sentry-core-model-indexer/src/main/java/org/apache/sentry/core/model/indexer/validator/IndexerRequiredInPrivilege.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sentry.core.model.indexer.validator;
+
+import org.apache.sentry.core.common.SentryConfigurationException;
+import org.apache.sentry.core.model.indexer.Indexer;
+import org.apache.sentry.core.model.indexer.IndexerModelAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+
+public class IndexerRequiredInPrivilege extends AbstractIndexerPrivilegeValidator {
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws SentryConfigurationException {
+    String privilege = context.getPrivilege();
+    Iterable<IndexerModelAuthorizable> authorizables = parsePrivilege(privilege);
+    boolean foundIndexerInAuthorizables = false;
+
+    for(IndexerModelAuthorizable authorizable : authorizables) {
+      if(authorizable instanceof Indexer) {
+        foundIndexerInAuthorizables = true;
+        break;
+      }
+    }
+    if(!foundIndexerInAuthorizables) {
+      String msg = "Missing indexer object in " + privilege;
+      throw new SentryConfigurationException(msg);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaActionFactory.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaActionFactory.java b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaActionFactory.java
index fc3bf7a..a1fec1f 100644
--- a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaActionFactory.java
+++ b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaActionFactory.java
@@ -52,9 +52,9 @@ public class KafkaActionFactory extends BitFieldActionFactory {
     DELETE(KafkaActionConstant.DELETE, 8),
     ALTER(KafkaActionConstant.ALTER, 16),
     DESCRIBE(KafkaActionConstant.DESCRIBE, 32),
-    CLUSTER_ACTION(KafkaActionConstant.CLUSTER_ACTION, 64),
+    CLUSTERACTION(KafkaActionConstant.CLUSTER_ACTION, 64),
     ALL(KafkaActionConstant.ALL, READ.getCode() | WRITE.getCode() | CREATE.getCode()
-        | DELETE.getCode() | ALTER.getCode()| DESCRIBE.getCode() | CLUSTER_ACTION.getCode());
+        | DELETE.getCode() | ALTER.getCode()| DESCRIBE.getCode() | CLUSTERACTION.getCode());
 
     private String name;
     private int code;

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaModelAuthorizables.java b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaModelAuthorizables.java
new file mode 100644
index 0000000..45a1148
--- /dev/null
+++ b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaModelAuthorizables.java
@@ -0,0 +1,57 @@
+/*
+ * 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.sentry.core.model.kafka;
+
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.model.kafka.KafkaAuthorizable.AuthorizableType;
+import org.apache.shiro.config.ConfigurationException;
+
+public class KafkaModelAuthorizables {
+  public static KafkaAuthorizable from(KeyValue keyValue) throws ConfigurationException {
+    String prefix = keyValue.getKey().toLowerCase();
+    String name = keyValue.getValue();
+    for (AuthorizableType type : AuthorizableType.values()) {
+      if (prefix.equalsIgnoreCase(type.name())) {
+        return from(type, name);
+      }
+    }
+    return null;
+  }
+
+  public static KafkaAuthorizable from(String keyValue) throws ConfigurationException {
+    return from(new KeyValue(keyValue));
+  }
+
+  public static KafkaAuthorizable from(AuthorizableType type, String name) throws ConfigurationException {
+    switch (type) {
+      case HOST:
+        return new Host(name);
+      case CLUSTER: {
+        if (!name.equals(Cluster.NAME)) {
+          throw new ConfigurationException("Kafka's cluster resource can only have name " + Cluster.NAME);
+        }
+        return new Cluster();
+      }
+      case TOPIC:
+        return new Topic(name);
+      case CONSUMERGROUP:
+        return new ConsumerGroup(name);
+      default:
+        return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaPrivilegeModel.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaPrivilegeModel.java b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaPrivilegeModel.java
new file mode 100644
index 0000000..74c887e
--- /dev/null
+++ b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/KafkaPrivilegeModel.java
@@ -0,0 +1,69 @@
+/**
+ * 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.sentry.core.model.kafka;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class KafkaPrivilegeModel implements Model {
+
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+  private static KafkaPrivilegeModel kafkaPrivilegeModel = new KafkaPrivilegeModel();
+
+  private KafkaPrivilegeModel() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = KafkaActionFactory.getInstance();
+
+    implyMethodMap.put(KafkaAuthorizable.AuthorizableType.CLUSTER.name().toLowerCase(),
+        ImplyMethodType.STRING);
+    implyMethodMap.put(KafkaAuthorizable.AuthorizableType.HOST.name().toLowerCase(),
+        ImplyMethodType.STRING);
+    implyMethodMap.put(KafkaAuthorizable.AuthorizableType.TOPIC.name().toLowerCase(),
+        ImplyMethodType.STRING);
+    implyMethodMap.put(KafkaAuthorizable.AuthorizableType.CONSUMERGROUP.name().toLowerCase(),
+        ImplyMethodType.STRING);
+  }
+
+  @Override
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  @Override
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static KafkaPrivilegeModel getInstance() {
+    return kafkaPrivilegeModel;
+  }
+
+  public ImmutableList<PrivilegeValidator> getPrivilegeValidators() {
+    return ImmutableList.<PrivilegeValidator>of(new KafkaPrivilegeValidator());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/validator/KafkaPrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/validator/KafkaPrivilegeValidator.java b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/validator/KafkaPrivilegeValidator.java
new file mode 100644
index 0000000..5c45865
--- /dev/null
+++ b/sentry-core/sentry-core-model-kafka/src/main/java/org/apache/sentry/core/model/kafka/validator/KafkaPrivilegeValidator.java
@@ -0,0 +1,119 @@
+/*
+ * 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.sentry.core.model.kafka.validator;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.core.common.utils.SentryConstants.PRIVILEGE_PREFIX;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.sentry.core.model.kafka.KafkaActionFactory;
+import org.apache.sentry.core.model.kafka.KafkaAuthorizable;
+import org.apache.sentry.core.model.kafka.Host;
+import org.apache.sentry.core.model.kafka.KafkaModelAuthorizables;
+import org.apache.shiro.config.ConfigurationException;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Validator for Kafka privileges.
+ * Below are the requirements for a kafka privilege to be valid.
+ * 1. Privilege must start with Host resource.
+ * 2. Privilege must have at most one non Host resource, Cluster or Topic or ConsumerGroup, followed
+ *    by Host resource.
+ * 3. Privilege must end with exactly one action.
+ */
+public class KafkaPrivilegeValidator implements PrivilegeValidator {
+
+  public static final String KafkaPrivilegeHelpMsg =
+      "Invalid Kafka privilege." +
+      " Kafka privilege must be of the form host=<HOST>-><RESOURCE>=<RESOURCE_NAME>->action=<ACTION>," +
+      " where <HOST> can be '*' or any valid host name," +
+      " <RESOURCE> can be one of " + Arrays.toString(getKafkaAuthorizablesExceptHost()) +
+      " <RESOURCE_NAME> is name of the resource," +
+      " <ACTION> can be one of " + Arrays.toString(KafkaActionFactory.KafkaActionType.values()) +
+      ".";
+
+  private static KafkaAuthorizable.AuthorizableType[] getKafkaAuthorizablesExceptHost() {
+    final KafkaAuthorizable.AuthorizableType[] authorizableTypes = KafkaAuthorizable.AuthorizableType.values();
+    List<KafkaAuthorizable.AuthorizableType> authorizableTypesWithoutHost = new ArrayList<>(authorizableTypes.length - 1);
+    for (KafkaAuthorizable.AuthorizableType authorizableType: authorizableTypes) {
+      if (!authorizableType.equals(KafkaAuthorizable.AuthorizableType.HOST)) {
+        authorizableTypesWithoutHost.add(authorizableType);
+      }
+    }
+    return authorizableTypesWithoutHost.toArray(new KafkaAuthorizable.AuthorizableType[authorizableTypesWithoutHost.size()]);
+  }
+
+  public KafkaPrivilegeValidator() {
+  }
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws ConfigurationException {
+    List<String> splits = Lists.newArrayList();
+    for (String section : AUTHORIZABLE_SPLITTER.split(context.getPrivilege())) {
+      splits.add(section);
+    }
+
+    // Check privilege splits length is 2 or 3
+    if (splits.size() < 2 || splits.size() > 3) {
+      throw new ConfigurationException(KafkaPrivilegeHelpMsg);
+    }
+
+    // Check privilege starts with Host resource
+    if (isAction(splits.get(0))) {
+      throw new ConfigurationException("Kafka privilege can not start with an action.\n" + KafkaPrivilegeHelpMsg);
+    }
+    KafkaAuthorizable hostAuthorizable = KafkaModelAuthorizables.from(splits.get(0));
+    if (hostAuthorizable == null) {
+      throw new ConfigurationException("No Kafka authorizable found for " + splits.get(0) + "\n." + KafkaPrivilegeHelpMsg);
+    }
+    if (!(hostAuthorizable instanceof Host)) {
+      throw new ConfigurationException("Kafka privilege must begin with host authorizable.\n" + KafkaPrivilegeHelpMsg);
+    }
+
+    // Check privilege has at most one non Host resource following Host resource
+    if (splits.size() == 3) {
+      if (isAction(splits.get(1))) {
+        throw new ConfigurationException("Kafka privilege can have action only at the end of privilege.\n" + KafkaPrivilegeHelpMsg);
+      }
+      KafkaAuthorizable authorizable = KafkaModelAuthorizables.from(splits.get(1));
+      if (authorizable == null) {
+        throw new ConfigurationException("No Kafka authorizable found for " + splits.get(1) + "\n." + KafkaPrivilegeHelpMsg);
+      }
+      if (authorizable instanceof Host) {
+        throw new ConfigurationException("Host authorizable can be specified just once in a Kafka privilege.\n" + KafkaPrivilegeHelpMsg);
+      }
+    }
+
+    // Check privilege ends with exactly one valid action
+    if (!isAction(splits.get(splits.size() - 1))) {
+      throw new ConfigurationException("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeHelpMsg);
+    }
+  }
+
+  private boolean isAction(String privilegePart) {
+    final String privilege = privilegePart.toLowerCase();
+    final String action = privilege.replace(PRIVILEGE_PREFIX, "").toLowerCase();
+    return privilege.startsWith(PRIVILEGE_PREFIX) &&
+        KafkaActionFactory.getInstance().getActionByName(action) != null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchModelAuthorizables.java b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchModelAuthorizables.java
new file mode 100644
index 0000000..c3292c7
--- /dev/null
+++ b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchModelAuthorizables.java
@@ -0,0 +1,46 @@
+/*
+ * 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.sentry.core.model.search;
+
+import org.apache.sentry.core.model.search.SearchModelAuthorizable.AuthorizableType;
+import org.apache.sentry.core.common.utils.KeyValue;
+
+public class SearchModelAuthorizables {
+
+  public static SearchModelAuthorizable from(KeyValue keyValue) {
+    String prefix = keyValue.getKey().toLowerCase();
+    String name = keyValue.getValue().toLowerCase();
+    for(AuthorizableType type : AuthorizableType.values()) {
+      if(prefix.equalsIgnoreCase(type.name())) {
+        return from(type, name);
+      }
+    }
+    return null;
+  }
+  public static SearchModelAuthorizable from(String s) {
+    return from(new KeyValue(s));
+  }
+
+  private static SearchModelAuthorizable from(AuthorizableType type, String name) {
+    switch (type) {
+    case Collection:
+      return new Collection(name);
+    default:
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchPrivilegeModel.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchPrivilegeModel.java b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchPrivilegeModel.java
new file mode 100644
index 0000000..9429a25
--- /dev/null
+++ b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/SearchPrivilegeModel.java
@@ -0,0 +1,60 @@
+/*
+ * 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.sentry.core.model.search;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.search.validator.CollectionRequiredInPrivilege;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SearchPrivilegeModel implements Model {
+
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+  private static SearchPrivilegeModel searchPrivilegeModel = new SearchPrivilegeModel();
+
+  private SearchPrivilegeModel() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = new SearchActionFactory();
+
+    implyMethodMap.put(SearchModelAuthorizable.AuthorizableType.Collection.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(SearchModelAuthorizable.AuthorizableType.Field.name().toLowerCase(), ImplyMethodType.STRING);
+  }
+
+  @Override
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  @Override
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static SearchPrivilegeModel getInstance() {
+    return searchPrivilegeModel;
+  }
+
+  public ImmutableList<PrivilegeValidator> getPrivilegeValidators() {
+    return ImmutableList.<PrivilegeValidator>of(new CollectionRequiredInPrivilege());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/AbstractSearchPrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/AbstractSearchPrivilegeValidator.java b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/AbstractSearchPrivilegeValidator.java
new file mode 100644
index 0000000..c06131c
--- /dev/null
+++ b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/AbstractSearchPrivilegeValidator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.sentry.core.model.search.validator;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.core.common.utils.SentryConstants.PRIVILEGE_PREFIX;
+
+import java.util.List;
+
+import org.apache.sentry.core.model.search.SearchModelAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.search.SearchModelAuthorizables;
+import org.apache.shiro.config.ConfigurationException;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+public abstract class AbstractSearchPrivilegeValidator implements PrivilegeValidator {
+
+  @VisibleForTesting
+  public static Iterable<SearchModelAuthorizable> parsePrivilege(String string) {
+    List<SearchModelAuthorizable> result = Lists.newArrayList();
+    System.err.println("privilege = " + string);
+    for(String section : AUTHORIZABLE_SPLITTER.split(string)) {
+      // XXX this ugly hack is because action is not an authorizable
+      if(!section.toLowerCase().startsWith(PRIVILEGE_PREFIX)) {
+        SearchModelAuthorizable authorizable = SearchModelAuthorizables.from(section);
+        if(authorizable == null) {
+          String msg = "No authorizable found for " + section;
+          throw new ConfigurationException(msg);
+        }
+        result.add(authorizable);
+      }
+    }
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/CollectionRequiredInPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/CollectionRequiredInPrivilege.java b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/CollectionRequiredInPrivilege.java
new file mode 100644
index 0000000..17b87df
--- /dev/null
+++ b/sentry-core/sentry-core-model-search/src/main/java/org/apache/sentry/core/model/search/validator/CollectionRequiredInPrivilege.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sentry.core.model.search.validator;
+
+import org.apache.sentry.core.common.SentryConfigurationException;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.core.model.search.SearchModelAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+
+public class CollectionRequiredInPrivilege extends AbstractSearchPrivilegeValidator {
+
+  @Override
+  public void validate(PrivilegeValidatorContext context) throws SentryConfigurationException {
+    String privilege = context.getPrivilege();
+    Iterable<SearchModelAuthorizable> authorizables = parsePrivilege(privilege);
+    boolean foundCollectionInAuthorizables = false;
+
+    for(SearchModelAuthorizable authorizable : authorizables) {
+      if(authorizable instanceof Collection) {
+        foundCollectionInAuthorizables = true;
+        break;
+      }
+    }
+    if(!foundCollectionInAuthorizables) {
+      String msg = "Missing collection object in " + privilege;
+      throw new SentryConfigurationException(msg);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopModelAuthorizables.java b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopModelAuthorizables.java
new file mode 100644
index 0000000..11ce7ec
--- /dev/null
+++ b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopModelAuthorizables.java
@@ -0,0 +1,52 @@
+/*
+ * 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.sentry.core.model.sqoop;
+
+import org.apache.sentry.core.model.sqoop.SqoopAuthorizable.AuthorizableType;
+import org.apache.sentry.core.common.utils.KeyValue;
+
+public class SqoopModelAuthorizables {
+  public static SqoopAuthorizable from(KeyValue keyValue) {
+    String prefix = keyValue.getKey().toLowerCase();
+    String name = keyValue.getValue().toLowerCase();
+    for (AuthorizableType type : AuthorizableType.values()) {
+      if(prefix.equalsIgnoreCase(type.name())) {
+        return from(type, name);
+      }
+    }
+    return null;
+  }
+
+  public static SqoopAuthorizable from(String keyValue) {
+    return from(new KeyValue(keyValue));
+  }
+
+  public static SqoopAuthorizable from(AuthorizableType type, String name) {
+    switch(type) {
+    case SERVER:
+      return new Server(name);
+    case JOB:
+      return new Job(name);
+    case CONNECTOR:
+      return new Connector(name);
+    case LINK:
+      return new Link(name);
+    default:
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopPrivilegeModel.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopPrivilegeModel.java b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopPrivilegeModel.java
new file mode 100644
index 0000000..4bd8f94
--- /dev/null
+++ b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/SqoopPrivilegeModel.java
@@ -0,0 +1,63 @@
+/*
+ * 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.sentry.core.model.sqoop;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.sqoop.validator.ServerNameRequiredMatch;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SqoopPrivilegeModel implements Model {
+
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+  private static SqoopPrivilegeModel sqoopPrivilegeModel = new SqoopPrivilegeModel();
+
+  private SqoopPrivilegeModel() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = new SqoopActionFactory();
+
+    implyMethodMap.put(SqoopAuthorizable.AuthorizableType.SERVER.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(SqoopAuthorizable.AuthorizableType.CONNECTOR.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(SqoopAuthorizable.AuthorizableType.LINK.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(SqoopAuthorizable.AuthorizableType.JOB.name().toLowerCase(), ImplyMethodType.STRING);
+  }
+
+  @Override
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  @Override
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static SqoopPrivilegeModel getInstance() {
+    return sqoopPrivilegeModel;
+  }
+
+  public ImmutableList<PrivilegeValidator> getPrivilegeValidators(String sqoopServerName) {
+    return ImmutableList.<PrivilegeValidator>of(new ServerNameRequiredMatch(sqoopServerName));
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/validator/ServerNameRequiredMatch.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/validator/ServerNameRequiredMatch.java b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/validator/ServerNameRequiredMatch.java
new file mode 100644
index 0000000..67347bc
--- /dev/null
+++ b/sentry-core/sentry-core-model-sqoop/src/main/java/org/apache/sentry/core/model/sqoop/validator/ServerNameRequiredMatch.java
@@ -0,0 +1,70 @@
+/*
+ * 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.sentry.core.model.sqoop.validator;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.core.common.utils.SentryConstants.PRIVILEGE_PREFIX;
+
+import java.util.List;
+
+import org.apache.sentry.core.model.sqoop.Server;
+import org.apache.sentry.core.model.sqoop.SqoopAuthorizable;
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.sentry.core.common.validator.PrivilegeValidator;
+import org.apache.sentry.core.model.sqoop.SqoopModelAuthorizables;
+import org.apache.shiro.config.ConfigurationException;
+
+import com.google.common.collect.Lists;
+
+public class ServerNameRequiredMatch implements PrivilegeValidator {
+  private final String sqoopServerName;
+  public ServerNameRequiredMatch(String sqoopServerName) {
+    this.sqoopServerName = sqoopServerName;
+  }
+  @Override
+  public void validate(PrivilegeValidatorContext context)
+      throws ConfigurationException {
+    Iterable<SqoopAuthorizable> authorizables = parsePrivilege(context.getPrivilege());
+    boolean match = false;
+    for (SqoopAuthorizable authorizable : authorizables) {
+      if (authorizable instanceof Server && authorizable.getName().equalsIgnoreCase(sqoopServerName)) {
+        match = true;
+        break;
+      }
+    }
+    if (!match) {
+      String msg = "server=[name] in " + context.getPrivilege()
+          + " is required. The name is expected " + sqoopServerName;
+      throw new ConfigurationException(msg);
+    }
+  }
+
+  private Iterable<SqoopAuthorizable> parsePrivilege(String string) {
+    List<SqoopAuthorizable> result = Lists.newArrayList();
+    for(String section : AUTHORIZABLE_SPLITTER.split(string)) {
+      if(!section.toLowerCase().startsWith(PRIVILEGE_PREFIX)) {
+        SqoopAuthorizable authorizable = SqoopModelAuthorizables.from(section);
+        if(authorizable == null) {
+          String msg = "No authorizable found for " + section;
+          throw new ConfigurationException(msg);
+        }
+        result.add(authorizable);
+      }
+    }
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-dist/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-dist/pom.xml b/sentry-dist/pom.xml
index 130de75..80ec9c9 100644
--- a/sentry-dist/pom.xml
+++ b/sentry-dist/pom.xml
@@ -92,24 +92,8 @@ limitations under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-db</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sentry</groupId>
       <artifactId>sentry-policy-indexer</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-search</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-sqoop</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-kafka</artifactId>
-    </dependency>
   </dependencies>
   <profiles>
     <profile>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-policy/pom.xml b/sentry-policy/pom.xml
index 4abcf03..14fe829 100644
--- a/sentry-policy/pom.xml
+++ b/sentry-policy/pom.xml
@@ -31,11 +31,8 @@ limitations under the License.
 
   <modules>
     <module>sentry-policy-common</module>
-    <module>sentry-policy-db</module>
+    <module>sentry-policy-engine</module>
     <module>sentry-policy-indexer</module>
-    <module>sentry-policy-search</module>
-    <module>sentry-policy-sqoop</module>
-    <module>sentry-policy-kafka</module>
   </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/pom.xml b/sentry-policy/sentry-policy-common/pom.xml
index 1f8c522..57fc9d9 100644
--- a/sentry-policy/sentry-policy-common/pom.xml
+++ b/sentry-policy/sentry-policy-common/pom.xml
@@ -45,6 +45,11 @@ limitations under the License.
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-core-model-db</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/CommonPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/CommonPrivilege.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/CommonPrivilege.java
new file mode 100644
index 0000000..dedd908
--- /dev/null
+++ b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/CommonPrivilege.java
@@ -0,0 +1,176 @@
+/*
+ * 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.sentry.policy.common;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.sentry.core.common.BitFieldAction;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.common.ImplyMethodType;
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.common.utils.PathUtils;
+import org.apache.sentry.core.common.utils.SentryConstants;
+
+import java.util.List;
+
+// The class is used to compare the privilege
+public class CommonPrivilege implements Privilege {
+
+  private ImmutableList<KeyValue> parts;
+
+  public CommonPrivilege(String privilegeStr) {
+    privilegeStr = Strings.nullToEmpty(privilegeStr).trim();
+    if (privilegeStr.isEmpty()) {
+      throw new IllegalArgumentException("Privilege string cannot be null or empty.");
+    }
+    List<KeyValue> parts = Lists.newArrayList();
+    for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.trimResults().split(
+            privilegeStr)) {
+      if (authorizable.isEmpty()) {
+        throw new IllegalArgumentException("Privilege '" + privilegeStr + "' has an empty section");
+      }
+      parts.add(new KeyValue(authorizable));
+    }
+    if (parts.isEmpty()) {
+      throw new AssertionError("Should never occur: " + privilegeStr);
+    }
+    this.parts = ImmutableList.copyOf(parts);
+  }
+
+  @Override
+  public boolean implies(Privilege privilege, Model model) {
+    // By default only supports comparisons with other IndexerWildcardPermissions
+    if (!(privilege instanceof CommonPrivilege)) {
+      return false;
+    }
+
+    List<KeyValue> otherParts = ((CommonPrivilege) privilege).getParts();
+    if(parts.equals(otherParts)) {
+      return true;
+    }
+
+    int index = 0;
+    for (KeyValue otherPart : otherParts) {
+      // If this privilege has less parts than the other privilege, everything
+      // after the number of parts contained
+      // in this privilege is automatically implied, so return true
+      if (parts.size() - 1 < index) {
+        return true;
+      } else {
+        KeyValue part = parts.get(index);
+        String policyKey = part.getKey();
+        // are the keys even equal
+        if(!policyKey.equalsIgnoreCase(otherPart.getKey())) {
+          // Support for action inheritance from parent to child
+          if (SentryConstants.PRIVILEGE_NAME.equalsIgnoreCase(policyKey)) {
+            continue;
+          }
+          return false;
+        }
+
+        // do the imply for action
+        if (SentryConstants.PRIVILEGE_NAME.equalsIgnoreCase(policyKey)) {
+          if (!impliesAction(part.getValue(), otherPart.getValue(), model.getBitFieldActionFactory())) {
+            return false;
+          }
+        } else {
+          if (!impliesResource(model.getImplyMethodMap().get(policyKey.toLowerCase()),
+                  part.getValue(), otherPart.getValue())) {
+            return false;
+          }
+        }
+
+        index++;
+      }
+    }
+
+    // If this privilege has more parts than the other parts, only imply it if
+    // all of the other parts are wildcards
+    for (; index < parts.size(); index++) {
+      KeyValue part = parts.get(index);
+      if (!SentryConstants.PRIVILEGE_WILDCARD_VALUE.equals(part.getValue())) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  // The method is used for compare the value of resource by the ImplyMethodType.
+  // for Hive, databaseName, tableName, columnName will be compared using String.equal(wildcard support)
+  //           url will be compared using PathUtils.impliesURI
+  private boolean impliesResource(ImplyMethodType implyMethodType, String policyValue, String requestValue) {
+    // wildcard support, "*", "+", "all"("+" and "all" are for backward compatibility) are represented as wildcard
+    // if requestValue is wildcard, means privilege request is to match with any value of given resource
+    if (SentryConstants.RESOURCE_WILDCARD_VALUE.equals(policyValue)
+            || SentryConstants.RESOURCE_WILDCARD_VALUE.equals(requestValue)
+            || SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equalsIgnoreCase(policyValue)
+            || SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equalsIgnoreCase(requestValue)
+            || SentryConstants.RESOURCE_WILDCARD_VALUE_SOME.equals(requestValue)) {
+      return true;
+    }
+
+    // compare as the url
+    if (ImplyMethodType.URL == implyMethodType) {
+      return PathUtils.impliesURI(policyValue, requestValue);
+    } else if (ImplyMethodType.STRING_CASE_SENSITIVE == implyMethodType) {
+      // compare as the string case sensitive
+      return policyValue.equals(requestValue);
+    }
+    // default: compare as the string case insensitive
+    return policyValue.equalsIgnoreCase(requestValue);
+  }
+
+  // The method is used for compare the action for the privilege model.
+  // for Hive, the action will be select, insert, etc.
+  // for Solr, the action will be update, query, etc.
+  private boolean impliesAction(String policyValue, String requestValue,
+                                BitFieldActionFactory bitFieldActionFactory) {
+    BitFieldAction currentAction = bitFieldActionFactory.getActionByName(policyValue);
+    BitFieldAction requestAction = bitFieldActionFactory.getActionByName(requestValue);
+    // the action in privilege is not supported
+    if (currentAction == null || requestAction == null) {
+      return false;
+    }
+    return currentAction.implies(requestAction);
+  }
+
+  @Override
+  public String toString() {
+    return SentryConstants.AUTHORIZABLE_JOINER.join(parts);
+  }
+
+  public List<KeyValue> getParts() {
+    return parts;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o instanceof CommonPrivilege) {
+      CommonPrivilege cp = (CommonPrivilege) o;
+      return parts.equals(cp.parts);
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return parts.hashCode();
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/KeyValue.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/KeyValue.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/KeyValue.java
deleted file mode 100644
index 77e5fdf..0000000
--- a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/KeyValue.java
+++ /dev/null
@@ -1,99 +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.sentry.policy.common;
-
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-public class KeyValue {
-  private final String key;
-  private final String value;
-
-  public KeyValue(String keyValue) {
-    List<String> kvList = Lists.newArrayList(PolicyConstants.KV_SPLITTER.trimResults().limit(2).split(keyValue));
-    if (kvList.size() != 2) {
-      throw new IllegalArgumentException("Invalid key value: " + keyValue + " " + kvList);
-    }
-    key = kvList.get(0);
-    value = kvList.get(1);
-    if (key.isEmpty()) {
-      throw new IllegalArgumentException("Key cannot be empty");
-    } else if (value.isEmpty()) {
-      throw new IllegalArgumentException("Value cannot be empty");
-    }
-  }
-
-  public KeyValue(String key, String value) {
-    super();
-    this.key = key;
-    this.value = value;
-  }
-
-  public String getKey() {
-    return key;
-  }
-
-  public String getValue() {
-    return value;
-  }
-
-  @Override
-  public String toString() {
-    return PolicyConstants.KV_JOINER.join(key, value);
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = 1;
-    result = prime * result + ((key == null) ? 0 : key.hashCode());
-    result = prime * result + ((value == null) ? 0 : value.hashCode());
-    return result;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    }
-    if (obj == null) {
-      return false;
-    }
-    if (getClass() != obj.getClass()) {
-      return false;
-    }
-    KeyValue other = (KeyValue) obj;
-    if (key == null) {
-      if (other.key != null) {
-        return false;
-      }
-    } else if (!key.equalsIgnoreCase(other.key)) {
-      return false;
-    }
-    if (value == null) {
-      if (other.value != null) {
-        return false;
-      }
-    } else if (!value.equalsIgnoreCase(other.value)) {
-      return false;
-    }
-    return true;
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PolicyConstants.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PolicyConstants.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PolicyConstants.java
deleted file mode 100644
index 0bad8c1..0000000
--- a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PolicyConstants.java
+++ /dev/null
@@ -1,38 +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.sentry.policy.common;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
-
-public class PolicyConstants {
-
-  public static final String ROLE_SEPARATOR = ",";
-  public static final String AUTHORIZABLE_SEPARATOR = "->";
-  public static final String KV_SEPARATOR = "=";
-
-  public static final Splitter ROLE_SPLITTER = Splitter.on(ROLE_SEPARATOR);
-  public static final Splitter AUTHORIZABLE_SPLITTER = Splitter.on(AUTHORIZABLE_SEPARATOR);
-  public static final Splitter KV_SPLITTER = Splitter.on(KV_SEPARATOR);
-  public static final Joiner ROLE_JOINER = Joiner.on(ROLE_SEPARATOR);
-  public static final Joiner AUTHORIZABLE_JOINER = Joiner.on(AUTHORIZABLE_SEPARATOR);
-  public static final Joiner KV_JOINER = Joiner.on(KV_SEPARATOR);
-
-  // TODO change to privilege
-  public static final String PRIVILEGE_NAME = "action";
-  public static final String PRIVILEGE_PREFIX = (PRIVILEGE_NAME + KV_SEPARATOR).toLowerCase();
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/Privilege.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/Privilege.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/Privilege.java
index 27d5afa..e9f4609 100644
--- a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/Privilege.java
+++ b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/Privilege.java
@@ -16,6 +16,8 @@
  */
 package org.apache.sentry.policy.common;
 
+import org.apache.sentry.core.common.Model;
+
 public interface Privilege {
-  boolean implies(Privilege p);
+  boolean implies(Privilege p, Model model);
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidator.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidator.java
deleted file mode 100644
index 36abdd4..0000000
--- a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidator.java
+++ /dev/null
@@ -1,24 +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.sentry.policy.common;
-
-import org.apache.shiro.config.ConfigurationException;
-
-public interface PrivilegeValidator {
-
-  void validate(PrivilegeValidatorContext context) throws ConfigurationException;
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidatorContext.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidatorContext.java b/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidatorContext.java
deleted file mode 100644
index 2b7fd1a..0000000
--- a/sentry-policy/sentry-policy-common/src/main/java/org/apache/sentry/policy/common/PrivilegeValidatorContext.java
+++ /dev/null
@@ -1,38 +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.sentry.policy.common;
-
-import javax.annotation.Nullable;
-
-public class PrivilegeValidatorContext {
-  private final String database;
-  private final String privilege;
-  public PrivilegeValidatorContext(String privilege) {
-    this(null, privilege);
-  }
-  public PrivilegeValidatorContext(@Nullable String database, String privilege) {
-    super();
-    this.database = database;
-    this.privilege = privilege;
-  }
-  public @Nullable String getDatabase() {
-    return database;
-  }
-  public String getPrivilege() {
-    return privilege;
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-policy/sentry-policy-common/src/test/java/org/apache/sentry/policy/common/ModelForTest.java
----------------------------------------------------------------------
diff --git a/sentry-policy/sentry-policy-common/src/test/java/org/apache/sentry/policy/common/ModelForTest.java b/sentry-policy/sentry-policy-common/src/test/java/org/apache/sentry/policy/common/ModelForTest.java
new file mode 100644
index 0000000..6c7ea08
--- /dev/null
+++ b/sentry-policy/sentry-policy-common/src/test/java/org/apache/sentry/policy/common/ModelForTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.sentry.policy.common;
+
+import org.apache.sentry.core.common.*;
+import org.apache.sentry.core.model.db.DBModelAuthorizable;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ModelForTest implements Model {
+
+  private Map<String, ImplyMethodType> implyMethodMap;
+  private BitFieldActionFactory bitFieldActionFactory;
+
+  public ModelForTest() {
+    implyMethodMap = new HashMap<String, ImplyMethodType>();
+    bitFieldActionFactory = new ActionFactoryForTest();
+
+    implyMethodMap.put(DBModelAuthorizable.AuthorizableType.Server.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(DBModelAuthorizable.AuthorizableType.Db.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(DBModelAuthorizable.AuthorizableType.Table.name().toLowerCase(), ImplyMethodType.STRING);
+    implyMethodMap.put(DBModelAuthorizable.AuthorizableType.Column.name().toLowerCase(), ImplyMethodType.STRING_CASE_SENSITIVE);
+    implyMethodMap.put(DBModelAuthorizable.AuthorizableType.URI.name().toLowerCase(), ImplyMethodType.URL);
+  }
+
+  public Map<String, ImplyMethodType> getImplyMethodMap() {
+    return implyMethodMap;
+  }
+
+  public BitFieldActionFactory getBitFieldActionFactory() {
+    return bitFieldActionFactory;
+  }
+
+  public static class ActionFactoryForTest extends BitFieldActionFactory {
+    enum ActionType {
+      SELECT("select", 1),
+      INSERT("insert", 2),
+      ALL("all", SELECT.getCode() | INSERT.getCode()),
+      ALL_STAR("*", SELECT.getCode() | INSERT.getCode());
+
+      private String name;
+      private int code;
+
+      ActionType(String name, int code) {
+        this.name = name;
+        this.code = code;
+      }
+
+      public int getCode() {
+        return code;
+      }
+
+      public String getName() {
+        return name;
+      }
+    }
+
+    public List<? extends BitFieldAction> getActionsByCode(int actionCode) {
+      return null;
+    }
+
+    public BitFieldAction getActionByName(String name) {
+      for (ActionType action : ActionType.values()) {
+        if (action.name.equalsIgnoreCase(name)) {
+          return new BitFieldAction(action.getName(), action.getCode());
+        }
+      }
+      return null;
+    }
+  }
+}