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 <[email protected]>
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 <[email protected]>
---
.../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 + ")");
+ }
+ }
+
}