blob: 5cbb1b2cce344b12640c942d0b317232a248f7a8 [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.biz;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicyDelta;
import org.apache.ranger.plugin.model.RangerSecurityZone;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.store.RoleStore;
import org.apache.ranger.plugin.policyengine.RangerPluginContext;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
import org.apache.ranger.plugin.store.SecurityZoneStore;
import org.apache.ranger.plugin.store.ServiceStore;
import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
public class RangerPolicyAdminCache {
private static final Log LOG = LogFactory.getLog(RangerPolicyAdminCache.class);
private final Map<String, RangerPolicyAdmin> policyAdminCache = Collections.synchronizedMap(new HashMap<>());
final RangerPolicyAdmin getServicePoliciesAdmin(String serviceName, ServiceStore svcStore, RoleStore roleStore, SecurityZoneStore zoneStore, RangerPolicyEngineOptions options) {
RangerPolicyAdmin ret = null;
if (serviceName == null || svcStore == null || roleStore == null || zoneStore == null) {
LOG.warn("Cannot get policy-admin for null serviceName or serviceStore or roleStore or zoneStore");
return ret;
}
ret = policyAdminCache.get(serviceName);
long policyVersion;
long roleVersion;
RangerRoles rangerRoles;
boolean isRolesUpdated = true;
try {
if (ret == null) {
policyVersion = -1L;
roleVersion = -1L;
rangerRoles = roleStore.getRangerRoles(serviceName, roleVersion);
if (rangerRoles == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("There are no roles in ranger-admin for service:" + serviceName + "]");
}
}
} else {
policyVersion = ret.getPolicyVersion();
roleVersion = ret.getRoleVersion();
rangerRoles = roleStore.getRangerRoles(serviceName, roleVersion);
if (rangerRoles == null) { // No changes to roles
rangerRoles = roleStore.getRangerRoles(serviceName, -1L);
isRolesUpdated = false;
}
}
ServicePolicies policies = svcStore.getServicePoliciesIfUpdated(serviceName, policyVersion, false);
if (policies != null) {
if (policies.getPolicyVersion() != null && !policies.getPolicyVersion().equals(policyVersion)) {
ServicePolicies updatedServicePolicies = getUpdatedServicePolicies(serviceName, policies, svcStore, zoneStore);
ret = addOrUpdatePolicyAdmin(ret, updatedServicePolicies, rangerRoles, options);
} else {
LOG.error("policies object is null or its version is null for getPolicyAdmin(" + serviceName + ") !!");
LOG.error("Returning old policy admin");
}
} else {
if (ret == null) {
LOG.error("getPolicyAdmin(" + serviceName + "): failed to get any policies from service-store");
} else {
if (isRolesUpdated) {
ret.setRangerRoles(rangerRoles);
}
}
}
} catch (Exception excp) {
LOG.error("getPolicyAdmin(" + serviceName + "): failed to get latest policies from service-store", excp);
}
return ret;
}
private RangerPolicyAdmin addOrUpdatePolicyAdmin(RangerPolicyAdmin policyAdmin, ServicePolicies policies, RangerRoles rangerRoles, RangerPolicyEngineOptions options) {
final RangerPolicyAdmin ret;
RangerPolicyAdminImpl oldPolicyAdmin = (RangerPolicyAdminImpl) policyAdmin;
synchronized(this) {
if (oldPolicyAdmin == null || CollectionUtils.isEmpty(policies.getPolicyDeltas())) {
ret = addPolicyAdmin(policies, rangerRoles, options);
} else {
RangerPolicyAdmin updatedPolicyAdmin = RangerPolicyAdminImpl.getPolicyAdmin(oldPolicyAdmin, policies);
if (updatedPolicyAdmin != null) {
updatedPolicyAdmin.setRangerRoles(rangerRoles);
policyAdminCache.put(policies.getServiceName(), updatedPolicyAdmin);
ret = updatedPolicyAdmin;
} else {
ret = addPolicyAdmin(policies, rangerRoles, options);
}
}
if (oldPolicyAdmin != null) {
oldPolicyAdmin.releaseResources();
}
}
return ret;
}
private RangerPolicyAdmin addPolicyAdmin(ServicePolicies policies, RangerRoles rangerRoles, RangerPolicyEngineOptions options) {
RangerServiceDef serviceDef = policies.getServiceDef();
String serviceType = (serviceDef != null) ? serviceDef.getName() : "";
RangerPluginContext rangerPluginContext = new RangerPluginContext(serviceType);
RangerPolicyAdmin ret = new RangerPolicyAdminImpl("ranger-admin", policies, options, rangerPluginContext, rangerRoles);
policyAdminCache.put(policies.getServiceName(), ret);
return ret;
}
private ServicePolicies getUpdatedServicePolicies(String serviceName, ServicePolicies policies, ServiceStore svcStore, SecurityZoneStore zoneStore) throws Exception{
ServicePolicies ret = policies;
if (ret == null) {
ret = svcStore.getServicePoliciesIfUpdated(serviceName, -1L, false);
}
if (zoneStore != null) {
Map<String, RangerSecurityZone.RangerSecurityZoneService> securityZones = zoneStore.getSecurityZonesForService(serviceName);
if (MapUtils.isNotEmpty(securityZones)) {
ret = getUpdatedServicePoliciesForZones(ret, securityZones);
}
}
return ret;
}
public static ServicePolicies getUpdatedServicePoliciesForZones(ServicePolicies servicePolicies, Map<String, RangerSecurityZone.RangerSecurityZoneService> securityZones) {
final ServicePolicies ret;
if (MapUtils.isNotEmpty(securityZones)) {
ret = new ServicePolicies();
ret.setServiceDef(servicePolicies.getServiceDef());
ret.setServiceId(servicePolicies.getServiceId());
ret.setServiceName(servicePolicies.getServiceName());
ret.setAuditMode(servicePolicies.getAuditMode());
ret.setPolicyVersion(servicePolicies.getPolicyVersion());
ret.setPolicyUpdateTime(servicePolicies.getPolicyUpdateTime());
Map<String, ServicePolicies.SecurityZoneInfo> securityZonesInfo = new HashMap<>();
if (CollectionUtils.isEmpty(servicePolicies.getPolicyDeltas())) {
List<RangerPolicy> allPolicies = new ArrayList<>(servicePolicies.getPolicies());
for (Map.Entry<String, RangerSecurityZone.RangerSecurityZoneService> entry : securityZones.entrySet()) {
List<RangerPolicy> zonePolicies = extractZonePolicies(allPolicies, entry.getKey());
if (CollectionUtils.isNotEmpty(zonePolicies)) {
allPolicies.removeAll(zonePolicies);
}
ServicePolicies.SecurityZoneInfo securityZoneInfo = new ServicePolicies.SecurityZoneInfo();
securityZoneInfo.setZoneName(entry.getKey());
securityZoneInfo.setPolicies(zonePolicies);
securityZoneInfo.setResources(entry.getValue().getResources());
securityZoneInfo.setContainsAssociatedTagService(false);
securityZonesInfo.put(entry.getKey(), securityZoneInfo);
}
ret.setPolicies(allPolicies);
ret.setTagPolicies(servicePolicies.getTagPolicies());
} else {
List<RangerPolicyDelta> allPolicyDeltas = new ArrayList<>(servicePolicies.getPolicyDeltas());
for (Map.Entry<String, RangerSecurityZone.RangerSecurityZoneService> entry : securityZones.entrySet()) {
List<RangerPolicyDelta> zonePolicyDeltas = extractZonePolicyDeltas(allPolicyDeltas, entry.getKey());
if (CollectionUtils.isNotEmpty(zonePolicyDeltas)) {
allPolicyDeltas.removeAll(zonePolicyDeltas);
}
ServicePolicies.SecurityZoneInfo securityZoneInfo = new ServicePolicies.SecurityZoneInfo();
securityZoneInfo.setZoneName(entry.getKey());
securityZoneInfo.setPolicyDeltas(zonePolicyDeltas);
securityZoneInfo.setResources(entry.getValue().getResources());
securityZoneInfo.setContainsAssociatedTagService(false);
securityZonesInfo.put(entry.getKey(), securityZoneInfo);
}
ret.setPolicyDeltas(allPolicyDeltas);
}
ret.setSecurityZones(securityZonesInfo);
} else {
ret = servicePolicies;
}
return ret;
}
private static List<RangerPolicy> extractZonePolicies(final List<RangerPolicy> allPolicies, final String zoneName) {
final List<RangerPolicy> ret = new ArrayList<>();
for (RangerPolicy policy : allPolicies) {
if (policy.getIsEnabled() && StringUtils.equals(policy.getZoneName(), zoneName)) {
ret.add(policy);
}
}
return ret;
}
private static List<RangerPolicyDelta> extractZonePolicyDeltas(final List<RangerPolicyDelta> allPolicyDeltas, final String zoneName) {
final List<RangerPolicyDelta> ret = new ArrayList<>();
for (RangerPolicyDelta delta : allPolicyDeltas) {
if (StringUtils.equals(delta.getZoneName(), zoneName)) {
ret.add(delta);
}
}
return ret;
}
}