Repository: incubator-sentry Updated Branches: refs/heads/db_policy_store a7df761dd -> 066f993e5
SENTRY-132 - Implement APIs that grant/revoke roles to groups (Brock via Shreepadma) Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/066f993e Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/066f993e Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/066f993e Branch: refs/heads/db_policy_store Commit: 066f993e57d23ecfcaade818b133d82e1a6b3f2f Parents: a7df761 Author: Shreepadma Venugopalan <[email protected]> Authored: Wed Mar 12 13:50:22 2014 -0700 Committer: Shreepadma Venugopalan <[email protected]> Committed: Wed Mar 12 13:50:22 2014 -0700 ---------------------------------------------------------------------- .../provider/db/service/model/MSentryGroup.java | 70 ++++++++- .../db/service/model/MSentryPrivilege.java | 120 +++++++++++++-- .../provider/db/service/model/MSentryRole.java | 62 +++++++- .../db/service/persistent/SentryStore.java | 112 ++++++++++++-- .../thrift/SentryPolicyStoreProcessor.java | 10 +- .../main/resources/sentry_policy_service.thrift | 8 +- .../db/service/persistent/TestSentryStore.java | 145 +++++++++++++++++++ 7 files changed, 487 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java index 15982a3..b5de36e 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java @@ -22,17 +22,21 @@ import java.util.Set; import javax.jdo.annotations.PersistenceCapable; +/** + * Database backed Sentry Group. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ @PersistenceCapable public class MSentryGroup { - String groupName; + private String groupName; // set of roles granted to this group - Set<MSentryRole> roles; - long createTime; - String grantorPrincipal; + private Set<MSentryRole> roles; + private long createTime; + private String grantorPrincipal; - MSentryGroup(String groupName, long createTime, String grantorPrincipal, - Set<MSentryRole> roles) { + public MSentryGroup(String groupName, long createTime, String grantorPrincipal, + Set<MSentryRole> roles) { this.setGroupName(groupName); this.createTime = createTime; this.grantorPrincipal = grantorPrincipal; @@ -71,7 +75,57 @@ public class MSentryGroup { this.groupName = groupName; } - public void appendRoles(Set<MSentryRole> roles) { - this.roles.addAll(roles); + public void appendRole(MSentryRole role) { + if (roles.add(role)) { + role.appendGroup(this); + } + } + + public void removeRole(MSentryRole role) { + if (roles.remove(role)) { + role.removeGroup(this); + } + } + + @Override + public String toString() { + return "MSentryGroup [groupName=" + groupName + ", roles=[...]" + + ", createTime=" + createTime + ", grantorPrincipal=" + + grantorPrincipal + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (createTime ^ (createTime >>> 32)); + result = prime * result + + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode()); + result = prime * result + ((groupName == null) ? 0 : groupName.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; + MSentryGroup other = (MSentryGroup) obj; + if (createTime != other.createTime) + return false; + if (grantorPrincipal == null) { + if (other.grantorPrincipal != null) + return false; + } else if (!grantorPrincipal.equals(other.grantorPrincipal)) + return false; + if (groupName == null) { + if (other.groupName != null) + return false; + } else if (!groupName.equals(other.groupName)) + return false; + return true; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java index 9642689..7215435 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java @@ -24,28 +24,32 @@ import java.util.Set; import javax.jdo.annotations.PersistenceCapable; +/** + * Database backed Sentry Privilege. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ @PersistenceCapable public class MSentryPrivilege { - String privilegeScope; - String privilegeName; - String serverName; - String dbName; - String tableName; - String URI; - String action; + private String privilegeScope; + private String privilegeName; + private String serverName; + private String dbName; + private String tableName; + private String URI; + private String action; // roles this privilege is a part of - Set<MSentryRole> roles; - long createTime; - String grantorPrincipal; + private Set<MSentryRole> roles; + private long createTime; + private String grantorPrincipal; public MSentryPrivilege() { this.roles = new HashSet<MSentryRole>(); } public MSentryPrivilege(String privilegeName, String privilegeScope, - String serverName, String dbName, String tableName, String URI, - String action) { + String serverName, String dbName, String tableName, String URI, + String action) { this.privilegeName = privilegeName; this.privilegeScope = privilegeScope; this.serverName = serverName; @@ -148,4 +152,96 @@ public class MSentryPrivilege { } } } + + public void removeRole(String roleName) { + for (MSentryRole role: roles) { + if (role.getRoleName().equalsIgnoreCase(roleName)) { + roles.remove(role); + return; + } + } + } + + @Override + public String toString() { + return "MSentryPrivilege [privilegeScope=" + privilegeScope + + ", privilegeName=" + privilegeName + ", serverName=" + serverName + + ", dbName=" + dbName + ", tableName=" + tableName + ", URI=" + URI + + ", action=" + action + ", roles=[...]" + ", createTime=" + + createTime + ", grantorPrincipal=" + grantorPrincipal + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((URI == null) ? 0 : URI.hashCode()); + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + (int) (createTime ^ (createTime >>> 32)); + result = prime * result + ((dbName == null) ? 0 : dbName.hashCode()); + result = prime * result + + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode()); + result = prime * result + + ((privilegeName == null) ? 0 : privilegeName.hashCode()); + result = prime * result + + ((privilegeScope == null) ? 0 : privilegeScope.hashCode()); + result = prime * result + + ((serverName == null) ? 0 : serverName.hashCode()); + result = prime * result + ((tableName == null) ? 0 : tableName.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; + MSentryPrivilege other = (MSentryPrivilege) obj; + if (URI == null) { + if (other.URI != null) + return false; + } else if (!URI.equals(other.URI)) + return false; + if (action == null) { + if (other.action != null) + return false; + } else if (!action.equals(other.action)) + return false; + if (createTime != other.createTime) + return false; + if (dbName == null) { + if (other.dbName != null) + return false; + } else if (!dbName.equals(other.dbName)) + return false; + if (grantorPrincipal == null) { + if (other.grantorPrincipal != null) + return false; + } else if (!grantorPrincipal.equals(other.grantorPrincipal)) + return false; + if (privilegeName == null) { + if (other.privilegeName != null) + return false; + } else if (!privilegeName.equals(other.privilegeName)) + return false; + if (privilegeScope == null) { + if (other.privilegeScope != null) + return false; + } else if (!privilegeScope.equals(other.privilegeScope)) + return false; + if (serverName == null) { + if (other.serverName != null) + return false; + } else if (!serverName.equals(other.serverName)) + return false; + if (tableName == null) { + if (other.tableName != null) + return false; + } else if (!tableName.equals(other.tableName)) + return false; + return true; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java index 9559c57..16be80b 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java @@ -26,6 +26,10 @@ import javax.jdo.annotations.PersistenceCapable; import org.apache.sentry.provider.db.service.persistent.SentryNoSuchObjectException; +/** + * Database backed Sentry Role. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ @PersistenceCapable public class MSentryRole { @@ -42,7 +46,7 @@ public class MSentryRole { } MSentryRole(String roleName, long createTime, String grantorPrincipal, - Set<MSentryPrivilege> privileges, Set<MSentryGroup> groups) { + Set<MSentryPrivilege> privileges, Set<MSentryGroup> groups) { this.roleName = roleName; this.createTime = createTime; this.grantorPrincipal = grantorPrincipal; @@ -115,7 +119,61 @@ public class MSentryRole { this.groups.addAll(groups); } + public void appendGroup(MSentryGroup group) { + if (groups.add(group)) { + group.appendRole(this); + } + } + + public void removeGroup(MSentryGroup group) { + if (groups.remove(group)) { + group.removeRole(this); + } + } + public void removePrivileges() { this.privileges.clear(); } -} \ No newline at end of file + + @Override + public String toString() { + return "MSentryRole [roleName=" + roleName + ", privileges=[..]" + + ", groups=[...]" + ", createTime=" + createTime + + ", grantorPrincipal=" + grantorPrincipal + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (createTime ^ (createTime >>> 32)); + result = prime * result + + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode()); + result = prime * result + ((roleName == null) ? 0 : roleName.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; + MSentryRole other = (MSentryRole) obj; + if (createTime != other.createTime) + return false; + if (grantorPrincipal == null) { + if (other.grantorPrincipal != null) + return false; + } else if (!grantorPrincipal.equals(other.grantorPrincipal)) + return false; + if (roleName == null) { + if (other.roleName != null) + return false; + } else if (!roleName.equals(other.roleName)) + return false; + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java index 5df6657..f1e502a 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java @@ -19,6 +19,7 @@ package org.apache.sentry.provider.db.service.persistent; import java.util.HashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.UUID; @@ -29,15 +30,21 @@ import javax.jdo.PersistenceManagerFactory; import javax.jdo.Query; import javax.jdo.Transaction; +import org.apache.sentry.provider.db.service.model.MSentryGroup; import org.apache.sentry.provider.db.service.model.MSentryPrivilege; import org.apache.sentry.provider.db.service.model.MSentryRole; +import org.apache.sentry.provider.db.service.thrift.TSentryGroup; import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege; import org.apache.sentry.provider.db.service.thrift.TSentryRole; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class SentryStore { private static final UUID SERVER_UUID = UUID.randomUUID(); + static final String DEFAULT_DATA_DIR = "sentry_policy_db"; /** * Commit order sequence id. This is used by notification handlers * to know the order in which events where committed to the database. @@ -48,13 +55,19 @@ public class SentryStore { private long commitSequenceId; private final Properties prop; private final PersistenceManagerFactory pmf; + private final String databaseName; - public SentryStore () { + public SentryStore(String dataDir) { commitSequenceId = 0; + databaseName = (dataDir = dataDir.trim()).isEmpty() ? DEFAULT_DATA_DIR : dataDir; prop = getDataSourceProperties(); pmf = JDOHelper.getPersistenceManagerFactory(prop); } + public SentryStore() { + this(""); + } + public synchronized void stop() { if (pmf != null) { pmf.close(); @@ -89,7 +102,7 @@ public class SentryStore { prop.setProperty("javax.jdo.option.ConnectionPassword", "Sentry"); prop.setProperty("javax.jdo.option.Multithreaded", "true"); prop.setProperty("javax.jdo.option.ConnectionURL", - "jdbc:derby:;databaseName=sentry_policy_db;create=true"); + "jdbc:derby:;databaseName=" + databaseName + ";create=true"); return prop; } @@ -142,7 +155,7 @@ public class SentryStore { } private void rollbackTransaction(PersistenceManager pm) { - if (pm == null) { + if (pm == null || pm.isClosed()) { return; } Transaction currentTransaction = pm.currentTransaction(); @@ -200,6 +213,7 @@ public class SentryStore { MSentryPrivilege mPrivilege = convertToMSentryPrivilege(privilege); // add privilege and role objects to each other. needed by datanucleus to model // m:n relationships correctly through a join table. + mPrivilege.appendRole(mRole); mRole.appendPrivilege(mPrivilege); pm.makePersistent(mRole); pm.makePersistent(mPrivilege); @@ -280,19 +294,88 @@ public class SentryStore { } } - public CommitContext alterSentryRoleAddGroups() + public CommitContext alterSentryRoleAddGroups(String grantorPrincipal, + String roleName, Set<TSentryGroup> groupNames) throws SentryNoSuchObjectException { - // TODO implement - throw new RuntimeException("TODO"); + boolean rollbackTransaction = true; + PersistenceManager pm = null; + try { + pm = openTransaction(); + Query query = pm.newQuery(MSentryRole.class); + query.setFilter("this.roleName == t"); + query.declareParameters("java.lang.String t"); + query.setUnique(true); + MSentryRole role = (MSentryRole) query.execute(roleName); + if (role == null) { + throw new SentryNoSuchObjectException("Role: " + roleName); + } else { + query = pm.newQuery(MSentryGroup.class); + query.setFilter("this.groupName == t"); + query.declareParameters("java.lang.String t"); + query.setUnique(true); + List<MSentryGroup> groups = Lists.newArrayList(); + for (TSentryGroup tGroup : groupNames) { + MSentryGroup group = (MSentryGroup) query.execute(tGroup.getGroupName()); + if (group == null) { + group = new MSentryGroup(tGroup.getGroupName(), System.currentTimeMillis(), + grantorPrincipal, Sets.newHashSet(role)); + } + group.appendRole(role); + groups.add(group); + } + pm.makePersistentAll(groups); + CommitContext commit = commitUpdateTransaction(pm); + rollbackTransaction = false; + return commit; + } + } finally { + if (rollbackTransaction) { + rollbackTransaction(pm); + } + } } - public CommitContext alterSentryRoleDeleteGroups() + public CommitContext alterSentryRoleDeleteGroups(String roleName, + Set<TSentryGroup> groupNames) throws SentryNoSuchObjectException { - // TODO implement - throw new RuntimeException("TODO"); + boolean rollbackTransaction = true; + PersistenceManager pm = null; + try { + pm = openTransaction(); + Query query = pm.newQuery(MSentryRole.class); + query.setFilter("this.roleName == t"); + query.declareParameters("java.lang.String t"); + query.setUnique(true); + MSentryRole role = (MSentryRole) query.execute(roleName); + if (role == null) { + throw new SentryNoSuchObjectException("Role: " + roleName); + } else { + query = pm.newQuery(MSentryGroup.class); + query.setFilter("this.groupName == t"); + query.declareParameters("java.lang.String t"); + query.setUnique(true); + List<MSentryGroup> groups = Lists.newArrayList(); + for (TSentryGroup tGroup : groupNames) { + MSentryGroup group = (MSentryGroup) query.execute(tGroup.getGroupName()); + if (group != null) { + group.removeRole(role); + groups.add(group); + } + } + pm.makePersistentAll(groups); + CommitContext commit = commitUpdateTransaction(pm); + rollbackTransaction = false; + return commit; + } + } finally { + if (rollbackTransaction) { + rollbackTransaction(pm); + } + } } - public TSentryRole getSentryRoleByName(String roleName) + @VisibleForTesting + MSentryRole getMSentryRoleByName(String roleName) throws SentryNoSuchObjectException { boolean rollbackTransaction = true; PersistenceManager pm = null; @@ -311,7 +394,7 @@ public class SentryStore { } rollbackTransaction = false; commitTransaction(pm); - return convertToSentryRole(sentryRole); + return sentryRole; } finally { if (rollbackTransaction) { rollbackTransaction(pm); @@ -319,6 +402,11 @@ public class SentryStore { } } + public TSentryRole getSentryRoleByName(String roleName) + throws SentryNoSuchObjectException { + return convertToSentryRole(getMSentryRoleByName(roleName)); + } + private MSentryRole convertToMSentryRole(TSentryRole role) { MSentryRole mRole = new MSentryRole(); mRole.setCreateTime(role.getCreateTime()); @@ -370,4 +458,4 @@ public class SentryStore { mSentryPrivilege.setPrivilegeName(privilege.getPrivilegeName()); return mSentryPrivilege; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java index 78e0a87..ff4817f 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java @@ -40,6 +40,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; @SuppressWarnings("unused") public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface { @@ -100,7 +101,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface { } //TODO:Validate privilege scope? - private String constructPrivilegeName(TSentryPrivilege privilege) throws SentryInvalidInputException { + @VisibleForTesting + public static String constructPrivilegeName(TSentryPrivilege privilege) throws SentryInvalidInputException { StringBuilder privilegeName = new StringBuilder(); String serverName = privilege.getServerName(); String dbName = privilege.getDbName(); @@ -219,6 +221,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface { LOGGER.error(msg, e); response.setStatus(Status.RuntimeError(msg, e)); } + return response; } @@ -249,7 +252,8 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface { TAlterSentryRoleAddGroupsRequest request) throws TException { TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse(); try { - CommitContext commitContext = sentryStore.alterSentryRoleAddGroups(); + CommitContext commitContext = sentryStore.alterSentryRoleAddGroups(request.getUserName(), + request.getRoleName(), request.getGroups()); response.setStatus(Status.OK()); notificationHandlerInvoker.alter_sentry_role_add_groups(commitContext, request, response); @@ -271,7 +275,7 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface { // TODO implement TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse(); try { - CommitContext commitContext = sentryStore.alterSentryRoleDeleteGroups(); + CommitContext commitContext = sentryStore.alterSentryRoleDeleteGroups(null, null); response.setStatus(Status.OK()); notificationHandlerInvoker.alter_sentry_role_delete_groups(commitContext, request, response); http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift b/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift index d6e05b7..7c54290 100644 --- a/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift +++ b/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift @@ -30,8 +30,8 @@ namespace php sentry.provider.db.service.thrift namespace cpp Apache.Sentry.Provider.Db.Service.Thrift struct TSentryPrivilege { -1: required string privilegeScope, -2: optional string privilegeName, +1: required string privilegeScope, # Valid values are SERVER, DATABASE, TABLE +2: optional string privilegeName, # Generated on server side 3: required string serverName, 4: optional string dbName, 5: optional string tableName, @@ -43,6 +43,8 @@ struct TSentryPrivilege { struct TSentryRole { 1: required string roleName, +# TODO privs should not be part of Sentry role as +# they are created when a grant is executed 2: required set<TSentryPrivilege> privileges, 3: required i64 createTime, 4: required string grantorPrincipal @@ -136,4 +138,4 @@ service SentryPolicyService TListSentryRolesResponse list_sentry_roles_by_group(1:TListSentryRolesRequest request) TListSentryRolesResponse list_sentry_roles_by_role_name(1:TListSentryRolesRequest request) -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/066f993e/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java new file mode 100644 index 0000000..be3d078 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java @@ -0,0 +1,145 @@ +/** + * 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.provider.db.service.persistent; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import java.io.File; +import java.util.Collections; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.provider.db.service.model.MSentryPrivilege; +import org.apache.sentry.provider.db.service.model.MSentryRole; +import org.apache.sentry.provider.db.service.thrift.SentryPolicyStoreProcessor; +import org.apache.sentry.provider.db.service.thrift.TSentryGroup; +import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.db.service.thrift.TSentryRole; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; +import com.google.common.io.Files; + +public class TestSentryStore { + + private static File dataDir; + private static SentryStore sentryStore; + + @BeforeClass + public static void setup() throws Exception { + dataDir = new File(Files.createTempDir(), SentryStore.DEFAULT_DATA_DIR); + sentryStore = new SentryStore(dataDir.getPath()); + } + + @AfterClass + public static void teardown() { + if (sentryStore != null) { + sentryStore.stop(); + } + if (dataDir != null) { + FileUtils.deleteQuietly(dataDir); + } + } + + private static CommitContext createRole(String r, String g) throws Exception { + TSentryRole role = new TSentryRole(); + role.setGrantorPrincipal(g); + role.setRoleName(r); + return sentryStore.createSentryRole(role); + } + + + @Test + public void testCreateDuplicateRole() throws Exception { + String roleName = "test-dup-role"; + String grantor = "g1"; + createRole(roleName, grantor); + try { + createRole(roleName, grantor); + fail("Expected SentryAlreadyExistsException"); + } catch(SentryAlreadyExistsException e) { + // expected + } + } + + @Test + public void testCreateDropRole() throws Exception { + String roleName = "test-drop-role"; + String grantor = "g1"; + long seqId = createRole(roleName, grantor).getSequenceId(); + assertEquals(seqId + 1, sentryStore.dropSentryRole(roleName).getSequenceId()); + } + + @Test(expected = SentryNoSuchObjectException.class) + public void testAddDeleteGroupsNonExistantRole() + throws Exception { + String roleName = "non-existant-role"; + String grantor = "g1"; + Set<TSentryGroup> groups = Sets.newHashSet(); + sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); + } + + @Test + public void testAddDeleteGroups() throws Exception { + String roleName = "test-groups"; + String grantor = "g1"; + long seqId = createRole(roleName, grantor).getSequenceId(); + Set<TSentryGroup> groups = Sets.newHashSet(); + TSentryGroup group = new TSentryGroup(); + group.setGroupName("test-groups-g1"); + groups.add(group); + group = new TSentryGroup(); + group.setGroupName("test-groups-g2"); + groups.add(group); + assertEquals(seqId + 1, sentryStore.alterSentryRoleAddGroups(grantor, + roleName, groups).getSequenceId()); + assertEquals(seqId + 2, sentryStore.alterSentryRoleDeleteGroups(roleName, groups) + .getSequenceId()); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + assertEquals(Collections.emptySet(), role.getGroups()); + } + + @Test + public void testGrantRevokePrivilege() throws Exception { + String roleName = "test-privilege"; + String grantor = "g1"; + long seqId = createRole(roleName, grantor).getSequenceId(); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName("server1"); + privilege.setDbName("db1"); + privilege.setTableName("tbl1"); + privilege.setAction("SELECT"); + privilege.setGrantorPrincipal(grantor); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setPrivilegeName(SentryPolicyStoreProcessor.constructPrivilegeName(privilege)); + assertEquals(seqId + 1, sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege) + .getSequenceId()); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set<MSentryPrivilege> privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + assertEquals(privilege.getPrivilegeName(), Iterables.get(privileges, 0).getPrivilegeName()); + assertEquals(seqId + 2, sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege.getPrivilegeName()) + .getSequenceId()); + } +}
