You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by rm...@apache.org on 2019/09/27 20:09:25 UTC
[ranger] branch master updated: RANGER-2512:RangerRolesRESTClient
for serving user group roles to the plugins for evaluation
This is an automated email from the ASF dual-hosted git repository.
rmani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new b69227e RANGER-2512:RangerRolesRESTClient for serving user group roles to the plugins for evaluation
b69227e is described below
commit b69227eb2f6b8aacb539a6454c714923257de059
Author: rmani <rm...@hortonworks.com>
AuthorDate: Thu Sep 26 23:27:31 2019 -0700
RANGER-2512:RangerRolesRESTClient for serving user group roles to the plugins for evaluation
Signed-off-by: rmani <rm...@hortonworks.com>
---
.../admin/client/AbstractRangerAdminClient.java | 5 +
.../ranger/admin/client/RangerAdminClient.java | 3 +
.../ranger/admin/client/RangerAdminRESTClient.java | 81 +++++
.../ranger/plugin/model/RangerPluginInfo.java | 49 +++
.../ranger/plugin/model/RangerPolicyDelta.java | 3 +-
.../plugin/policyengine/RangerPolicyEngine.java | 7 +-
.../policyengine/RangerPolicyEngineCache.java | 4 +-
.../policyengine/RangerPolicyEngineImpl.java | 68 +++-
.../ranger/plugin/service/RangerAuthContext.java | 14 +-
.../ranger/plugin/service/RangerBasePlugin.java | 30 +-
.../apache/ranger/plugin/util/PolicyRefresher.java | 20 +-
.../apache/ranger/plugin/util/RangerRESTUtils.java | 20 ++
.../org/apache/ranger/plugin/util/RangerRoles.java | 78 +++++
.../ranger/plugin/util/RangerRolesProvider.java | 352 +++++++++++++++++++++
.../apache/ranger/plugin/util/RangerRolesUtil.java | 106 +++++++
.../apache/ranger/plugin/util/ServicePolicies.java | 15 +-
.../plugin/policyengine/TestPolicyEngine.java | 48 ++-
.../admin/client/RangerAdminJersey2RESTClient.java | 87 +++++
.../optimized/current/ranger_core_db_mysql.sql | 2 +
.../043-add-role-version-in-serviceVersionInfo.sql | 34 ++
.../optimized/current/ranger_core_db_oracle.sql | 2 +
.../043-add-role-version-in-serviceVersionInfo.sql | 28 ++
.../optimized/current/ranger_core_db_postgres.sql | 2 +
.../043-add-role-version-in-serviceVersionInfo.sql | 36 +++
.../current/ranger_core_db_sqlanywhere.sql | 2 +
.../043-add-role-version-in-serviceVersionInfo.sql | 25 ++
.../optimized/current/ranger_core_db_sqlserver.sql | 2 +
.../042-add-role-version-in-serviceVersionInfo.sql | 29 ++
.../main/java/org/apache/ranger/biz/AssetMgr.java | 123 +++++--
.../java/org/apache/ranger/biz/RoleDBStore.java | 39 +++
.../java/org/apache/ranger/biz/ServiceDBStore.java | 69 +---
.../org/apache/ranger/common/RangerRoleCache.java | 142 +++++++++
.../org/apache/ranger/db/XXGlobalStateDao.java | 47 +++
.../apache/ranger/entity/XXServiceVersionInfo.java | 22 ++
.../main/java/org/apache/ranger/rest/RoleREST.java | 189 +++++++++++
.../java/org/apache/ranger/rest/ServiceREST.java | 2 -
.../apache/ranger/service/RangerRoleService.java | 43 +++
37 files changed, 1688 insertions(+), 140 deletions(-)
diff --git a/agents-common/src/main/java/org/apache/ranger/admin/client/AbstractRangerAdminClient.java b/agents-common/src/main/java/org/apache/ranger/admin/client/AbstractRangerAdminClient.java
index 6367235..2bc7557 100644
--- a/agents-common/src/main/java/org/apache/ranger/admin/client/AbstractRangerAdminClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/admin/client/AbstractRangerAdminClient.java
@@ -37,6 +37,11 @@ public abstract class AbstractRangerAdminClient implements RangerAdminClient {
}
@Override
+ public RangerRoles getRolesIfUpdated(long lastKnownRoleVersion, long lastActivationTimeInMillis) throws Exception {
+ return null;
+ }
+
+ @Override
public RangerRole createRole(RangerRole request) throws Exception {
return null;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminClient.java b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminClient.java
index b09a9be..9510888 100644
--- a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminClient.java
@@ -23,6 +23,7 @@
import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.GrantRevokeRoleRequest;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.apache.ranger.plugin.util.ServiceTags;
@@ -35,6 +36,8 @@ public interface RangerAdminClient {
ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion, long lastActivationTimeInMillis) throws Exception;
+ RangerRoles getRolesIfUpdated(long lastKnownRoleVersion, long lastActivationTimeInMills) throws Exception;
+
RangerRole createRole(RangerRole request) throws Exception;
void dropRole(String execUser, String roleName) throws Exception;
diff --git a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
index 5939f38..f564ba5 100644
--- a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
@@ -195,6 +195,87 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
}
@Override
+ public RangerRoles getRolesIfUpdated(final long lastKnownRoleVersion, final long lastActivationTimeInMillis) throws Exception {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerAdminRESTClient.getRolesIfUpdated(" + lastKnownRoleVersion + ", " + lastActivationTimeInMillis + ")");
+ }
+
+ final RangerRoles ret;
+ final UserGroupInformation user = MiscUtil.getUGILoginUser();
+ final boolean isSecureMode = user != null && UserGroupInformation.isSecurityEnabled();
+ final ClientResponse response;
+
+ Map<String, String> queryParams = new HashMap<String, String>();
+ queryParams.put(RangerRESTUtils.REST_PARAM_LAST_KNOWN_ROLE_VERSION, Long.toString(lastKnownRoleVersion));
+ queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
+ queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, pluginId);
+ queryParams.put(RangerRESTUtils.REST_PARAM_CLUSTER_NAME, clusterName);
+
+ if (isSecureMode) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Checking Roles updated as user : " + user);
+ }
+ PrivilegedAction<ClientResponse> action = new PrivilegedAction<ClientResponse>() {
+ public ClientResponse run() {
+ ClientResponse clientRes = null;
+ String relativeURL = RangerRESTUtils.REST_URL_SERVICE_SERCURE_GET_USER_GROUP_ROLES + serviceNameUrlParam;
+ try {
+ clientRes = restClient.get(relativeURL, queryParams);
+ } catch (Exception e) {
+ LOG.error("Failed to get response, Error is : "+e.getMessage());
+ }
+ return clientRes;
+ }
+ };
+ response = user.doAs(action);
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Checking Roles updated as user : " + user);
+ }
+ String relativeURL = RangerRESTUtils.REST_URL_SERVICE_GET_USER_GROUP_ROLES + serviceNameUrlParam;
+ response = restClient.get(relativeURL, queryParams);
+ }
+
+ if (response == null || response.getStatus() == HttpServletResponse.SC_NOT_MODIFIED) {
+ if (response == null) {
+ LOG.error("Error getting Roles; Received NULL response!!. secureMode=" + isSecureMode + ", user=" + user + ", serviceName=" + serviceName);
+ } else {
+ RESTResponse resp = RESTResponse.fromClientResponse(response);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No change in Roles. secureMode=" + isSecureMode + ", user=" + user
+ + ", response=" + resp + ", serviceName=" + serviceName
+ + ", " + "lastKnownRoleVersion=" + lastKnownRoleVersion
+ + ", " + "lastActivationTimeInMillis=" + lastActivationTimeInMillis);
+ }
+ }
+ ret = null;
+ } else if (response.getStatus() == HttpServletResponse.SC_OK) {
+ ret = response.getEntity(RangerRoles.class);
+ } else if (response.getStatus() == HttpServletResponse.SC_NOT_FOUND) {
+ ret = null;
+ LOG.error("Error getting Roles; service not found. secureMode=" + isSecureMode + ", user=" + user
+ + ", response=" + response.getStatus() + ", serviceName=" + serviceName
+ + ", " + "lastKnownRoleVersion=" + lastKnownRoleVersion
+ + ", " + "lastActivationTimeInMillis=" + lastActivationTimeInMillis);
+ String exceptionMsg = response.hasEntity() ? response.getEntity(String.class) : null;
+
+ RangerServiceNotFoundException.throwExceptionIfServiceNotFound(serviceName, exceptionMsg);
+
+ LOG.warn("Received 404 error code with body:[" + exceptionMsg + "], Ignoring");
+ } else {
+ RESTResponse resp = RESTResponse.fromClientResponse(response);
+ LOG.warn("Error getting Roles. secureMode=" + isSecureMode + ", user=" + user + ", response=" + resp + ", serviceName=" + serviceName);
+ ret = null;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerAdminRESTClient.getRolesIfUpdated(" + lastKnownRoleVersion + ", " + lastActivationTimeInMillis + "): ");
+ }
+
+ return ret;
+ }
+
+ @Override
public RangerRole createRole(final RangerRole request) throws Exception {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerAdminRESTClient.createRole(" + request + ")");
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPluginInfo.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPluginInfo.java
index e3f9f15..4bd374e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPluginInfo.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPluginInfo.java
@@ -43,6 +43,7 @@ public class RangerPluginInfo implements Serializable {
public static final int ENTITY_TYPE_POLICIES = 0;
public static final int ENTITY_TYPE_TAGS = 1;
+ public static final int ENTITY_TYPE_ROLES = 2;
public static final String PLUGIN_INFO_POLICY_DOWNLOAD_TIME = "policyDownloadTime";
public static final String PLUGIN_INFO_POLICY_DOWNLOADED_VERSION = "policyDownloadedVersion";
@@ -53,6 +54,10 @@ public class RangerPluginInfo implements Serializable {
public static final String PLUGIN_INFO_TAG_ACTIVATION_TIME = "tagActivationTime";
public static final String PLUGIN_INFO_TAG_ACTIVE_VERSION = "tagActiveVersion";
+ public static final String PLUGIN_INFO_ROLE_DOWNLOAD_TIME = "roleDownloadTime";
+ public static final String PLUGIN_INFO_ROLE_DOWNLOADED_VERSION = "roleDownloadedVersion";
+ public static final String PLUGIN_INFO_ROLE_ACTIVATION_TIME = "roleActivationTime";
+ public static final String PLUGIN_INFO_ROLE_ACTIVE_VERSION = "roleActiveVersion";
public static final String RANGER_ADMIN_LAST_POLICY_UPDATE_TIME = "lastPolicyUpdateTime";
public static final String RANGER_ADMIN_LATEST_POLICY_VERSION = "latestPolicyVersion";
@@ -271,6 +276,50 @@ public class RangerPluginInfo implements Serializable {
return StringUtils.isNotBlank(updateTimeString) ? Long.valueOf(updateTimeString) : null;
}
+ @JsonIgnore
+ public void setRoleDownloadTime(Long roleDownloadTime) {
+ getInfo().put(PLUGIN_INFO_ROLE_DOWNLOAD_TIME, roleDownloadTime == null ? null : Long.toString(roleDownloadTime));
+ }
+
+ @JsonIgnore
+ public Long getRoleDownloadTime() {
+ String downloadTimeString = getInfo().get(PLUGIN_INFO_ROLE_DOWNLOAD_TIME);
+ return StringUtils.isNotBlank(downloadTimeString) ? Long.valueOf(downloadTimeString) : null;
+ }
+
+ @JsonIgnore
+ public void setRoleDownloadedVersion(Long roleDownloadedVersion) {
+ getInfo().put(PLUGIN_INFO_ROLE_DOWNLOADED_VERSION, roleDownloadedVersion == null ? null : Long.toString(roleDownloadedVersion));
+ }
+
+ @JsonIgnore
+ public Long getRoleDownloadedVersion() {
+ String downloadedVersionString = getInfo().get(PLUGIN_INFO_ROLE_DOWNLOADED_VERSION);
+ return StringUtils.isNotBlank(downloadedVersionString) ? Long.valueOf(downloadedVersionString) : null;
+ }
+
+ @JsonIgnore
+ public void setRoleActivationTime(Long roleActivationTime) {
+ getInfo().put(PLUGIN_INFO_ROLE_ACTIVATION_TIME, roleActivationTime == null ? null : Long.toString(roleActivationTime));
+ }
+
+ @JsonIgnore
+ public Long getRoleActivationTime() {
+ String activationTimeString = getInfo().get(PLUGIN_INFO_ROLE_ACTIVATION_TIME);
+ return StringUtils.isNotBlank(activationTimeString) ? Long.valueOf(activationTimeString) : null;
+ }
+
+ @JsonIgnore
+ public void setRoleActiveVersion(Long roleActiveVersion) {
+ getInfo().put(PLUGIN_INFO_ROLE_ACTIVE_VERSION, roleActiveVersion == null ? null : Long.toString(roleActiveVersion));
+ }
+
+ @JsonIgnore
+ public Long getRoleActiveVersion() {
+ String activeVersionString = getInfo().get(PLUGIN_INFO_POLICY_ACTIVE_VERSION);
+ return StringUtils.isNotBlank(activeVersionString) ? Long.valueOf(activeVersionString) : null;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyDelta.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyDelta.java
index 1b69d8d..1d2b143 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyDelta.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyDelta.java
@@ -44,8 +44,9 @@ public class RangerPolicyDelta implements java.io.Serializable {
public static final int CHANGE_TYPE_RANGER_ADMIN_START = 5;
public static final int CHANGE_TYPE_LOG_ERROR = 6;
public static final int CHANGE_TYPE_INVALIDATE_POLICY_DELTAS = 7;
+ public static final int CHANGE_TYPE_ROLE_UPDATE = 8;
- private static String[] changeTypeNames = { "POLICY_CREATE", "POLICY_UPDATE", "POLICY_DELETE", "SERVICE_CHANGE", "SERVICE_DEF_CHANGE", "RANGER_ADMIN_START", "LOG_ERROR", "INVALIDATE_POLICY_DELTAS" };
+ private static String[] changeTypeNames = { "POLICY_CREATE", "POLICY_UPDATE", "POLICY_DELETE", "SERVICE_CHANGE", "SERVICE_DEF_CHANGE", "RANGER_ADMIN_START", "LOG_ERROR", "INVALIDATE_POLICY_DELTAS", "ROLE_UPDATE" };
private Long id;
private Integer changeType;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
index d201aa6..72628ea 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
@@ -29,6 +29,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
public interface RangerPolicyEngine {
@@ -93,7 +94,11 @@ public interface RangerPolicyEngine {
List<RangerPolicy> getAllowedPolicies(String user, Set<String> userGroups, String accessType);
- RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies);
+ RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies, RangerRoles rangerRoles);
+
+ RangerRoles getRangerRoles();
+
+ void setRangerRoles(RangerRoles rangerRoles);
Set<String> getRolesFromUserAndGroups(String user, Set<String> groups);
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
index 015ca09..5dae0c1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
@@ -92,7 +92,7 @@ public class RangerPolicyEngineCache {
if (CollectionUtils.isNotEmpty(policies.getPolicyDeltas())) {
- RangerPolicyEngine updatedEngine = policyEngine.cloneWithDelta(policies);
+ RangerPolicyEngine updatedEngine = policyEngine.cloneWithDelta(policies, policyEngine.getRangerRoles());
if (updatedEngine != null) {
policyEngineCache.put(policies.getServiceName(), updatedEngine);
ret = updatedEngine;
@@ -120,8 +120,6 @@ public class RangerPolicyEngineCache {
ret.setAuditMode(servicePolicies.getAuditMode());
ret.setPolicyVersion(servicePolicies.getPolicyVersion());
ret.setPolicyUpdateTime(servicePolicies.getPolicyUpdateTime());
- ret.setUserRoles(servicePolicies.getUserRoles());
- ret.setGroupRoles(servicePolicies.getGroupRoles());
Map<String, ServicePolicies.SecurityZoneInfo> securityZonesInfo = new HashMap<>();
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index c23a2d4..77648fd 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -30,6 +30,7 @@ import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicyDelta;
+import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher;
@@ -43,6 +44,8 @@ import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.RangerResourceTrie;
import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil;
+import org.apache.ranger.plugin.util.RangerRoles;
+import org.apache.ranger.plugin.util.RangerRolesUtil;
import org.apache.ranger.plugin.util.ServicePolicies;
import java.util.ArrayList;
@@ -74,6 +77,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
private final RangerPolicyRepository tagPolicyRepository;
private List<RangerContextEnricher> allContextEnrichers;
+ private RangerRoles rangerRoles;
private boolean useForwardedIPAddress;
private String[] trustedProxyAddresses;
@@ -81,18 +85,27 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
private Map<String, RangerPolicyRepository> policyRepositories = new HashMap<>();
private Map<String, RangerResourceTrie> trieMap;
+ private Map<String, Set<String>> userRoleMapping;
+ private Map<String, Set<String>> groupRoleMapping;
private Map<String, String> zoneTagServiceMap;
- private final Map<String, Set<String>> userRoleMapping;
- private final Map<String, Set<String>> groupRoleMapping;
private final RangerPluginContext pluginContext;
public RangerPolicyEngineImpl(final RangerPolicyEngineImpl other, ServicePolicies servicePolicies) {
+ this(other,servicePolicies, null);
+ }
+
+ public RangerPolicyEngineImpl(final RangerPolicyEngineImpl other, ServicePolicies servicePolicies, RangerRoles rangerRoles) {
long policyVersion = servicePolicies.getPolicyVersion();
this.useForwardedIPAddress = other.useForwardedIPAddress;
this.trustedProxyAddresses = other.trustedProxyAddresses;
+ if (rangerRoles != null) {
+ this.rangerRoles = rangerRoles;
+ setUserGroupRoleMapping(rangerRoles);
+ }
+
this.pluginContext = other.pluginContext;
List<RangerPolicyDelta> defaultZoneDeltas = new ArrayList<>();
@@ -206,15 +219,19 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
this.allContextEnrichers = tmpList;
- // Initialize role-related information
- userRoleMapping = MapUtils.isNotEmpty(servicePolicies.getUserRoles()) ? servicePolicies.getUserRoles() : null;
- groupRoleMapping = MapUtils.isNotEmpty(servicePolicies.getGroupRoles()) ? servicePolicies.getGroupRoles() : null;
-
reorderPolicyEvaluators();
}
+ public RangerPolicyEngineImpl(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options) {
+ this(appId, servicePolicies, options, null);
+ }
+
public RangerPolicyEngineImpl(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options, RangerPluginContext rangerPluginContext) {
+ this(appId, servicePolicies, options, rangerPluginContext, null);
+ }
+
+ public RangerPolicyEngineImpl(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options, RangerPluginContext rangerPluginContext, RangerRoles rangerRoles) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> RangerPolicyEngineImpl(" + appId + ", " + servicePolicies + ", " + options + ", " + rangerPluginContext + ")");
@@ -235,6 +252,11 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
this.pluginContext = (rangerPluginContext != null) ? rangerPluginContext : new RangerPluginContext(servicePolicies.getServiceDef().getName());
+ if (rangerRoles != null) {
+ this.rangerRoles = rangerRoles;
+ setUserGroupRoleMapping(rangerRoles);
+ }
+
RangerAuthContext authContext = new RangerAuthContext(this, null, this.pluginContext);
this.pluginContext.setAuthContext(authContext);
@@ -305,10 +327,6 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
}
- // Initialize role-related information
- userRoleMapping = MapUtils.isNotEmpty(servicePolicies.getUserRoles()) ? servicePolicies.getUserRoles() : null;
- groupRoleMapping = MapUtils.isNotEmpty(servicePolicies.getGroupRoles()) ? servicePolicies.getGroupRoles() : null;
-
RangerPerfTracer.log(perf);
if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) {
@@ -323,7 +341,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
@Override
- public RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies) {
+ public RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies, RangerRoles rangerRoles) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> cloneWithDelta(" + Arrays.toString(servicePolicies.getPolicyDeltas().toArray()) + ", " + servicePolicies.getPolicyVersion() + ")");
}
@@ -359,7 +377,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
if (isValidDeltas) {
- ret = new RangerPolicyEngineImpl(this, servicePolicies);
+ ret = new RangerPolicyEngineImpl(this, servicePolicies, rangerRoles);
} else {
ret = null;
}
@@ -1328,7 +1346,13 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
@Override
public Set<String> getRolesFromUserAndGroups(String user, Set<String> groups) {
Set<String> allRoles = new HashSet<>();
- if (MapUtils.isNotEmpty(userRoleMapping) && StringUtils.isNotEmpty(user)) {
+
+ if (rangerRoles != null ) {
+ userRoleMapping = MapUtils.isNotEmpty(this.userRoleMapping) ? this.userRoleMapping : null;
+ groupRoleMapping = MapUtils.isNotEmpty(this.groupRoleMapping) ? this.groupRoleMapping : null;
+ }
+
+ if (MapUtils.isNotEmpty(userRoleMapping) && StringUtils.isNotEmpty(user)) {
Set<String> userRoles = userRoleMapping.get(user);
if (CollectionUtils.isNotEmpty(userRoles)) {
allRoles.addAll(userRoles);
@@ -1353,6 +1377,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
return allRoles;
}
+ public RangerRoles getRangerRoles() {
+ return this.rangerRoles;
+ }
+
+ public void setRangerRoles(RangerRoles rangerRoles) {
+ this.rangerRoles = rangerRoles;
+ }
+
public List<RangerPolicy> getResourcePolicies(String zoneName) {
RangerPolicyRepository zoneResourceRepository = policyRepositories.get(zoneName);
return zoneResourceRepository == null ? ListUtils.EMPTY_LIST : zoneResourceRepository.getPolicies();
@@ -1985,4 +2017,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
return other;
}
+
+ private void setUserGroupRoleMapping(RangerRoles rangerRoles) {
+ Set<RangerRole> rangerRoleSet = rangerRoles.getRangerRoles();
+ if (CollectionUtils.isNotEmpty(rangerRoleSet)) {
+ RangerRolesUtil rangerRolesUtil = new RangerRolesUtil();
+ rangerRolesUtil.init(rangerRoleSet);
+ userRoleMapping = rangerRolesUtil.getUserRoleMapping();
+ groupRoleMapping = rangerRolesUtil.getGroupRoleMapping();
+ }
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java
index 842c58b..6cd1df6 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java
@@ -39,6 +39,7 @@ import org.apache.ranger.plugin.policyengine.RangerResourceACLs;
import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
import java.util.Collection;
@@ -351,9 +352,9 @@ public class RangerAuthContext implements RangerPolicyEngine {
}
@Override
- public RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies) {
+ public RangerPolicyEngine cloneWithDelta(ServicePolicies servicePolicies, RangerRoles rangerRoles) {
if (policyEngine != null) {
- return policyEngine.cloneWithDelta(servicePolicies);
+ return policyEngine.cloneWithDelta(servicePolicies, rangerRoles);
}
return null;
}
@@ -366,5 +367,14 @@ public class RangerAuthContext implements RangerPolicyEngine {
return null;
}
+ public RangerRoles getRangerRoles() {
+ return policyEngine.getRangerRoles();
+ }
+ @Override
+ public void setRangerRoles(RangerRoles rangerRoles) {
+ if (policyEngine != null) {
+ policyEngine.setRangerRoles(rangerRoles);
+ }
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
index cf833b7..1325a40 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
@@ -77,6 +77,8 @@ public class RangerBasePlugin {
private Timer policyEngineRefreshTimer;
private RangerAuthContextListener authContextListener;
private AuditProviderFactory auditProviderFactory;
+ private RangerRolesProvider rangerRolesProvider;
+ private RangerRoles rangerRoles;
private final BlockingQueue<DownloadTrigger> policyDownloadQueue = new LinkedBlockingQueue<>();
private final DownloadTrigger accessTrigger = new DownloadTrigger();
@@ -151,6 +153,14 @@ public class RangerBasePlugin {
this.clusterName = clusterName;
}
+ public RangerRoles getRangerRoles() {
+ return this.rangerRoles;
+ }
+
+ public void setRangerRoles(RangerRoles rangerRoles) {
+ this.rangerRoles = rangerRoles;
+ }
+
public RangerServiceDef getServiceDef() {
RangerPolicyEngine policyEngine = this.policyEngine;
@@ -225,7 +235,9 @@ public class RangerBasePlugin {
RangerAdminClient admin = createAdminClient(serviceName, appId, propertyPrefix);
- refresher = new PolicyRefresher(this, serviceType, appId, serviceName, admin, policyDownloadQueue, cacheDir);
+ rangerRolesProvider = new RangerRolesProvider(serviceType, appId, serviceName, admin, cacheDir);
+
+ refresher = new PolicyRefresher(this, serviceType, appId, serviceName, admin, policyDownloadQueue, cacheDir, rangerRolesProvider);
refresher.setDaemon(true);
refresher.startRefresher();
@@ -279,6 +291,7 @@ public class RangerBasePlugin {
ServicePolicies servicePolicies = null;
boolean isValid = true;
boolean usePolicyDeltas = false;
+ boolean updateRangerRolesOnly = false;
if (policies == null) {
policies = getDefaultSvcPolicies();
@@ -287,7 +300,7 @@ public class RangerBasePlugin {
isValid = false;
}
} else {
- if ((policies.getPolicies() == null && policies.getPolicyDeltas() == null) || (policies.getPolicies() != null && policies.getPolicyDeltas() != null)) {
+ if ((policies.getPolicies() != null && policies.getPolicyDeltas() != null)) {
LOG.error("Invalid servicePolicies: Both policies and policy-deltas cannot be null OR both of them cannot be non-null");
isValid = false;
} else if (policies.getPolicies() != null) {
@@ -302,6 +315,9 @@ public class RangerBasePlugin {
isValid = false;
LOG.error("Could not apply deltas=" + Arrays.toString(policies.getPolicyDeltas().toArray()));
}
+ } else if (policies.getPolicies() == null && policies.getPolicyDeltas() == null && rangerRoles != null) {
+ // When no policies changes and only the role changes happens then update the policyengine with Role changes only.
+ updateRangerRolesOnly = true;
} else {
LOG.error("Should not get here!!");
isValid = false;
@@ -311,11 +327,13 @@ public class RangerBasePlugin {
if (isValid) {
RangerPolicyEngine newPolicyEngine = null;
- if (!usePolicyDeltas) {
+ if(updateRangerRolesOnly) {
+ this.policyEngine.setRangerRoles(rangerRoles);
+ } else if (!usePolicyDeltas) {
if (LOG.isDebugEnabled()) {
LOG.debug("policies are not null. Creating engine from policies");
}
- newPolicyEngine = new RangerPolicyEngineImpl(appId, policies, policyEngineOptions, rangerPluginContext);
+ newPolicyEngine = new RangerPolicyEngineImpl(appId, policies, policyEngineOptions, rangerPluginContext, rangerRoles);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("policy-deltas are not null");
@@ -324,7 +342,7 @@ public class RangerBasePlugin {
if (LOG.isDebugEnabled()) {
LOG.debug("Non empty policy-deltas found. Cloning engine using policy-deltas");
}
- newPolicyEngine = oldPolicyEngine.cloneWithDelta(policies);
+ newPolicyEngine = oldPolicyEngine.cloneWithDelta(policies, rangerRoles);
if (newPolicyEngine != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Applied policyDeltas=" + Arrays.toString(policies.getPolicyDeltas().toArray()) + ")");
@@ -334,7 +352,7 @@ public class RangerBasePlugin {
LOG.debug("Failed to apply policyDeltas=" + Arrays.toString(policies.getPolicyDeltas().toArray()) + "), Creating engine from policies");
LOG.debug("Creating new engine from servicePolicies:[" + servicePolicies + "]");
}
- newPolicyEngine = new RangerPolicyEngineImpl(appId, servicePolicies, policyEngineOptions, rangerPluginContext);
+ newPolicyEngine = new RangerPolicyEngineImpl(appId, servicePolicies, policyEngineOptions, rangerPluginContext, rangerRoles);
}
} else {
if (LOG.isDebugEnabled()) {
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
index 0e52c31..d4d7902 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
@@ -47,6 +47,7 @@ public class PolicyRefresher extends Thread {
private final String serviceName;
private final RangerAdminClient rangerAdmin;
private final BlockingQueue<DownloadTrigger> policyDownloadQueue;
+ private final RangerRolesProvider rangerRolesProvider;
private final String cacheFileName;
private final String cacheDir;
@@ -58,7 +59,7 @@ public class PolicyRefresher extends Thread {
private boolean policiesSetInPlugin;
private boolean serviceDefSetInPlugin;
- public PolicyRefresher(RangerBasePlugin plugIn, String serviceType, String appId, String serviceName, RangerAdminClient rangerAdmin, BlockingQueue<DownloadTrigger> policyDownloadQueue, String cacheDir) {
+ public PolicyRefresher(RangerBasePlugin plugIn, String serviceType, String appId, String serviceName, RangerAdminClient rangerAdmin, BlockingQueue<DownloadTrigger> policyDownloadQueue, String cacheDir, RangerRolesProvider rangerRolesProvider) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").PolicyRefresher()");
}
@@ -68,6 +69,7 @@ public class PolicyRefresher extends Thread {
this.serviceName = serviceName;
this.rangerAdmin = rangerAdmin;
this.policyDownloadQueue = policyDownloadQueue;
+ this.rangerRolesProvider = rangerRolesProvider;
if(StringUtils.isEmpty(appId)) {
appId = serviceType;
@@ -133,7 +135,7 @@ public class PolicyRefresher extends Thread {
}
public void startRefresher() {
-
+ loadRoles();
loadPolicy();
super.start();
@@ -158,6 +160,7 @@ public class PolicyRefresher extends Thread {
while(true) {
try {
DownloadTrigger trigger = policyDownloadQueue.take();
+ loadRoles();
loadPolicy();
trigger.signalCompletion();
} catch(InterruptedException excp) {
@@ -428,4 +431,17 @@ public class PolicyRefresher extends Thread {
LOG.debug("<== PolicyRefresher.disableCache(serviceName=" + serviceName + ")");
}
}
+
+ private void loadRoles() {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadRoles()");
+ }
+
+ //Load the Ranger UserGroup Roles
+ rangerRolesProvider.loadUserGroupRoles(plugIn);
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadRoles()");
+ }
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java
index bdb77e7..d612e7f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTUtils.java
@@ -45,6 +45,9 @@ public class RangerRESTUtils {
public static final String REST_URL_SECURE_SERVICE_GRANT_ACCESS = "/service/plugins/secure/services/grant/";
public static final String REST_URL_SECURE_SERVICE_REVOKE_ACCESS = "/service/plugins/secure/services/revoke/";
+ public static final String REST_URL_ROLE_GET_FOR_SECURE_SERVICE_IF_UPDATED = "/service/roles/secure/download/";
+ public static final String REST_URL_ROLE_GET_FOR_SERVICE_IF_UPDATED = "/service/roles/download/";
+
public static final String REST_URL_SERVICE_CREATE_ROLE = "/service/public/v2/api/roles/";
public static final String REST_URL_SERVICE_DROP_ROLE = "/service/public/v2/api/roles/name/";
public static final String REST_URL_SERVICE_GET_ALL_ROLES = "/service/public/v2/api/roles/names/";
@@ -53,6 +56,9 @@ public class RangerRESTUtils {
public static final String REST_URL_SERVICE_GRANT_ROLE = "/service/public/v2/api/roles/grant/";
public static final String REST_URL_SERVICE_REVOKE_ROLE = "/service/public/v2/api/roles/revoke/";
+ public static final String REST_URL_SERVICE_SERCURE_GET_USER_GROUP_ROLES = "/service/roles/secure/download/";
+ public static final String REST_URL_SERVICE_GET_USER_GROUP_ROLES = "/service/roles/download/";
+
public static final String REST_URL_GET_SERVICE_TAGS_IF_UPDATED = "/service/tags/download/";
public static final String REST_URL_GET_SECURE_SERVICE_TAGS_IF_UPDATED = "/service/tags/secure/download/";
public static final String SERVICE_NAME_PARAM = "serviceName";
@@ -68,6 +74,8 @@ public class RangerRESTUtils {
public static final String REST_PARAM_LAST_ACTIVATION_TIME = "lastActivationTime";
public static final String REST_PARAM_PLUGIN_ID = "pluginId";
+ public static final String REST_PARAM_LAST_KNOWN_ROLE_VERSION = "lastKnownRoleVersion";
+
private static final int MAX_PLUGIN_ID_LEN = 255;
public static final String REST_PARAM_CLUSTER_NAME = "clusterName";
@@ -115,11 +123,23 @@ public class RangerRESTUtils {
return url;
}
+ public String getUrlForRoleUpdate(String baseUrl, String serviceName) {
+ String url = baseUrl + REST_URL_ROLE_GET_FOR_SERVICE_IF_UPDATED + serviceName;
+
+ return url;
+ }
+
+
public String getSecureUrlForPolicyUpdate(String baseUrl, String serviceName) {
String url = baseUrl + REST_URL_POLICY_GET_FOR_SECURE_SERVICE_IF_UPDATED + serviceName;
return url;
}
+ public String getSecureUrlForRoleUpdate(String baseUrl, String serviceName) {
+ String url = baseUrl + REST_URL_ROLE_GET_FOR_SECURE_SERVICE_IF_UPDATED + serviceName;
+ return url;
+ }
+
public String getUrlForTagUpdate(String baseUrl, String serviceName) {
String url = baseUrl + REST_URL_GET_SERVICE_TAGS_IF_UPDATED + serviceName;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRoles.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRoles.java
new file mode 100644
index 0000000..354bf44
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRoles.java
@@ -0,0 +1,78 @@
+/*
+ * 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.plugin.util;
+
+import org.apache.ranger.plugin.model.RangerRole;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+
+@JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RangerRoles implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String serviceName;
+ private Long roleVersion;
+ private Date roleUpdateTime;
+ private Set<RangerRole> rangerRoles;
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public Long getRoleVersion() {
+ return roleVersion;
+ }
+
+ public void setRoleVersion(Long roleVersion) {
+ this.roleVersion = roleVersion;
+ }
+
+ public Date getRoleUpdateTime() {
+ return roleUpdateTime;
+ }
+
+ public void setRoleUpdateTime(Date roleUpdateTime) {
+ this.roleUpdateTime = roleUpdateTime;
+ }
+
+ public Set<RangerRole> getRangerRoles(){
+ return this.rangerRoles;
+ }
+
+ public void setRangerRoles(Set<RangerRole> rangerRoles){
+ this.rangerRoles = rangerRoles;
+ }
+}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesProvider.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesProvider.java
new file mode 100644
index 0000000..5ba3cca
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesProvider.java
@@ -0,0 +1,352 @@
+/*
+ * 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.plugin.util;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.admin.client.RangerAdminClient;
+import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+
+public class RangerRolesProvider {
+ private static final Log LOG = LogFactory.getLog(RangerRolesProvider.class);
+
+ private static final Log PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init");
+
+ private final String serviceType;
+ private final String serviceName;
+ private final RangerAdminClient rangerAdmin;
+
+ private final String cacheFileName;
+ private final String cacheFileNamePrefix;
+ private final String cacheDir;
+ private final Gson gson;
+ private final boolean disableCacheIfServiceNotFound;
+
+ private long lastActivationTimeInMillis;
+ private long lastKnownRoleVersion = -1L;
+ private boolean rangerUserGroupRolesSetInPlugin;
+ private boolean serviceDefSetInPlugin;
+
+ public RangerRolesProvider(String serviceType, String appId, String serviceName, RangerAdminClient rangerAdmin, String cacheDir) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()");
+ }
+
+ this.serviceType = serviceType;
+ this.serviceName = serviceName;
+ this.rangerAdmin = rangerAdmin;
+
+
+ if (StringUtils.isEmpty(appId)) {
+ appId = serviceType;
+ }
+
+ cacheFileNamePrefix = "roles";
+ String cacheFilename = String.format("%s_%s_%s.json", appId, serviceName, cacheFileNamePrefix);
+ cacheFilename = cacheFilename.replace(File.separatorChar, '_');
+ cacheFilename = cacheFilename.replace(File.pathSeparatorChar, '_');
+
+ this.cacheFileName = cacheFilename;
+ this.cacheDir = cacheDir;
+
+ Gson gson = null;
+ try {
+ gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create();
+ } catch (Throwable excp) {
+ LOG.fatal("RangerRolesProvider(): failed to create GsonBuilder object", excp);
+ }
+ this.gson = gson;
+
+ String propertyPrefix = "ranger.plugin." + serviceType;
+ disableCacheIfServiceNotFound = RangerConfiguration.getInstance().getBoolean(propertyPrefix + ".disable.cache.if.servicenotfound", true);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()");
+ }
+ }
+
+ public long getLastActivationTimeInMillis() {
+ return lastActivationTimeInMillis;
+ }
+
+ public void setLastActivationTimeInMillis(long lastActivationTimeInMillis) {
+ this.lastActivationTimeInMillis = lastActivationTimeInMillis;
+ }
+
+ public void loadUserGroupRoles(RangerBasePlugin plugIn) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider(serviceName= " + serviceName + " serviceType= " + serviceType +").loadUserGroupRoles()");
+ }
+
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRoles(serviceName=" + serviceName + ")");
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory);
+ }
+
+ try {
+ //load userGroupRoles from ranger admin
+ RangerRoles rangerRoles = loadUserGroupRolesFromAdmin();
+
+ if (rangerRoles == null) {
+ //if userGroupRoles fetch from ranger Admin Fails, load from cache
+ if (!rangerUserGroupRolesSetInPlugin) {
+ rangerRoles = loadUserGroupRolesFromCache();
+ }
+ }
+
+ if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) {
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory);
+ }
+
+ if (rangerRoles != null) {
+ plugIn.setRangerRoles(rangerRoles);
+ rangerUserGroupRolesSetInPlugin = true;
+ setLastActivationTimeInMillis(System.currentTimeMillis());
+ lastKnownRoleVersion = rangerRoles.getRoleVersion();
+ } else {
+ if (!rangerUserGroupRolesSetInPlugin && !serviceDefSetInPlugin) {
+ plugIn.setRangerRoles(null);
+ serviceDefSetInPlugin = true;
+ }
+ }
+ } catch (RangerServiceNotFoundException snfe) {
+ if (disableCacheIfServiceNotFound) {
+ disableCache();
+ plugIn.setRangerRoles(null);
+ setLastActivationTimeInMillis(System.currentTimeMillis());
+ lastKnownRoleVersion = -1L;
+ serviceDefSetInPlugin = true;
+ }
+ } catch (Exception excp) {
+ LOG.error("Encountered unexpected exception, ignoring..", excp);
+ }
+
+ RangerPerfTracer.log(perf);
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRoles()");
+ }
+ }
+
+ private RangerRoles loadUserGroupRolesFromAdmin() throws RangerServiceNotFoundException {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRolesFromAdmin()");
+ }
+
+ RangerRoles rangerRoles = null;
+
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRolesFromAdmin(serviceName=" + serviceName + ")");
+ }
+
+ try {
+ rangerRoles = rangerAdmin.getRolesIfUpdated(lastKnownRoleVersion, lastActivationTimeInMillis);
+
+ boolean isUpdated = rangerRoles != null;
+
+ if(isUpdated) {
+ long newVersion = rangerRoles.getRoleVersion() == null ? -1 : rangerRoles.getRoleVersion().longValue();
+ saveToCache(rangerRoles);
+ LOG.info("RangerRolesProvider(serviceName=" + serviceName + "): found updated version. lastKnownRoleVersion=" + lastKnownRoleVersion + "; newVersion=" + newVersion );
+ } else {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("RangerRolesProvider(serviceName=" + serviceName + ").run(): no update found. lastKnownRoleVersion=" + lastKnownRoleVersion );
+ }
+ }
+ } catch (RangerServiceNotFoundException snfe) {
+ LOG.error("RangerRolesProvider(serviceName=" + serviceName + "): failed to find service. Will clean up local cache of rangerRoles (" + lastKnownRoleVersion + ")", snfe);
+ throw snfe;
+ } catch (Exception excp) {
+ LOG.error("RangerRolesProvider(serviceName=" + serviceName + "): failed to refresh rangerRoles. Will continue to use last known version of rangerRoles (" + "lastKnowRoleVersion= " + lastKnownRoleVersion, excp);
+ rangerRoles = null;
+ }
+
+ RangerPerfTracer.log(perf);
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + " serviceType= " + serviceType + " ).loadUserGroupRolesFromAdmin()");
+ }
+
+ return rangerRoles;
+ }
+
+ private RangerRoles loadUserGroupRolesFromCache() {
+
+ RangerRoles rangerRoles = null;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRolesFromCache()");
+ }
+
+ File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName);
+
+ if (cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) {
+ Reader reader = null;
+
+ RangerPerfTracer perf = null;
+
+ if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRolesFromCache(serviceName=" + serviceName + ")");
+ }
+
+ try {
+ reader = new FileReader(cacheFile);
+
+ rangerRoles = gson.fromJson(reader, RangerRoles.class);
+
+ if (rangerRoles != null) {
+ if (!StringUtils.equals(serviceName, rangerRoles.getServiceName())) {
+ LOG.warn("ignoring unexpected serviceName '" + rangerRoles.getServiceName() + "' in cache file '" + cacheFile.getAbsolutePath() + "'");
+
+ rangerRoles.setServiceName(serviceName);
+ }
+
+ lastKnownRoleVersion = rangerRoles.getRoleVersion() == null ? -1 : rangerRoles.getRoleVersion().longValue();
+ }
+ } catch (Exception excp) {
+ LOG.error("failed to load userGroupRoles from cache file " + cacheFile.getAbsolutePath(), excp);
+ } finally {
+ RangerPerfTracer.log(perf);
+
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Exception excp) {
+ LOG.error("error while closing opened cache file " + cacheFile.getAbsolutePath(), excp);
+ }
+ }
+ }
+ } else {
+ LOG.warn("cache file does not exist or not readable '" + (cacheFile == null ? null : cacheFile.getAbsolutePath()) + "'");
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()");
+ }
+
+ return rangerRoles;
+ }
+
+ public void saveToCache(RangerRoles rangerRoles) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").saveToCache()");
+ }
+
+ if(rangerRoles != null) {
+ File cacheFile = null;
+ if (cacheDir != null) {
+ // Create the cacheDir if it doesn't already exist
+ File cacheDirTmp = new File(cacheDir);
+ if (cacheDirTmp.exists()) {
+ cacheFile = new File(cacheDir + File.separator + cacheFileName);
+ } else {
+ try {
+ cacheDirTmp.mkdirs();
+ cacheFile = new File(cacheDir + File.separator + cacheFileName);
+ } catch (SecurityException ex) {
+ LOG.error("Cannot create cache directory", ex);
+ }
+ }
+ }
+
+ if(cacheFile != null) {
+
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.saveToCache(serviceName=" + serviceName + ")");
+ }
+
+ Writer writer = null;
+
+ try {
+ writer = new FileWriter(cacheFile);
+
+ gson.toJson(rangerRoles, writer);
+ } catch (Exception excp) {
+ LOG.error("failed to save rangerRoles to cache file '" + cacheFile.getAbsolutePath() + "'", excp);
+ } finally {
+ if(writer != null) {
+ try {
+ writer.close();
+ } catch(Exception excp) {
+ LOG.error("error while closing opened cache file '" + cacheFile.getAbsolutePath() + "'", excp);
+ }
+ }
+ }
+
+ RangerPerfTracer.log(perf);
+ }
+ } else {
+ LOG.info("rangerRoles is null. Nothing to save in cache");
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider.saveToCache(serviceName=" + serviceName + ")");
+ }
+ }
+
+ private void disableCache() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRolesProvider.disableCache(serviceName=" + serviceName + ")");
+ }
+
+ File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName);
+
+ if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) {
+ LOG.warn("Cleaning up local RangerRoles cache");
+ String renamedCacheFile = cacheFile.getAbsolutePath() + "_" + System.currentTimeMillis();
+ if (!cacheFile.renameTo(new File(renamedCacheFile))) {
+ LOG.error("Failed to move " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile);
+ } else {
+ LOG.warn("Moved " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile);
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No local RangerRoles cache found. No need to disable it!");
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRolesProvider.disableCache(serviceName=" + serviceName + ")");
+ }
+ }
+}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java
new file mode 100644
index 0000000..c96d250
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java
@@ -0,0 +1,106 @@
+/*
+ * 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.plugin.util;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.plugin.model.RangerRole;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class RangerRolesUtil {
+
+ Map<String, Set<String>> userRoleMapping = new HashMap<>();
+ Map<String, Set<String>> groupRoleMapping = new HashMap<>();
+
+ public Map<String, Set<String>> getUserRoleMapping() {
+ return this.userRoleMapping;
+ }
+
+ public Map<String, Set<String>> getGroupRoleMapping() {
+ return this.groupRoleMapping;
+ }
+
+ public RangerRoles init(Set<RangerRole> rangerRoles) {
+ RangerRoles ret = new RangerRoles();
+ if (rangerRoles != null) {
+ if (CollectionUtils.isNotEmpty(rangerRoles)) {
+ for (RangerRole role : rangerRoles) {
+ Set<RangerRole> containedRoles = getAllContainedRoles(rangerRoles, role);
+ buildMap(userRoleMapping, role, containedRoles, true);
+ buildMap(groupRoleMapping, role, containedRoles, false);
+ }
+ }
+ }
+ return ret;
+ }
+
+ public Set<RangerRole> getAllContainedRoles(Set<RangerRole> rangerRoles, RangerRole role) {
+ Set<RangerRole> allRoles = new HashSet<>();
+ allRoles.add(role);
+ addContainedRoles(allRoles, rangerRoles, role);
+ return allRoles;
+ }
+
+ private void addContainedRoles(Set<RangerRole> allRoles, Set<RangerRole> rangerRoles, RangerRole role) {
+ List<RangerRole.RoleMember> roleMembers = role.getRoles();
+ for (RangerRole.RoleMember roleMember : roleMembers) {
+ RangerRole containedRole = getContainedRole(rangerRoles, roleMember.getName());
+ if (containedRole!= null && !allRoles.contains(containedRole)) {
+ allRoles.add(containedRole);
+ addContainedRoles(allRoles, rangerRoles, containedRole);
+ }
+ }
+ }
+
+ public void buildMap(Map<String, Set<String>> map, RangerRole role, Set<RangerRole> containedRoles, boolean isUser) {
+ buildMap(map, role, role.getName(), isUser);
+ for (RangerRole containedRole : containedRoles) {
+ buildMap(map, containedRole, role.getName(), isUser);
+ }
+ }
+
+ public void buildMap(Map<String, Set<String>> map, RangerRole role, String roleName, boolean isUser) {
+ for (RangerRole.RoleMember userOrGroup : isUser ? role.getUsers() : role.getGroups()) {
+ if (StringUtils.isNotEmpty(userOrGroup.getName())) {
+ Set<String> roleNames = map.get(userOrGroup.getName());
+ if (roleNames == null) {
+ roleNames = new HashSet<>();
+ map.put(userOrGroup.getName(), roleNames);
+ }
+ roleNames.add(roleName);
+ }
+ }
+ }
+
+ public RangerRole getContainedRole(Set<RangerRole> rangerRoles, String role) {
+ return (rangerRoles
+ .stream()
+ .filter(containedRole -> role.equals(containedRole.getName()))
+ .findAny()
+ .orElse(null));
+ }
+}
+
+
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServicePolicies.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServicePolicies.java
index 8c63434..f6beac6 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServicePolicies.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServicePolicies.java
@@ -25,7 +25,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -60,8 +59,6 @@ public class ServicePolicies implements java.io.Serializable {
private TagPolicies tagPolicies;
private Map<String, SecurityZoneInfo> securityZones;
private List<RangerPolicyDelta> policyDeltas;
- private Map<String, Set<String>> userRoles;
- private Map<String, Set<String>> groupRoles;
/**
* @return the serviceName
@@ -162,12 +159,6 @@ public class ServicePolicies implements java.io.Serializable {
this.securityZones = securityZones;
}
- public Map<String, Set<String>> getUserRoles() { return userRoles; }
- public Map<String, Set<String>> getGroupRoles() { return groupRoles; }
-
- public void setUserRoles(Map<String, Set<String>> userRoles) { this.userRoles = userRoles; }
- public void setGroupRoles(Map<String, Set<String>> groupRoles) { this.groupRoles = groupRoles; }
-
@Override
public String toString() {
return "serviceName=" + serviceName + ", "
@@ -179,9 +170,7 @@ public class ServicePolicies implements java.io.Serializable {
+ "policyDeltas=" + policyDeltas + ", "
+ "serviceDef=" + serviceDef + ", "
+ "auditMode=" + auditMode + ", "
- + "securityZones=" + securityZones + ", "
- + "userRoles=" + userRoles + ", "
- + "groupRoles=" + groupRoles + ", "
+ + "securityZones=" + securityZones
;
}
public List<RangerPolicyDelta> getPolicyDeltas() { return this.policyDeltas; }
@@ -363,8 +352,6 @@ public class ServicePolicies implements java.io.Serializable {
ret.setServiceDef(source.getServiceDef());
ret.setPolicyUpdateTime(source.getPolicyUpdateTime());
ret.setSecurityZones(source.getSecurityZones());
- ret.setUserRoles(source.getUserRoles());
- ret.setGroupRoles(source.getGroupRoles());
ret.setPolicies(Collections.emptyList());
ret.setPolicyDeltas(null);
if (source.getTagPolicies() != null) {
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
index d0e0cfc..83bbffc 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
@@ -36,6 +36,7 @@ import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicyDelta;
+import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator;
@@ -44,6 +45,7 @@ import org.apache.ranger.plugin.policyengine.TestPolicyEngine.PolicyEngineTestCa
import org.apache.ranger.plugin.policyevaluator.RangerValidityScheduleEvaluator;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerRequestedResources;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -57,7 +59,9 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -410,8 +414,6 @@ public class TestPolicyEngine {
servicePolicies.setServiceDef(testCase.serviceDef);
servicePolicies.setPolicies(testCase.policies);
servicePolicies.setSecurityZones(testCase.securityZones);
- servicePolicies.setUserRoles(testCase.userRoles);
- servicePolicies.setGroupRoles(testCase.groupRoles);
if (StringUtils.isNotBlank(testCase.auditMode)) {
servicePolicies.setAuditMode(testCase.auditMode);
@@ -446,7 +448,43 @@ public class TestPolicyEngine {
RangerPluginContext pluginContext = new RangerPluginContext("hive");
pluginContext.setClusterName("cl1");
pluginContext.setClusterType("on-prem");
- RangerPolicyEngine policyEngine = new RangerPolicyEngineImpl(testName, servicePolicies, policyEngineOptions, pluginContext);
+
+ RangerRoles rangerRoles = new RangerRoles();
+ rangerRoles.setServiceName(testCase.serviceName);
+ rangerRoles.setRoleVersion(-1L);
+ Set<RangerRole> rangerRoleSet = new HashSet<>();
+
+ Map<String, Set<String>> userRoleMapping = testCase.userRoles;
+ Map<String, Set<String>> groupRoleMapping = testCase.groupRoles;
+ if (userRoleMapping != null) {
+ for (Map.Entry<String, Set<String>> userRole : userRoleMapping.entrySet()) {
+ String user = userRole.getKey();
+ Set<String> userRoles = userRole.getValue();
+ RangerRole.RoleMember userRoleMember = new RangerRole.RoleMember(user, true);
+ List<RangerRole.RoleMember> userRoleMembers = Arrays.asList(userRoleMember);
+ for (String usrRole : userRoles) {
+ RangerRole rangerUserRole = new RangerRole(usrRole, usrRole, null, userRoleMembers, null);
+ rangerRoleSet.add(rangerUserRole);
+ }
+ }
+ }
+
+ if (groupRoleMapping != null) {
+ for (Map.Entry<String, Set<String>> groupRole : groupRoleMapping.entrySet()) {
+ String group = groupRole.getKey();
+ Set<String> groupRoles = groupRole.getValue();
+ RangerRole.RoleMember groupRoleMember = new RangerRole.RoleMember(group, true);
+ List<RangerRole.RoleMember> groupRoleMembers = Arrays.asList(groupRoleMember);
+ for (String grpRole : groupRoles) {
+ RangerRole rangerGroupRole = new RangerRole(grpRole, grpRole, null, groupRoleMembers, null);
+ rangerRoleSet.add(rangerGroupRole);
+ }
+ }
+ }
+
+ rangerRoles.setRangerRoles(rangerRoleSet);
+
+ RangerPolicyEngine policyEngine = new RangerPolicyEngineImpl(testName, servicePolicies, policyEngineOptions, pluginContext, rangerRoles);
policyEngine.setUseForwardedIPAddress(useForwardedIPAddress);
policyEngine.setTrustedProxyAddresses(trustedProxyAddresses);
@@ -464,8 +502,8 @@ public class TestPolicyEngine {
if (testCase.updatedPolicies != null) {
servicePolicies.setPolicyDeltas(testCase.updatedPolicies.policyDeltas);
servicePolicies.setSecurityZones(testCase.updatedPolicies.securityZones);
- RangerPolicyEngine updatedPolicyEngine = policyEngine.cloneWithDelta(servicePolicies);
- RangerPolicyEngine updatedPolicyEngineForResourceAccessInfo = policyEngineForResourceAccessInfo.cloneWithDelta(servicePolicies);
+ RangerPolicyEngine updatedPolicyEngine = policyEngine.cloneWithDelta(servicePolicies, rangerRoles);
+ RangerPolicyEngine updatedPolicyEngineForResourceAccessInfo = policyEngineForResourceAccessInfo.cloneWithDelta(servicePolicies, rangerRoles);
runTestCaseTests(updatedPolicyEngine, updatedPolicyEngineForResourceAccessInfo, testCase.serviceDef, testName, testCase.updatedTests);
}
}
diff --git a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
index 5dcce11..53be9c2 100644
--- a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
+++ b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
@@ -206,6 +206,93 @@ public class RangerAdminJersey2RESTClient extends AbstractRangerAdminClient {
}
@Override
+ public RangerRoles getRolesIfUpdated(final long lastKnowRoleVersion, final long lastActivationTimeInMillis) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerAdminJersey2RESTClient.getRolesIfUpdated(" + lastKnowRoleVersion + ", " + lastActivationTimeInMillis + ")");
+ }
+
+ UserGroupInformation user = MiscUtil.getUGILoginUser();
+ boolean isSecureMode = user != null && UserGroupInformation.isSecurityEnabled();
+
+ String relativeURL = null;
+ RangerRoles ret = null;
+ Response response = null;
+
+ Map<String, String> queryParams = new HashMap<String, String>();
+ queryParams.put(RangerRESTUtils.REST_PARAM_LAST_KNOWN_ROLE_VERSION, Long.toString(lastKnowRoleVersion));
+ queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
+ queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId);
+ queryParams.put(RangerRESTUtils.REST_PARAM_CLUSTER_NAME, _clusterName);
+
+ if (isSecureMode) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Checking Roles if updated as user : " + user);
+ }
+
+ relativeURL = _utils.getSecureUrlForRoleUpdate(_baseUrl, _serviceName);
+ final String secureRelativeUrl = relativeURL;
+ PrivilegedAction<Response> action = new PrivilegedAction<Response>() {
+ public Response run() {
+ return get(queryParams, secureRelativeUrl);
+ }
+ };
+ response = user.doAs(action);
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Checking Roles if updated with old api call");
+ }
+
+ relativeURL = _utils.getUrlForRoleUpdate(_baseUrl, _serviceName);
+ response = get(queryParams, relativeURL);
+ }
+
+ int httpResponseCode = response == null ? -1 : response.getStatus();
+ String body = null;
+
+ switch (httpResponseCode) {
+ case 200:
+ body = response.readEntity(String.class);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Response from 200 server: " + body);
+ }
+
+ Gson gson = getGson();
+ ret = gson.fromJson(body, RangerRoles.class);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deserialized response to: " + ret);
+ }
+ break;
+ case 304:
+ LOG.debug("Got response: 304. Ok. Returning null");
+ break;
+ case -1:
+ LOG.warn("Unexpected: Null response from policy server while trying to get policies! Returning null!");
+ break;
+ case 404: {
+ if (response.hasEntity()) {
+ body = response.readEntity(String.class);
+ if (StringUtils.isNotBlank(body)) {
+ RangerServiceNotFoundException.throwExceptionIfServiceNotFound(_serviceName, body);
+ }
+ }
+ LOG.warn("Received 404 error code with body:[" + body + "], Ignoring");
+ break;
+ }
+ default:
+ body = response.readEntity(String.class);
+ LOG.warn(String.format("Unexpected: Received status[%d] with body[%s] form url[%s]", httpResponseCode, body, relativeURL));
+ break;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerAdminJersey2RESTClient.getRolesIfUpdated(" + lastKnowRoleVersion + ", " + lastActivationTimeInMillis + "): " + ret);
+ }
+ return ret;
+ }
+
+ @Override
public void grantAccess(GrantRevokeRequest request) throws Exception {
if(LOG.isDebugEnabled()) {
diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
index 8e42bd9..1857a77 100644
--- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
+++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
@@ -1234,6 +1234,8 @@ CREATE TABLE `x_service_version_info` (
`policy_update_time` datetime NULL DEFAULT NULL,
`tag_version` bigint(20) NOT NULL DEFAULT 0,
`tag_update_time` datetime NULL DEFAULT NULL,
+`role_version` bigint(20) NOT NULL DEFAULT 0,
+`role_update_time` datetime NULL DEFAULT NULL,
primary key (`id`),
CONSTRAINT `x_service_version_info_FK_service_id` FOREIGN KEY (`service_id`) REFERENCES `x_service` (`id`)
)ROW_FORMAT=DYNAMIC;
diff --git a/security-admin/db/mysql/patches/043-add-role-version-in-serviceVersionInfo.sql b/security-admin/db/mysql/patches/043-add-role-version-in-serviceVersionInfo.sql
new file mode 100644
index 0000000..def5678
--- /dev/null
+++ b/security-admin/db/mysql/patches/043-add-role-version-in-serviceVersionInfo.sql
@@ -0,0 +1,34 @@
+-- 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.
+
+drop procedure if exists add-role-version-in-serviceVersionInfo;
+
+delimiter ;;
+create procedure add-role-version-in-serviceVersionInfo() begin
+
+if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_service_version_info' and column_name='role_version') then
+ ALTER TABLE x_service_version_info ADD role_version bigint(20) NOT NULL DEFAULT 0;
+end if;
+end;;
+
+if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_service_version_info' and column_name='role_update_time') then
+ ALTER TABLE x_service_version_info ADD role_update_time datetime NULL DEFAULT NULL;
+end if;
+end;;
+
+delimiter ;
+call add-role-version-in-serviceVersionInfo();
+
+drop procedure if exists add-role-version-in-serviceVersionInfo;
diff --git a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
index 1b158c9..0293abe 100644
--- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
+++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
@@ -1310,6 +1310,8 @@ policy_version NUMBER(20) DEFAULT 0 NOT NULL,
policy_update_time DATE DEFAULT NULL NULL,
tag_version NUMBER(20) DEFAULT 0 NOT NULL,
tag_update_time DATE DEFAULT NULL NULL,
+role_version NUMBER(20) DEFAULT 0 NOT NULL,
+role_update_time DATE DEFAULT NULL NULL,
primary key (id),
CONSTRAINT x_svc_ver_info_FK_service_id FOREIGN KEY (service_id) REFERENCES x_service(id)
);
diff --git a/security-admin/db/oracle/patches/043-add-role-version-in-serviceVersionInfo.sql b/security-admin/db/oracle/patches/043-add-role-version-in-serviceVersionInfo.sql
new file mode 100644
index 0000000..a3fd43d
--- /dev/null
+++ b/security-admin/db/oracle/patches/043-add-role-version-in-serviceVersionInfo.sql
@@ -0,0 +1,28 @@
+-- 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.
+
+DECLARE
+ v_count number:=0;
+BEGIN
+ select count(*) into v_count from user_tab_cols where table_name='X_SERVICE_VERSION_INFO' and column_name='ROLE_VERSION';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_service_version_info ADD role_version NUMBER(20) DEFAULT 0 NOT NULL';
+ end if;
+
+ select count(*) into v_count from user_tab_cols where table_name='X_SERVICE_VERSION_INFO' and column_name='ROLE_UPDATE_TIME';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_service_version_info ADD role_update_time DATE DEFAULT NULL NULL';
+ end if;
+END;/
diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
index 0034759..1d1a31c 100644
--- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
+++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
@@ -1165,6 +1165,8 @@ policy_version bigint NOT NULL DEFAULT '0',
policy_update_time TIMESTAMP DEFAULT NULL,
tag_version bigint NOT NULL DEFAULT '0',
tag_update_time TIMESTAMP DEFAULT NULL,
+role_version bigint NOT NULL DEFAULT '0',
+role_update_time TIMESTAMP DEFAULT NULL,
primary key (id),
CONSTRAINT x_service_version_info_service_id FOREIGN KEY (service_id) REFERENCES x_service (id)
);
diff --git a/security-admin/db/postgres/patches/043-add-role-version-in-serviceVersionInfo.sql b/security-admin/db/postgres/patches/043-add-role-version-in-serviceVersionInfo.sql
new file mode 100644
index 0000000..4801ec3
--- /dev/null
+++ b/security-admin/db/postgres/patches/043-add-role-version-in-serviceVersionInfo.sql
@@ -0,0 +1,36 @@
+-- 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.
+
+-- function add-role-version-in-serviceVersionInfo
+select 'delimiter start';
+CREATE OR REPLACE FUNCTION add-role-version-in-serviceVersionInfo()
+RETURNS void AS $$
+DECLARE
+ v_column_exists integer := 0;
+BEGIN
+ select count(*) into v_column_exists from pg_attribute where attrelid in(select oid from pg_class where relname='x_service_version_info') and attname='role_version';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_service_version_info ADD COLUMN role_version bigint NOT NULL DEFAULT '0';
+ END IF;
+ select count(*) into v_column_exists from pg_attribute where attrelid in(select oid from pg_class where relname='x_service_version_info') and attname='role_update_time';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_service_version_info ADD COLUMN role_update_time TIMESTAMP DEFAULT NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+select 'delimiter end';
+
+select add-role-version-in-serviceVersionInfo();
+select 'delimiter end';
diff --git a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
index 9dc7656..5381398 100644
--- a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
+++ b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
@@ -1005,6 +1005,8 @@ CREATE TABLE dbo.x_service_version_info(
policy_update_time datetime DEFAULT NULL NULL,
tag_version bigint NOT NULL DEFAULT 0,
tag_update_time datetime DEFAULT NULL NULL,
+ role_version bigint NOT NULL DEFAULT 0,
+ role_update_time datetime DEFAULT NULL NULL,
CONSTRAINT x_service_version_info_PK_id PRIMARY KEY CLUSTERED(id)
)
GO
diff --git a/security-admin/db/sqlanywhere/patches/043-add-role-version-in-serviceVersionInfo.sql b/security-admin/db/sqlanywhere/patches/043-add-role-version-in-serviceVersionInfo.sql
new file mode 100644
index 0000000..3862ea3
--- /dev/null
+++ b/security-admin/db/sqlanywhere/patches/043-add-role-version-in-serviceVersionInfo.sql
@@ -0,0 +1,25 @@
+-- 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.
+
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_service_version_info' and cname = 'role_version') THEN
+ ALTER TABLE dbo.x_service_version_info ADD role_version bigint NOT NULL DEFAULT 0;
+END IF;
+GO
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_service_version_info' and cname = 'role_update_time') THEN
+ ALTER TABLE dbo.x_service_version_info ADD role_update_time datetime DEFAULT NULL NULL;
+END IF;
+GO
+
+exit
diff --git a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
index 9383d1a..d24de68 100644
--- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
+++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
@@ -2048,6 +2048,8 @@ CREATE TABLE [dbo].[x_service_version_info](
[policy_update_time] [datetime2] DEFAULT NULL NULL,
[tag_version] [bigint] NOT NULL DEFAULT 0,
[tag_update_time] [datetime2] DEFAULT NULL NULL,
+ [policy_version] [bigint] NOT NULL DEFAULT 0,
+ [role_update_time] [datetime2] DEFAULT NULL NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
diff --git a/security-admin/db/sqlserver/patches/042-add-role-version-in-serviceVersionInfo.sql b/security-admin/db/sqlserver/patches/042-add-role-version-in-serviceVersionInfo.sql
new file mode 100644
index 0000000..4f9b379
--- /dev/null
+++ b/security-admin/db/sqlserver/patches/042-add-role-version-in-serviceVersionInfo.sql
@@ -0,0 +1,29 @@
+-- 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.
+
+GO
+IF NOT EXISTS(select * from INFORMATION_SCHEMA.columns where table_name = 'x_service_version_info' and column_name = 'role_version')
+BEGIN
+ ALTER TABLE [dbo].[x_service_version_info] ADD [policy_version] [bigint] NOT NULL DEFAULT 0;
+END
+GO
+GO
+IF NOT EXISTS(select * from INFORMATION_SCHEMA.columns where table_name = 'x_service_version_info' and column_name = 'role_update_time')
+BEGIN
+ ALTER TABLE [dbo].[x_service_version_info] ADD [role_update_time] [datetime2] DEFAULT NULL NULL;
+END
+GO
+
+exit
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
index 63959c9..9d26fb5 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java
@@ -684,24 +684,34 @@ public class AssetMgr extends AssetMgrBase {
pluginSvcVersionInfo.setHostName(hostName);
pluginSvcVersionInfo.setIpAddress(ipAddress);
- if (entityType == RangerPluginInfo.ENTITY_TYPE_POLICIES) {
- pluginSvcVersionInfo.setPolicyActiveVersion(lastKnownVersion);
- pluginSvcVersionInfo.setPolicyActivationTime(lastActivationTime);
- pluginSvcVersionInfo.setPolicyDownloadedVersion(downloadedVersion);
- pluginSvcVersionInfo.setPolicyDownloadTime(new Date().getTime());
- } else {
- pluginSvcVersionInfo.setTagActiveVersion(lastKnownVersion);
- pluginSvcVersionInfo.setTagActivationTime(lastActivationTime);
- pluginSvcVersionInfo.setTagDownloadedVersion(downloadedVersion);
- pluginSvcVersionInfo.setTagDownloadTime(new Date().getTime());
+ switch (entityType) {
+ case 0:
+ pluginSvcVersionInfo.setPolicyActiveVersion(lastKnownVersion);
+ pluginSvcVersionInfo.setPolicyActivationTime(lastActivationTime);
+ pluginSvcVersionInfo.setPolicyDownloadedVersion(downloadedVersion);
+ pluginSvcVersionInfo.setPolicyDownloadTime(new Date().getTime());
+ break;
+ case 1:
+ pluginSvcVersionInfo.setTagActiveVersion(lastKnownVersion);
+ pluginSvcVersionInfo.setTagActivationTime(lastActivationTime);
+ pluginSvcVersionInfo.setTagDownloadedVersion(downloadedVersion);
+ pluginSvcVersionInfo.setTagDownloadTime(new Date().getTime());
+ break;
+ case 2:
+ pluginSvcVersionInfo.setRoleActiveVersion(lastKnownVersion);
+ pluginSvcVersionInfo.setRoleActivationTime(lastActivationTime);
+ pluginSvcVersionInfo.setRoleDownloadedVersion(downloadedVersion);
+ pluginSvcVersionInfo.setRoleDownloadTime(new Date().getTime());
+ break;
}
- createOrUpdatePluginInfo(pluginSvcVersionInfo, entityType == RangerPluginInfo.ENTITY_TYPE_POLICIES, httpCode, clusterName);
+ createOrUpdatePluginInfo(pluginSvcVersionInfo, entityType , httpCode, clusterName);
}
- private void createOrUpdatePluginInfo(final RangerPluginInfo pluginInfo, final boolean isPolicyDownloadRequest, final int httpCode, String clusterName) {
+ private void createOrUpdatePluginInfo(final RangerPluginInfo pluginInfo, int entityType, final int httpCode, String clusterName) {
+
if (logger.isDebugEnabled()) {
- logger.debug("==> createOrUpdatePluginInfo(pluginInfo = " + pluginInfo + ", isPolicyDownloadRequest = " + isPolicyDownloadRequest + ", httpCode = " + httpCode + ")");
+ logger.debug("==> createOrUpdatePluginInfo(pluginInfo = " + pluginInfo + ", isPolicyDownloadRequest = " + isPolicyDownloadRequest(entityType) + ", httpCode = " + httpCode + ")");
}
final boolean isTagVersionResetNeeded;
@@ -711,23 +721,33 @@ public class AssetMgr extends AssetMgrBase {
// then the TransactionManager will roll-back the changes because the HTTP return code is
// HttpServletResponse.SC_NOT_MODIFIED
- if (isPolicyDownloadRequest) {
- isTagVersionResetNeeded = rangerDaoManager.getXXService().findAssociatedTagService(pluginInfo.getServiceName()) == null;
- } else {
- isTagVersionResetNeeded = false;
+ switch (entityType) {
+ case 0:
+ isTagVersionResetNeeded = rangerDaoManager.getXXService().findAssociatedTagService(pluginInfo.getServiceName()) == null;
+ break;
+ case 1:
+ isTagVersionResetNeeded = false;
+ break;
+ case 2:
+ isTagVersionResetNeeded = false;
+ break;
+ default:
+ isTagVersionResetNeeded = false;
+ break;
}
Runnable commitWork = new Runnable() {
@Override
public void run() {
- doCreateOrUpdateXXPluginInfo(pluginInfo, isPolicyDownloadRequest, isTagVersionResetNeeded, clusterName);
+ doCreateOrUpdateXXPluginInfo(pluginInfo, entityType, isTagVersionResetNeeded, clusterName);
}
};
activityLogger.commitAfterTransactionComplete(commitWork);
} else if (httpCode == HttpServletResponse.SC_NOT_FOUND) {
Runnable commitWork;
- if ((isPolicyDownloadRequest && (pluginInfo.getPolicyActiveVersion() == null || pluginInfo.getPolicyActiveVersion() == -1))
- || (!isPolicyDownloadRequest && (pluginInfo.getTagActiveVersion() == null || pluginInfo.getTagActiveVersion() == -1))) {
+ if ((isPolicyDownloadRequest(entityType) && (pluginInfo.getPolicyActiveVersion() == null || pluginInfo.getPolicyActiveVersion() == -1))
+ || (isTagDownloadRequest(entityType) && (pluginInfo.getTagActiveVersion() == null || pluginInfo.getTagActiveVersion() == -1))
+ || (isRoleDownloadRequest(entityType) && (pluginInfo.getRoleActiveVersion() == null || pluginInfo.getRoleActiveVersion() == -1))) {
commitWork = new Runnable() {
@Override
public void run() {
@@ -738,7 +758,7 @@ public class AssetMgr extends AssetMgrBase {
commitWork = new Runnable() {
@Override
public void run() {
- doCreateOrUpdateXXPluginInfo(pluginInfo, isPolicyDownloadRequest, false, clusterName);
+ doCreateOrUpdateXXPluginInfo(pluginInfo, entityType, false, clusterName);
}
};
}
@@ -746,15 +766,15 @@ public class AssetMgr extends AssetMgrBase {
} else {
isTagVersionResetNeeded = false;
- doCreateOrUpdateXXPluginInfo(pluginInfo, isPolicyDownloadRequest, isTagVersionResetNeeded, clusterName);
+ doCreateOrUpdateXXPluginInfo(pluginInfo, entityType, isTagVersionResetNeeded, clusterName);
}
if (logger.isDebugEnabled()) {
- logger.debug("<== createOrUpdatePluginInfo(pluginInfo = " + pluginInfo + ", isPolicyDownloadRequest = " + isPolicyDownloadRequest + ", httpCode = " + httpCode + ")");
+ logger.debug("<== createOrUpdatePluginInfo(pluginInfo = " + pluginInfo + ", isPolicyDownloadRequest = " + isPolicyDownloadRequest(entityType) + ", httpCode = " + httpCode + ")");
}
}
- private XXPluginInfo doCreateOrUpdateXXPluginInfo(RangerPluginInfo pluginInfo, final boolean isPolicyDownloadRequest, final boolean isTagVersionResetNeeded, String clusterName) {
+ private XXPluginInfo doCreateOrUpdateXXPluginInfo(RangerPluginInfo pluginInfo, int entityType, final boolean isTagVersionResetNeeded, String clusterName) {
XXPluginInfo ret = null;
Map<String, String> infoMap = null;
@@ -770,14 +790,21 @@ public class AssetMgr extends AssetMgrBase {
pluginInfo.setInfo(infoMap);
}
// ranger-admin is restarted, plugin contains latest versions and no earlier record for this plug-in client
- if (isPolicyDownloadRequest) {
+ if (isPolicyDownloadRequest(entityType)) {
if (pluginInfo.getPolicyDownloadedVersion() != null && pluginInfo.getPolicyDownloadedVersion().equals(pluginInfo.getPolicyActiveVersion())) {
// This is our best guess of when policies may have been downloaded
pluginInfo.setPolicyDownloadTime(pluginInfo.getPolicyActivationTime());
}
- } else if (pluginInfo.getTagDownloadedVersion() != null && pluginInfo.getTagDownloadedVersion().equals(pluginInfo.getTagActiveVersion())) {
- // This is our best guess of when tags may have been downloaded
- pluginInfo.setTagDownloadTime(pluginInfo.getTagActivationTime());
+ } else if (isTagDownloadRequest(entityType)) {
+ if (pluginInfo.getTagDownloadedVersion() != null && pluginInfo.getTagDownloadedVersion().equals(pluginInfo.getTagActiveVersion())) {
+ // This is our best guess of when tags may have been downloaded
+ pluginInfo.setTagDownloadTime(pluginInfo.getTagActivationTime());
+ }
+ } else {
+ if (pluginInfo.getRoleDownloadTime() != null && pluginInfo.getRoleDownloadedVersion().equals(pluginInfo.getRoleActiveVersion())) {
+ // This is our best guess of when role may have been downloaded
+ pluginInfo.setRoleDownloadTime(pluginInfo.getRoleActivationTime());
+ }
}
xObj = pluginInfoService.populateDBObject(pluginInfo);
@@ -802,7 +829,7 @@ public class AssetMgr extends AssetMgrBase {
dbObj.setIpAddress(pluginInfo.getIpAddress());
needsUpdating = true;
}
- if (isPolicyDownloadRequest) {
+ if (isPolicyDownloadRequest(entityType)) {
if (dbObj.getPolicyDownloadedVersion() == null || !dbObj.getPolicyDownloadedVersion().equals(pluginInfo.getPolicyDownloadedVersion())) {
dbObj.setPolicyDownloadedVersion(pluginInfo.getPolicyDownloadedVersion());
dbObj.setPolicyDownloadTime(pluginInfo.getPolicyDownloadTime());
@@ -824,7 +851,7 @@ public class AssetMgr extends AssetMgrBase {
dbObj.setPolicyActivationTime(lastPolicyActivationTime);
needsUpdating = true;
}
- } else {
+ } else if (isTagDownloadRequest(entityType)){
if (dbObj.getTagDownloadedVersion() == null || !dbObj.getTagDownloadedVersion().equals(pluginInfo.getTagDownloadedVersion())) {
// First download for tags after tag-service is associated with resource-service
dbObj.setTagDownloadedVersion(pluginInfo.getTagDownloadedVersion());
@@ -849,6 +876,30 @@ public class AssetMgr extends AssetMgrBase {
dbObj.setTagActivationTime(lastTagActivationTime);
needsUpdating = true;
}
+ } else {
+ if (dbObj.getRoleDownloadedVersion() == null || !dbObj.getRoleDownloadedVersion().equals(pluginInfo.getRoleDownloadedVersion())) {
+ dbObj.setRoleDownloadedVersion(pluginInfo.getRoleDownloadedVersion());
+ dbObj.setRoleDownloadTime(pluginInfo.getRoleDownloadTime());
+ needsUpdating = true;
+ }
+
+ Long lastKnownRoleVersion = pluginInfo.getRoleActiveVersion();
+ Long lastRoleActivationTime = pluginInfo.getRoleActivationTime();
+
+ if (lastKnownRoleVersion != null && lastKnownRoleVersion == -1) {
+ dbObj.setRoleDownloadTime(pluginInfo.getRoleDownloadTime());
+ needsUpdating = true;
+ }
+
+ if (lastKnownRoleVersion != null && lastKnownRoleVersion > 0 && (dbObj.getRoleActiveVersion() == null || !dbObj.getRoleActiveVersion().equals(lastKnownRoleVersion))) {
+ dbObj.setRoleActiveVersion(lastKnownRoleVersion);
+ needsUpdating = true;
+ }
+
+ if (lastRoleActivationTime != null && lastRoleActivationTime > 0 && (dbObj.getRoleActivationTime() == null || !dbObj.getRoleActivationTime().equals(lastRoleActivationTime))) {
+ dbObj.setRoleActivationTime(lastRoleActivationTime);
+ needsUpdating = true;
+ }
}
if (isTagVersionResetNeeded) {
@@ -1178,4 +1229,16 @@ public class AssetMgr extends AssetMgrBase {
throw restErrorUtil.createRESTException("Please provide a valid syncSource", MessageEnums.INVALID_INPUT_DATA);
}
}
+
+ private boolean isPolicyDownloadRequest(int entityType) {
+ return entityType == 0;
+ }
+
+ private boolean isTagDownloadRequest(int entityType) {
+ return entityType == 1;
+ }
+
+ private boolean isRoleDownloadRequest(int entityType) {
+ return entityType == 2;
+ }
}
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
index 7a67e9c..9151a72 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
@@ -32,12 +32,14 @@ import org.apache.commons.logging.LogFactory;
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.common.RangerRoleCache;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.*;
import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.store.AbstractPredicateUtil;
import org.apache.ranger.plugin.store.RolePredicateUtil;
import org.apache.ranger.plugin.store.RoleStore;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.service.RangerRoleService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -50,6 +52,8 @@ import com.google.gson.GsonBuilder;
public class RoleDBStore implements RoleStore {
private static final Log LOG = LogFactory.getLog(RoleDBStore.class);
+ private static final String RANGER_ROLE_GLOBAL_STATE_NAME = "RangerRole";
+
@Autowired
RangerRoleService roleService;
@@ -97,6 +101,8 @@ public class RoleDBStore implements RoleStore {
throw restErrorUtil.createRESTException("role with name: " + role.getName() + " already exists", MessageEnums.ERROR_DUPLICATE_OBJECT);
}
+ daoMgr.getXXGlobalState().onGlobalAppDataChange(RANGER_ROLE_GLOBAL_STATE_NAME);
+
RangerRole createdRole = roleService.create(role);
if (createdRole == null) {
throw new Exception("Cannot create role:[" + role + "]");
@@ -119,6 +125,8 @@ public class RoleDBStore implements RoleStore {
Gson gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create();
RangerRole oldRole = gsonBuilder.fromJson(xxRole.getRoleText(), RangerRole.class);
+ daoMgr.getXXGlobalState().onGlobalAppDataChange(RANGER_ROLE_GLOBAL_STATE_NAME);
+
RangerRole updatedRole = roleService.update(role);
if (updatedRole == null) {
throw new Exception("Cannot update role:[" + role + "]");
@@ -128,6 +136,8 @@ public class RoleDBStore implements RoleStore {
roleService.updatePolicyVersions(updatedRole.getId());
+ roleService.updateRoleVersions(updatedRole.getId());
+
List<XXTrxLog> trxLogList = roleService.getTransactionLog(updatedRole, oldRole, "update");
bizUtil.createTrxLog(trxLogList);
return role;
@@ -139,6 +149,9 @@ public class RoleDBStore implements RoleStore {
if (xxRole == null) {
throw restErrorUtil.createRESTException("Role with name: " + roleName + " does not exist");
}
+
+ daoMgr.getXXGlobalState().onGlobalAppDataChange(RANGER_ROLE_GLOBAL_STATE_NAME);
+
RangerRole role = roleService.read(xxRole.getId());
roleRefUpdater.cleanupRefTables(role);
roleService.delete(role);
@@ -151,6 +164,8 @@ public class RoleDBStore implements RoleStore {
public void deleteRole(Long roleId) throws Exception {
RangerRole role = roleService.read(roleId);
+ daoMgr.getXXGlobalState().onGlobalAppDataChange(RANGER_ROLE_GLOBAL_STATE_NAME);
+
roleRefUpdater.cleanupRefTables(role);
roleService.delete(role);
List<XXTrxLog> trxLogList = roleService.getTransactionLog(role, null, "delete");
@@ -262,5 +277,29 @@ public class RoleDBStore implements RoleStore {
return service == null ? ListUtils.EMPTY_LIST : getRoles(service.getId());
}
+ public RangerRoles getRangerRoles(String serviceName, Long lastKnownRoleVersion) throws Exception {
+ RangerRoles ret = null;
+ Long rangerRoleVersionInDB = getRoleVersion(serviceName);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB);
+ }
+
+ if (rangerRoleVersionInDB != null) {
+ ret = RangerRoleCache.getInstance().getLatestRangerRoleOrCached(serviceName, this, lastKnownRoleVersion, rangerRoleVersionInDB);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<= RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB + " RangerRoles= " + ret);
+ }
+
+ return ret;
+ }
+
+ public Long getRoleVersion(String serviceName) {
+ XXServiceVersionInfo xxServiceVersionInfo = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
+ return (xxServiceVersionInfo != null) ? xxServiceVersionInfo.getRoleVersion():null;
+ }
+
}
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 92436ac..85db577 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -68,7 +68,6 @@ import org.apache.ranger.common.RangerCommonEnums;
import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
import org.apache.ranger.db.XXPolicyDao;
import org.apache.ranger.entity.XXTagChangeLog;
-import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.model.RangerSecurityZone;
import org.apache.ranger.plugin.util.ServiceTags;
import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
@@ -123,7 +122,6 @@ import org.apache.ranger.entity.XXPolicyRefAccessType;
import org.apache.ranger.entity.XXPolicyRefCondition;
import org.apache.ranger.entity.XXPolicyRefResource;
import org.apache.ranger.entity.XXResourceDef;
-import org.apache.ranger.entity.XXRoleRefRole;
import org.apache.ranger.entity.XXSecurityZone;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceConfigDef;
@@ -2812,25 +2810,6 @@ public class ServiceDBStore extends AbstractServiceStore {
ret.setTagPolicies(tagPolicies);
}
- if (ret != null) {
- // Add role mapping
- List<RangerRole> rolesForService = roleStore.getRoles(serviceDbObj.getId());
- if (CollectionUtils.isNotEmpty(rolesForService)) {
- Map<String, Set<String>> userRoleMapping = new HashMap<>();
- Map<String, Set<String>> groupRoleMapping = new HashMap<>();
- for (RangerRole role : rolesForService) {
- // Get a closure set of all contained roles too
- Set<RangerRole> containedRoles = getAllContainedRoles(role);
-
- buildMap(userRoleMapping, role, containedRoles, true);
- buildMap(groupRoleMapping, role, containedRoles, false);
- }
-
- ret.setUserRoles(userRoleMapping);
- ret.setGroupRoles(groupRoleMapping);
- }
- }
-
if (LOG.isDebugEnabled()) {
LOG.debug("<== ServiceDBStore.getServicePolicies(" + serviceName + ", " + lastKnownVersion + "): count=" + ((ret == null || ret.getPolicies() == null) ? 0 : ret.getPolicies().size()) + ", delta-count=" + ((ret == null || ret.getPolicyDeltas() == null) ? 0 : ret.getPolicyDeltas().size()));
}
@@ -2838,45 +2817,6 @@ public class ServiceDBStore extends AbstractServiceStore {
return ret;
}
- private Set<RangerRole> getAllContainedRoles(RangerRole role) {
- Set<RangerRole> allRoles = new HashSet<>();
- allRoles.add(role);
- addContainedRoles(allRoles, role);
- return allRoles;
- }
-
- private void addContainedRoles(Set<RangerRole> allRoles, RangerRole role) {
- List<XXRoleRefRole> roles = daoMgr.getXXRoleRefRole().findByRoleId(role.getId());
- for (XXRoleRefRole xRefRole : roles) {
- RangerRole containedRole = roleService.read(xRefRole.getSubRoleId());
- if (!allRoles.contains(containedRole)) {
- allRoles.add(containedRole);
- addContainedRoles(allRoles, containedRole);
- }
- }
- }
-
- private void buildMap(Map<String, Set<String>> map, RangerRole role, Set<RangerRole> containedRoles, boolean isUser) {
- buildMap(map, role, role.getName(), isUser);
-
- for (RangerRole containedRole : containedRoles) {
- buildMap(map, containedRole, role.getName(), isUser);
- }
- }
-
- private void buildMap(Map<String, Set<String>> map, RangerRole role, String roleName, boolean isUser) {
- for (RangerRole.RoleMember userOrGroup : isUser ? role.getUsers() : role.getGroups()) {
- if (StringUtils.isNotEmpty(userOrGroup.getName())) {
- Set<String> roleNames = map.get(userOrGroup.getName());
- if (roleNames == null) {
- roleNames = new HashSet<>();
- map.put(userOrGroup.getName(), roleNames);
- }
- roleNames.add(roleName);
- }
- }
- }
-
private static class RangerPolicyDeltaComparator implements Comparator<RangerPolicyDelta>, java.io.Serializable {
@Override
public int compare(RangerPolicyDelta me, RangerPolicyDelta other) {
@@ -3353,7 +3293,7 @@ public class ServiceDBStore extends AbstractServiceStore {
updatePolicyVersion(service, policyDeltaType, policy);
}
- public enum VERSION_TYPE { POLICY_VERSION, TAG_VERSION, POLICY_AND_TAG_VERSION }
+ public enum VERSION_TYPE { POLICY_VERSION, TAG_VERSION, POLICY_AND_TAG_VERSION, ROLE_VERSION }
private void updatePolicyVersion(RangerService service, Integer policyDeltaType, RangerPolicy policy) throws Exception {
if(service == null || service.getId() == null) {
@@ -3419,6 +3359,13 @@ public class ServiceDBStore extends AbstractServiceStore {
serviceVersionInfoDbObj.setTagUpdateTime(now);
}
+ if (versionType == VERSION_TYPE.ROLE_VERSION) {
+ // get the LatestRoleVersion from the GlobalTable and update ServiceInfo for a service
+ Long currentRoleVersion = daoMgr.getXXGlobalState().getRoleVersion("RangerRole");
+ serviceVersionInfoDbObj.setRolVersion(currentRoleVersion);
+ serviceVersionInfoDbObj.setRoleUpdateTime(now);
+ }
+
serviceVersionInfoDao.update(serviceVersionInfoDbObj);
} else {
diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java b/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
new file mode 100644
index 0000000..b0bd427
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
@@ -0,0 +1,142 @@
+/*
+ * 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.common;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
+import org.apache.ranger.biz.RoleDBStore;
+import org.apache.ranger.plugin.model.RangerRole;
+
+import org.apache.ranger.plugin.util.RangerRoles;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class RangerRoleCache {
+ private static final Log LOG = LogFactory.getLog(RangerRoleCache.class);
+
+ private static final int MAX_WAIT_TIME_FOR_UPDATE = 10;
+
+ public static volatile RangerRoleCache sInstance = null;
+ private final int waitTimeInSeconds;
+ final ReentrantLock lock = new ReentrantLock();
+
+ RangerRoleCacheWrapper rangerRoleCacheWrapper = null;
+
+ public static RangerRoleCache getInstance() {
+ if (sInstance == null) {
+ synchronized (RangerRoleCache.class) {
+ if (sInstance == null) {
+ sInstance = new RangerRoleCache();
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ private RangerRoleCache() {
+ waitTimeInSeconds = RangerConfiguration.getInstance().getInt("ranger.admin.policy.download.cache.max.waittime.for.update", MAX_WAIT_TIME_FOR_UPDATE);
+ }
+
+ public RangerRoles getLatestRangerRoleOrCached(String serviceName, RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rangerRoleVersionInDB) throws Exception {
+ RangerRoles ret = null;
+
+ if (lastKnownRoleVersion == null || !lastKnownRoleVersion.equals(rangerRoleVersionInDB)) {
+ rangerRoleCacheWrapper = new RangerRoleCacheWrapper();
+ ret = rangerRoleCacheWrapper.getLatestRangerRoles(serviceName, roleDBStore, lastKnownRoleVersion, rangerRoleVersionInDB);
+ } else if (lastKnownRoleVersion.equals(rangerRoleVersionInDB)) {
+ ret = null;
+ } else {
+ ret = rangerRoleCacheWrapper.getRangerRoles();
+ }
+
+ return ret;
+ }
+
+ private class RangerRoleCacheWrapper {
+ RangerRoles rangerRoles;
+ Long rangerRoleVersion;
+
+ RangerRoleCacheWrapper() {
+ this.rangerRoles = null;
+ this.rangerRoleVersion = -1L;
+ }
+
+ public RangerRoles getRangerRoles() {
+ return this.rangerRoles;
+ }
+
+ public Long getRangerRoleVersion() {
+ return this.rangerRoleVersion;
+ }
+
+ public RangerRoles getLatestRangerRoles(String serviceName, RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rangerRoleVersionInDB) throws Exception {
+ RangerRoles ret = null;
+ boolean lockResult = false;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerRoleCache.getLatestRangerRoles(ServiceName= " + serviceName + " lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB + ")");
+ }
+
+ try {
+ lockResult = lock.tryLock(waitTimeInSeconds, TimeUnit.SECONDS);
+
+ if (lockResult) {
+ // We are getting all the Roles to be downloaded for now. Should do downloades for each service based on what roles are there in the policies.
+ SearchFilter searchFilter = null;
+ final Set<RangerRole> rangerRoleInDB = new HashSet<>(roleDBStore.getRoles(searchFilter));
+
+ Date updateTime = new Date();
+
+ if (rangerRoleInDB != null) {
+ ret = new RangerRoles();
+ ret.setRangerRoles(rangerRoleInDB);
+ ret.setRoleUpdateTime(updateTime);
+ ret.setRoleVersion(rangerRoleVersionInDB);
+ rangerRoleVersion = rangerRoleVersionInDB;
+ } else {
+ LOG.error("Could not get Ranger Roles from database ...");
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Could not get lock in [" + waitTimeInSeconds + "] seconds, returning cached RangerRoles");
+ }
+ ret = getRangerRoles();
+ }
+ } catch (InterruptedException exception) {
+ LOG.error("RangerRoleCache.getLatestRangerRoles:lock got interrupted..", exception);
+ } finally {
+ if (lockResult) {
+ lock.unlock();
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerRoleCache.getLatestRangerRoles(ServiceName= " + serviceName + " lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB + " RangerRoles= " + ret + ")");
+ }
+ return ret;
+ }
+ }
+}
+
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java
index f6b9e1a..d687e73 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXGlobalStateDao.java
@@ -17,6 +17,7 @@
package org.apache.ranger.db;
+import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.ranger.common.DateUtil;
@@ -26,11 +27,15 @@ import org.springframework.stereotype.Service;
import javax.persistence.NoResultException;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
@Service
public class XXGlobalStateDao extends BaseDao<XXGlobalState> {
private static final Logger logger = Logger.getLogger(RangerDaoManager.class);
+ final static String RANGER_ROLE_VERSION_LABEL = "RangerRoleVersion";
+
public void onGlobalStateChange(String stateName) throws Exception {
if (StringUtils.isBlank(stateName)) {
@@ -58,6 +63,48 @@ public class XXGlobalStateDao extends BaseDao<XXGlobalState> {
}
}
}
+
+ public void onGlobalAppDataChange(String stateName) throws Exception {
+
+ if (StringUtils.isBlank(stateName)) {
+ logger.error("Invalid name for state:[" + stateName +"]");
+ throw new Exception("Invalid name for state:[" + stateName +"]");
+ } else {
+ try {
+ XXGlobalState globalState = findByStateName(stateName);
+ if (globalState == null) {
+ globalState = new XXGlobalState();
+ globalState.setStateName(stateName);
+ Map<String,String> roleVersion = new HashMap<>();
+ roleVersion.put(RANGER_ROLE_VERSION_LABEL,new String(Long.toString(1L)));
+ globalState.setAppData(new Gson().toJson(roleVersion));
+ create(globalState);
+ } else {
+ Map<String,String> roleVersionJson = new Gson().fromJson(globalState.getAppData(),Map.class);
+ Long roleVersion = Long.valueOf(roleVersionJson.get(RANGER_ROLE_VERSION_LABEL)) + 1L;
+ roleVersionJson.put(RANGER_ROLE_VERSION_LABEL,new String(Long.toString(roleVersion)));
+ globalState.setAppData(new Gson().toJson(roleVersionJson));
+ update(globalState);
+ }
+ } catch (Exception exception) {
+ logger.error("Cannot create/update GlobalState for state:[" + stateName + "]", exception);
+ throw exception;
+ }
+ }
+ }
+
+ public Long getRoleVersion(String stateName) {
+ Long ret = null;
+ try {
+ XXGlobalState globalState = findByStateName(stateName);
+ Map<String, String> roleVersionJson = new Gson().fromJson(globalState.getAppData(), Map.class);
+ ret = Long.valueOf(roleVersionJson.get(RANGER_ROLE_VERSION_LABEL));
+ } catch (Exception exception) {
+ logger.warn("Unable to find the role version in Ranger Database");
+ }
+ return ret;
+ }
+
/**
* Default Constructor
*/
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java b/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
index cef3863..1d81337 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
@@ -68,6 +68,13 @@ public class XXServiceVersionInfo implements java.io.Serializable {
@Column(name="tag_update_time" )
protected Date tagUpdateTime = DateUtil.getUTCDate();
+ @Column(name = "role_version")
+ protected Long roleVersion;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name="role_update_time" )
+ protected Date roleUpdateTime = DateUtil.getUTCDate();
+
/**
* Default constructor. This will set all the attributes to default value.
*/
@@ -130,6 +137,21 @@ public class XXServiceVersionInfo implements java.io.Serializable {
return this.tagUpdateTime;
}
+ public void setRolVersion(Long roleVersion) {
+ this.roleVersion = roleVersion;
+ }
+
+ public Long getRoleVersion() {
+ return this.roleVersion;
+ }
+
+ public void setRoleUpdateTime( Date updateTime ) {
+ this.roleUpdateTime = updateTime;
+ }
+
+ public Date getRoleUpdateTime( ) {
+ return this.roleUpdateTime;
+ }
/**
* This return the bean content in string format
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RoleREST.java b/security-admin/src/main/java/org/apache/ranger/rest/RoleREST.java
index 4af768a..d28cf3d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RoleREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RoleREST.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
@@ -36,6 +37,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.admin.client.datatype.RESTResponse;
import org.apache.ranger.authorization.utils.StringUtil;
+import org.apache.ranger.biz.AssetMgr;
import org.apache.ranger.biz.RangerBizUtil;
import org.apache.ranger.biz.RoleDBStore;
import org.apache.ranger.biz.ServiceDBStore;
@@ -43,14 +45,21 @@ import org.apache.ranger.biz.XUserMgr;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerSearchUtil;
import org.apache.ranger.common.RangerValidatorFactory;
+import org.apache.ranger.common.ServiceUtil;
import org.apache.ranger.common.UserSessionBase;
import org.apache.ranger.common.RangerConstants;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.ContextUtil;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerPluginInfo;
import org.apache.ranger.plugin.model.RangerRole;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.plugin.util.GrantRevokeRoleRequest;
+import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.service.RangerRoleService;
import org.apache.ranger.service.XUserService;
@@ -71,10 +80,18 @@ public class RoleREST {
private static List<String> INVALID_USERS = new ArrayList<>();
+ public static final String Allowed_User_List_For_Download = "policy.download.auth.users";
+
@Autowired
RESTErrorUtil restErrorUtil;
@Autowired
+ AssetMgr assetMgr;
+
+ @Autowired
+ RangerDaoManager daoManager;
+
+ @Autowired
RoleDBStore roleStore;
@Autowired
@@ -90,6 +107,9 @@ public class RoleREST {
RangerSearchUtil searchUtil;
@Autowired
+ ServiceUtil serviceUtil;
+
+ @Autowired
RangerValidatorFactory validatorFactory;
@Autowired
@@ -658,6 +678,175 @@ public class RoleREST {
return new ArrayList<>(ret);
}
+ @GET
+ @Path("/download/{serviceName}")
+ @Produces({ "application/json", "application/xml" })
+ public RangerRoles getRangerRolesIfUpdated(
+ @PathParam("serviceName") String serviceName,
+ @QueryParam("lastKnownRoleVersion") Long lastKnownRoleVersion,
+ @DefaultValue("0") @QueryParam("lastActivationTime") Long lastActivationTime,
+ @QueryParam("pluginId") String pluginId,
+ @DefaultValue("") @QueryParam("clusterName") String clusterName,
+ @Context HttpServletRequest request) throws Exception {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RoleREST.getRangerRolesIfUpdated("
+ + serviceName + ", " + lastKnownRoleVersion + ", " + lastActivationTime + ")");
+ }
+ RangerRoles ret = null;
+
+ boolean isValid = false;
+ int httpCode = HttpServletResponse.SC_OK;
+ Long downloadedVersion = null;
+ String logMsg = null;
+
+ try {
+ isValid = serviceUtil.isValidService(serviceName, request);
+ } catch (WebApplicationException webException) {
+ httpCode = webException.getResponse().getStatus();
+ logMsg = webException.getResponse().getEntity().toString();
+ } catch (Exception e) {
+ httpCode = HttpServletResponse.SC_BAD_REQUEST;
+ logMsg = e.getMessage();
+ }
+ if (isValid) {
+ if (lastKnownRoleVersion == null) {
+ lastKnownRoleVersion = Long.valueOf(-1);
+ }
+ try {
+ RangerRoles rangerRoles = roleStore.getRangerRoles(serviceName, lastKnownRoleVersion);
+ if (rangerRoles == null) {
+ downloadedVersion = lastKnownRoleVersion;
+ httpCode = HttpServletResponse.SC_NOT_MODIFIED;
+ logMsg = "No change since last update";
+ } else {
+ downloadedVersion = rangerRoles.getRoleVersion();
+ rangerRoles.setServiceName(serviceName);
+ ret = rangerRoles;
+ httpCode = HttpServletResponse.SC_OK;
+ logMsg = "Returning RangerRoles =>" + (ret.toString());
+ }
+
+ } catch (Throwable excp) {
+ LOG.error("getRangerRolesIfUpdated(" + serviceName + ", " + lastKnownRoleVersion + ", " + lastActivationTime + ") failed", excp);
+ httpCode = HttpServletResponse.SC_BAD_REQUEST;
+ logMsg = excp.getMessage();
+ }
+ }
+
+ assetMgr.createPluginInfo(serviceName, pluginId, request, RangerPluginInfo.ENTITY_TYPE_ROLES, downloadedVersion, lastKnownRoleVersion, lastActivationTime, httpCode, clusterName);
+
+ if (httpCode != HttpServletResponse.SC_OK) {
+ boolean logError = httpCode != HttpServletResponse.SC_NOT_MODIFIED;
+ throw restErrorUtil.createRESTException(httpCode, logMsg, logError);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RoleREST.getRangerRolesIfUpdated(" + serviceName + ", " + lastKnownRoleVersion + ", " + lastActivationTime + ")" + ret);
+ }
+ return ret;
+ }
+
+ @GET
+ @Path("/secure/download/{serviceName}")
+ @Produces({ "application/json", "application/xml" })
+ public RangerRoles getSecureRangerRolesIfUpdated(
+ @PathParam("serviceName") String serviceName,
+ @QueryParam("lastKnownRoleVersion") Long lastKnownRoleVersion,
+ @DefaultValue("0") @QueryParam("lastActivationTime") Long lastActivationTime,
+ @QueryParam("pluginId") String pluginId,
+ @DefaultValue("") @QueryParam("clusterName") String clusterName,
+ @Context HttpServletRequest request) throws Exception {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RoleREST.getSecureRangerRolesIfUpdated("
+ + serviceName + ", " + lastKnownRoleVersion + ", " + lastKnownRoleVersion + ")");
+ }
+ RangerRoles ret = null;
+ int httpCode = HttpServletResponse.SC_OK;
+ String logMsg = null;
+ boolean isAllowed = false;
+ boolean isAdmin = bizUtil.isAdmin();
+ boolean isKeyAdmin = bizUtil.isKeyAdmin();
+ Long downloadedVersion = null;
+
+ request.setAttribute("downloadPolicy", "secure");
+
+ boolean isValid = false;
+ try {
+ isValid = serviceUtil.isValidService(serviceName, request);
+ } catch (WebApplicationException webException) {
+ httpCode = webException.getResponse().getStatus();
+ logMsg = webException.getResponse().getEntity().toString();
+ } catch (Exception e) {
+ httpCode = HttpServletResponse.SC_BAD_REQUEST;
+ logMsg = e.getMessage();
+ }
+ if (isValid) {
+ if (lastKnownRoleVersion == null) {
+ lastKnownRoleVersion = Long.valueOf(-1);
+ }
+ try {
+ XXService xService = daoManager.getXXService().findByName(serviceName);
+ if (xService == null) {
+ LOG.error("Requested Service not found. serviceName=" + serviceName);
+ throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Service:" + serviceName + " not found",
+ false);
+ }
+ XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());
+ RangerService rangerService = svcStore.getServiceByName(serviceName);
+
+ if (org.apache.commons.lang.StringUtils.equals(xServiceDef.getImplclassname(), EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
+ if (isKeyAdmin) {
+ isAllowed = true;
+ }else {
+ isAllowed = bizUtil.isUserAllowed(rangerService, Allowed_User_List_For_Download);
+ }
+ }else{
+ if (isAdmin) {
+ isAllowed = true;
+ }else{
+ isAllowed = bizUtil.isUserAllowed(rangerService, Allowed_User_List_For_Download);
+ }
+ }
+
+ if (isAllowed) {
+ RangerRoles rangerRoles = roleStore.getRangerRoles(serviceName, lastKnownRoleVersion);
+ if (rangerRoles == null) {
+ downloadedVersion = lastKnownRoleVersion;
+ httpCode = HttpServletResponse.SC_NOT_MODIFIED;
+ logMsg = "No change since last update";
+ } else {
+ downloadedVersion = rangerRoles.getRoleVersion();
+ rangerRoles.setServiceName(serviceName);
+ ret = rangerRoles;
+ httpCode = HttpServletResponse.SC_OK;
+ logMsg = "Returning RangerRoles =>" + (ret.toString());
+ }
+ } else {
+ LOG.error("getSecureRangerRolesIfUpdated(" + serviceName + ", " + lastKnownRoleVersion + ") failed as User doesn't have permission to UserGroupRoles");
+ httpCode = HttpServletResponse.SC_UNAUTHORIZED;
+ logMsg = "User doesn't have permission to download UserGroupRoles";
+ }
+
+ } catch (Throwable excp) {
+ LOG.error("getSecureRangerRolesIfUpdated(" + serviceName + ", " + lastKnownRoleVersion + ", " + lastActivationTime + ") failed", excp);
+ httpCode = HttpServletResponse.SC_BAD_REQUEST;
+ logMsg = excp.getMessage();
+ }
+ }
+
+ assetMgr.createPluginInfo(serviceName, pluginId, request, RangerPluginInfo.ENTITY_TYPE_ROLES, downloadedVersion, lastKnownRoleVersion, lastActivationTime, httpCode, clusterName);
+
+ if (httpCode != HttpServletResponse.SC_OK) {
+ boolean logError = httpCode != HttpServletResponse.SC_NOT_MODIFIED;
+ throw restErrorUtil.createRESTException(httpCode, logMsg, logError);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RoleREST.getSecureRangerRolesIfUpdated(" + serviceName + ", " + lastKnownRoleVersion + ", " + lastActivationTime + ")" + ret);
+ }
+ return ret;
+ }
+
private void ensureAdminAccess(String serviceName, String userName) throws Exception {
/* If userName (execUser) is not same as logged in user then check
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index cfeaadd..190c6f5 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -3811,8 +3811,6 @@ public class ServiceREST {
ret.setPolicies(servicePolicies.getPolicies());
ret.setTagPolicies(servicePolicies.getTagPolicies());
ret.setSecurityZones(servicePolicies.getSecurityZones());
- ret.setUserRoles(servicePolicies.getUserRoles());
- ret.setGroupRoles(servicePolicies.getGroupRoles());
if (containsDisabledResourcePolicies) {
List<RangerPolicy> filteredPolicies = new ArrayList<RangerPolicy>();
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
index 8857afd..e168278 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
@@ -285,6 +285,23 @@ public class RangerRoleService extends RangerRoleServiceBase<XXRole, RangerRole>
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()) {
@@ -330,5 +347,31 @@ public class RangerRoleService extends RangerRoleServiceBase<XXRole, RangerRole>
}
}
+ 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);
+ }
+
+ 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);
+ }
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("<== updatePolicyVersions(roleIds=" + roleIds + ")");
+ }
+ }
+
}