blob: 9699aa76366937d70219b82b68b05395e4ef9e24 [file] [log] [blame]
/*
* 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.ranger.service;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.biz.ServiceDBStore;
import org.apache.ranger.common.AppConstants;
import org.apache.ranger.common.RangerConstants;
import org.apache.ranger.common.view.VTrxLogAttr;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.db.XXServiceDao;
import org.apache.ranger.entity.XXPortalUser;
import org.apache.ranger.entity.XXRole;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.entity.XXUser;
import org.apache.ranger.plugin.model.RangerPolicyDelta;
import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.util.RangerEnumUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@Service
@Scope("singleton")
public class RangerRoleService extends RangerRoleServiceBase<XXRole, RangerRole> {
@Autowired
RangerEnumUtil xaEnumUtil;
private static final Log logger = LogFactory.getLog(RangerRoleService.class);
private static final Gson gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create();
static HashMap<String, VTrxLogAttr> trxLogAttrs = new HashMap<>();
static {
trxLogAttrs.put("name", new VTrxLogAttr("name", "Role Name", false));
trxLogAttrs.put("description", new VTrxLogAttr("description", "Role Description", false));
trxLogAttrs.put("options", new VTrxLogAttr("options", "Options", false));
trxLogAttrs.put("users", new VTrxLogAttr("users", "Users", false));
trxLogAttrs.put("adminUsers", new VTrxLogAttr("adminUsers", "Admin Users", false));
trxLogAttrs.put("groups", new VTrxLogAttr("groups", "Groups", false));
trxLogAttrs.put("adminGroups", new VTrxLogAttr("adminGroups", "Admin Groups", false));
trxLogAttrs.put("roles", new VTrxLogAttr("roles", "Roles", false));
trxLogAttrs.put("adminRoles", new VTrxLogAttr("adminRoles", "Admin Roles", false));
trxLogAttrs.put("createdByUser", new VTrxLogAttr("createdByUser", "Created By User", false)); }
public RangerRoleService() {
super();
}
@Override
protected void validateForCreate(RangerRole vObj) {
}
@Override
protected void validateForUpdate(RangerRole vObj, XXRole entityObj) {
}
@Override
protected XXRole mapViewToEntityBean(RangerRole rangerRole, XXRole xxRole, int OPERATION_CONTEXT) {
XXRole ret = super.mapViewToEntityBean(rangerRole, xxRole, OPERATION_CONTEXT);
ret.setRoleText(gsonBuilder.toJson(rangerRole));
return ret;
}
@Override
protected RangerRole mapEntityToViewBean(RangerRole rangerRole, XXRole xxRole) {
RangerRole ret = super.mapEntityToViewBean(rangerRole, xxRole);
if (StringUtils.isNotEmpty(xxRole.getRoleText())) {
if (logger.isDebugEnabled()) {
logger.debug("roleText=" + xxRole.getRoleText());
}
RangerRole roleFromJsonData = gsonBuilder.fromJson(xxRole.getRoleText(), RangerRole.class);
if (roleFromJsonData == null) {
logger.info("Cannot read jsonData into RangerRole object in [" + xxRole.getRoleText() + "]!!");
} else {
if (logger.isDebugEnabled()) {
logger.debug("Role object built from JSON :[" + roleFromJsonData +"]");
}
ret.setOptions(roleFromJsonData.getOptions());
ret.setUsers(roleFromJsonData.getUsers());
ret.setGroups(roleFromJsonData.getGroups());
ret.setRoles(roleFromJsonData.getRoles());
ret.setCreatedByUser(roleFromJsonData.getCreatedByUser());
}
} else {
logger.info("Empty string representing jsonData in [" + xxRole + "]!!");
}
return ret;
}
public List<XXTrxLog> getTransactionLog(RangerRole current, RangerRole former, String action) {
if (current == null || action == null || ("update".equalsIgnoreCase(action) && former == null)) {
return null;
}
List<XXTrxLog> trxLogList = new ArrayList<>();
Field[] fields = current.getClass().getDeclaredFields();
String users = RangerConstants.MODULE_USER_GROUPS.split("/")[0];
String groups = RangerConstants.MODULE_USER_GROUPS.split("/")[1];
try {
Field nameField = current.getClass().getDeclaredField("name");
nameField.setAccessible(true);
String objectName = "" + nameField.get(current);
for (Field field : fields) {
String fieldName = field.getName();
if (!trxLogAttrs.containsKey(fieldName)) {
continue;
}
field.setAccessible(true);
VTrxLogAttr vTrxLogAttr = trxLogAttrs.get(fieldName);
XXTrxLog xTrxLog = new XXTrxLog();
xTrxLog.setAttributeName(vTrxLogAttr
.getAttribUserFriendlyName());
xTrxLog.setAction(action);
xTrxLog.setObjectId(current.getId());
xTrxLog.setObjectClassType(AppConstants.CLASS_TYPE_RANGER_ROLE);
xTrxLog.setObjectName(objectName);
if(!StringUtils.isNotBlank(current.getCreatedByUser())){
if (logger.isDebugEnabled()) {
logger.debug("Created User = " + current.getCreatedByUser());
}
XXPortalUser xXPortalUser = daoMgr.getXXPortalUser().findByLoginId(current.getCreatedByUser());
if(xXPortalUser != null){
if (logger.isDebugEnabled()) {
logger.debug("User Id for " + current.getCreatedByUser() + " = " + xXPortalUser.getId());
}
xTrxLog.setAddedByUserId(xXPortalUser.getId());
xTrxLog.setUpdatedByUserId(xXPortalUser.getId());
}
}
String value;
if (vTrxLogAttr.isEnum()) {
String enumName = XXUser.getEnumName(fieldName);
int enumValue = field.get(current) == null ? 0 : Integer
.parseInt("" + field.get(current));
value = xaEnumUtil.getLabel(enumName, enumValue);
} else {
value = "" + field.get(current);
if (fieldName.equalsIgnoreCase(users) || fieldName.equalsIgnoreCase(groups)
|| fieldName.equalsIgnoreCase(RangerConstants.ROLE_FIELD)) {
if (fieldName.equalsIgnoreCase(users)) {
value = JsonUtils.listToJson(current.getUsers());
}
else if (fieldName.equalsIgnoreCase(groups)) {
value = JsonUtils.listToJson(current.getGroups());
}
else if (fieldName.equalsIgnoreCase(RangerConstants.ROLE_FIELD)) {
value = JsonUtils.listToJson(current.getRoles());
}
}
if ((value == null || "null".equalsIgnoreCase(value))
&& !"update".equalsIgnoreCase(action)) {
continue;
}
}
if("options".equalsIgnoreCase(fieldName)) {
value = JsonUtils.mapToJson(current.getOptions());
}
if ("create".equalsIgnoreCase(action)) {
xTrxLog.setNewValue(value);
trxLogList.add(xTrxLog);
}
else if ("delete".equalsIgnoreCase(action)) {
xTrxLog.setPreviousValue(value);
trxLogList.add(xTrxLog);
}
else if ("update".equalsIgnoreCase(action)) {
String formerValue = null;
Field[] mFields = current.getClass().getDeclaredFields();
for (Field mField : mFields) {
mField.setAccessible(true);
String mFieldName = mField.getName();
if (fieldName.equalsIgnoreCase(mFieldName)) {
if("options".equalsIgnoreCase(mFieldName)) {
formerValue = JsonUtils.mapToJson(former.getOptions());
}
else {
formerValue = mField.get(former) + "";
if (fieldName.equalsIgnoreCase(users) || fieldName.equalsIgnoreCase(groups)
|| fieldName.equalsIgnoreCase(RangerConstants.ROLE_FIELD)) {
if (fieldName.equalsIgnoreCase(users)) {
formerValue = JsonUtils.listToJson(former.getUsers());
}
else if (fieldName.equalsIgnoreCase(groups)) {
formerValue = JsonUtils.listToJson(former.getGroups());
}
else if (fieldName.equalsIgnoreCase(RangerConstants.ROLE_FIELD)) {
formerValue = JsonUtils.listToJson(former.getRoles());
}
}
}
break;
}
}
value = ((value == null) ? "" : value);
formerValue = ((formerValue == null) ? "" : formerValue);
if (formerValue.equalsIgnoreCase(value)) {
continue;
}
xTrxLog.setPreviousValue(formerValue);
xTrxLog.setNewValue(value);
trxLogList.add(xTrxLog);
}
if(logger.isDebugEnabled()) {
logger.debug("AddedByUserId for " + xTrxLog.getObjectName() + " = " + xTrxLog.getAddedByUserId());
}
}
if (trxLogList.isEmpty()) {
if(logger.isDebugEnabled()) {
logger.debug("trxLogList is empty!!");
}
trxLogList = null;
}
} catch (IllegalAccessException e) {
logger.error("Transaction log failure.", e);
} catch (NoSuchFieldException e) {
logger.error("Transaction log failure.", e);
}
return trxLogList;
}
public void updatePolicyVersions(Long roleId) {
if (logger.isDebugEnabled()) {
logger.debug("==> updatePolicyVersions(roleId=" + roleId + ")");
}
// Get all roles which include this role because change to this affects all these roles
Set<Long> containingRoles = getContainingRoles(roleId);
if (logger.isDebugEnabled()) {
logger.debug("All containing Roles for roleId:[" + roleId +"] are [" + containingRoles + "]");
}
updatePolicyVersions(containingRoles);
if (logger.isDebugEnabled()) {
logger.debug("<== updatePolicyVersions(roleId=" + roleId + ")");
}
}
private Set<Long> getContainingRoles(Long roleId) {
Set<Long> ret = new HashSet<>();
addContainingRoles(roleId, ret);
return ret;
}
public void updateRoleVersions(Long roleId) {
if (logger.isDebugEnabled()) {
logger.debug("==> updateRoleVersions(roleId=" + roleId + ")");
}
// Get all roles which include this role because change to this affects all these roles
Set<Long> containingRoles = getContainingRoles(roleId);
if (logger.isDebugEnabled()) {
logger.debug("All containing Roles for roleId:[" + roleId +"] are [" + containingRoles + "]");
}
updateRoleVersions(containingRoles);
if (logger.isDebugEnabled()) {
logger.debug("<== updateRoleVersions(roleId=" + roleId + ")");
}
}
private void addContainingRoles(Long roleId, Set<Long> allRoles) {
if (logger.isDebugEnabled()) {
logger.debug("==> addContainingRoles(roleId=" + roleId + ")");
}
if (!allRoles.contains(roleId)) {
allRoles.add(roleId);
Set<Long> roles = daoMgr.getXXRoleRefRole().getContainingRoles(roleId);
for (Long role : roles) {
addContainingRoles(role, allRoles);
}
}
if (logger.isDebugEnabled()) {
logger.debug("<== addContainingRoles(roleId=" + roleId + ")");
}
}
private void updatePolicyVersions(Set<Long> roleIds) {
if (logger.isDebugEnabled()) {
logger.debug("==> updatePolicyVersions(roleIds=" + roleIds + ")");
}
if (CollectionUtils.isNotEmpty(roleIds)) {
Set<Long> allAffectedServiceIds = new HashSet<>();
for (Long roleId : roleIds) {
List<Long> affectedServiceIds = daoMgr.getXXPolicy().findServiceIdsByRoleId(roleId);
allAffectedServiceIds.addAll(affectedServiceIds);
}
if (CollectionUtils.isNotEmpty(allAffectedServiceIds)) {
for (final Long serviceId : allAffectedServiceIds) {
Runnable serviceVersionUpdater = new ServiceDBStore.ServiceVersionUpdater(daoMgr, serviceId, ServiceDBStore.VERSION_TYPE.POLICY_VERSION, null, RangerPolicyDelta.CHANGE_TYPE_SERVICE_CHANGE, null);
daoMgr.getRangerTransactionSynchronizationAdapter().executeOnTransactionCommit(serviceVersionUpdater);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("<== updatePolicyVersions(roleIds=" + roleIds + ")");
}
}
private void updateRoleVersions(Set<Long> roleIds) {
if (logger.isDebugEnabled()) {
logger.debug("==> updatePolicyVersions(roleIds=" + roleIds + ")");
}
if (CollectionUtils.isNotEmpty(roleIds)) {
Set<Long> allAffectedServiceIds = new HashSet<>();
for (Long roleId : roleIds) {
List<Long> affectedServiceIds = daoMgr.getXXPolicy().findServiceIdsByRoleId(roleId);
allAffectedServiceIds.addAll(affectedServiceIds);
}
XXServiceDao serviceDao = daoMgr.getXXService();
if (CollectionUtils.isNotEmpty(allAffectedServiceIds)) {
for (final Long serviceId : allAffectedServiceIds) {
Runnable serviceVersionUpdater = new ServiceDBStore.ServiceVersionUpdater(daoMgr, serviceId, ServiceDBStore.VERSION_TYPE.ROLE_VERSION, null, RangerPolicyDelta.CHANGE_TYPE_ROLE_UPDATE, null);
daoMgr.getRangerTransactionSynchronizationAdapter().executeOnTransactionCommit(serviceVersionUpdater);
XXService serviceDbObj = serviceDao.getById(serviceId);
boolean isTagService = serviceDbObj.getType() == EmbeddedServiceDefsUtil.instance().getTagServiceDefId();
if (isTagService) {
updateRoleVersionOfAllServicesRefferingTag(daoMgr, serviceDao, serviceId);
}
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("<== updatePolicyVersions(roleIds=" + roleIds + ")");
}
}
private void updateRoleVersionOfAllServicesRefferingTag(RangerDaoManager daoManager, XXServiceDao serviceDao, Long serviceId) {
List<XXService> referringServices = serviceDao.findByTagServiceId(serviceId);
if(CollectionUtils.isNotEmpty(referringServices)) {
for(XXService referringService : referringServices) {
final Long referringServiceId = referringService.getId();
Runnable roleVersionUpdater = new ServiceDBStore.ServiceVersionUpdater(daoManager, referringServiceId, ServiceDBStore.VERSION_TYPE.ROLE_VERSION, null, RangerPolicyDelta.CHANGE_TYPE_ROLE_UPDATE, null);
daoMgr.getRangerTransactionSynchronizationAdapter().executeOnTransactionCommit(roleVersionUpdater);
}
}
}
}