You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by pr...@apache.org on 2020/06/01 11:08:56 UTC
[ranger] 02/02: RANGER-2840 : Create policy with non existing group
is failing due to multiple threads creating same group
This is an automated email from the ASF dual-hosted git repository.
pradeep pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 5d1f87cd92eeed7cc7deb3fd0f7e688ef71e9250
Author: Dineshkumar Yadav <di...@outlook.com>
AuthorDate: Fri May 29 16:30:44 2020 +0530
RANGER-2840 : Create policy with non existing group is failing due to multiple threads creating same group
Signed-off-by: pradeep <pr...@apache.org>
---
.../org/apache/ranger/biz/PolicyRefUpdater.java | 254 ++++++++++++++++++---
1 file changed, 223 insertions(+), 31 deletions(-)
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
index f978d5d..564a2e7 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
@@ -28,6 +28,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.common.RangerCommonEnums;
+import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXAccessTypeDef;
import org.apache.ranger.entity.XXDataMaskTypeDef;
@@ -44,6 +45,7 @@ import org.apache.ranger.entity.XXPolicyRefUser;
import org.apache.ranger.entity.XXResourceDef;
import org.apache.ranger.entity.XXRole;
import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.entity.XXUser;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
@@ -53,6 +55,8 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.service.RangerAuditFields;
+import org.apache.ranger.service.RangerTransactionService;
+import org.apache.ranger.service.XGroupService;
import org.apache.ranger.service.XUserService;
import org.apache.ranger.view.VXGroup;
import org.springframework.beans.factory.annotation.Autowired;
@@ -83,6 +87,15 @@ public class PolicyRefUpdater {
@Autowired
RangerBizUtil rangerBizUtil;
+ @Autowired
+ XGroupService xGroupService;
+
+ @Autowired
+ RangerTransactionSynchronizationAdapter rangerTransactionSynchronizationAdapter;
+
+ @Autowired
+ RangerTransactionService transactionService;
+
public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy, XXServiceDef xServiceDef) throws Exception {
if(policy == null) {
return;
@@ -180,7 +193,6 @@ public class PolicyRefUpdater {
RangerBizUtil.setBulkMode(oldBulkMode);
daoMgr.getXXPolicyRefRole().batchCreate(xPolRoles);
- List<XXPolicyRefGroup> xPolGroups = new ArrayList<>();
for (String group : groupNames) {
if (StringUtils.isBlank(group)) {
continue;
@@ -190,24 +202,13 @@ public class PolicyRefUpdater {
Long groupId = null;
if (xGroup != null) {
groupId = xGroup.getId();
+ groupPolicyAssociation(xPolicy,groupId,group );
}
else {
- RangerBizUtil.setBulkMode(false);
- groupId = createGroupForPolicy(group);
+ createGroupForPolicy(group, xPolicy);
}
-
- XXPolicyRefGroup xPolGroup = rangerAuditFields.populateAuditFields(new XXPolicyRefGroup(), xPolicy);
-
- xPolGroup.setPolicyId(policy.getId());
- xPolGroup.setGroupId(groupId);
- xPolGroup.setGroupName(group);
-
- xPolGroups.add(xPolGroup);
}
- RangerBizUtil.setBulkMode(oldBulkMode);
- daoMgr.getXXPolicyRefGroup().batchCreate(xPolGroups);
- List<XXPolicyRefUser> xPolUsers = new ArrayList<>();
for (String user : userNames) {
if (StringUtils.isBlank(user)) {
continue;
@@ -217,23 +218,13 @@ public class PolicyRefUpdater {
Long userId = null;
if(xUser != null){
userId = xUser.getId();
+ userPolicyAssociation(xPolicy,userId, user );
}
else {
- RangerBizUtil.setBulkMode(false);
-
- userId = createUserForPolicy(user);
+ createUserForPolicy(user,xPolicy);
}
- XXPolicyRefUser xPolUser = rangerAuditFields.populateAuditFields(new XXPolicyRefUser(), xPolicy);
-
- xPolUser.setPolicyId(policy.getId());
- xPolUser.setUserId(userId);
- xPolUser.setUserName(user);
-
- xPolUsers.add(xPolUser);
}
- RangerBizUtil.setBulkMode(oldBulkMode);
- daoMgr.getXXPolicyRefUser().batchCreate(xPolUsers);
List<XXPolicyRefAccessType> xPolAccesses = new ArrayList<>();
for (String accessType : accessTypes) {
@@ -290,18 +281,44 @@ public class PolicyRefUpdater {
daoMgr.getXXPolicyRefDataMaskType().batchCreate(xxDataMaskInfos);
}
- private Long createUserForPolicy(String user) {
+ private void createUserForPolicy(String user, XXPolicy xPolicy) {
LOG.warn("User specified in policy does not exist in ranger admin, creating new user, User = " + user);
- return xUserMgr.createExternalUser(user).getId();
+ final PolicyUserCreateContext policyUserCreateContext = new PolicyUserCreateContext(user, xPolicy);
+ Runnable CreateAndAssociateUser = new Runnable () {
+ @Override
+ public void run() {
+ Runnable realTask = new Runnable () {
+ @Override
+ public void run() {
+ doCreateAndAssociatePolicyUser(policyUserCreateContext);
+ }
+ };
+ transactionService.scheduleToExecuteInOwnTransaction(realTask, 0L);
+ }
+ };
+ rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(CreateAndAssociateUser);
}
- private Long createGroupForPolicy(String group) {
+ private void createGroupForPolicy(String group, XXPolicy xPolicy) {
LOG.warn("Group specified in policy does not exist in ranger admin, creating new group, Group = " + group);
VXGroup vxGroup = new VXGroup();
vxGroup.setName(group);
vxGroup.setGroupSource(RangerCommonEnums.GROUP_EXTERNAL);
- VXGroup vxGroupCreated= xUserMgr.createXGroup(vxGroup);
- return vxGroupCreated.getId();
+ final PolicyGroupCreateContext policyGroupCreateContext = new PolicyGroupCreateContext(vxGroup, xPolicy);
+ Runnable createAndAssociatePolicyGroup = new Runnable() {
+ @Override
+ public void run() {
+ Runnable realTask = new Runnable() {
+ @Override
+ public void run() {
+ doCreateAndAssociatePolicyGroup(policyGroupCreateContext);
+ }
+ };
+ transactionService.scheduleToExecuteInOwnTransaction(realTask, 0L);
+ }
+ };
+ rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(createAndAssociatePolicyGroup);
+
}
private Long createRoleForPolicy(String role) throws Exception {
@@ -363,4 +380,179 @@ public class PolicyRefUpdater {
return ret;
}
+
+ public void groupPolicyAssociation(XXPolicy xPolicy, Long groupId, String groupName) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.groupPolicyAssociation()");
+ }
+
+ XXPolicyRefGroup xPolGroup = rangerAuditFields.populateAuditFields(new XXPolicyRefGroup(), xPolicy);
+
+ xPolGroup.setPolicyId(xPolicy.getId());
+ xPolGroup.setGroupId(groupId);
+ xPolGroup.setGroupName(groupName);
+ daoMgr.getXXPolicyRefGroup().create(xPolGroup);
+ }
+
+ private static final class PolicyGroupCreateContext {
+ final VXGroup group;
+ final XXPolicy xPolicy;
+
+ PolicyGroupCreateContext(VXGroup group, XXPolicy xPolicy) {
+ this.group = group;
+ this.xPolicy = xPolicy;
+ }
+
+ @Override
+ public String toString() {
+ return "{group=" + group + ", xPolicy=" + xPolicy + "}";
+ }
+ }
+
+ void doAssociatePolicyGroup(final PolicyGroupCreateContext context) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.doAssociatePolicyGroup()");
+ }
+ XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(context.group.getName());
+
+ if (xGroup == null) {
+ LOG.error("No Group created!! Irrecoverable error! PolicyGroupContext:[" + context + "]");
+ } else {
+ try {
+ groupPolicyAssociation(context.xPolicy, xGroup.getId(), context.group.getName());
+ } catch (Exception exception) {
+ LOG.error("Failed to associate group and policy, PolicyGroupContext:[" + context + "]", exception);
+ }
+ }
+ }
+
+ void doCreateAndAssociatePolicyGroup(final PolicyGroupCreateContext context) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.doCreateAndAssociatePolicyGroup()");
+ }
+ XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(context.group.getName());
+
+ if (xGroup != null) {
+ groupPolicyAssociation(context.xPolicy, xGroup.getId(), context.group.getName());
+ } else {
+ try {
+ // Create group
+ VXGroup vXGroup = xGroupService.createXGroupWithOutLogin(context.group);
+ if (null != vXGroup) {
+ List<XXTrxLog> trxLogList = xGroupService.getTransactionLog(vXGroup, "create");
+ for(XXTrxLog xTrxLog : trxLogList) {
+ xTrxLog.setAddedByUserId(context.xPolicy.getAddedByUserId());
+ xTrxLog.setUpdatedByUserId(context.xPolicy.getAddedByUserId());
+ }
+ rangerBizUtil.createTrxLog(trxLogList);
+ }
+ } catch (Exception exception) {
+ LOG.error("Failed to create Group or to associate group and policy, PolicyGroupContext:[" + context + "]",
+ exception);
+ } finally {
+ // This transaction may still fail at commit time because another transaction
+ // has already created the group
+ // So, associate the group to policy in a different transaction
+ Runnable associatePolicyGroup = new Runnable() {
+ @Override
+ public void run() {
+ Runnable realTask = new Runnable() {
+ @Override
+ public void run() {
+ doAssociatePolicyGroup(context);
+ }
+ };
+ transactionService.scheduleToExecuteInOwnTransaction(realTask, 0L);
+ }
+ };
+ rangerTransactionSynchronizationAdapter.executeOnTransactionCompletion(associatePolicyGroup);
+
+ }
+ }
+ }
+
+ private static final class PolicyUserCreateContext {
+ final String userName;
+ final XXPolicy xPolicy;
+
+ PolicyUserCreateContext(String userName, XXPolicy xPolicy) {
+ this.userName = userName;
+ this.xPolicy = xPolicy;
+ }
+
+ @Override
+ public String toString() {
+ return "{userName=" + userName + ", xPolicy=" + xPolicy + "}";
+ }
+ }
+
+ public void userPolicyAssociation(XXPolicy xPolicy, Long userId, String userName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.userPolicyAssociation()");
+ }
+
+ XXPolicyRefUser xPolUser = rangerAuditFields.populateAuditFields(new XXPolicyRefUser(), xPolicy);
+
+ xPolUser.setPolicyId(xPolicy.getId());
+ xPolUser.setUserId(userId);
+ xPolUser.setUserName(userName);
+ daoMgr.getXXPolicyRefUser().create(xPolUser);
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<=== PolicyRefUpdater.userPolicyAssociation()");
+ }
+ }
+
+ void doAssociatePolicyUser(final PolicyUserCreateContext context) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.doAssociatePolicyUser()");
+ }
+ XXUser xUser = daoMgr.getXXUser().findByUserName(context.userName);
+
+ if (xUser == null) {
+ LOG.error("No User created!! Irrecoverable error! PolicyUserContext:[" + context + "]");
+ } else {
+ try {
+ userPolicyAssociation(context.xPolicy, xUser.getId(), context.userName);
+ } catch (Exception exception) {
+ LOG.error("Failed to associate user and policy, PolicyUserContext:[" + context + "]", exception);
+ }
+ }
+ }
+
+ void doCreateAndAssociatePolicyUser(final PolicyUserCreateContext context) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("===> PolicyRefUpdater.doCreateAndAssociatePolicyUser()");
+ }
+ XXUser xUser = daoMgr.getXXUser().findByUserName(context.userName);
+
+ if (xUser != null) {
+ userPolicyAssociation(context.xPolicy, xUser.getId(), context.userName);
+ } else {
+ try {
+ // Create External user
+ xUserMgr.createServiceConfigUser(context.userName);
+ } catch (Exception exception) {
+ LOG.error("Failed to create User or to associate user and policy, PolicyUserContext:[" + context + "]",
+ exception);
+ } finally {
+ // This transaction may still fail at commit time because another transaction
+ // has already created the user
+ // So, associate the user to policy in a different transaction
+ Runnable associatePolicyUser = new Runnable() {
+ @Override
+ public void run() {
+ Runnable realTask = new Runnable() {
+ @Override
+ public void run() {
+ doAssociatePolicyUser(context);
+ }
+ };
+ transactionService.scheduleToExecuteInOwnTransaction(realTask, 0L);
+ }
+ };
+ rangerTransactionSynchronizationAdapter.executeOnTransactionCompletion(associatePolicyUser);
+ }
+ }
+
+ }
}