You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ab...@apache.org on 2018/03/05 06:27:10 UTC
[1/4] ranger git commit: RANGER-2000: Policy effective dates to
support time-bound and temporary authorization
Repository: ranger
Updated Branches:
refs/heads/master 703792005 -> 844315cdb
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasNotificationMapper.java
----------------------------------------------------------------------
diff --git a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasNotificationMapper.java b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasNotificationMapper.java
index 916aad3..85c7c20 100644
--- a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasNotificationMapper.java
+++ b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasNotificationMapper.java
@@ -28,6 +28,7 @@ import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.model.RangerTag;
import org.apache.ranger.plugin.model.RangerTagDef;
import org.apache.ranger.plugin.model.RangerTagDef.RangerTagAttributeDef;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.util.ServiceTags;
import org.apache.ranger.tagsync.source.atlasrest.RangerAtlasEntity;
import org.apache.ranger.tagsync.source.atlasrest.RangerAtlasEntityWithTags;
@@ -38,295 +39,315 @@ import java.util.List;
import java.util.Map;
public class AtlasNotificationMapper {
- private static final Log LOG = LogFactory.getLog(AtlasNotificationMapper.class);
-
-
- private static Map<String, Long> unhandledEventTypes = new HashMap<String, Long>();
-
- private static void logUnhandledEntityNotification(EntityNotificationWrapper entityNotification) {
-
- final int REPORTING_INTERVAL_FOR_UNHANDLED_ENTITYTYPE_IN_MILLIS = 5 * 60 * 1000; // 5 minutes
-
- boolean loggingNeeded = false;
- String entityTypeName = entityNotification.getEntityTypeName();
-
- if (entityTypeName != null) {
- Long timeInMillis = unhandledEventTypes.get(entityTypeName);
- long currentTimeInMillis = System.currentTimeMillis();
- if (timeInMillis == null ||
- (currentTimeInMillis - timeInMillis) >= REPORTING_INTERVAL_FOR_UNHANDLED_ENTITYTYPE_IN_MILLIS) {
- unhandledEventTypes.put(entityTypeName, currentTimeInMillis);
- loggingNeeded = true;
- }
- } else {
- LOG.error("EntityNotification contains NULL entity or NULL entity-type");
- }
-
- if (loggingNeeded) {
- LOG.warn("Ignoring entity notification of type " + entityTypeName);
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Ignoring entity notification of type " + entityTypeName);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static ServiceTags processEntityNotification(EntityNotificationWrapper entityNotification) {
-
- ServiceTags ret = null;
-
- if (isNotificationHandled(entityNotification)) {
- try {
- RangerAtlasEntityWithTags entityWithTags = new RangerAtlasEntityWithTags(entityNotification);
-
- if (entityNotification.getIsEntityDeleteOp()) {
- ret = buildServiceTagsForEntityDeleteNotification(entityWithTags);
- } else {
- ret = buildServiceTags(entityWithTags, null);
- }
-
- } catch (Exception exception) {
- LOG.error("createServiceTags() failed!! ", exception);
- }
- } else {
- logUnhandledEntityNotification(entityNotification);
- }
- return ret;
- }
-
- public static Map<String, ServiceTags> processAtlasEntities(List<RangerAtlasEntityWithTags> atlasEntities) {
- Map<String, ServiceTags> ret = null;
-
- try {
- ret = buildServiceTags(atlasEntities);
- } catch (Exception exception) {
- LOG.error("Failed to build serviceTags", exception);
- }
-
- return ret;
- }
-
- static private boolean isNotificationHandled(EntityNotificationWrapper entityNotification) {
- boolean ret = false;
-
- EntityNotificationWrapper.NotificationType opType = entityNotification.getEntityNotificationType();
-
- if (opType != null) {
- switch (opType) {
- case ENTITY_CREATE:
- ret = ! entityNotification.getIsEmptyClassifications();
- break;
- case ENTITY_UPDATE:
- case ENTITY_DELETE:
- case CLASSIFICATION_ADD:
- case CLASSIFICATION_UPDATE:
- case CLASSIFICATION_DELETE: {
- ret = true;
- break;
- }
- default:
- LOG.error(opType + ": unknown notification received - not handled");
- break;
- }
- if (ret) {
- ret = entityNotification.getIsEntityTypeHandled();
- }
- }
-
- return ret;
- }
-
- static private ServiceTags buildServiceTagsForEntityDeleteNotification(RangerAtlasEntityWithTags entityWithTags) throws Exception {
- final ServiceTags ret;
-
- RangerAtlasEntity entity = entityWithTags.getEntity();
-
- String guid = entity.getGuid();
- if (StringUtils.isNotBlank(guid)) {
- ret = new ServiceTags();
- RangerServiceResource serviceResource = new RangerServiceResource();
- serviceResource.setGuid(guid);
- ret.getServiceResources().add(serviceResource);
- } else {
- ret = buildServiceTags(entityWithTags, null);
- if (ret != null) {
- // tag-definitions should NOT be deleted as part of service-resource delete
- ret.setTagDefinitions(MapUtils.EMPTY_MAP);
- // Ranger deletes tags associated with deleted service-resource
- ret.setTags(MapUtils.EMPTY_MAP);
- }
- }
-
- if (ret != null) {
- ret.setOp(ServiceTags.OP_DELETE);
- }
-
- return ret;
- }
-
- static private Map<String, ServiceTags> buildServiceTags(List<RangerAtlasEntityWithTags> entitiesWithTags) throws Exception {
-
- Map<String, ServiceTags> ret = new HashMap<String, ServiceTags>();
-
- for (RangerAtlasEntityWithTags element : entitiesWithTags) {
- RangerAtlasEntity entity = element.getEntity();
- if (entity != null) {
- buildServiceTags(element, ret);
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Ignoring entity because its State is not ACTIVE: " + element);
- }
- }
- }
-
- // Remove duplicate tag definitions
- if(CollectionUtils.isNotEmpty(ret.values())) {
- for (ServiceTags serviceTag : ret.values()) {
- if(MapUtils.isNotEmpty(serviceTag.getTagDefinitions())) {
- Map<String, RangerTagDef> uniqueTagDefs = new HashMap<String, RangerTagDef>();
-
- for (RangerTagDef tagDef : serviceTag.getTagDefinitions().values()) {
- RangerTagDef existingTagDef = uniqueTagDefs.get(tagDef.getName());
-
- if (existingTagDef == null) {
- uniqueTagDefs.put(tagDef.getName(), tagDef);
- } else {
- if(CollectionUtils.isNotEmpty(tagDef.getAttributeDefs())) {
- for(RangerTagAttributeDef tagAttrDef : tagDef.getAttributeDefs()) {
- boolean attrDefExists = false;
-
- if(CollectionUtils.isNotEmpty(existingTagDef.getAttributeDefs())) {
- for(RangerTagAttributeDef existingTagAttrDef : existingTagDef.getAttributeDefs()) {
- if(StringUtils.equalsIgnoreCase(existingTagAttrDef.getName(), tagAttrDef.getName())) {
- attrDefExists = true;
- break;
- }
- }
- }
-
- if(! attrDefExists) {
- existingTagDef.getAttributeDefs().add(tagAttrDef);
- }
- }
- }
- }
- }
-
- serviceTag.getTagDefinitions().clear();
- for(RangerTagDef tagDef : uniqueTagDefs.values()) {
- serviceTag.getTagDefinitions().put(tagDef.getId(), tagDef);
- }
- }
- }
- }
-
- if (MapUtils.isNotEmpty(ret)) {
- for (Map.Entry<String, ServiceTags> entry : ret.entrySet()) {
- ServiceTags serviceTags = entry.getValue();
- serviceTags.setOp(ServiceTags.OP_REPLACE);
- }
- }
- return ret;
- }
-
- static private ServiceTags buildServiceTags(RangerAtlasEntityWithTags entityWithTags, Map<String, ServiceTags> serviceTagsMap) throws Exception {
- ServiceTags ret = null;
- RangerAtlasEntity entity = entityWithTags.getEntity();
- RangerServiceResource serviceResource = AtlasResourceMapperUtil.getRangerServiceResource(entity);
-
- if (serviceResource != null) {
-
- List<RangerTag> tags = getTags(entityWithTags);
- List<RangerTagDef> tagDefs = getTagDefs(entityWithTags);
- String serviceName = serviceResource.getServiceName();
-
- ret = createOrGetServiceTags(serviceTagsMap, serviceName);
-
- if (serviceTagsMap == null || CollectionUtils.isNotEmpty(tags)) {
-
- serviceResource.setId((long) ret.getServiceResources().size());
- ret.getServiceResources().add(serviceResource);
-
- List<Long> tagIds = new ArrayList<Long>();
-
- if (CollectionUtils.isNotEmpty(tags)) {
- for (RangerTag tag : tags) {
- tag.setId((long) ret.getTags().size());
- ret.getTags().put(tag.getId(), tag);
-
- tagIds.add(tag.getId());
- }
- }
- ret.getResourceToTagIds().put(serviceResource.getId(), tagIds);
-
- if (CollectionUtils.isNotEmpty(tagDefs)) {
- for (RangerTagDef tagDef : tagDefs) {
- tagDef.setId((long) ret.getTagDefinitions().size());
- ret.getTagDefinitions().put(tagDef.getId(), tagDef);
- }
- }
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Entity " + entityWithTags + " does not have any tags associated with it when full-sync is being done.");
- LOG.debug("Will not add this entity to serviceTags, so that this entity, if exists, will be removed from ranger");
- }
- }
- } else {
- LOG.error("Failed to build serviceResource for entity:" + entity.getGuid());
- }
-
- return ret;
- }
-
- static private ServiceTags createOrGetServiceTags(Map<String, ServiceTags> serviceTagsMap, String serviceName) {
- ServiceTags ret = serviceTagsMap == null ? null : serviceTagsMap.get(serviceName);
-
- if (ret == null) {
- ret = new ServiceTags();
-
- if (serviceTagsMap != null) {
- serviceTagsMap.put(serviceName, ret);
- }
-
- ret.setOp(ServiceTags.OP_ADD_OR_UPDATE);
- ret.setServiceName(serviceName);
- }
-
- return ret;
- }
-
- static private List<RangerTag> getTags(RangerAtlasEntityWithTags entityWithTags) {
- List<RangerTag> ret = new ArrayList<RangerTag>();
-
- if (entityWithTags != null && MapUtils.isNotEmpty(entityWithTags.getTags())) {
- Map<String, Map<String, String>> tags = entityWithTags.getTags();
-
- for (Map.Entry<String, Map<String, String>> tag : tags.entrySet()) {
- ret.add(new RangerTag(null, tag.getKey(), tag.getValue(), RangerTag.OWNER_SERVICERESOURCE));
- }
- }
-
- return ret;
- }
-
- static private List<RangerTagDef> getTagDefs(RangerAtlasEntityWithTags entityWithTags) {
- List<RangerTagDef> ret = new ArrayList<RangerTagDef>();
-
- if (entityWithTags != null && MapUtils.isNotEmpty(entityWithTags.getTags())) {
- Map<String, Map<String, String>> tags = entityWithTags.getTags();
-
- for (Map.Entry<String, Map<String, String>> tag : tags.entrySet()) {
- RangerTagDef tagDef = new RangerTagDef(tag.getKey(), "Atlas");
- if (MapUtils.isNotEmpty(tag.getValue())) {
- for (String attributeName : tag.getValue().keySet()) {
- tagDef.getAttributeDefs().add(new RangerTagAttributeDef(attributeName, entityWithTags.getTagAttributeType(tag.getKey(), attributeName)));
- }
- }
- ret.add(tagDef);
- }
- }
-
- return ret;
- }
+ private static final int REPORTING_INTERVAL_FOR_UNHANDLED_ENTITYTYPE_IN_MILLIS = 5 * 60 * 1000; // 5 minutes
+
+ private static final Log LOG = LogFactory.getLog(AtlasNotificationMapper.class);
+ private static Map<String, Long> unhandledEventTypes = new HashMap<>();
+
+ private static void logUnhandledEntityNotification(EntityNotificationWrapper entityNotification) {
+
+ boolean skipLogging = entityNotification.getIsEntityCreateOp() && entityNotification.getIsEmptyClassifications()
+ || ! entityNotification.getIsEntityActive();
+
+ if (!skipLogging) {
+ boolean loggingNeeded = false;
+
+ String entityTypeName = entityNotification.getEntityTypeName();
+
+ if (entityTypeName != null) {
+ Long timeInMillis = unhandledEventTypes.get(entityTypeName);
+ long currentTimeInMillis = System.currentTimeMillis();
+ if (timeInMillis == null ||
+ (currentTimeInMillis - timeInMillis) >= REPORTING_INTERVAL_FOR_UNHANDLED_ENTITYTYPE_IN_MILLIS) {
+ unhandledEventTypes.put(entityTypeName, currentTimeInMillis);
+ loggingNeeded = true;
+ }
+ } else {
+ LOG.error("EntityNotification contains NULL entity or NULL entity-type");
+ }
+
+ if (loggingNeeded) {
+ LOG.warn("Did not process entity notification for [" + entityTypeName + "]");
+ }
+
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ServiceTags processEntityNotification(EntityNotificationWrapper entityNotification) {
+
+ ServiceTags ret = null;
+
+ if (isNotificationHandled(entityNotification)) {
+ try {
+ RangerAtlasEntityWithTags entityWithTags = new RangerAtlasEntityWithTags(entityNotification);
+
+ if (entityNotification.getIsEntityDeleteOp()) {
+ ret = buildServiceTagsForEntityDeleteNotification(entityWithTags);
+ } else {
+ ret = buildServiceTags(entityWithTags, null);
+ }
+
+ } catch (Exception exception) {
+ LOG.error("createServiceTags() failed!! ", exception);
+ }
+ } else {
+ logUnhandledEntityNotification(entityNotification);
+ }
+ return ret;
+ }
+
+ public static Map<String, ServiceTags> processAtlasEntities(List<RangerAtlasEntityWithTags> atlasEntities) {
+ Map<String, ServiceTags> ret = null;
+
+ try {
+ ret = buildServiceTags(atlasEntities);
+ } catch (Exception exception) {
+ LOG.error("Failed to build serviceTags", exception);
+ }
+
+ return ret;
+ }
+
+ static private boolean isNotificationHandled(EntityNotificationWrapper entityNotification) {
+ boolean ret = false;
+
+ EntityNotificationWrapper.NotificationOpType opType = entityNotification.getOpType();
+
+ if (opType != null) {
+ switch (opType) {
+ case ENTITY_CREATE:
+ ret = ! entityNotification.getIsEmptyClassifications();
+ break;
+ case ENTITY_UPDATE:
+ case ENTITY_DELETE:
+ case CLASSIFICATION_ADD:
+ case CLASSIFICATION_UPDATE:
+ case CLASSIFICATION_DELETE: {
+ ret = true;
+ break;
+ }
+ default:
+ LOG.error(opType + ": unknown notification received - not handled");
+ break;
+ }
+ if (ret) {
+ ret = entityNotification.getIsEntityTypeHandled();
+ }
+ if (!ret) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Notification : [" + entityNotification + "] will NOT be processed.");
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ static private ServiceTags buildServiceTagsForEntityDeleteNotification(RangerAtlasEntityWithTags entityWithTags) {
+ final ServiceTags ret;
+
+ RangerAtlasEntity entity = entityWithTags.getEntity();
+ String guid = entity.getGuid();
+
+ if (StringUtils.isNotBlank(guid)) {
+ ret = new ServiceTags();
+ RangerServiceResource serviceResource = new RangerServiceResource();
+ serviceResource.setGuid(guid);
+ ret.getServiceResources().add(serviceResource);
+ } else {
+ ret = buildServiceTags(entityWithTags, null);
+ if (ret != null) {
+ // tag-definitions should NOT be deleted as part of service-resource delete
+ ret.setTagDefinitions(MapUtils.EMPTY_MAP);
+ // Ranger deletes tags associated with deleted service-resource
+ ret.setTags(MapUtils.EMPTY_MAP);
+ }
+ }
+
+ if (ret != null) {
+ ret.setOp(ServiceTags.OP_DELETE);
+ }
+
+ return ret;
+ }
+
+ static private Map<String, ServiceTags> buildServiceTags(List<RangerAtlasEntityWithTags> entitiesWithTags) {
+
+ Map<String, ServiceTags> ret = new HashMap<>();
+
+ for (RangerAtlasEntityWithTags element : entitiesWithTags) {
+ RangerAtlasEntity entity = element.getEntity();
+ if (entity != null) {
+ buildServiceTags(element, ret);
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Ignoring entity because its State is not ACTIVE: " + element);
+ }
+ }
+ }
+
+ // Remove duplicate tag definitions
+ if(CollectionUtils.isNotEmpty(ret.values())) {
+ for (ServiceTags serviceTag : ret.values()) {
+ if(MapUtils.isNotEmpty(serviceTag.getTagDefinitions())) {
+ Map<String, RangerTagDef> uniqueTagDefs = new HashMap<>();
+
+ for (RangerTagDef tagDef : serviceTag.getTagDefinitions().values()) {
+ RangerTagDef existingTagDef = uniqueTagDefs.get(tagDef.getName());
+
+ if (existingTagDef == null) {
+ uniqueTagDefs.put(tagDef.getName(), tagDef);
+ } else {
+ if(CollectionUtils.isNotEmpty(tagDef.getAttributeDefs())) {
+ for(RangerTagAttributeDef tagAttrDef : tagDef.getAttributeDefs()) {
+ boolean attrDefExists = false;
+
+ if(CollectionUtils.isNotEmpty(existingTagDef.getAttributeDefs())) {
+ for(RangerTagAttributeDef existingTagAttrDef : existingTagDef.getAttributeDefs()) {
+ if(StringUtils.equalsIgnoreCase(existingTagAttrDef.getName(), tagAttrDef.getName())) {
+ attrDefExists = true;
+ break;
+ }
+ }
+ }
+
+ if(! attrDefExists) {
+ existingTagDef.getAttributeDefs().add(tagAttrDef);
+ }
+ }
+ }
+ }
+ }
+
+ serviceTag.getTagDefinitions().clear();
+ for(RangerTagDef tagDef : uniqueTagDefs.values()) {
+ serviceTag.getTagDefinitions().put(tagDef.getId(), tagDef);
+ }
+ }
+ }
+ }
+
+ if (MapUtils.isNotEmpty(ret)) {
+ for (Map.Entry<String, ServiceTags> entry : ret.entrySet()) {
+ ServiceTags serviceTags = entry.getValue();
+ serviceTags.setOp(ServiceTags.OP_REPLACE);
+ }
+ }
+ return ret;
+ }
+
+ static private ServiceTags buildServiceTags(RangerAtlasEntityWithTags entityWithTags, Map<String, ServiceTags> serviceTagsMap) {
+ ServiceTags ret = null;
+ RangerAtlasEntity entity = entityWithTags.getEntity();
+ RangerServiceResource serviceResource = AtlasResourceMapperUtil.getRangerServiceResource(entity);
+
+ if (serviceResource != null) {
+
+ List<RangerTag> tags = getTags(entityWithTags);
+ List<RangerTagDef> tagDefs = getTagDefs(entityWithTags);
+ String serviceName = serviceResource.getServiceName();
+
+ ret = createOrGetServiceTags(serviceTagsMap, serviceName);
+
+ if (serviceTagsMap == null || CollectionUtils.isNotEmpty(tags)) {
+
+ serviceResource.setId((long) ret.getServiceResources().size());
+ ret.getServiceResources().add(serviceResource);
+
+ List<Long> tagIds = new ArrayList<>();
+
+ if (CollectionUtils.isNotEmpty(tags)) {
+ for (RangerTag tag : tags) {
+ tag.setId((long) ret.getTags().size());
+ ret.getTags().put(tag.getId(), tag);
+
+ tagIds.add(tag.getId());
+ }
+ }
+ ret.getResourceToTagIds().put(serviceResource.getId(), tagIds);
+
+ if (CollectionUtils.isNotEmpty(tagDefs)) {
+ for (RangerTagDef tagDef : tagDefs) {
+ tagDef.setId((long) ret.getTagDefinitions().size());
+ ret.getTagDefinitions().put(tagDef.getId(), tagDef);
+ }
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Entity " + entityWithTags + " does not have any tags associated with it when full-sync is being done.");
+ LOG.debug("Will not add this entity to serviceTags, so that this entity, if exists, will be removed from ranger");
+ }
+ }
+ } else {
+ LOG.error("Failed to build serviceResource for entity:" + entity.getGuid());
+ }
+
+ return ret;
+ }
+
+ static private ServiceTags createOrGetServiceTags(Map<String, ServiceTags> serviceTagsMap, String serviceName) {
+ ServiceTags ret = serviceTagsMap == null ? null : serviceTagsMap.get(serviceName);
+
+ if (ret == null) {
+ ret = new ServiceTags();
+
+ if (serviceTagsMap != null) {
+ serviceTagsMap.put(serviceName, ret);
+ }
+
+ ret.setOp(ServiceTags.OP_ADD_OR_UPDATE);
+ ret.setServiceName(serviceName);
+ }
+
+ return ret;
+ }
+
+ static private List<RangerTag> getTags(RangerAtlasEntityWithTags entityWithTags) {
+ List<RangerTag> ret = new ArrayList<>();
+
+ if (entityWithTags != null && CollectionUtils.isNotEmpty(entityWithTags.getTags())) {
+ List<EntityNotificationWrapper.RangerAtlasClassification> tags = entityWithTags.getTags();
+
+ for (EntityNotificationWrapper.RangerAtlasClassification tag : tags) {
+ RangerTag rangerTag = new RangerTag(null, tag.getName(), tag.getAttributes(), RangerTag.OWNER_SERVICERESOURCE);
+
+ List<RangerValiditySchedule> validityPeriods = tag.getValidityPeriods();
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ rangerTag.setValidityPeriods(validityPeriods);
+ }
+ ret.add(rangerTag);
+ }
+ }
+
+ return ret;
+ }
+
+ static private List<RangerTagDef> getTagDefs(RangerAtlasEntityWithTags entityWithTags) {
+ List<RangerTagDef> ret = new ArrayList<>();
+
+ if (entityWithTags != null && CollectionUtils.isNotEmpty(entityWithTags.getTags())) {
+
+ Map<String, String> tagNames = new HashMap<>();
+
+ for (EntityNotificationWrapper.RangerAtlasClassification tag : entityWithTags.getTags()) {
+
+ if (!tagNames.containsKey(tag.getName())) {
+ tagNames.put(tag.getName(), tag.getName());
+
+ RangerTagDef tagDef = new RangerTagDef(tag.getName(), "Atlas");
+ if (MapUtils.isNotEmpty(tag.getAttributes())) {
+ for (String attributeName : tag.getAttributes().keySet()) {
+ tagDef.getAttributeDefs().add(new RangerTagAttributeDef(attributeName, entityWithTags.getTagAttributeType(tag.getName(), attributeName)));
+ }
+ }
+ ret.add(tagDef);
+ }
+ }
+ }
+
+ return ret;
+ }
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasTagSource.java
----------------------------------------------------------------------
diff --git a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasTagSource.java b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasTagSource.java
index a13a789..ea4c20c 100644
--- a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasTagSource.java
+++ b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/AtlasTagSource.java
@@ -141,7 +141,7 @@ public class AtlasTagSource extends AbstractTagSource {
private static String getPrintableEntityNotification(EntityNotificationWrapper notification) {
StringBuilder sb = new StringBuilder();
- sb.append("{ Notification-Type: ").append(notification.getEntityNotificationType()).append(", ");
+ sb.append("{ Notification-Type: ").append(notification.getOpType()).append(", ");
RangerAtlasEntityWithTags entityWithTags = new RangerAtlasEntityWithTags(notification);
sb.append(entityWithTags.toString());
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/EntityNotificationWrapper.java
----------------------------------------------------------------------
diff --git a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/EntityNotificationWrapper.java b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/EntityNotificationWrapper.java
index e680b14..f08c331 100644
--- a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/EntityNotificationWrapper.java
+++ b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlas/EntityNotificationWrapper.java
@@ -19,6 +19,7 @@
package org.apache.ranger.tagsync.source.atlas;
+import org.apache.atlas.model.TimeBoundary;
import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.notification.EntityNotification;
@@ -30,9 +31,11 @@ import org.apache.atlas.v1.model.notification.EntityNotificationV2;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.tagsync.source.atlasrest.RangerAtlasEntity;
import javax.annotation.Nonnull;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -40,64 +43,199 @@ import java.util.Map;
public class EntityNotificationWrapper {
private static final Log LOG = LogFactory.getLog(EntityNotificationWrapper.class);
- public enum NotificationType { UNKNOWN, ENTITY_CREATE, ENTITY_UPDATE, ENTITY_DELETE, CLASSIFICATION_ADD, CLASSIFICATION_UPDATE, CLASSIFICATION_DELETE}
-
- private final EntityNotification notification;
- private final EntityNotification.EntityNotificationType notificationType;
- private final RangerAtlasEntity rangerAtlasEntity;
- private final String entityTypeName;
- private final boolean isEntityTypeHandled;
- private final boolean isEntityDeleteOp;
- private final boolean isEmptyClassifications;
-
- EntityNotificationWrapper(@Nonnull EntityNotification notification) {
- this.notification = notification;
- notificationType = this.notification.getType();
-
- switch (notificationType) {
- case ENTITY_NOTIFICATION_V2: {
-
- EntityNotificationV2 v2Notification = (EntityNotificationV2) notification;
- AtlasEntity atlasEntity = v2Notification.getEntity();
- String guid = atlasEntity.getGuid();
- String typeName = atlasEntity.getTypeName();
-
- rangerAtlasEntity = new RangerAtlasEntity(typeName, guid, atlasEntity.getAttributes());
- entityTypeName = atlasEntity.getTypeName();
- isEntityTypeHandled = atlasEntity.getStatus() == AtlasEntity.Status.ACTIVE
- && AtlasResourceMapperUtil.isEntityTypeHandled(entityTypeName);
- isEntityDeleteOp = EntityNotificationV2.OperationType.ENTITY_DELETE == v2Notification.getOperationType();
- isEmptyClassifications = CollectionUtils.isNotEmpty(v2Notification.getClassifications());
- }
- break;
- case ENTITY_NOTIFICATION_V1: {
- EntityNotificationV1 v1Notification = (EntityNotificationV1) notification;
-
- Referenceable atlasEntity = v1Notification.getEntity();
- String guid = atlasEntity.getId()._getId();
- String typeName = atlasEntity.getTypeName();
-
- rangerAtlasEntity = new RangerAtlasEntity(typeName, guid, atlasEntity.getValues());
- entityTypeName = atlasEntity.getTypeName();
- isEntityTypeHandled = atlasEntity.getId().getState() == Id.EntityState.ACTIVE
- && AtlasResourceMapperUtil.isEntityTypeHandled(entityTypeName);
- isEntityDeleteOp = EntityNotificationV1.OperationType.ENTITY_DELETE == v1Notification.getOperationType();
- isEmptyClassifications = CollectionUtils.isNotEmpty(v1Notification.getAllTraits());
- }
- break;
- default: {
- LOG.error("Unknown notification type - [" + notificationType + "]");
-
- rangerAtlasEntity = null;
- entityTypeName = null;
- isEntityTypeHandled = false;
- isEntityDeleteOp = false;
- isEmptyClassifications = true;
- }
-
- break;
+ public enum NotificationOpType { UNKNOWN, ENTITY_CREATE, ENTITY_UPDATE, ENTITY_DELETE, CLASSIFICATION_ADD, CLASSIFICATION_UPDATE, CLASSIFICATION_DELETE}
+
+ public static class RangerAtlasClassification {
+ private final String name;
+ private final Map<String, String> attributes;
+ private final List<RangerValiditySchedule> validityPeriods;
+
+ public RangerAtlasClassification(String name, Map<String, String> attributes, List<RangerValiditySchedule> validityPeriods) {
+ this.name = name;
+ this.attributes = attributes;
+ this.validityPeriods = validityPeriods;
+ }
+ public String getName() {
+ return name;
+ }
+ public Map<String, String> getAttributes() {
+ return attributes;
+ }
+ public List<RangerValiditySchedule> getValidityPeriods() {
+ return validityPeriods;
}
+
}
+ private final RangerAtlasEntity rangerAtlasEntity;
+ private final String entityTypeName;
+ private final boolean isEntityActive;
+ private final boolean isEntityTypeHandled;
+ private final boolean isEntityDeleteOp;
+ private final boolean isEntityCreateOp;
+ private final boolean isEmptyClassifications;
+ private final List<RangerAtlasClassification> classifications;
+ private final NotificationOpType opType;
+
+ EntityNotificationWrapper(@Nonnull EntityNotification notification) {
+ EntityNotification.EntityNotificationType notificationType = notification.getType();
+
+ switch (notificationType) {
+ case ENTITY_NOTIFICATION_V2: {
+ EntityNotificationV2 v2Notification = (EntityNotificationV2) notification;
+ AtlasEntity atlasEntity = v2Notification.getEntity();
+ String guid = atlasEntity.getGuid();
+ String typeName = atlasEntity.getTypeName();
+
+ rangerAtlasEntity = new RangerAtlasEntity(typeName, guid, atlasEntity.getAttributes());
+ entityTypeName = atlasEntity.getTypeName();
+ isEntityActive = atlasEntity.getStatus() == AtlasEntity.Status.ACTIVE;
+ isEntityTypeHandled = isEntityActive && AtlasResourceMapperUtil.isEntityTypeHandled(entityTypeName);
+ isEntityDeleteOp = EntityNotificationV2.OperationType.ENTITY_DELETE == v2Notification.getOperationType();
+ isEntityCreateOp = EntityNotificationV2.OperationType.ENTITY_CREATE == v2Notification.getOperationType();
+ isEmptyClassifications = CollectionUtils.isNotEmpty(v2Notification.getClassifications());
+
+ List<AtlasClassification> allClassifications = v2Notification.getClassifications();
+
+ if (CollectionUtils.isNotEmpty(allClassifications)) {
+ classifications = new ArrayList<>();
+
+ for (AtlasClassification classification : allClassifications) {
+ String classificationName = classification.getTypeName();
+
+ Map<String, Object> valuesMap = classification.getAttributes();
+ Map<String, String> attributes = new HashMap<>();
+
+ if (valuesMap != null) {
+ for (Map.Entry<String, Object> value : valuesMap.entrySet()) {
+ if (value.getValue() != null) {
+ attributes.put(value.getKey(), value.getValue().toString());
+ }
+ }
+ }
+
+ List<RangerValiditySchedule> validitySchedules = null;
+ List<TimeBoundary> validityPeriods = classification.getValidityPeriods();
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ validitySchedules = convertTimeSpecFromAtlasToRanger(validityPeriods);
+ }
+ classifications.add(new RangerAtlasClassification(classificationName, attributes, validitySchedules));
+ }
+ } else {
+ classifications = null;
+ }
+
+ EntityNotificationV2.OperationType operationType = v2Notification.getOperationType();
+ switch (operationType) {
+ case ENTITY_CREATE:
+ opType = NotificationOpType.ENTITY_CREATE;
+ break;
+ case ENTITY_UPDATE:
+ opType = NotificationOpType.ENTITY_UPDATE;
+ break;
+ case ENTITY_DELETE:
+ opType = NotificationOpType.ENTITY_DELETE;
+ break;
+ case CLASSIFICATION_ADD:
+ opType = NotificationOpType.CLASSIFICATION_ADD;
+ break;
+ case CLASSIFICATION_UPDATE:
+ opType = NotificationOpType.CLASSIFICATION_UPDATE;
+ break;
+ case CLASSIFICATION_DELETE:
+ opType = NotificationOpType.CLASSIFICATION_DELETE;
+ break;
+ default:
+ LOG.error("Received OperationType [" + operationType + "], converting to UNKNOWN");
+ opType = NotificationOpType.UNKNOWN;
+ break;
+ }
+ }
+ break;
+
+ case ENTITY_NOTIFICATION_V1: {
+ EntityNotificationV1 v1Notification = (EntityNotificationV1) notification;
+ Referenceable atlasEntity = v1Notification.getEntity();
+ String guid = atlasEntity.getId()._getId();
+ String typeName = atlasEntity.getTypeName();
+
+ rangerAtlasEntity = new RangerAtlasEntity(typeName, guid, atlasEntity.getValues());
+ entityTypeName = atlasEntity.getTypeName();
+ isEntityActive = atlasEntity.getId().getState() == Id.EntityState.ACTIVE;
+ isEntityTypeHandled = isEntityActive && AtlasResourceMapperUtil.isEntityTypeHandled(entityTypeName);
+ isEntityDeleteOp = EntityNotificationV1.OperationType.ENTITY_DELETE == v1Notification.getOperationType();
+ isEntityCreateOp = EntityNotificationV1.OperationType.ENTITY_CREATE == v1Notification.getOperationType();
+ isEmptyClassifications = CollectionUtils.isNotEmpty(v1Notification.getAllTraits());
+
+ List<Struct> allTraits = ((EntityNotificationV1) notification).getAllTraits();
+
+ if (CollectionUtils.isNotEmpty(allTraits)) {
+ classifications = new ArrayList<>();
+
+ for (Struct trait : allTraits) {
+ String traitName = trait.getTypeName();
+ Map<String, Object> valuesMap = trait.getValuesMap();
+ Map<String, String> attributes = new HashMap<>();
+
+ if (valuesMap != null) {
+ for (Map.Entry<String, Object> value : valuesMap.entrySet()) {
+ if (value.getValue() != null) {
+ attributes.put(value.getKey(), value.getValue().toString());
+ }
+ }
+ }
+
+ classifications.add(new RangerAtlasClassification(traitName, attributes, null));
+ }
+ } else {
+ classifications = null;
+ }
+
+ EntityNotificationV1.OperationType operationType = v1Notification.getOperationType();
+ switch (operationType) {
+ case ENTITY_CREATE:
+ opType = NotificationOpType.ENTITY_CREATE;
+ break;
+ case ENTITY_UPDATE:
+ opType = NotificationOpType.ENTITY_UPDATE;
+ break;
+ case ENTITY_DELETE:
+ opType = NotificationOpType.ENTITY_DELETE;
+ break;
+ case TRAIT_ADD:
+ opType = NotificationOpType.CLASSIFICATION_ADD;
+ break;
+ case TRAIT_UPDATE:
+ opType = NotificationOpType.CLASSIFICATION_UPDATE;
+ break;
+ case TRAIT_DELETE:
+ opType = NotificationOpType.CLASSIFICATION_DELETE;
+ break;
+ default:
+ LOG.error("Received OperationType [" + operationType + "], converting to UNKNOWN");
+ opType = NotificationOpType.UNKNOWN;
+ break;
+ }
+ }
+ break;
+
+ default: {
+ LOG.error("Unknown notification type - [" + notificationType + "]");
+
+ rangerAtlasEntity = null;
+ entityTypeName = null;
+ isEntityActive = false;
+ isEntityTypeHandled = false;
+ isEntityDeleteOp = false;
+ isEntityCreateOp = false;
+ isEmptyClassifications = true;
+ classifications = null;
+ opType = NotificationOpType.UNKNOWN;
+ }
+
+ break;
+ }
+ }
public RangerAtlasEntity getRangerAtlasEntity() {
return rangerAtlasEntity;
@@ -115,128 +253,41 @@ public class EntityNotificationWrapper {
return isEntityDeleteOp;
}
+ public boolean getIsEntityCreateOp() {
+ return isEntityCreateOp;
+ }
+
public boolean getIsEmptyClassifications() {
return isEmptyClassifications;
}
- public NotificationType getEntityNotificationType() {
- NotificationType ret = NotificationType.UNKNOWN;
-
- switch (notificationType) {
- case ENTITY_NOTIFICATION_V2: {
- EntityNotificationV2.OperationType opType = ((EntityNotificationV2) notification).getOperationType();
- switch (opType) {
- case ENTITY_CREATE:
- ret = NotificationType.ENTITY_CREATE;
- break;
- case ENTITY_UPDATE:
- ret = NotificationType.ENTITY_UPDATE;
- break;
- case ENTITY_DELETE:
- ret = NotificationType.ENTITY_DELETE;
- break;
- case CLASSIFICATION_ADD:
- ret = NotificationType.CLASSIFICATION_ADD;
- break;
- case CLASSIFICATION_UPDATE:
- ret = NotificationType.CLASSIFICATION_UPDATE;
- break;
- case CLASSIFICATION_DELETE:
- ret = NotificationType.CLASSIFICATION_DELETE;
- break;
- default:
- LOG.error("Received OperationType [" + opType + "], converting to UNKNOWN");
- break;
- }
- break;
- }
- case ENTITY_NOTIFICATION_V1: {
- EntityNotificationV1.OperationType opType = ((EntityNotificationV1) notification).getOperationType();
- switch (opType) {
- case ENTITY_CREATE:
- ret = NotificationType.ENTITY_CREATE;
- break;
- case ENTITY_UPDATE:
- ret = NotificationType.ENTITY_UPDATE;
- break;
- case ENTITY_DELETE:
- ret = NotificationType.ENTITY_DELETE;
- break;
- case TRAIT_ADD:
- ret = NotificationType.CLASSIFICATION_ADD;
- break;
- case TRAIT_UPDATE:
- ret = NotificationType.CLASSIFICATION_UPDATE;
- break;
- case TRAIT_DELETE:
- ret = NotificationType.CLASSIFICATION_DELETE;
- break;
- default:
- LOG.error("Received OperationType [" + opType + "], converting to UNKNOWN");
- break;
- }
- break;
- }
- default: {
- LOG.error("Unknown notification type - [" + notificationType + "]");
- }
- break;
- }
-
- return ret;
+ public List<RangerAtlasClassification> getClassifications() {
+ return classifications;
}
- public Map<String, Map<String, String>> getAllClassifications() {
- Map<String, Map<String, String>> ret = new HashMap<>();
-
- switch (notificationType) {
- case ENTITY_NOTIFICATION_V2: {
- List<AtlasClassification> allClassifications = ((EntityNotificationV2) notification).getClassifications();
- if (CollectionUtils.isNotEmpty(allClassifications)) {
- for (AtlasClassification classification : allClassifications) {
- String classificationName = classification.getTypeName();
-
- Map<String, Object> valuesMap = classification.getAttributes();
- Map<String, String> attributes = new HashMap<>();
- if (valuesMap != null) {
- for (Map.Entry<String, Object> value : valuesMap.entrySet()) {
- if (value.getValue() != null) {
- attributes.put(value.getKey(), value.getValue().toString());
- }
- }
- }
- ret.put(classificationName, attributes);
- }
- }
- }
- break;
- case ENTITY_NOTIFICATION_V1: {
- List<Struct> allTraits = ((EntityNotificationV1) notification).getAllTraits();
- if (CollectionUtils.isNotEmpty(allTraits)) {
- for (Struct trait : allTraits) {
- String traitName = trait.getTypeName();
-
- Map<String, Object> valuesMap = trait.getValuesMap();
- Map<String, String> attributes = new HashMap<>();
- if (valuesMap != null) {
- for (Map.Entry<String, Object> value : valuesMap.entrySet()) {
- if (value.getValue() != null) {
- attributes.put(value.getKey(), value.getValue().toString());
- }
- }
- }
- ret.put(traitName, attributes);
- }
- }
- }
- break;
- default: {
- LOG.error("Unknown notification type - [" + notificationType + "]");
- }
- break;
- }
+ public NotificationOpType getOpType() {
+ return opType;
+ }
- return ret;
- }
+ public boolean getIsEntityActive() { return isEntityActive; }
+
+ public static List<RangerValiditySchedule> convertTimeSpecFromAtlasToRanger(List<TimeBoundary> atlasTimeSpec) {
+ List<RangerValiditySchedule> rangerTimeSpec = null;
+
+ if (CollectionUtils.isNotEmpty(atlasTimeSpec)) {
+ rangerTimeSpec = new ArrayList<>();
+
+ for (TimeBoundary validityPeriod : atlasTimeSpec) {
+ RangerValiditySchedule validitySchedule = new RangerValiditySchedule();
+
+ validitySchedule.setStartTime(validityPeriod.getStartTime());
+ validitySchedule.setEndTime(validityPeriod.getEndTime());
+ validitySchedule.setTimeZone(validityPeriod.getTimeZone());
+
+ rangerTimeSpec.add(validitySchedule);
+ }
+ }
+ return rangerTimeSpec;
+ }
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/AtlasRESTTagSource.java
----------------------------------------------------------------------
diff --git a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/AtlasRESTTagSource.java b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/AtlasRESTTagSource.java
index b715869..2b4a668 100644
--- a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/AtlasRESTTagSource.java
+++ b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/AtlasRESTTagSource.java
@@ -25,6 +25,7 @@ import org.apache.atlas.AtlasClientV2;
import org.apache.atlas.AtlasServiceException;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.SearchFilter;
+import org.apache.atlas.model.TimeBoundary;
import org.apache.atlas.model.discovery.AtlasSearchResult;
import org.apache.atlas.model.discovery.SearchParameters;
import org.apache.atlas.model.instance.AtlasClassification;
@@ -44,6 +45,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.util.ServiceTags;
import org.apache.ranger.tagsync.model.AbstractTagSource;
import org.apache.ranger.tagsync.model.TagSink;
@@ -51,6 +53,7 @@ import org.apache.ranger.tagsync.process.TagSyncConfig;
import org.apache.ranger.tagsync.process.TagSynchronizer;
import org.apache.ranger.tagsync.source.atlas.AtlasNotificationMapper;
import org.apache.ranger.tagsync.source.atlas.AtlasResourceMapperUtil;
+import org.apache.ranger.tagsync.source.atlas.EntityNotificationWrapper;
import java.io.IOException;
import java.text.DateFormat;
@@ -229,143 +232,171 @@ public class AtlasRESTTagSource extends AbstractTagSource implements Runnable {
}
- private List<RangerAtlasEntityWithTags> getAtlasActiveEntities() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("==> getAtlasActiveEntities()");
- }
- List<RangerAtlasEntityWithTags> ret = null;
-
- SearchParameters searchParams = new SearchParameters();
- AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
- AtlasTypeRegistry.AtlasTransientTypeRegistry tty = null;
- AtlasSearchResult searchResult = null;
-
- searchParams.setClassification("*");
- searchParams.setIncludeClassificationAttributes(true);
- searchParams.setOffset(0);
- searchParams.setLimit(Integer.MAX_VALUE);
-
- boolean commitUpdates = false;
- try {
- AtlasClientV2 atlasClient = getAtlasClient();
- searchResult = atlasClient.facetedSearch(searchParams);
- AtlasTypesDef typesDef = atlasClient.getAllTypeDefs(new SearchFilter());
- tty = typeRegistry.lockTypeRegistryForUpdate();
- tty.addTypes(typesDef);
- commitUpdates = true;
- } catch (AtlasServiceException | AtlasBaseException | IOException excp) {
- LOG.error("failed to download tags from Atlas", excp);
- } catch (Exception unexpectedException) {
- LOG.error("Failed to download tags from Atlas due to unexpected exception", unexpectedException);
- } finally {
- if (tty != null) {
- typeRegistry.releaseTypeRegistryForUpdate(tty, commitUpdates);
- }
- }
+ private List<RangerAtlasEntityWithTags> getAtlasActiveEntities() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> getAtlasActiveEntities()");
+ }
+ List<RangerAtlasEntityWithTags> ret = null;
+
+ SearchParameters searchParams = new SearchParameters();
+ AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
+ AtlasTypeRegistry.AtlasTransientTypeRegistry tty = null;
+ AtlasSearchResult searchResult = null;
+
+ searchParams.setClassification("*");
+ searchParams.setIncludeClassificationAttributes(true);
+ searchParams.setOffset(0);
+ searchParams.setLimit(Integer.MAX_VALUE);
+
+ boolean commitUpdates = false;
+ try {
+ AtlasClientV2 atlasClient = getAtlasClient();
+ searchResult = atlasClient.facetedSearch(searchParams);
+ AtlasTypesDef typesDef = atlasClient.getAllTypeDefs(new SearchFilter());
+ tty = typeRegistry.lockTypeRegistryForUpdate();
+ tty.addTypes(typesDef);
+ commitUpdates = true;
+ } catch (AtlasServiceException | AtlasBaseException | IOException excp) {
+ LOG.error("failed to download tags from Atlas", excp);
+ } catch (Exception unexpectedException) {
+ LOG.error("Failed to download tags from Atlas due to unexpected exception", unexpectedException);
+ } finally {
+ if (tty != null) {
+ typeRegistry.releaseTypeRegistryForUpdate(tty, commitUpdates);
+ }
+ }
- if (commitUpdates && searchResult != null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug(AtlasType.toJson(searchResult));
- }
- ret = new ArrayList<>();
- List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
- if (CollectionUtils.isNotEmpty(entityHeaders)) {
- for (AtlasEntityHeader header : entityHeaders) {
- if (!header.getStatus().equals(AtlasEntity.Status.ACTIVE)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Skipping entity because it is not ACTIVE, header:[" + header + "]");
- }
- continue;
- }
+ if (commitUpdates && searchResult != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AtlasType.toJson(searchResult));
+ }
+ ret = new ArrayList<>();
+ List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
+ if (CollectionUtils.isNotEmpty(entityHeaders)) {
+ for (AtlasEntityHeader header : entityHeaders) {
+ if (!header.getStatus().equals(AtlasEntity.Status.ACTIVE)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Skipping entity because it is not ACTIVE, header:[" + header + "]");
+ }
+ continue;
+ }
+
+ String typeName = header.getTypeName();
+ if (!AtlasResourceMapperUtil.isEntityTypeHandled(typeName)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Not fetching Atlas entities of type:[" + typeName + "]");
+ }
+ continue;
+ }
+
+ List<EntityNotificationWrapper.RangerAtlasClassification> allTagsForEntity = new ArrayList<>();
+
+ for (AtlasClassification classification : header.getClassifications()) {
+ List<EntityNotificationWrapper.RangerAtlasClassification> tags = resolveTag(typeRegistry, classification);
+ if (tags != null) {
+ allTagsForEntity.addAll(tags);
+ }
+ }
+
+ if (CollectionUtils.isNotEmpty(allTagsForEntity)) {
+ RangerAtlasEntity entity = new RangerAtlasEntity(typeName, header.getGuid(), header.getAttributes());
+ RangerAtlasEntityWithTags entityWithTags = new RangerAtlasEntityWithTags(entity, allTagsForEntity, typeRegistry);
+
+ ret.add(entityWithTags);
+ }
+ }
+ }
+ }
- String typeName = header.getTypeName();
- if (!AtlasResourceMapperUtil.isEntityTypeHandled(typeName)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Not fetching Atlas entities of type:[" + typeName + "]");
- }
- continue;
- }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== getAtlasActiveEntities()");
+ }
- Map<String, Map<String, String>> allTagsForEntity = new HashMap<>();
+ return ret;
+ }
- for (AtlasClassification classification : header.getClassifications()) {
- Map<String, Map<String, String>> tags = resolveTag(typeRegistry, classification.getTypeName(), classification.getAttributes());
- if (tags != null) {
- allTagsForEntity.putAll(tags);
- }
- }
+ /*
+ * Returns a list of <EntityNotificationWrapper.RangerAtlasClassification>
+ */
+ private List<EntityNotificationWrapper.RangerAtlasClassification> resolveTag(AtlasTypeRegistry typeRegistry, AtlasClassification classification) {
+ List<EntityNotificationWrapper.RangerAtlasClassification> ret = new ArrayList<>();
+ String typeName = classification.getTypeName();
+ Map<String, Object> attributes = classification.getAttributes();
- if (MapUtils.isNotEmpty(allTagsForEntity)) {
+ try {
+ AtlasClassificationType classificationType = typeRegistry.getClassificationTypeByName(typeName);
- RangerAtlasEntity entity = new RangerAtlasEntity(typeName, header.getGuid(), header.getAttributes());
- RangerAtlasEntityWithTags entityWithTags = new RangerAtlasEntityWithTags(entity, allTagsForEntity, typeRegistry);
- ret.add(entityWithTags);
- }
- }
- }
- }
+ if (classificationType != null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("<== getAtlasActiveEntities()");
- }
+ Map<String, String> allAttributes = new HashMap<>();
- return ret;
- }
+ if (MapUtils.isNotEmpty(attributes) && MapUtils.isNotEmpty(classificationType.getAllAttributes())) {
+ for (Map.Entry<String, Object> attribute : attributes.entrySet()) {
- /*
- * Returns a map of <tag-name, List<attributeName, [attributeValue, attributeType]>>
- */
- private Map<String, Map<String, String>> resolveTag(AtlasTypeRegistry typeRegistry, String typeName, Map<String, Object> attributes) {
- Map<String, Map<String, String>> ret = new HashMap<>();
-
- try {
- AtlasClassificationType classificationType = typeRegistry.getClassificationTypeByName(typeName);
- if (classificationType != null) {
- Map<String, String> allAttributes = new HashMap<>();
- if (MapUtils.isNotEmpty(attributes) && MapUtils.isNotEmpty(classificationType.getAllAttributes())) {
- for (Map.Entry<String, Object> attribute : attributes.entrySet()) {
- String name = attribute.getKey();
- Object value = attribute.getValue();
- if (value != null) {
- String stringValue = value.toString();
- AtlasStructType.AtlasAttribute atlasAttribute = classificationType.getAttribute(name);
- if (atlasAttribute != null) {
- if (value instanceof Number) {
- if (atlasAttribute.getAttributeType() instanceof AtlasBuiltInTypes.AtlasDateType) {
- stringValue = DATE_FORMATTER.get().format(value);
- }
- }
- allAttributes.put(name, stringValue);
- }
- }
- }
- }
- // Put most derived classificationType with all attributes
- ret.put(typeName, allAttributes);
-
- // Find base classification types
- Set<String> superTypeNames = classificationType.getAllSuperTypes();
- for (String superTypeName : superTypeNames) {
- AtlasClassificationType superType = typeRegistry.getClassificationTypeByName(superTypeName);
- if (superType != null) {
- Map<String, String> attributeMap = new HashMap<>();
- if (MapUtils.isNotEmpty(attributes) && MapUtils.isNotEmpty(superType.getAllAttributes())) {
- for (String name : superType.getAllAttributes().keySet()) {
- String stringValue = allAttributes.get(name);
- if (stringValue != null) {
- attributeMap.put(name, stringValue);
- }
- }
- }
- ret.put(superTypeName, attributeMap);
- }
- }
- }
- } catch (Exception exception) {
- LOG.error("Error in resolving tags for type:[" + typeName + "]", exception);
- }
- return ret;
- }
+ String name = attribute.getKey();
+ Object value = attribute.getValue();
+
+ if (value != null) {
+
+ String stringValue = value.toString();
+ AtlasStructType.AtlasAttribute atlasAttribute = classificationType.getAttribute(name);
+
+ if (atlasAttribute != null) {
+ if (value instanceof Number) {
+ if (atlasAttribute.getAttributeType() instanceof AtlasBuiltInTypes.AtlasDateType) {
+ stringValue = DATE_FORMATTER.get().format(value);
+ }
+ }
+ allAttributes.put(name, stringValue);
+ }
+ }
+ }
+ }
+ List<TimeBoundary> validityPeriods = classification.getValidityPeriods();
+ List<RangerValiditySchedule> validitySchedules = null;
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ validitySchedules = EntityNotificationWrapper.convertTimeSpecFromAtlasToRanger(validityPeriods);
+ }
+
+ // Add most derived classificationType with all attributes
+ ret.add(new EntityNotificationWrapper.RangerAtlasClassification(typeName, allAttributes, validitySchedules));
+
+ // Find base classification types
+ Set<String> superTypeNames = classificationType.getAllSuperTypes();
+ for (String superTypeName : superTypeNames) {
+
+ AtlasClassificationType superType = typeRegistry.getClassificationTypeByName(superTypeName);
+
+ if (superType != null) {
+
+ Map<String, String> attributeMap = new HashMap<>();
+
+ if (MapUtils.isNotEmpty(attributes) && MapUtils.isNotEmpty(superType.getAllAttributes())) {
+ for (String name : superType.getAllAttributes().keySet()) {
+
+ String stringValue = allAttributes.get(name);
+
+ if (stringValue != null) {
+ attributeMap.put(name, stringValue);
+ }
+ }
+ }
+ validityPeriods = classification.getValidityPeriods();
+ validitySchedules = null;
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ validitySchedules = EntityNotificationWrapper.convertTimeSpecFromAtlasToRanger(validityPeriods);
+ }
+ ret.add(new EntityNotificationWrapper.RangerAtlasClassification(superTypeName, attributeMap, validitySchedules));
+ }
+ }
+ }
+ } catch (Exception exception) {
+ LOG.error("Error in resolving tags for type:[" + typeName + "]", exception);
+ }
+ return ret;
+ }
private AtlasClientV2 getAtlasClient() throws IOException {
final AtlasClientV2 ret;
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/RangerAtlasEntityWithTags.java
----------------------------------------------------------------------
diff --git a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/RangerAtlasEntityWithTags.java b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/RangerAtlasEntityWithTags.java
index ecbc502..c31c73c 100644
--- a/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/RangerAtlasEntityWithTags.java
+++ b/tagsync/src/main/java/org/apache/ranger/tagsync/source/atlasrest/RangerAtlasEntityWithTags.java
@@ -21,28 +21,28 @@ package org.apache.ranger.tagsync.source.atlasrest;
import org.apache.atlas.type.AtlasClassificationType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.tagsync.source.atlas.EntityNotificationWrapper;
+import java.util.List;
import java.util.Map;
public class RangerAtlasEntityWithTags {
- private final RangerAtlasEntity entity;
- private final Map<String, Map<String, String>> tags;
- private final AtlasTypeRegistry typeRegistry;
+ private final RangerAtlasEntity entity;
+ private final List<EntityNotificationWrapper.RangerAtlasClassification> tags;
+ private final AtlasTypeRegistry typeRegistry;
public RangerAtlasEntityWithTags(EntityNotificationWrapper notification ) {
-
- this.entity = notification.getRangerAtlasEntity();
-
- this.tags = notification.getAllClassifications();
-
+ this.entity = notification.getRangerAtlasEntity();
+ this.tags = notification.getClassifications();
this.typeRegistry = null;
}
- public RangerAtlasEntityWithTags(RangerAtlasEntity entity, Map<String, Map<String, String>> tags, AtlasTypeRegistry typeRegistry) {
- this.entity = entity;
- this.tags = tags;
+ public RangerAtlasEntityWithTags(RangerAtlasEntity entity, List<EntityNotificationWrapper.RangerAtlasClassification> tags, AtlasTypeRegistry typeRegistry) {
+ this.entity = entity;
+ this.tags = tags;
this.typeRegistry = typeRegistry;
}
@@ -50,26 +50,26 @@ public class RangerAtlasEntityWithTags {
return entity;
}
- public Map<String, Map<String, String>> getTags() {
+ public List<EntityNotificationWrapper.RangerAtlasClassification> getTags() {
return tags;
}
- public String getTagAttributeType(String tagTypeName, String tagAttributeName) {
- String ret = StringUtils.EMPTY;
+ public String getTagAttributeType(String tagTypeName, String tagAttributeName) {
+ String ret = StringUtils.EMPTY;
- if (typeRegistry != null) {
- AtlasClassificationType classificationType = typeRegistry.getClassificationTypeByName(tagTypeName);
- if (classificationType != null) {
- AtlasStructType.AtlasAttribute atlasAttribute = classificationType.getAttribute(tagAttributeName);
+ if (typeRegistry != null) {
+ AtlasClassificationType classificationType = typeRegistry.getClassificationTypeByName(tagTypeName);
+ if (classificationType != null) {
+ AtlasStructType.AtlasAttribute atlasAttribute = classificationType.getAttribute(tagAttributeName);
- if (atlasAttribute != null) {
- ret = atlasAttribute.getTypeName();
- }
- }
- }
+ if (atlasAttribute != null) {
+ ret = atlasAttribute.getTypeName();
+ }
+ }
+ }
- return ret;
- }
+ return ret;
+ }
@Override
public String toString() {
@@ -78,18 +78,31 @@ public class RangerAtlasEntityWithTags {
if (entity != null) {
sb.append("{entity=").append(entity).append(", ");
}
- sb.append("tags={");
- for (Map.Entry<String, Map<String, String>> tag : tags.entrySet()) {
- sb.append("{tagName=").append(tag.getKey());
- sb.append(", attributes={");
- for (Map.Entry<String, String> attribute : tag.getValue().entrySet()) {
- sb.append("{attributeName=").append(attribute.getKey());
- sb.append(",attributeValue=").append(attribute.getValue());
+ sb.append(", classifications={");
+
+ if (CollectionUtils.isNotEmpty(tags)) {
+ for (EntityNotificationWrapper.RangerAtlasClassification tag : tags) {
+ sb.append("classificationName=").append(tag.getName());
+ sb.append(", attributes={");
+ for (Map.Entry<String, String> attribute : tag.getAttributes().entrySet()) {
+ sb.append("{attributeName=").append(attribute.getKey());
+ sb.append(",attributeValue=").append(attribute.getValue());
+ sb.append("}");
+ }
+ sb.append("}");
+ sb.append(", validityPeriods={");
+ if (CollectionUtils.isNotEmpty(tag.getValidityPeriods())) {
+ for (RangerValiditySchedule period : tag.getValidityPeriods()) {
+ sb.append("{").append(period).append("}");
+ }
+ }
sb.append("}");
}
- sb.append("}");
- sb.append("}");
}
+
+ sb.append("}");
+ sb.append("}");
+
return sb.toString();
}
}
[3/4] ranger git commit: RANGER-2000: Policy effective dates to
support time-bound and temporary authorization
Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
----------------------------------------------------------------------
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 f8241c5..29ecfa8 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
@@ -39,6 +39,7 @@ import org.apache.ranger.plugin.util.ServicePolicies;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -656,7 +657,8 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
List<RangerPolicy> ret = new ArrayList<>();
- // TODO: run through evaluator in tagPolicyRepository as well
+
+ // TODO: run through evaluator in tagPolicyRepository as well
for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
RangerPolicy policy = evaluator.getPolicy();
@@ -680,42 +682,56 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
RangerAccessResult ret = createAccessResult(request, policyType);
+ Date accessTime = request.getAccessTime();
- if (ret != null && request != null) {
-
- if (hasTagPolicies()) {
+ if (ret != null && request != null) {
- evaluateTagPolicies(request, policyType, ret);
+ evaluateTagPolicies(request, policyType, ret);
- if (LOG.isDebugEnabled()) {
- if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) {
- LOG.debug("RangerPolicyEngineImpl.evaluatePoliciesNoAudit() - access and audit determined by tag policy. request=" + request + ", result=" + ret);
+ if (LOG.isDebugEnabled()) {
+ if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) {
+ if (!ret.getIsAllowed()) {
+ LOG.debug("RangerPolicyEngineImpl.evaluatePoliciesNoAudit() - audit determined and access denied by a tag policy. Higher priority resource policies will be evaluated to check for allow, request=" + request + ", result=" + ret);
+ } else {
+ LOG.debug("RangerPolicyEngineImpl.evaluatePoliciesNoAudit() - audit determined and access allowed by a tag policy. Same or higher priority resource policies will be evaluated to check for deny, request=" + request + ", result=" + ret);
}
}
}
boolean isAllowedByTags = ret.getIsAccessDetermined() && ret.getIsAllowed();
boolean isDeniedByTags = ret.getIsAccessDetermined() && !ret.getIsAllowed();
- boolean evaluateResourcePolicies = hasResourcePolicies() && (!isDeniedByTags || !ret.getIsAuditedDetermined());
+ boolean evaluateResourcePolicies = hasResourcePolicies();
if (evaluateResourcePolicies) {
-
boolean findAuditByResource = !ret.getIsAuditedDetermined();
boolean foundInCache = findAuditByResource && policyRepository.setAuditEnabledFromCache(request, ret);
- if(isAllowedByTags) {
- ret.setIsAccessDetermined(false); // discard allowed result by tag-policies, to evaluate resource policies for possible deny
- }
+ ret.setIsAccessDetermined(false); // discard result by tag-policies, to evaluate resource policies for possible override
List<RangerPolicyEvaluator> evaluators = policyRepository.getLikelyMatchPolicyEvaluators(request.getResource(), policyType);
for (RangerPolicyEvaluator evaluator : evaluators) {
+ if (!evaluator.isApplicable(accessTime)) {
+ continue;
+ }
+
+ if (isDeniedByTags) {
+ if (ret.getPolicyPriority() >= evaluator.getPolicyPriority()) {
+ ret.setIsAccessDetermined(true);
+ }
+ } else if (isAllowedByTags) {
+ if (ret.getPolicyPriority() > evaluator.getPolicyPriority()) {
+ ret.setIsAccessDetermined(true);
+ }
+ }
ret.incrementEvaluatedPoliciesCount();
evaluator.evaluate(request, ret);
- if (ret.getIsAllowed() && !evaluator.hasDeny()) { // all policies having deny have been evaluated
- ret.setIsAccessDetermined(true);
+ if (ret.getIsAllowed()) {
+ if (!evaluator.hasDeny()) { // No more deny policies left
+ ret.setIsAccessDetermined(true);
+ }
}
if (ret.getIsAuditedDetermined() && ret.getIsAccessDetermined()) {
@@ -724,6 +740,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
}
+ if (!ret.getIsAccessDetermined()) {
+ if (isDeniedByTags) {
+ ret.setIsAllowed(false);
+ } else if (isAllowedByTags) {
+ ret.setIsAllowed(true);
+ }
+ }
+
if(ret.getIsAllowed()) {
ret.setIsAccessDetermined(true);
}
@@ -746,15 +770,16 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
LOG.debug("==> RangerPolicyEngineImpl.evaluateTagPolicies(" + request + ", policyType =" + policyType + ", " + result + ")");
}
+ Date accessTime = request.getAccessTime();
+
Set<RangerTagForEval> tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());
- List<PolicyEvaluatorForTag> policyEvaluators = tagPolicyRepository.getLikelyMatchPolicyEvaluators(tags, policyType);
+ List<PolicyEvaluatorForTag> policyEvaluators = tagPolicyRepository == null ? null : tagPolicyRepository.getLikelyMatchPolicyEvaluators(tags, policyType, accessTime);
if (CollectionUtils.isNotEmpty(policyEvaluators)) {
-
for (PolicyEvaluatorForTag policyEvaluator : policyEvaluators) {
-
RangerPolicyEvaluator evaluator = policyEvaluator.getEvaluator();
+
RangerTagForEval tag = policyEvaluator.getTag();
RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request);
@@ -771,8 +796,10 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
evaluator.evaluate(tagEvalRequest, tagEvalResult);
- if (tagEvalResult.getIsAllowed() && !evaluator.hasDeny()) { // all policies having deny have been evaluated
- tagEvalResult.setIsAccessDetermined(true);
+ if (tagEvalResult.getIsAllowed()) {
+ if (!evaluator.hasDeny()) { // No Deny policies left now
+ tagEvalResult.setIsAccessDetermined(true);
+ }
}
if (tagEvalResult.getIsAudited()) {
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index 23d1efa..088b729 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -43,6 +43,7 @@ import org.apache.ranger.plugin.util.ServicePolicies;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -286,10 +287,10 @@ class RangerPolicyRepository {
}
List<RangerPolicyEvaluator> getRowFilterPolicyEvaluators() {
- return rowFilterPolicyEvaluators;
+ return rowFilterPolicyEvaluators;
}
- List<PolicyEvaluatorForTag> getLikelyMatchPolicyEvaluators(Set<RangerTagForEval> tags, int policyType) {
+ List<PolicyEvaluatorForTag> getLikelyMatchPolicyEvaluators(Set<RangerTagForEval> tags, int policyType, Date accessTime) {
List<PolicyEvaluatorForTag> ret = Collections.EMPTY_LIST;
if (CollectionUtils.isNotEmpty(tags) && getServiceDef() != null) {
@@ -297,26 +298,34 @@ class RangerPolicyRepository {
ret = new ArrayList<PolicyEvaluatorForTag>();
for (RangerTagForEval tag : tags) {
- RangerAccessResource resource = new RangerTagResource(tag.getType(), getServiceDef());
- List<RangerPolicyEvaluator> evaluators = getLikelyMatchPolicyEvaluators(resource, policyType);
-
- if (CollectionUtils.isNotEmpty(evaluators)) {
- for (RangerPolicyEvaluator evaluator : evaluators) {
- ret.add(new PolicyEvaluatorForTag(evaluator, tag));
- }
- }
+ if (tag.isApplicable(accessTime)) {
+ RangerAccessResource resource = new RangerTagResource(tag.getType(), getServiceDef());
+ List<RangerPolicyEvaluator> evaluators = getLikelyMatchPolicyEvaluators(resource, policyType);
+
+ if (CollectionUtils.isNotEmpty(evaluators)) {
+ for (RangerPolicyEvaluator evaluator : evaluators) {
+ if (evaluator.isApplicable(accessTime)) {
+ ret.add(new PolicyEvaluatorForTag(evaluator, tag));
+ }
+ }
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Tag:[" + tag.getType() + "] is not applicable at accessTime:[" + accessTime +"]");
+ }
+ }
}
if (CollectionUtils.isNotEmpty(ret)) {
switch(policyType) {
case RangerPolicy.POLICY_TYPE_ACCESS:
- Collections.sort(ret, new PolicyEvaluatorForTag.PolicyEvalOrderComparator());
+ Collections.sort(ret, PolicyEvaluatorForTag.EVAL_ORDER_COMPARATOR);
break;
case RangerPolicy.POLICY_TYPE_DATAMASK:
- Collections.sort(ret, new PolicyEvaluatorForTag.PolicyNameComparator());
+ Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR);
break;
case RangerPolicy.POLICY_TYPE_ROWFILTER:
- Collections.sort(ret, new PolicyEvaluatorForTag.PolicyNameComparator());
+ Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR);
break;
default:
LOG.warn("Unknown policy-type:[" + policyType + "]. Ignoring..");
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
index d218c73..4e6ca2f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
@@ -74,6 +74,11 @@ public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvalu
}
@Override
+ public int getPolicyPriority() {
+ return policy != null && policy.getPolicyPriority() != null ? policy.getPolicyPriority() : RangerPolicy.POLICY_PRIORITY_NORMAL;
+ }
+
+ @Override
public RangerServiceDef getServiceDef() {
return serviceDef;
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java
index 349ab36..bfdf581 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java
@@ -18,8 +18,6 @@
*/
package org.apache.ranger.plugin.policyevaluator;
-
-
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
@@ -44,7 +42,7 @@ public class RangerDefaultDataMaskPolicyItemEvaluator extends RangerDefaultPolic
}
@Override
- public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, Long policyId) {
+ public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, RangerPolicy policy) {
RangerPolicyItemDataMaskInfo dataMaskInfo = getDataMaskInfo();
if (dataMaskInfo != null) {
@@ -54,6 +52,7 @@ public class RangerDefaultDataMaskPolicyItemEvaluator extends RangerDefaultPolic
result.setMaskType(dataMaskInfo.getDataMaskType());
result.setMaskCondition(dataMaskInfo.getConditionExpr());
result.setMaskedValue(dataMaskInfo.getValueExpr());
+ result.setPolicyPriority(policy.getPolicyPriority());
result.setPolicyId(policyId);
}
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index 2b66c70..ffeea26 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.policyevaluator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -40,6 +41,7 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
@@ -61,6 +63,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
private static final Log PERF_POLICY_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policy.request");
private RangerPolicyResourceMatcher resourceMatcher;
+ private List<RangerValidityScheduleEvaluator> validityScheduleEvaluators;
private List<RangerPolicyItemEvaluator> allowEvaluators;
private List<RangerPolicyItemEvaluator> denyEvaluators;
private List<RangerPolicyItemEvaluator> allowExceptionEvaluators;
@@ -117,6 +120,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
resourceMatcher.init();
if(policy != null) {
+ validityScheduleEvaluators = createValidityScheduleEvaluators(policy);
allowEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW);
denyEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY);
allowExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS);
@@ -124,6 +128,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
dataMaskEvaluators = createDataMaskPolicyItemEvaluators(policy, serviceDef, options, policy.getDataMaskPolicyItems());
rowFilterEvaluators = createRowFilterPolicyItemEvaluators(policy, serviceDef, options, policy.getRowFilterPolicyItems());
} else {
+ validityScheduleEvaluators = Collections.<RangerValidityScheduleEvaluator>emptyList();
allowEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
denyEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
allowExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
@@ -150,6 +155,32 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
}
}
+ @Override
+ public boolean isApplicable(Date accessTime) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerDefaultPolicyEvaluator.isApplicable(" + accessTime + ")");
+ }
+
+ boolean ret = false;
+
+ if (accessTime != null && CollectionUtils.isNotEmpty(validityScheduleEvaluators)) {
+ for (RangerValidityScheduleEvaluator evaluator : validityScheduleEvaluators) {
+ if (evaluator.isApplicable(accessTime.getTime())) {
+ ret = true;
+ break;
+ }
+ }
+ } else {
+ ret = true;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerDefaultPolicyEvaluator.isApplicable(" + accessTime + ") : " + ret);
+ }
+
+ return ret;
+ }
+
@Override
public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
if (LOG.isDebugEnabled()) {
@@ -373,7 +404,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
RangerPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, result);
if(matchedPolicyItem != null) {
- matchedPolicyItem.updateAccessResult(result, matchType, getPolicy().getId());
+ matchedPolicyItem.updateAccessResult(result, matchType, getPolicy());
}
if(LOG.isDebugEnabled()) {
@@ -583,6 +614,22 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
return ret;
}
+ private List<RangerValidityScheduleEvaluator> createValidityScheduleEvaluators(RangerPolicy policy) {
+ List<RangerValidityScheduleEvaluator> ret = null;
+
+ if (CollectionUtils.isNotEmpty(policy.getValiditySchedules())) {
+ ret = new ArrayList<>();
+
+ for (RangerValiditySchedule schedule : policy.getValiditySchedules()) {
+ ret.add(new RangerValidityScheduleEvaluator(schedule));
+ }
+ } else {
+ ret = Collections.<RangerValidityScheduleEvaluator>emptyList();
+ }
+
+ return ret;
+ }
+
private List<RangerPolicyItemEvaluator> createPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, int policyItemType) {
List<RangerPolicyItemEvaluator> ret = null;
List<RangerPolicyItem> policyItems = null;
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
index 9564565..312deef 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
@@ -350,16 +350,18 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
}
@Override
- public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, Long policyId) {
+ public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, RangerPolicy policy) {
if(getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) {
if(matchType != RangerPolicyResourceMatcher.MatchType.DESCENDANT) {
result.setIsAllowed(false);
+ result.setPolicyPriority(policy.getPolicyPriority());
result.setPolicyId(policyId);
result.setReason(getComments());
}
} else {
if(! result.getIsAllowed()) { // if access is not yet allowed by another policy
result.setIsAllowed(true);
+ result.setPolicyPriority(policy.getPolicyPriority());
result.setPolicyId(policyId);
result.setReason(getComments());
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java
index cacae5a..a6cea95 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java
@@ -18,7 +18,6 @@
*/
package org.apache.ranger.plugin.policyevaluator;
-
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
@@ -43,7 +42,7 @@ public class RangerDefaultRowFilterPolicyItemEvaluator extends RangerDefaultPoli
}
@Override
- public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, Long policyId) {
+ public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, RangerPolicy policy) {
RangerPolicyItemRowFilterInfo rowFilterInfo = getRowFilterInfo();
if (rowFilterInfo != null) {
@@ -51,6 +50,7 @@ public class RangerDefaultRowFilterPolicyItemEvaluator extends RangerDefaultPoli
result.setIsAccessDetermined(true);
result.setFilterExpr(rowFilterInfo.getFilterExpr());
+ result.setPolicyPriority(policy.getPolicyPriority());
result.setPolicyId(policyId);
}
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
index 7a890b8..60b350e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.policyevaluator;
import java.io.Serializable;
import java.util.Comparator;
+import java.util.Date;
import java.util.Map;
import java.util.Set;
@@ -38,6 +39,7 @@ import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvalua
public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
Comparator<RangerPolicyEvaluator> EVAL_ORDER_COMPARATOR = new RangerPolicyEvaluator.PolicyEvalOrderComparator();
+ Comparator<RangerPolicyEvaluator> NAME_COMPARATOR = new RangerPolicyEvaluator.PolicyNameComparator();
String EVALUATOR_TYPE_AUTO = "auto";
String EVALUATOR_TYPE_OPTIMIZED = "optimized";
@@ -53,6 +55,10 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
boolean hasDeny();
+ int getPolicyPriority();
+
+ boolean isApplicable(Date accessTime);
+
int getEvalOrder();
long getUsageCount();
@@ -84,6 +90,12 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
class PolicyEvalOrderComparator implements Comparator<RangerPolicyEvaluator>, Serializable {
@Override
public int compare(RangerPolicyEvaluator me, RangerPolicyEvaluator other) {
+ int result = Integer.compare(other.getPolicyPriority(), me.getPolicyPriority());
+
+ return result == 0 ? compareNormal(me, other) : result;
+ }
+
+ private int compareNormal(RangerPolicyEvaluator me, RangerPolicyEvaluator other) {
int result;
if (me.hasDeny() && !other.hasDeny()) {
@@ -102,4 +114,27 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
}
}
+ class PolicyNameComparator implements Comparator<RangerPolicyEvaluator>, Serializable {
+ @Override
+ public int compare(RangerPolicyEvaluator me, RangerPolicyEvaluator other) {
+ int result = Integer.compare(other.getPolicyPriority(), me.getPolicyPriority());
+
+ return result == 0 ? compareNormal(me, other) : result;
+ }
+
+ private int compareNormal(RangerPolicyEvaluator me, RangerPolicyEvaluator other) {
+ final int result;
+
+ if (me.hasDeny() && !other.hasDeny()) {
+ result = -1;
+ } else if (!me.hasDeny() && other.hasDeny()) {
+ result = 1;
+ } else {
+ result = me.getPolicy().getName().compareTo(other.getPolicy().getName());
+ }
+
+ return result;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
index e486403..bd61cfd 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Set;
import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator;
+import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
@@ -65,6 +66,6 @@ public interface RangerPolicyItemEvaluator {
return Integer.compare(me.getEvalOrder(), other.getEvalOrder());
}
}
- void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, Long policyId);
+ void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, RangerPolicy policy);
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerValidityScheduleEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerValidityScheduleEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerValidityScheduleEvaluator.java
new file mode 100644
index 0000000..8f996d1
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerValidityScheduleEvaluator.java
@@ -0,0 +1,588 @@
+/*
+ * 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.policyevaluator;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerValidityRecurrence;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+import org.apache.ranger.plugin.resourcematcher.ScheduledTimeAlwaysMatcher;
+import org.apache.ranger.plugin.resourcematcher.ScheduledTimeExactMatcher;
+import org.apache.ranger.plugin.resourcematcher.ScheduledTimeMatcher;
+import org.apache.ranger.plugin.resourcematcher.ScheduledTimeRangeMatcher;
+import org.apache.ranger.plugin.util.RangerPerfTracer;
+
+import javax.annotation.Nonnull;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+
+public class RangerValidityScheduleEvaluator {
+ private static final Log LOG = LogFactory.getLog(RangerValidityScheduleEvaluator.class);
+ private static final Log PERF_LOG = LogFactory.getLog("test.perf.RangerValidityScheduleEvaluator");
+
+ private final static TimeZone defaultTZ = TimeZone.getDefault();
+
+ private static final ThreadLocal<DateFormat> DATE_FORMATTER = new ThreadLocal<DateFormat>() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat(RangerValiditySchedule.VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION);
+ }
+ };
+
+ private final Date startTime;
+ private final Date endTime;
+ private final String timeZone;
+ private final List<RangerRecurrenceEvaluator> recurrenceEvaluators = new ArrayList<>();
+
+ public RangerValidityScheduleEvaluator(@Nonnull RangerValiditySchedule validitySchedule) {
+ this(validitySchedule.getStartTime(), validitySchedule.getEndTime(), validitySchedule.getTimeZone(), validitySchedule.getRecurrences());
+ }
+
+ public RangerValidityScheduleEvaluator(String startTimeStr, String endTimeStr, String timeZone, List<RangerValidityRecurrence> recurrences) {
+ Date startTime = null;
+ Date endTime = null;
+
+ if (startTimeStr != null) {
+ try {
+ startTime = DATE_FORMATTER.get().parse(startTimeStr);
+ } catch (ParseException exception) {
+ LOG.error("Error parsing startTime:[" + startTimeStr + "]", exception);
+ }
+ }
+
+ if (endTimeStr != null) {
+ try {
+ endTime = DATE_FORMATTER.get().parse(endTimeStr);
+ } catch (ParseException exception) {
+ LOG.error("Error parsing endTime:[" + endTimeStr + "]", exception);
+ }
+ }
+
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.timeZone = timeZone;
+
+ if (CollectionUtils.isNotEmpty(recurrences)) {
+ for (RangerValidityRecurrence recurrence : recurrences) {
+ recurrenceEvaluators.add(new RangerRecurrenceEvaluator(recurrence));
+ }
+ }
+ }
+
+ public boolean isApplicable(long accessTime) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("===> isApplicable(accessTime=" + accessTime + ")");
+ }
+
+ boolean ret = false;
+ RangerPerfTracer perf = null;
+
+ if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerValidityScheduleEvaluator.isApplicable(accessTime=" + accessTime + ")");
+ }
+
+ long startTimeInMSs = startTime == null ? 0 : startTime.getTime();
+ long endTimeInMSs = endTime == null ? 0 : endTime.getTime();
+
+ if (StringUtils.isNotBlank(timeZone)) {
+ TimeZone targetTZ = TimeZone.getTimeZone(timeZone);
+
+ if (startTimeInMSs > 0) {
+ startTimeInMSs = getAdjustedTime(startTimeInMSs, targetTZ);
+ }
+
+ if (endTimeInMSs > 0) {
+ endTimeInMSs = getAdjustedTime(endTimeInMSs, targetTZ);
+ }
+ }
+
+ if ((startTimeInMSs == 0 || accessTime >= startTimeInMSs) && (endTimeInMSs == 0 || accessTime <= endTimeInMSs)) {
+ if (CollectionUtils.isEmpty(recurrenceEvaluators)) {
+ ret = true;
+ } else {
+ Calendar now = new GregorianCalendar();
+ now.setTime(new Date(accessTime));
+
+ for (RangerRecurrenceEvaluator recurrenceEvaluator : recurrenceEvaluators) {
+ ret = recurrenceEvaluator.isApplicable(now);
+
+ if (ret) {
+ break;
+ }
+ }
+ }
+ }
+
+ RangerPerfTracer.log(perf);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<=== isApplicable(accessTime=" + accessTime + ") :" + ret);
+ }
+ return ret;
+ }
+
+ public static long getAdjustedTime(long localTime, TimeZone timeZone) {
+ long ret = localTime;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Input:[" + new Date(localTime) + ", target-timezone" + timeZone + "], default-timezone:[" + defaultTZ + "]");
+ }
+
+ if (!defaultTZ.equals(timeZone)) {
+ int targetOffset = timeZone.getOffset(localTime);
+ int defaultOffset = defaultTZ.getOffset(localTime);
+ int diff = defaultOffset - targetOffset;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Offset of target-timezone from UTC :[" + targetOffset + "]");
+ LOG.debug("Offset of default-timezone from UTC :[" + defaultOffset + "]");
+ LOG.debug("Difference between default-timezone and target-timezone :[" + diff + "]");
+ }
+
+ ret += diff;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Output:[" + new Date(ret) + "]");
+ }
+
+ return ret;
+ }
+
+ static class RangerRecurrenceEvaluator {
+ private final List<ScheduledTimeMatcher> minutes = new ArrayList<>();
+ private final List<ScheduledTimeMatcher> hours = new ArrayList<>();
+ private final List<ScheduledTimeMatcher> daysOfMonth = new ArrayList<>();
+ private final List<ScheduledTimeMatcher> daysOfWeek = new ArrayList<>();
+ private final List<ScheduledTimeMatcher> months = new ArrayList<>();
+ private final List<ScheduledTimeMatcher> years = new ArrayList<>();
+ private final RangerValidityRecurrence recurrence;
+ private int intervalInMinutes = 0;
+
+
+ public RangerRecurrenceEvaluator(RangerValidityRecurrence recurrence) {
+ this.recurrence = recurrence;
+
+ if (recurrence != null) {
+ intervalInMinutes = RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval());
+
+ if (intervalInMinutes > 0) {
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, minutes);
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, hours);
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, daysOfMonth);
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, daysOfWeek);
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, months);
+ addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, years);
+ }
+ }
+ }
+
+ public boolean isApplicable(Calendar now) {
+ boolean ret = false;
+
+ RangerPerfTracer perf = null;
+
+ if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerRecurrenceEvaluator.isApplicable(accessTime=" + now.getTime().getTime() + ")");
+ }
+
+ if (recurrence != null && intervalInMinutes > 0) { // recurring schedule
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Access-Time:[" + now.getTime() + "]");
+ }
+
+ Calendar startOfInterval = getClosestPastEpoch(now);
+
+ if (startOfInterval != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Start-of-Interval:[" + startOfInterval.getTime() + "]");
+ }
+
+ Calendar endOfInterval = (Calendar) startOfInterval.clone();
+ endOfInterval.add(Calendar.MINUTE, recurrence.getInterval().getMinutes());
+ endOfInterval.add(Calendar.HOUR, recurrence.getInterval().getHours());
+ endOfInterval.add(Calendar.DAY_OF_MONTH, recurrence.getInterval().getDays());
+
+ endOfInterval.getTime(); // for recomputation
+ now.getTime();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("End-of-Interval:[" + endOfInterval.getTime() + "]");
+ }
+
+ ret = startOfInterval.compareTo(now) <= 0 && endOfInterval.compareTo(now) >= 0;
+ }
+
+ } else {
+ ret = true;
+ }
+
+ RangerPerfTracer.log(perf);
+ return ret;
+ }
+
+ private void addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List<ScheduledTimeMatcher> list) {
+ final String str = recurrence.getSchedule().getFieldValue(fieldSpec);
+ final boolean isMonth = fieldSpec == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month;
+
+ if (StringUtils.isNotBlank(str)) {
+ String[] specs = str.split(",");
+
+ for (String spec : specs) {
+ String[] range = spec.split("-");
+
+ if (range.length == 1) {
+ if (StringUtils.equals(range[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ list.clear();
+ list.add(new ScheduledTimeAlwaysMatcher());
+
+ break;
+ } else {
+ list.add(new ScheduledTimeExactMatcher(Integer.valueOf(range[0]) - (isMonth ? 1 : 0)));
+ }
+ } else {
+ if (StringUtils.equals(range[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD) || StringUtils.equals(range[1], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ list.clear();
+ list.add(new ScheduledTimeAlwaysMatcher());
+
+ break;
+ } else {
+ list.add(new ScheduledTimeRangeMatcher(Integer.valueOf(range[0]) - (isMonth ? 1 : 0), Integer.valueOf(range[1]) - (isMonth ? 1 : 0)));
+ }
+ }
+ }
+
+ Collections.reverse(list);
+ }
+
+ }
+
+ /*
+ Given a Calendar object, get the closest, earlier Calendar object based on configured validity schedules.
+ Returns - a valid Calendar object. Throws exception if any errors during processing or no suitable Calendar object is found.
+ Description - Typically, a caller will call this with Calendar constructed with current time, and use returned object
+ along with specified interval to ensure that next schedule time is after the input Calendar.
+ Algorithm - This involves doing a Calendar arithmetic (subtraction) with borrow. The tricky parts are ensuring that
+ Calendar arithmetic yields a valid Calendar object.
+ - Start with minutes, and then hours.
+ - Must make sure that the later of the two Calendars - one computed with dayOfMonth, another computed with
+ dayOfWeek - is picked
+ - For dayOfMonth calculation, consider that months have different number of days
+ */
+
+ private class ValueWithBorrow {
+ int value;
+ boolean borrow;
+
+ ValueWithBorrow() {
+ }
+
+ ValueWithBorrow(int value) {
+ this(value, false);
+ }
+
+ ValueWithBorrow(int value, boolean borrow) {
+ this.value = value;
+ this.borrow = borrow;
+ }
+
+ void setValue(int value) {
+ this.value = value;
+ }
+
+ void setBorrow(boolean borrow) {
+ this.borrow = borrow;
+ }
+
+ int getValue() {
+ return value;
+ }
+
+ boolean getBorrow() {
+ return borrow;
+ }
+
+ @Override
+ public String toString() {
+ return "value=" + value + ", borrow=" + borrow;
+ }
+ }
+
+ private Calendar getClosestPastEpoch(Calendar current) {
+ Calendar ret = null;
+
+ try {
+ ValueWithBorrow input = new ValueWithBorrow();
+
+ input.setValue(current.get(Calendar.MINUTE));
+ input.setBorrow(false);
+ ValueWithBorrow closestMinute = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, minutes, input);
+
+ input.setValue(current.get(Calendar.HOUR_OF_DAY));
+ input.setBorrow(closestMinute.borrow);
+ ValueWithBorrow closestHour = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, hours, input);
+
+ Calendar dayOfMonthCalendar = getClosestDayOfMonth(current, closestMinute, closestHour);
+
+ Calendar dayOfWeekCalendar = getClosestDayOfWeek(current, closestMinute, closestHour);
+
+ ret = getEarlierCalendar(dayOfMonthCalendar, dayOfWeekCalendar);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("ClosestPastEpoch:[" + (ret != null ? ret.getTime() : null) + "]");
+ }
+
+ } catch (Exception e) {
+ LOG.error("Could not find ClosestPastEpoch, Exception=", e);
+ }
+ return ret;
+ }
+
+ private Calendar getClosestDayOfMonth(Calendar current, ValueWithBorrow closestMinute, ValueWithBorrow closestHour) throws Exception {
+ Calendar ret = null;
+ if (StringUtils.isNotBlank(recurrence.getSchedule().getDayOfMonth())) {
+ int initialDayOfMonth = current.get(Calendar.DAY_OF_MONTH);
+
+ int currentDayOfMonth = initialDayOfMonth, currentMonth = current.get(Calendar.MONTH), currentYear = current.get(Calendar.YEAR);
+ int maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(current);
+
+ if (closestHour.borrow) {
+ initialDayOfMonth--;
+ Calendar dayOfMonthCalc = (GregorianCalendar) current.clone();
+ dayOfMonthCalc.add(Calendar.DAY_OF_MONTH, -1);
+ dayOfMonthCalc.getTime();
+ int previousDayOfMonth = dayOfMonthCalc.get(Calendar.DAY_OF_MONTH);
+ if (initialDayOfMonth < previousDayOfMonth) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Need to borrow from previous month, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "], dayOfMonthCalc:[" + dayOfMonthCalc.getTime() + "]");
+ }
+ currentDayOfMonth = previousDayOfMonth;
+ currentMonth = dayOfMonthCalc.get(Calendar.MONTH);
+ currentYear = dayOfMonthCalc.get(Calendar.YEAR);
+ maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(dayOfMonthCalc);
+ } else if (initialDayOfMonth == previousDayOfMonth) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No need to borrow from previous month, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]");
+ }
+ } else {
+ LOG.error("Should not get here, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]");
+ throw new Exception("Should not get here, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]");
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("currentDayOfMonth:[" + currentDayOfMonth + "], maximumDaysInPreviourMonth:[" + maximumDaysInPreviousMonth + "]");
+ }
+ ValueWithBorrow input = new ValueWithBorrow();
+ input.setValue(currentDayOfMonth);
+ input.setBorrow(false);
+ ValueWithBorrow closestDayOfMonth = null;
+ do {
+ int i = 0;
+ try {
+ closestDayOfMonth = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, daysOfMonth, input, maximumDaysInPreviousMonth);
+ } catch (Exception e) {
+ i++;
+ Calendar c = (GregorianCalendar) current.clone();
+ c.set(Calendar.YEAR, currentYear);
+ c.set(Calendar.MONTH, currentMonth);
+ c.set(Calendar.DAY_OF_MONTH, currentDayOfMonth);
+ c.add(Calendar.MONTH, -i);
+ c.getTime();
+ currentMonth = c.get(Calendar.MONTH);
+ currentYear = c.get(Calendar.YEAR);
+ currentDayOfMonth = c.get(Calendar.DAY_OF_MONTH);
+ maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(c);
+ input.setValue(currentDayOfMonth);
+ input.setBorrow(false);
+ }
+ } while (closestDayOfMonth == null);
+
+ // Build calendar for dayOfMonth
+ ret = new GregorianCalendar();
+ ret.set(Calendar.DAY_OF_MONTH, closestDayOfMonth.value);
+ ret.set(Calendar.HOUR_OF_DAY, closestHour.value);
+ ret.set(Calendar.MINUTE, closestMinute.value);
+ ret.set(Calendar.SECOND, 0);
+ ret.set(Calendar.MILLISECOND, 0);
+
+ ret.set(Calendar.YEAR, currentYear);
+
+ if (closestDayOfMonth.borrow) {
+ ret.set(Calendar.MONTH, currentMonth - 1);
+ } else {
+ ret.set(Calendar.MONTH, currentMonth);
+ }
+ ret.getTime(); // For recomputation
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Best guess using DAY_OF_MONTH:[" + ret.getTime() + "]");
+ }
+ }
+ return ret;
+ }
+
+ private Calendar getClosestDayOfWeek(Calendar current, ValueWithBorrow closestMinute, ValueWithBorrow closestHour) throws Exception {
+ Calendar ret = null;
+ if (StringUtils.isNotBlank(recurrence.getSchedule().getDayOfWeek())) {
+ ValueWithBorrow input = new ValueWithBorrow();
+
+ input.setValue(current.get(Calendar.DAY_OF_WEEK));
+ input.setBorrow(closestHour.borrow);
+
+
+ ValueWithBorrow closestDayOfWeek = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, daysOfWeek, input);
+
+ int daysToGoback = closestHour.borrow ? 1 : 0;
+ int range = RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum - RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.minimum + 1;
+
+ if (closestDayOfWeek.borrow) {
+ if (input.value - closestDayOfWeek.value != daysToGoback) {
+ daysToGoback = range + input.value - closestDayOfWeek.value;
+ }
+ } else {
+ daysToGoback = input.value - closestDayOfWeek.value;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Need to go back [" + daysToGoback + "] days to match dayOfWeek");
+ }
+
+ ret = (GregorianCalendar) current.clone();
+ ret.set(Calendar.MINUTE, closestMinute.value);
+ ret.set(Calendar.HOUR_OF_DAY, closestHour.value);
+ ret.add(Calendar.DAY_OF_MONTH, (0 - daysToGoback));
+ ret.set(Calendar.SECOND, 0);
+ ret.set(Calendar.MILLISECOND, 0);
+
+ ret.getTime();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Best guess using DAY_OF_WEEK:[" + ret.getTime() + "]");
+ }
+ }
+ return ret;
+
+ }
+
+ private int getMaximumValForPreviousMonth(Calendar current) {
+ Calendar cal = (Calendar) current.clone();
+ cal.add(Calendar.MONTH, -1);
+ cal.getTime(); // For recomputation
+
+ return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+ }
+
+ private Calendar getEarlierCalendar(Calendar dayOfMonthCalendar, Calendar dayOfWeekCalendar) throws Exception {
+
+ Calendar withDayOfMonth = fillOutCalendar(dayOfMonthCalendar);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("dayOfMonthCalendar:[" + (withDayOfMonth != null ? withDayOfMonth.getTime() : null) + "]");
+ }
+
+ Calendar withDayOfWeek = fillOutCalendar(dayOfWeekCalendar);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("dayOfWeekCalendar:[" + (withDayOfWeek != null ? withDayOfWeek.getTime() : null) + "]");
+ }
+
+ if (withDayOfMonth != null && withDayOfWeek != null) {
+ return withDayOfMonth.after(withDayOfWeek) ? withDayOfMonth : withDayOfWeek;
+ } else if (withDayOfMonth == null) {
+ return withDayOfWeek;
+ } else {
+ return withDayOfMonth;
+ }
+ }
+
+ private Calendar fillOutCalendar(Calendar calendar) throws Exception {
+ Calendar ret = null;
+
+ if (calendar != null) {
+ ValueWithBorrow input = new ValueWithBorrow(calendar.get(Calendar.MONTH));
+ ValueWithBorrow closestMonth = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, months, input);
+
+ input.setValue(calendar.get(Calendar.YEAR));
+ input.setBorrow(closestMonth.borrow);
+ ValueWithBorrow closestYear = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, years, input);
+
+ // Build calendar
+ ret = (Calendar) calendar.clone();
+ ret.set(Calendar.YEAR, closestYear.value);
+ ret.set(Calendar.MONTH, closestMonth.value);
+ ret.set(Calendar.SECOND, 0);
+
+ ret.getTime(); // for recomputation
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Filled-out-Calendar:[" + ret.getTime() + "]");
+ }
+ }
+ return ret;
+ }
+
+ private ValueWithBorrow getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List<ScheduledTimeMatcher> searchList, ValueWithBorrow input) throws Exception {
+ return getPastFieldValueWithBorrow(fieldSpec, searchList, input, fieldSpec.maximum);
+ }
+
+ private ValueWithBorrow getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List<ScheduledTimeMatcher> searchList, ValueWithBorrow input, int maximum) throws Exception {
+
+ ValueWithBorrow ret;
+ boolean borrow = false;
+
+ int value = input.value - (input.borrow ? 1 : 0);
+
+ if (CollectionUtils.isNotEmpty(searchList)) {
+ int range = fieldSpec.maximum - fieldSpec.minimum + 1;
+
+ for (int i = 0; i < range; i++, value--) {
+ if (value < fieldSpec.minimum) {
+ value = maximum;
+ borrow = true;
+ }
+ for (ScheduledTimeMatcher time : searchList) {
+ if (time.isMatch(value)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Found match in field:[" + fieldSpec + "], value:[" + value + "], borrow:[" + borrow + "], maximum:[" + maximum + "]");
+ }
+ return new ValueWithBorrow(value, borrow);
+ }
+ }
+ }
+ // Not found
+ throw new Exception("No match found in field:[" + fieldSpec + "] for [input=" + input + "]");
+ } else {
+ if (value < fieldSpec.minimum) {
+ value = maximum;
+ }
+ ret = new ValueWithBorrow(value, false);
+ }
+ return ret;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java
new file mode 100644
index 0000000..414efcf
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java
@@ -0,0 +1,27 @@
+/*
+ * 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.resourcematcher;
+
+public class ScheduledTimeAlwaysMatcher implements ScheduledTimeMatcher {
+ @Override
+ public boolean isMatch(int currentTime) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeExactMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeExactMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeExactMatcher.java
new file mode 100644
index 0000000..da71040
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeExactMatcher.java
@@ -0,0 +1,32 @@
+/*
+ * 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.resourcematcher;
+
+public class ScheduledTimeExactMatcher implements ScheduledTimeMatcher {
+ private int scheduledTime;
+
+ public ScheduledTimeExactMatcher(int scheduledTime) {
+ this.scheduledTime = scheduledTime;
+ }
+ @Override
+ public boolean isMatch(int currentTime) {
+ return currentTime == scheduledTime;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeMatcher.java
new file mode 100644
index 0000000..3c388ca
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeMatcher.java
@@ -0,0 +1,24 @@
+/*
+ * 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.resourcematcher;
+
+public interface ScheduledTimeMatcher {
+ boolean isMatch(int targetTime);
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeRangeMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeRangeMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeRangeMatcher.java
new file mode 100644
index 0000000..8c0bcd5
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ScheduledTimeRangeMatcher.java
@@ -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.
+ */
+
+package org.apache.ranger.plugin.resourcematcher;
+
+public class ScheduledTimeRangeMatcher implements ScheduledTimeMatcher {
+ private int lowerBound;
+ private int upperBound;
+
+ public ScheduledTimeRangeMatcher(int lowerBound, int upperBound) {
+ this.lowerBound = lowerBound;
+ this.upperBound = upperBound;
+ }
+ @Override
+ public boolean isMatch(int currentTime) {
+ return currentTime >= lowerBound && currentTime <= upperBound;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java
index 1e3f145..4d2bc62 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java
@@ -96,7 +96,8 @@ public class AbstractPredicateUtil {
addPredicateForPartialPolicyName(filter.getParam(SearchFilter.POLICY_NAME_PARTIAL), predicates);
addPredicateForResourceSignature(filter.getParam(SearchFilter.RESOURCE_SIGNATURE), predicates);
addPredicateForPolicyType(filter.getParam(SearchFilter.POLICY_TYPE), predicates);
- addPredicateForPartialPolicyLabels(filter.getParam(SearchFilter.POLICY_LABELS_PARTIAL), predicates);
+ addPredicateForPolicyPriority(filter.getParam(SearchFilter.POLICY_PRIORITY), predicates);
+ addPredicateForPartialPolicyLabels(filter.getParam(SearchFilter.POLICY_LABELS_PARTIAL), predicates);
}
public Comparator<RangerBaseModelObject> getSorter(SearchFilter filter) {
@@ -825,45 +826,86 @@ public class AbstractPredicateUtil {
return ret;
}
- private Predicate addPredicateForPartialPolicyLabels(final String policyLabels, List<Predicate> predicates) {
- if (StringUtils.isEmpty(policyLabels)) {
- return null;
- }
-
- Predicate ret = new Predicate() {
- @Override
- public boolean evaluate(Object object) {
- if (object == null) {
- return false;
- }
- boolean ret = false;
-
- if (object instanceof RangerPolicy) {
- RangerPolicy policy = (RangerPolicy) object;
- // exact match
+ private Predicate addPredicateForPartialPolicyLabels(final String policyLabels, List<Predicate> predicates) {
+ if (StringUtils.isEmpty(policyLabels)) {
+ return null;
+ }
+
+ Predicate ret = new Predicate() {
+ @Override
+ public boolean evaluate(Object object) {
+ if (object == null) {
+ return false;
+ }
+ boolean ret = false;
+
+ if (object instanceof RangerPolicy) {
+ RangerPolicy policy = (RangerPolicy) object;
+ // exact match
/*if (policy.getPolicyLabels().contains(policyLabels)) {
ret = true;
}*/
- /*partial match*/
- for (String label :policy.getPolicyLabels()){
- ret = StringUtils.containsIgnoreCase(label, policyLabels);
- if(ret){
- return ret;
- }
- }
-
- } else {
- ret = true;
- }
- return ret;
- }
- };
- if (predicates != null) {
- predicates.add(ret);
- }
-
- return ret;
- }
+ /*partial match*/
+ for (String label :policy.getPolicyLabels()){
+ ret = StringUtils.containsIgnoreCase(label, policyLabels);
+ if(ret){
+ return ret;
+ }
+ }
+
+ } else {
+ ret = true;
+ }
+ return ret;
+ }
+ };
+ if (predicates != null) {
+ predicates.add(ret);
+ }
+
+ return ret;
+ }
+
+ private Predicate addPredicateForPolicyPriority(final String policyPriority, List<Predicate> predicates) {
+ if(StringUtils.isEmpty(policyPriority)) {
+ return null;
+ }
+
+ Predicate ret = new Predicate() {
+ @Override
+ public boolean evaluate(Object object) {
+ if (object == null) {
+ return false;
+ }
+
+ boolean ret = true;
+
+ if (object instanceof RangerPolicy) {
+ RangerPolicy policy = (RangerPolicy) object;
+
+ Integer priority = policy.getPolicyPriority() != null ? policy.getPolicyPriority() : RangerPolicy.POLICY_PRIORITY_NORMAL;
+
+ if (priority == RangerPolicy.POLICY_PRIORITY_NORMAL) {
+ ret = StringUtils.equalsIgnoreCase(policyPriority, policy.POLICY_PRIORITY_NAME_NORMAL)
+ || StringUtils.equalsIgnoreCase(policyPriority, priority.toString());
+ } else if (priority == RangerPolicy.POLICY_PRIORITY_OVERRIDE) {
+ ret = StringUtils.equalsIgnoreCase(policyPriority, policy.POLICY_PRIORITY_NAME_OVERRIDE)
+ || StringUtils.equalsIgnoreCase(policyPriority, priority.toString());
+ } else {
+ ret = false;
+ }
+ }
+ return ret;
+ }
+
+ };
+
+ if(predicates != null) {
+ predicates.add(ret);
+ }
+
+ return ret;
+ }
public Predicate createPredicateForResourceSignature(final String policySignature) {
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
index 4a8f139..33f82dd 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
@@ -51,6 +51,7 @@ public class SearchFilter {
public static final String SORT_BY = "sortBy";
public static final String RESOURCE_SIGNATURE = "resourceSignature:"; // search
public static final String POLICY_TYPE = "policyType"; // search
+ public static final String POLICY_PRIORITY = "policyPriority"; // search
public static final String GUID = "guid"; //search
public static final String POLICY_LABEL = "policyLabel"; // search
public static final String POLICY_LABELS_PARTIAL = "policyLabelsPartial"; // search
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
----------------------------------------------------------------------
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 f8c692b..97ae8a2 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
@@ -27,6 +27,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.audit.provider.AuditHandler;
import org.apache.ranger.audit.provider.AuditProviderFactory;
@@ -35,7 +36,11 @@ 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.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+import org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
import org.apache.ranger.plugin.policyengine.TestPolicyEngine.PolicyEngineTestCase.TestData;
+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.ServicePolicies;
@@ -50,6 +55,8 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -62,7 +69,7 @@ public class TestPolicyEngine {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
- gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z")
+ gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ")
.setPrettyPrinting()
.registerTypeAdapter(RangerAccessRequest.class, new RangerAccessRequestDeserializer())
.registerTypeAdapter(RangerAccessResource.class, new RangerResourceDeserializer())
@@ -301,6 +308,12 @@ public class TestPolicyEngine {
runTestsFromResourceFiles(resourceFiles);
}
+ @Test
+ public void testPolicyEngine_temporary() {
+ String[] resourceFiles = {"/policyengine/test_policyengine_temporary.json"};
+
+ runTestsFromResourceFiles(resourceFiles);
+ }
@Test
public void testPolicyEngine_atlas() {
@@ -505,8 +518,88 @@ public class TestPolicyEngine {
public List<RangerPolicy> tagPolicies;
}
}
-
- static class RangerAccessRequestDeserializer implements JsonDeserializer<RangerAccessRequest> {
+
+ static class ValiditySchedulerTestResult {
+ boolean isValid;
+ int validationFailureCount;
+ boolean isApplicable;
+ }
+
+ static class ValiditySchedulerTestCase {
+ String name;
+ List<RangerValiditySchedule> validitySchedules;
+ Date accessTime;
+ ValiditySchedulerTestResult result;
+ }
+
+ @Test
+ public void testValiditySchedularInvalid() {
+ String resourceName = "/policyengine/validityscheduler/test-validity-schedules-invalid.json";
+
+ runValiditySchedulerTests(resourceName);
+ }
+
+ @Test
+ public void testValiditySchedularValid() {
+ String resourceName = "/policyengine/validityscheduler/test-validity-schedules-valid.json";
+
+ runValiditySchedulerTests(resourceName);
+ }
+
+ @Test
+ public void testValiditySchedularApplicable() {
+ String resourceName = "/policyengine/validityscheduler/test-validity-schedules-valid-and-applicable.json";
+
+ runValiditySchedulerTests(resourceName);
+ }
+
+ private void runValiditySchedulerTests(String resourceName) {
+ List<ValiditySchedulerTestCase> testCases = null;
+ InputStream inStream = this.getClass().getResourceAsStream(resourceName);
+ InputStreamReader reader = new InputStreamReader(inStream);
+ try {
+ Type listType = new TypeToken<List<ValiditySchedulerTestCase>>() {}.getType();
+ testCases = gsonBuilder.fromJson(reader, listType);
+ } catch (Exception e) {
+ assertFalse("Exception in reading validity-scheduler test cases.", true);
+ }
+
+ assertNotNull("TestCases are null!", testCases);
+
+
+ if (CollectionUtils.isNotEmpty(testCases)) {
+ for (ValiditySchedulerTestCase testCase : testCases) {
+ boolean isValid = true;
+ List<ValidationFailureDetails> validationFailures = new ArrayList<>();
+ boolean isApplicable = false;
+
+ List<RangerValiditySchedule> validatedSchedules = new ArrayList<>();
+
+ for (RangerValiditySchedule validitySchedule : testCase.validitySchedules) {
+ RangerValidityScheduleValidator validator = new RangerValidityScheduleValidator(validitySchedule);
+ RangerValiditySchedule validatedSchedule = validator.validate(validationFailures);
+ isValid = isValid && validatedSchedule != null;
+ if (isValid) {
+ validatedSchedules.add(validatedSchedule);
+ }
+ }
+ if (isValid) {
+ for (RangerValiditySchedule validSchedule : validatedSchedules) {
+ isApplicable = new RangerValidityScheduleEvaluator(validSchedule).isApplicable(testCase.accessTime.getTime());
+ if (isApplicable) {
+ break;
+ }
+ }
+ }
+
+ assertTrue(testCase.name, isValid == testCase.result.isValid);
+ assertTrue(testCase.name, isApplicable == testCase.result.isApplicable);
+ assertTrue(testCase.name + ", [" + validationFailures +"]", validationFailures.size() == testCase.result.validationFailureCount);
+ }
+ }
+ }
+
+ static class RangerAccessRequestDeserializer implements JsonDeserializer<RangerAccessRequest> {
@Override
public RangerAccessRequest deserialize(JsonElement jsonObj, Type type,
JsonDeserializationContext context) throws JsonParseException {
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/log4j.xml b/agents-common/src/test/resources/log4j.xml
index 558e27b..ddf57b9 100644
--- a/agents-common/src/test/resources/log4j.xml
+++ b/agents-common/src/test/resources/log4j.xml
@@ -78,12 +78,12 @@
-->
<logger name="org.apache.ranger.perf.policyresourcematcher" additivity="false">
- <level value="debug" />
+ <level value="warn" />
<appender-ref ref="ranger_perf_appender" />
</logger>
<root>
- <level value="warn" />
+ <level value="debug" />
<appender-ref ref="console" />
</root>
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/resources/policyengine/test_policyengine_temporary.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_temporary.json b/agents-common/src/test/resources/policyengine/test_policyengine_temporary.json
new file mode 100644
index 0000000..17cf322
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_temporary.json
@@ -0,0 +1,347 @@
+{
+ "serviceName":"hdfsdev",
+ "serviceDef":{
+ "name":"hdfs",
+ "id":1,
+ "resources":[
+ {"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Resource Path","description":"HDFS file or directory path"}
+ ],
+ "options": {
+ "enableDenyAndExceptionsInPolicies":"true"
+ },
+ "accessTypes":[
+ {"name":"read","label":"Read"},
+ {"name":"write","label":"Write"},
+ {"name":"execute","label":"Execute"}
+ ]
+ },
+ "policies":[
+ {
+ "id": 99,
+ "name": "/resource: allow: groups=public",
+ "isEnabled": true,
+ "isAuditEnabled": true,
+ "resources": {
+ "path": { "values": [ "/resource" ], "isRecursive": true }
+ },
+ "policyItems": [
+ {
+ "accesses":[
+ {"type":"read"},
+ {"type": "execute" },
+ {"type":"write"}
+ ],
+ "groups" : ["public"]
+ }
+ ]
+ },
+ {
+ "id": 1,
+ "name": "/resource: allow: users=super; deny: user=user",
+ "isEnabled": true,
+ "isAuditEnabled": true,
+ "resources": {
+ "path": { "values": [ "/resource" ], "isRecursive": true }
+ },
+ "policyPriority":1,
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/02/13 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0,10,20,30,40,50",
+ "hour": "*",
+ "dayOfMonth": "*",
+ "dayOfWeek": "5,7",
+ "month": "*",
+ "year": "2018"
+ },
+ "interval": {
+ "minutes": 4
+ }
+ }
+ ]
+ }
+ ],
+ "policyItems": [
+ {
+ "accesses":[
+ {"type":"read"},
+ {"type":"write"}
+ ],
+ "users":["super"]
+ }
+ ],
+ "allowExceptions":[ ],
+ "denyPolicyItems": [
+ {
+ "accesses": [
+ { "type": "read" },
+ { "type": "execute" },
+ { "type": "write" }
+ ],
+ "users": [ "user"]
+ }
+ ],
+ "denyExceptions":[ ]
+ },
+ {
+ "id": 2,
+ "name": "/unaudited-resource: allow: users=super deny: user=user",
+ "isEnabled": true,
+ "isAuditEnabled": false,
+ "resources": {
+ "path": { "values": [ "/unaudited-resource" ], "isRecursive": true }
+ },
+ "validitySchedules": [],
+ "policyItems": [
+ {
+ "accesses":[
+ {"type":"read" },
+ {"type":"write" }
+ ],
+ "users":["super"]
+ }
+ ],
+ "allowExceptions":[ ],
+ "denyPolicyItems": [
+ {
+ "accesses": [
+ { "type": "read" },
+ { "type": "execute" },
+ { "type": "write" }
+ ],
+ "users": [ "user" ]
+ }
+ ],
+ "denyExceptions":[ ]
+ }
+ ],
+
+ "tagPolicyInfo": {
+ "serviceName":"tagdev",
+ "serviceDef": {
+ "name": "tag",
+ "id": 100,
+ "resources": [
+ { "name": "tag", "type": "string", "level": 1, "mandatory": true, "matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", "matcherOptions": { "wildCard": false, "ignoreCase": false }, "label": "TAG", "description": "TAG" }
+ ],
+ "accessTypes": [
+ { "name": "hdfs:read", "label": "hdfs:Read" },
+ { "name": "hdfs:write", "label": "hdfs:Write" },
+ { "name": "hdfs:execute", "label": "hdfs:Execute" }
+ ],
+ "contextEnrichers": [ ],
+ "policyConditions": [ ]
+ },
+ "tagPolicies":[
+ {
+ "id":101,
+ "name":"PII",
+ "isEnabled":true,
+ "isAuditEnabled":true,
+ "resources":{"tag":{"values":["PII"],"isRecursive":false}},
+ "policyItems":[
+ {
+ "accesses":[
+ {"type":"hdfs:read", "isAllowed":true},
+ {"type":"hdfs:write", "isAllowed":true}
+ ],
+ "users":["super"]
+ }
+ ],
+ "allowExceptions":[ ],
+ "denyPolicyItems":[
+ {
+ "accesses":[
+ {"type":"hdfs:read" },
+ {"type":"hdfs:write" }
+ ],
+ "users":["user"]
+ }
+ ],
+ "denyExceptions":[ ],
+ "policyPriority":1,
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/02/13 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0,10,20,30,40,50",
+ "hour": "*",
+ "dayOfMonth": "*",
+ "dayOfWeek": "5,7",
+ "month": "*",
+ "year": "2018"
+ },
+ "interval": {
+ "minutes": 5
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id":102,
+ "name":"Unaudited-TAG",
+ "isEnabled":true,
+ "isAuditEnabled":false,
+ "resources":{"tag":{"values":["Unaudited-TAG"],"isRecursive":false}},
+ "validitySchedules": [],
+ "policyItems":[
+ {
+ "accesses":[
+ {"type":"hdfs:read" },
+ {"type":"hdfs:write" }
+ ],
+ "users":["super"]
+ }
+ ],
+ "allowExceptions":[ ],
+ "denyPolicyItems":[
+ {
+ "accesses":[
+ {"type":"hdfs:read" },
+ {"type":"hdfs:write" }
+ ],
+ "users":["user"]
+ }
+ ],
+ "denyExceptions":[ ]
+ }
+ ]
+ },
+ "tests":[
+ {
+ "name": "ALLOW 'read /resource' for u=user no tag temporarily",
+ "request": {
+ "resource": {
+ "elements": {
+ "path": "/resource"
+ }
+ },
+ "accessType": "read",
+ "user": "user",
+ "userGroups": [],
+ "requestData": "read /resource for u=user no tag temporarily",
+ "context": {
+ "TAGS": "[{\"type\":\"PII\",\"options\":{\"TAG_VALIDITY_PERIODS\":\"[{\\\"startTime\\\":\\\"2018/01/12 14:32:00\\\",\\\"endTime\\\":\\\"2020/02/13 12:16:00\\\",\\\"recurrences\\\":[{\\\"schedule\\\":{\\\"minute\\\":\\\"0,10,20,30,40,50\\\",\\\"hour\\\":\\\"*\\\",\\\"dayOfMonth\\\":\\\"*\\\",\\\"dayOfWeek\\\":\\\"5,7\\\",\\\"month\\\":\\\"*\\\",\\\"year\\\":\\\"2018\\\"},\\\"interval\\\":{\\\"days\\\":0,\\\"hours\\\":0,\\\"minutes\\\":4}}]}]\"}}]"
+ },
+ "accessTime": "20180127-10:06:00.000-0800"
+ },
+ "result": {"isAudited": true, "isAllowed": true, "policyId": 99}
+ },
+ {
+ "name": "DENY 'read /resource' for u=user tag temporarily",
+ "request": {
+ "resource": {
+ "elements": {
+ "path": "/resource"
+ }
+ },
+ "accessType": "read",
+ "user": "user",
+ "userGroups": [],
+ "requestData": "read /resource for u=user tag temporarily",
+ "context": {
+ "TAGS": "[{\"type\":\"PII\",\"options\":{\"TAG_VALIDITY_PERIODS\":\"[{\\\"startTime\\\":\\\"2018/01/12 14:32:00\\\",\\\"endTime\\\":\\\"2020/02/13 12:16:00\\\",\\\"recurrences\\\":[{\\\"schedule\\\":{\\\"minute\\\":\\\"0,10,20,30,40,50\\\",\\\"hour\\\":\\\"*\\\",\\\"dayOfMonth\\\":\\\"*\\\",\\\"dayOfWeek\\\":\\\"5,7\\\",\\\"month\\\":\\\"*\\\",\\\"year\\\":\\\"2018\\\"},\\\"interval\\\":{\\\"days\\\":0,\\\"hours\\\":0,\\\"minutes\\\":7}}]}]\"}}]"
+ },
+ "accessTime": "20180127-10:05:00.000-0800"
+ },
+ "result": {"isAudited": true, "isAllowed": false, "policyId": 101}
+ },
+ {
+ "name": "ALLOW 'read /resource' for u=user temporarily",
+ "request": {
+ "resource": {
+ "elements": {
+ "path": "/resource"
+ }
+ },
+ "accessType": "read",
+ "user": "user",
+ "userGroups": [],
+ "requestData": "read /resource temporarily",
+ "accessTime": "20180127-10:06:00.000-0800"
+ },
+ "result": {"isAudited": true, "isAllowed": true, "policyId": 99}
+ },
+ {
+ "name": "DENY 'read /resource' for u=user temporarily",
+ "request": {
+ "resource": {
+ "elements": {
+ "path": "/resource"
+ }
+ },
+ "accessType": "read",
+ "user": "user",
+ "userGroups": [],
+ "requestData": "read /resource temporarily",
+ "accessTime": "20180127-10:03:00.000-0800"
+ },
+ "result": {"isAudited": true, "isAllowed": false, "policyId": 1}
+ },
+ {
+ "name": "DENY 'read /resource' for u=user",
+ "request": {
+ "resource": { "elements": { "path": "/resource" } },
+ "accessType": "read",
+ "user": "user",
+ "userGroups": [ ],
+ "requestData": "read /resource for u=user",
+ "accessTime": "20180127-10:03:00.000-0800",
+ "context": {
+ "TAGS": "[{\"type\":\"PII\"}]"
+ }
+ },
+ "result": { "isAudited": true, "isAllowed": false, "policyId": 101 }
+ },
+ {
+ "name": "ALLOW 'read /resource' for u=super",
+ "request": {
+ "resource": { "elements": { "path": "/resource" } },
+ "accessType": "read",
+ "user": "super",
+ "userGroups": [ ],
+ "requestData": "read /resource for u=super",
+ "accessTime": "20180127-10:03:00.000-0800",
+ "context": {
+ "TAGS": "[{\"type\":\"PII\"}]"
+ }
+ },
+ "result": { "isAudited": true, "isAllowed": true, "policyId": 101 }
+ }
+ ,
+ {
+ "name": "ALLOW 'read /resource' for u=super",
+ "request": {
+ "resource": { "elements": { "path": "/resource" } },
+ "accessType": "read",
+ "user": "super",
+ "userGroups": [ ],
+ "requestData": "read /resource for u=super",
+ "accessTime": "20180127-10:03:00.000-0800"
+
+ },
+ "result": { "isAudited": true, "isAllowed": true, "policyId": 1 }
+ },
+ {
+ "name": "ALLOW 'read /resource' for u=any",
+ "request": {
+ "resource": { "elements": { "path": "/resource" } },
+ "accessType": "read",
+ "user": "any",
+ "userGroups": [ ],
+ "requestData": "read /resource for u=any"
+ },
+ "result": { "isAudited": true, "isAllowed": true, "policyId": 99 }
+ }
+
+ ]
+}
[4/4] ranger git commit: RANGER-2000: Policy effective dates to
support time-bound and temporary authorization
Posted by ab...@apache.org.
RANGER-2000: Policy effective dates to support time-bound and temporary authorization
Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/844315cd
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/844315cd
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/844315cd
Branch: refs/heads/master
Commit: 844315cdbc5e4589f5a4f873c33533d8f7bb014e
Parents: 7037920
Author: Abhay Kulkarni <ak...@hortonworks.com>
Authored: Sun Mar 4 22:08:21 2018 -0800
Committer: Abhay Kulkarni <ak...@hortonworks.com>
Committed: Sun Mar 4 22:08:21 2018 -0800
----------------------------------------------------------------------
.../ranger/authorization/utils/JsonUtils.java | 121 ++++
.../contextenricher/RangerTagEnricher.java | 8 +-
.../contextenricher/RangerTagForEval.java | 129 +++-
.../plugin/errors/ValidationErrorCode.java | 2 +
.../ranger/plugin/model/RangerPolicy.java | 105 +++-
.../model/RangerPolicyResourceSignature.java | 10 +-
.../apache/ranger/plugin/model/RangerTag.java | 77 ++-
.../plugin/model/RangerValidityRecurrence.java | 231 +++++++
.../plugin/model/RangerValiditySchedule.java | 93 +++
.../model/validation/RangerPolicyValidator.java | 51 +-
.../model/validation/RangerValidator.java | 2 +-
.../RangerValidityScheduleValidator.java | 480 +++++++++++++++
.../policyengine/PolicyEvaluatorForTag.java | 61 +-
.../plugin/policyengine/RangerAccessResult.java | 6 +
.../policyengine/RangerPolicyEngineImpl.java | 67 ++-
.../policyengine/RangerPolicyRepository.java | 35 +-
.../RangerAbstractPolicyEvaluator.java | 5 +
...angerDefaultDataMaskPolicyItemEvaluator.java | 5 +-
.../RangerDefaultPolicyEvaluator.java | 49 +-
.../RangerDefaultPolicyItemEvaluator.java | 4 +-
...ngerDefaultRowFilterPolicyItemEvaluator.java | 4 +-
.../policyevaluator/RangerPolicyEvaluator.java | 35 ++
.../RangerPolicyItemEvaluator.java | 3 +-
.../RangerValidityScheduleEvaluator.java | 588 ++++++++++++++++++
.../ScheduledTimeAlwaysMatcher.java | 27 +
.../ScheduledTimeExactMatcher.java | 32 +
.../resourcematcher/ScheduledTimeMatcher.java | 24 +
.../ScheduledTimeRangeMatcher.java | 34 ++
.../plugin/store/AbstractPredicateUtil.java | 116 ++--
.../apache/ranger/plugin/util/SearchFilter.java | 1 +
.../plugin/policyengine/TestPolicyEngine.java | 99 ++-
agents-common/src/test/resources/log4j.xml | 4 +-
.../test_policyengine_temporary.json | 347 +++++++++++
.../test-validity-schedules-invalid.json | 146 +++++
...validity-schedules-valid-and-applicable.json | 507 ++++++++++++++++
.../test-validity-schedules-valid.json | 152 +++++
.../optimized/current/ranger_core_db_mysql.sql | 3 +
...policy-and-tag-for-time-based-processing.sql | 44 ++
.../optimized/current/ranger_core_db_oracle.sql | 3 +
...policy-and-tag-for-time-based-processing.sql | 34 ++
.../current/ranger_core_db_postgres.sql | 3 +
...policy-and-tag-for-time-based-processing.sql | 53 ++
.../current/ranger_core_db_sqlanywhere.sql | 3 +
...policy-and-tag-for-time-based-processing.sql | 29 +
.../current/ranger_core_db_sqlserver.sql | 3 +
...policy-and-tag-for-time-based-processing.sql | 35 ++
.../ranger/biz/RangerPolicyRetriever.java | 96 +--
.../apache/ranger/biz/RangerTagDBRetriever.java | 17 +-
.../java/org/apache/ranger/biz/TagDBStore.java | 41 +-
.../apache/ranger/common/RangerSearchUtil.java | 4 +-
.../org/apache/ranger/entity/XXPolicyBase.java | 67 ++-
.../java/org/apache/ranger/entity/XXTag.java | 20 +-
.../ranger/service/RangerPolicyServiceBase.java | 47 +-
.../ranger/service/RangerTagServiceBase.java | 32 +
src/main/assembly/tagsync.xml | 1 +
.../source/atlas/AtlasNotificationMapper.java | 603 ++++++++++---------
.../tagsync/source/atlas/AtlasTagSource.java | 2 +-
.../source/atlas/EntityNotificationWrapper.java | 395 ++++++------
.../source/atlasrest/AtlasRESTTagSource.java | 287 +++++----
.../atlasrest/RangerAtlasEntityWithTags.java | 81 +--
60 files changed, 4738 insertions(+), 825 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java b/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java
new file mode 100644
index 0000000..bc4a8b5
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/authorization/utils/JsonUtils.java
@@ -0,0 +1,121 @@
+/*
+ * 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.authorization.utils;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerValidityRecurrence;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JsonUtils {
+ private static final Log LOG = LogFactory.getLog(JsonUtils.class);
+
+ private static final HashMap<String, String> MAP_STRING_STRING = new HashMap<>();
+
+ private static final Gson gson;
+
+ static {
+ gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z")
+ .setPrettyPrinting()
+ .create();
+ }
+
+ public static String mapToJson(Map<?, ?> map) {
+ String ret = null;
+ if (MapUtils.isNotEmpty(map)) {
+ try {
+ ret = gson.toJson(map);
+ } catch (Exception e) {
+ LOG.error("Invalid input data: ", e);
+ }
+ }
+ return ret;
+ }
+
+ public static String listToJson(List<?> list) {
+ String ret = null;
+ if (CollectionUtils.isNotEmpty(list)) {
+ try {
+ ret = gson.toJson(list);
+ } catch (Exception e) {
+ LOG.error("Invalid input data: ", e);
+ }
+ }
+ return ret;
+ }
+
+ public static <T> T jsonToObject(String jsonStr, Class<T> clz) {
+ T ret = null;
+
+ if(StringUtils.isNotEmpty(jsonStr)) {
+ try {
+ ret = gson.fromJson(jsonStr, clz);
+ } catch(Exception excp) {
+ LOG.warn("jsonToObject() failed to convert json to object: " + jsonStr, excp);
+ }
+ }
+
+ return ret;
+ }
+
+ public static Map<String, String> jsonToMapStringString(String jsonStr) {
+ Map<String, String> ret = null;
+
+ if(StringUtils.isNotEmpty(jsonStr)) {
+ try {
+ ret = gson.fromJson(jsonStr, MAP_STRING_STRING.getClass());
+ } catch(Exception excp) {
+ LOG.warn("jsonToObject() failed to convert json to object: " + jsonStr, excp);
+ }
+ }
+
+ return ret;
+ }
+
+ public static List<RangerValiditySchedule> jsonToRangerValiditySchedule(String jsonStr) {
+ try {
+ Type listType = new TypeToken<List<RangerValiditySchedule>>() {
+ }.getType();
+ return gson.fromJson(jsonStr, listType);
+ } catch (Exception e) {
+ LOG.error("Cannot get List<RangerValiditySchedule> from " + jsonStr, e);
+ return null;
+ }
+ }
+ public static List<RangerValidityRecurrence> jsonToRangerValidityRecurringSchedule(String jsonStr) {
+ try {
+ Type listType = new TypeToken<List<RangerValidityRecurrence>>() {
+ }.getType();
+ return gson.fromJson(jsonStr, listType);
+ } catch (Exception e) {
+ LOG.error("Cannot get List<RangerValidityRecurrence> from " + jsonStr, e);
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index 415d4a4..d5d14a2 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -335,10 +335,12 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
}
}
- if (LOG.isDebugEnabled()) {
- if (CollectionUtils.isEmpty(ret)) {
+ if (CollectionUtils.isEmpty(ret)) {
+ if (LOG.isDebugEnabled()) {
LOG.debug("RangerTagEnricher.findMatchingTags(" + resource + ") - No tags Found ");
- } else {
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
LOG.debug("RangerTagEnricher.findMatchingTags(" + resource + ") - " + ret.size() + " tags Found ");
}
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagForEval.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagForEval.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagForEval.java
index e31efa3..524605d 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagForEval.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagForEval.java
@@ -19,9 +19,17 @@
package org.apache.ranger.plugin.contextenricher;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.plugin.model.RangerTag;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+import org.apache.ranger.plugin.policyevaluator.RangerValidityScheduleEvaluator;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
@@ -29,6 +37,10 @@ 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.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
import java.util.Map;
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
@@ -41,26 +53,80 @@ import java.util.Map;
// from JSON specification
public class RangerTagForEval implements Serializable {
- private String type;
- private Map<String, String> attributes;
+ private static final Log LOG = LogFactory.getLog(RangerTagForEval.class);
+
+ private String type;
+ private Map<String, String> attributes;
+ private Map<String, Object> options;
private RangerPolicyResourceMatcher.MatchType matchType = RangerPolicyResourceMatcher.MatchType.SELF;
+ @JsonIgnore
+ private List<RangerValiditySchedule> validityPeriods;
+ @JsonIgnore
+ private List<RangerValidityScheduleEvaluator> validityPeriodEvaluators;
+
private RangerTagForEval() {}
public RangerTagForEval(RangerTag tag, RangerPolicyResourceMatcher.MatchType matchType) {
- this.type = tag.getType();
- this.attributes = tag.getAttributes();
- this.matchType = matchType;
- }
+ this.type = tag.getType();
+ this.attributes = tag.getAttributes();
+ this.options = tag.getOptions();
+ this.matchType = matchType;
+ this.validityPeriods = tag.getValidityPeriods();
- public RangerPolicyResourceMatcher.MatchType getMatchType() {
- return matchType;
+ this.validityPeriodEvaluators = createValidityPeriodEvaluators();
}
public String getType() { return type;}
- public Map<String, String> getAttributes() {
- return attributes;
+ public Map<String, String> getAttributes() { return attributes; }
+
+ public Map<String, Object> getOptions() { return options; }
+
+ public RangerPolicyResourceMatcher.MatchType getMatchType() { return matchType; }
+
+ public List<RangerValiditySchedule> getValidityPeriods() { return validityPeriods; }
+
+ public boolean isApplicable(Date accessTime) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerTagForEval.isApplicable(type=" + type + ", " + accessTime + ")");
+ }
+
+ boolean ret = false;
+
+ List<RangerValidityScheduleEvaluator> validityPeriodEvaluators = this.validityPeriodEvaluators;
+
+ // Specifically for unit-testing using TestPolicyEngine
+ if (MapUtils.isNotEmpty(options) && CollectionUtils.isEmpty(validityPeriodEvaluators)) {
+ Object value = getOption(RangerTag.OPTION_TAG_VALIDITY_PERIODS);
+
+ if (value != null && value instanceof String) {
+ this.validityPeriods = JsonUtils.jsonToRangerValiditySchedule((String) value);
+
+ validityPeriodEvaluators = createValidityPeriodEvaluators();
+ } else {
+ validityPeriodEvaluators = Collections.emptyList();
+ }
+
+ this.validityPeriodEvaluators = validityPeriodEvaluators;
+ }
+
+ if (accessTime != null && CollectionUtils.isNotEmpty(validityPeriodEvaluators)) {
+ for (RangerValidityScheduleEvaluator evaluator : validityPeriodEvaluators) {
+ if (evaluator.isApplicable(accessTime.getTime())) {
+ ret = true;
+ break;
+ }
+ }
+ } else {
+ ret = true;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerTagForEval.isApplicable(type=" + type + ", " + accessTime + ") : " + ret);
+ }
+
+ return ret;
}
@Override
@@ -83,6 +149,14 @@ public class RangerTagForEval implements Serializable {
}
sb.append(" }");
sb.append(", matchType=").append(matchType);
+
+ if (options != null) {
+ sb.append(", options={").append(options).append("}");
+ }
+
+ if (validityPeriods != null) {
+ sb.append(", validityPeriods=").append(validityPeriods);
+ }
sb.append(" }");
return sb;
}
@@ -97,6 +171,11 @@ public class RangerTagForEval implements Serializable {
+ ((attributes == null) ? 0 : attributes.hashCode());
result = prime * result
+ ((matchType == null) ? 0 : matchType.hashCode());
+ result = prime * result
+ + ((validityPeriods == null) ? 0 : validityPeriods.hashCode());
+ result = prime * result
+ + ((options == null) ? 0 : options.hashCode());
+
return result;
}
@@ -124,7 +203,37 @@ public class RangerTagForEval implements Serializable {
return false;
} else if (!matchType.equals(other.matchType))
return false;
+ if (options == null) {
+ if (other.options != null)
+ return false;
+ } else if (!options.equals(other.options))
+ return false;
+ if (validityPeriods == null) {
+ if (other.validityPeriods != null)
+ return false;
+ } else if (!validityPeriods.equals(other.validityPeriods))
+ return false;
return true;
}
+
+ private Object getOption(String name) {
+ return options != null ? options.get(name) : null;
+ }
+
+ private List<RangerValidityScheduleEvaluator> createValidityPeriodEvaluators() {
+ final List<RangerValidityScheduleEvaluator> ret;
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ ret = new ArrayList<>();
+
+ for (RangerValiditySchedule schedule : validityPeriods) {
+ ret.add(new RangerValidityScheduleEvaluator(schedule));
+ }
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ return ret;
+ }
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
index a7f7c39..ab120b7 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/errors/ValidationErrorCode.java
@@ -91,6 +91,8 @@ public enum ValidationErrorCode {
POLICY_VALIDATION_ERR_MISSING_RESOURCE_LIST(3026, "Resource list was empty or contains null. At least one resource must be specified"),
POLICY_VALIDATION_ERR_POLICY_UPDATE_MOVE_SERVICE_NOT_ALLOWED(3027, "attempt to move policy id={0} from service={1} to service={2} is not allowed"),
POLICY_VALIDATION_ERR_POLICY_TYPE_CHANGE_NOT_ALLOWED(3028, "attempt to change type of policy id={0} from type={1} to type={2} is not allowed"),
+ POLICY_VALIDATION_ERR_POLICY_INVALID_VALIDITY_SCHEDULE(3029, "Invalid validity schedule specification"),
+ POLICY_VALIDATION_ERR_POLICY_INVALID_PRIORITY(3030, "Invalid priority value"),
;
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
index 534fe49..c2185a7 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
@@ -28,6 +28,7 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.commons.collections.CollectionUtils;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
@@ -54,12 +55,19 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
public static final String MASK_TYPE_NONE = "MASK_NONE";
public static final String MASK_TYPE_CUSTOM = "CUSTOM";
+ public static final int POLICY_PRIORITY_NORMAL = 0;
+ public static final int POLICY_PRIORITY_OVERRIDE = 1;
+
+ public static final String POLICY_PRIORITY_NAME_NORMAL = "NORMAL";
+ public static final String POLICY_PRIORITY_NAME_OVERRIDE = "OVERRIDE";
+
// For future use
private static final long serialVersionUID = 1L;
private String service;
private String name;
private Integer policyType;
+ private Integer policyPriority;
private String description;
private String resourceSignature;
private Boolean isAuditEnabled;
@@ -70,15 +78,13 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
private List<RangerPolicyItem> denyExceptions;
private List<RangerDataMaskPolicyItem> dataMaskPolicyItems;
private List<RangerRowFilterPolicyItem> rowFilterPolicyItems;
- private String serviceType;
- private List<String> policyLabels;
+ private String serviceType;
+ private Map<String, Object> options;
+ private List<RangerValiditySchedule> validitySchedules;
+ private List<String> policyLabels;
-
- /**
- * @param
- */
public RangerPolicy() {
- this(null, null, null, null, null, null, null, null);
+ this(null, null, null, null, null, null, null, null, null, null, null);
}
/**
@@ -90,12 +96,13 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
* @param policyItems
* @param resourceSignature TODO
*/
- public RangerPolicy(String service, String name, Integer policyType, String description, Map<String, RangerPolicyResource> resources, List<RangerPolicyItem> policyItems, String resourceSignature, List<String> policyLables) {
+ public RangerPolicy(String service, String name, Integer policyType, Integer policyPriority, String description, Map<String, RangerPolicyResource> resources, List<RangerPolicyItem> policyItems, String resourceSignature, Map<String, Object> options, List<RangerValiditySchedule> validitySchedules, List<String> policyLables) {
super();
setService(service);
setName(name);
setPolicyType(policyType);
+ setPolicyPriority(policyPriority);
setDescription(description);
setResourceSignature(resourceSignature);
setIsAuditEnabled(null);
@@ -106,7 +113,10 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
setDenyExceptions(null);
setDataMaskPolicyItems(null);
setRowFilterPolicyItems(null);
- setPolicyLabels(policyLables);
+ setOptions(options);
+ setValiditySchedules(validitySchedules);
+ setPolicyLabels(policyLables);
+
}
/**
@@ -118,6 +128,7 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
setService(other.getService());
setName(other.getName());
setPolicyType(other.getPolicyType());
+ setPolicyPriority(other.getPolicyPriority());
setDescription(other.getDescription());
setResourceSignature(other.getResourceSignature());
setIsAuditEnabled(other.getIsAuditEnabled());
@@ -128,7 +139,9 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
setDenyExceptions(other.getDenyExceptions());
setDataMaskPolicyItems(other.getDataMaskPolicyItems());
setRowFilterPolicyItems(other.getRowFilterPolicyItems());
- setPolicyLabels(other.getPolicyLabels());
+ setOptions(other.getOptions());
+ setValiditySchedules(other.getValiditySchedules());
+ setPolicyLabels(other.getPolicyLabels());
}
/**
@@ -174,6 +187,20 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
}
/**
+ * @return the policyPriority
+ */
+ public Integer getPolicyPriority() {
+ return policyPriority;
+ }
+
+ /**
+ * @param policyPriority the policyPriority to set
+ */
+ public void setPolicyPriority(Integer policyPriority) {
+ this.policyPriority = policyPriority == null ? RangerPolicy.POLICY_PRIORITY_NORMAL : policyPriority;
+ }
+
+ /**
* @return the description
*/
public String getDescription() {
@@ -415,6 +442,40 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
}
}
+ public Map<String, Object> getOptions() { return options; }
+
+ public void setOptions(Map<String, Object> options) {
+ if (this.options == null) {
+ this.options = new HashMap<>();
+ }
+ if (this.options == options) {
+ return;
+ }
+ this.options.clear();
+
+ if(options != null) {
+ for(Map.Entry<String, Object> e : options.entrySet()) {
+ this.options.put(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ public List<RangerValiditySchedule> getValiditySchedules() { return validitySchedules; }
+
+ public void setValiditySchedules(List<RangerValiditySchedule> validitySchedules) {
+ if (this.validitySchedules == null) {
+ this.validitySchedules = new ArrayList<>();
+ }
+ if (this.validitySchedules == validitySchedules) {
+ return;
+ }
+ this.validitySchedules.clear();
+
+ if(validitySchedules != null) {
+ this.validitySchedules.addAll(validitySchedules);
+ }
+ }
+
@Override
public String toString( ) {
StringBuilder sb = new StringBuilder();
@@ -432,10 +493,11 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
sb.append("service={").append(service).append("} ");
sb.append("name={").append(name).append("} ");
sb.append("policyType={").append(policyType).append("} ");
+ sb.append("policyPriority={").append(policyPriority).append("} ");
sb.append("description={").append(description).append("} ");
sb.append("resourceSignature={").append(resourceSignature).append("} ");
sb.append("isAuditEnabled={").append(isAuditEnabled).append("} ");
- sb.append("serviceType={").append(serviceType).append("} ");
+ sb.append("serviceType={").append(serviceType).append("} ");
sb.append("resources={");
if(resources != null) {
@@ -515,6 +577,27 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
}
sb.append("} ");
+ sb.append("options={");
+ if(options != null) {
+ for(Map.Entry<String, Object> e : options.entrySet()) {
+ sb.append(e.getKey()).append("={");
+ sb.append(e.getValue().toString());
+ sb.append("} ");
+ }
+ }
+ sb.append("} ");
+
+ //sb.append("validitySchedules={").append(validitySchedules).append("} ");
+ sb.append("validitySchedules={");
+ if (CollectionUtils.isNotEmpty(validitySchedules)) {
+ for (RangerValiditySchedule schedule : validitySchedules) {
+ if (schedule != null) {
+ sb.append("schedule={").append(schedule).append("}");
+ }
+ }
+ }
+ sb.append("}");
+
sb.append("}");
return sb;
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
index 00e60e2..b56b8dd 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
@@ -27,6 +27,7 @@ import java.util.Objects;
import java.util.TreeMap;
import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
@@ -45,7 +46,7 @@ public class RangerPolicyResourceSignature {
_policy = policy;
PolicySerializer serializer = new PolicySerializer(_policy);
_string = serializer.toString();
- _hash = DigestUtils.sha256Hex(_string);
+ _hash = DigestUtils.sha256Hex(_string);
}
/**
@@ -136,6 +137,13 @@ public class RangerPolicyResourceSignature {
resources.put(resourceName, resourceView);
}
String resource = resources.toString();
+ if (CollectionUtils.isNotEmpty(_policy.getValiditySchedules())) {
+ resource += _policy.getValiditySchedules().toString();
+ }
+ if (_policy.getPolicyPriority() != null && _policy.getPolicyPriority() != RangerPolicy.POLICY_PRIORITY_NORMAL) {
+ resource += _policy.getPolicyPriority();
+ }
+
String result = String.format("{version=%d,type=%d,resource=%s}", _SignatureVersion, type, resource);
return result;
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerTag.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerTag.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerTag.java
index 743b028..9e620c3 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerTag.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerTag.java
@@ -26,7 +26,9 @@ 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.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
@@ -40,12 +42,15 @@ public class RangerTag extends RangerBaseModelObject {
public static final short OWNER_SERVICERESOURCE = 0;
public static final short OWNER_GLOBAL = 1;
- private String type;
- private Short owner = OWNER_SERVICERESOURCE;
+ public static final String OPTION_TAG_VALIDITY_PERIODS = "TAG_VALIDITY_PERIODS";
- private Map<String, String> attributes;
+ private String type;
+ private Short owner = OWNER_SERVICERESOURCE;
+ private Map<String, String> attributes;
+ private Map<String, Object> options;
+ private List<RangerValiditySchedule> validityPeriods;
- public RangerTag(String guid, String type, Map<String, String> attributes, Short owner) {
+ public RangerTag(String guid, String type, Map<String, String> attributes, Short owner, Map<String, Object> options, List<RangerValiditySchedule> validityPeriods) {
super();
setGuid(guid);
@@ -53,14 +58,20 @@ public class RangerTag extends RangerBaseModelObject {
setOwner(owner);
setAttributes(attributes);
setOwner(owner);
+ setOptions(options);
+ setValidityPeriods(validityPeriods);
+ }
+
+ public RangerTag(String guid, String type, Map<String, String> attributes, Short owner) {
+ this(guid, type, attributes, owner, null, null);
}
public RangerTag(String type, Map<String, String> attributes) {
- this(null, type, attributes, OWNER_SERVICERESOURCE);
+ this(null, type, attributes, OWNER_SERVICERESOURCE, null, null);
}
public RangerTag() {
- this(null, null, null, OWNER_SERVICERESOURCE);
+ this(null, null, null, OWNER_SERVICERESOURCE, null, null);
}
public String getType() {
@@ -87,6 +98,39 @@ public class RangerTag extends RangerBaseModelObject {
this.owner = owner;
}
+ public Map<String, Object> getOptions() { return options; }
+
+ public void setOptions(Map<String, Object> options) {
+ if (this.options == null) {
+ this.options = new HashMap<>();
+ }
+ if (this.options == options) {
+ return;
+ }
+ this.options.clear();
+
+ if(options != null) {
+ for(Map.Entry<String, Object> e : options.entrySet()) {
+ this.options.put(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ public List<RangerValiditySchedule> getValidityPeriods() { return validityPeriods; }
+
+ public void setValidityPeriods(List<RangerValiditySchedule> validityPeriods) {
+ if (this.validityPeriods == null) {
+ this.validityPeriods = new ArrayList<>();
+ }
+ if (this.validityPeriods == validityPeriods) {
+ return;
+ }
+ this.validityPeriods.clear();
+
+ if(validityPeriods != null) {
+ this.validityPeriods.addAll(validityPeriods);
+ }
+ }
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -114,7 +158,12 @@ public class RangerTag extends RangerBaseModelObject {
}
sb.append("} ");
- sb.append(" }");
+ if (validityPeriods != null) {
+ sb.append("validityPeriods={").append(validityPeriods).append("} ");
+ }
+ sb.append("options={").append(options).append("} ");
+
+ sb.append(" }");
return sb;
}
@@ -129,6 +178,10 @@ public class RangerTag extends RangerBaseModelObject {
+ ((owner == null) ? 0 : owner.hashCode());
result = prime * result
+ ((attributes == null) ? 0 : attributes.hashCode());
+ result = prime * result
+ + ((options == null) ? 0 : options.hashCode());
+ result = prime * result
+ + ((validityPeriods == null) ? 0 : validityPeriods.hashCode());
return result;
}
@@ -156,6 +209,16 @@ public class RangerTag extends RangerBaseModelObject {
return false;
} else if (!attributes.equals(other.attributes))
return false;
+ if (options == null) {
+ if (other.options != null)
+ return false;
+ } else if (!options.equals(other.options))
+ return false;
+ if (validityPeriods == null) {
+ if (other.validityPeriods != null)
+ return false;
+ } else if (!validityPeriods.equals(other.validityPeriods))
+ return false;
return true;
}
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValidityRecurrence.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValidityRecurrence.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValidityRecurrence.java
new file mode 100644
index 0000000..4bff3ea
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValidityRecurrence.java
@@ -0,0 +1,231 @@
+/*
+ * 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.model;
+
+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;
+
+@JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+
+public class RangerValidityRecurrence {
+
+ @JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY)
+ @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+ @JsonIgnoreProperties(ignoreUnknown=true)
+ @XmlRootElement
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class ValidityInterval {
+ private final int days;
+ private final int hours;
+ private final int minutes;
+
+ public static int getValidityIntervalInMinutes(ValidityInterval interval) {
+ return interval != null ?
+ (interval.getDays()*24 + interval.getHours())*60 + interval.getMinutes() : 0;
+ }
+
+ public ValidityInterval() {
+ this.days = 0;
+ this.hours = 0;
+ this.minutes = 0;
+ }
+ public ValidityInterval(int days, int hours, int minutes) {
+ this.days = days;
+ this.hours = hours;
+ this.minutes = minutes;
+ }
+ public int getDays() { return days; }
+ public int getHours() { return hours; }
+ public int getMinutes() { return minutes; }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("ValidityInterval={");
+
+ sb.append(" Interval={");
+ sb.append("days=").append(days);
+ sb.append(", hours=").append(hours);
+ sb.append(", minutes=").append(minutes);
+ sb.append(" }");
+
+ return sb.toString();
+ }
+ }
+
+ @JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY)
+ @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+ @JsonIgnoreProperties(ignoreUnknown=true)
+ @XmlRootElement
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class RecurrenceSchedule {
+ static final String PERMITTED_SPECIAL_CHARACTERS = "*,-";
+ static final String PERMITTED_SPECIAL_CHARACTERS_FOR_MINUTES = ",";
+ public static final String WILDCARD = "*";
+
+ public enum ScheduleFieldSpec {
+ minute(0, 59, PERMITTED_SPECIAL_CHARACTERS_FOR_MINUTES),
+ hour(0, 23, PERMITTED_SPECIAL_CHARACTERS),
+ dayOfMonth(1, 31, PERMITTED_SPECIAL_CHARACTERS),
+ dayOfWeek(1, 7, PERMITTED_SPECIAL_CHARACTERS),
+ month(0, 11, PERMITTED_SPECIAL_CHARACTERS),
+ year(2017, 2100, PERMITTED_SPECIAL_CHARACTERS),
+ ;
+
+ public final int minimum;
+ public final int maximum;
+ public final String specialChars;
+
+ ScheduleFieldSpec(int minimum, int maximum, String specialChars) {
+ this.minimum = minimum;
+ this.maximum = maximum;
+ this.specialChars = specialChars;
+ }
+ }
+
+
+ private String minute;
+ private String hour;
+ private String dayOfMonth;
+ private String dayOfWeek;
+ private String month;
+ private String year;
+
+ public RecurrenceSchedule() {}
+
+ public RecurrenceSchedule(String minute, String hour, String dayOfMonth, String dayOfWeek, String month, String year) {
+ setMinute(minute);
+ setHour(hour);
+ setDayOfMonth(dayOfMonth);
+ setDayOfWeek(dayOfWeek);
+ setMonth(month);
+ setYear(year);
+ }
+ public String getMinute() { return minute;}
+ public String getHour() { return hour;}
+ public String getDayOfMonth() { return dayOfMonth;}
+ public String getDayOfWeek() { return dayOfWeek;}
+ public String getMonth() { return month;}
+ public String getYear() { return year;}
+
+ public void setMinute(String minute) { this.minute = minute;}
+ public void setHour(String hour) { this.hour = hour;}
+ public void setDayOfMonth(String dayOfMonth) { this.dayOfMonth = dayOfMonth;}
+ public void setDayOfWeek(String dayOfWeek) { this.dayOfWeek = dayOfWeek;}
+ public void setMonth(String month) { this.month = month;}
+ public void setYear(String year) { this.year = year;}
+
+ public void setFieldValue(ScheduleFieldSpec field, String value) {
+ switch (field) {
+ case minute:
+ setMinute(value);
+ break;
+ case hour:
+ setHour(value);
+ break;
+ case dayOfMonth:
+ setDayOfMonth(value);
+ break;
+ case dayOfWeek:
+ setDayOfWeek(value);
+ break;
+ case month:
+ setMonth(value);
+ break;
+ case year:
+ setYear(value);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public String getFieldValue(ScheduleFieldSpec field) {
+ switch (field) {
+ case minute:
+ return getMinute();
+ case hour:
+ return getHour();
+ case dayOfMonth:
+ return getDayOfMonth();
+ case dayOfWeek:
+ return getDayOfWeek();
+ case month:
+ return getMonth();
+ case year:
+ return getYear();
+ default:
+ return null;
+ }
+ }
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" Schedule={");
+ sb.append(" minute=").append(minute);
+ sb.append(", hour=").append(hour);
+ sb.append(", dayOfMonth=").append(dayOfMonth);
+ sb.append(", dayOfWeek=").append(dayOfWeek);
+ sb.append(", month=").append(month);
+ sb.append(", year=").append(year);
+ sb.append(" }");
+
+ return sb.toString();
+ }
+ }
+
+ private RecurrenceSchedule schedule;
+ private ValidityInterval interval;
+
+ public RangerValidityRecurrence() {
+ }
+
+ public RangerValidityRecurrence(RecurrenceSchedule schedule, ValidityInterval interval) {
+ setSchedule(schedule);
+ setInterval(interval);
+ }
+
+ public void setSchedule(RecurrenceSchedule schedule) { this.schedule = schedule;}
+
+ public void setInterval(ValidityInterval interval) { this.interval = interval; }
+
+ public RecurrenceSchedule getSchedule() { return schedule;}
+
+ public ValidityInterval getInterval() {
+ return interval;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{RangerValidityRecurrence= {");
+ sb.append(schedule).append(interval);
+ sb.append(" }");
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValiditySchedule.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValiditySchedule.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValiditySchedule.java
new file mode 100644
index 0000000..8fe3231
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerValiditySchedule.java
@@ -0,0 +1,93 @@
+/*
+ * 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.model;
+
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+@JsonAutoDetect(fieldVisibility=Visibility.ANY)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+
+public class RangerValiditySchedule {
+
+ private static final Log LOG = LogFactory.getLog(RangerValiditySchedule.class);
+
+ public static final String VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION = "yyyy/MM/dd HH:mm:ss";
+
+ private String startTime;
+ private String endTime;
+ private String timeZone;
+
+ private List<RangerValidityRecurrence> recurrences;
+
+ public RangerValiditySchedule(String startTime, String endTime, String timeZone, List<RangerValidityRecurrence> recurrences) {
+ setTimeZone(timeZone);
+ setStartTime(startTime);
+ setEndTime(endTime);
+ setRecurrences(recurrences);
+ }
+
+ public RangerValiditySchedule() {
+ this(null, null, null, null);
+ }
+
+ public String getTimeZone() { return timeZone; }
+ public String getStartTime() { return startTime;}
+ public String getEndTime() { return endTime;}
+ public List<RangerValidityRecurrence> getRecurrences() { return recurrences;}
+
+ public void setTimeZone(String timeZone) { this.timeZone = timeZone; }
+ public void setStartTime(String startTime) { this.startTime = startTime;}
+ public void setEndTime(String endTime) { this.endTime = endTime;}
+ public void setRecurrences(List<RangerValidityRecurrence> recurrences) { this.recurrences = recurrences == null ? new ArrayList<>() : recurrences;}
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RangerValiditySchedule={");
+
+ sb.append(", startTime=").append(startTime);
+ sb.append(", endTime=").append(endTime);
+ sb.append(", timeZone=").append(timeZone);
+
+ sb.append(", recurrences=").append(Arrays.toString(getRecurrences().toArray()));
+
+ sb.append("}");
+
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
index 95eeca7..4d2fa23 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -37,6 +37,7 @@ import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.store.ServiceStore;
public class RangerPolicyValidator extends RangerValidator {
@@ -123,6 +124,19 @@ public class RangerPolicyValidator extends RangerValidator {
.build());
valid = false;
} else {
+ Integer priority = policy.getPolicyPriority();
+ if (priority != null) {
+ if (priority < RangerPolicy.POLICY_PRIORITY_NORMAL || priority > RangerPolicy.POLICY_PRIORITY_OVERRIDE) {
+ ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_POLICY_INVALID_PRIORITY;
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policyPriority")
+ .isSemanticallyIncorrect()
+ .becauseOf(error.getMessage("out of range"))
+ .errorCode(error.getErrorCode())
+ .build());
+ valid = false;
+ }
+ }
Long id = policy.getId();
RangerPolicy existingPolicy = null;
@@ -306,6 +320,7 @@ public class RangerPolicyValidator extends RangerValidator {
}
if (serviceNameValid) { // resource checks can't be done meaningfully otherwise
+ valid = isValidValiditySchedule(policy, failures, action) && valid;
valid = isValidResources(policy, failures, action, isAdmin, serviceDef) && valid;
valid = isValidAccessTypeDef(policy, failures, action, isAdmin, serviceDef) && valid;
}
@@ -413,7 +428,41 @@ public class RangerPolicyValidator extends RangerValidator {
}
return valid;
}
-
+
+ boolean isValidValiditySchedule(RangerPolicy policy, final List<ValidationFailureDetails> failures, Action action) {
+
+ boolean valid = true;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValidValiditySchedule(%s, %s, %s)", policy, failures, action));
+ }
+ List<RangerValiditySchedule> validitySchedules = policy.getValiditySchedules();
+ List<RangerValiditySchedule> normalizedValiditySchedules = null;
+
+ for (RangerValiditySchedule entry : validitySchedules) {
+ RangerValidityScheduleValidator validator = new RangerValidityScheduleValidator(entry);
+
+ RangerValiditySchedule normalizedValiditySchedule = validator.validate(failures);
+ if (normalizedValiditySchedule == null) {
+ valid = false;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Invalid Validity-Schedule:[" + entry +"]");
+ }
+ } else {
+ if (normalizedValiditySchedules == null) {
+ normalizedValiditySchedules = new ArrayList<>();
+ }
+ normalizedValiditySchedules.add(normalizedValiditySchedule);
+ }
+ }
+ if (valid && CollectionUtils.isNotEmpty(normalizedValiditySchedules)) {
+ policy.setValiditySchedules(normalizedValiditySchedules);
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValidValiditySchedule(%s, %s, %s): %s", policy, failures, action, valid));
+ }
+ return valid;
+ }
+
boolean isPolicyResourceUnique(RangerPolicy policy, final List<ValidationFailureDetails> failures, Action action) {
if(LOG.isDebugEnabled()) {
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
index 509c188..55973f5 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -96,7 +96,7 @@ public abstract class RangerValidator {
return false;
}
- String serializeFailures(List<ValidationFailureDetails> failures) {
+ public static String serializeFailures(List<ValidationFailureDetails> failures) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerValidator.getFailureMessage()");
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidityScheduleValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidityScheduleValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidityScheduleValidator.java
new file mode 100644
index 0000000..63e8bc0
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidityScheduleValidator.java
@@ -0,0 +1,480 @@
+/*
+ * 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.model.validation;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TimeZone;
+
+import org.apache.ranger.plugin.model.RangerValidityRecurrence;
+import org.apache.ranger.plugin.model.RangerValidityRecurrence.RecurrenceSchedule;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+
+import javax.annotation.Nonnull;
+
+public class RangerValidityScheduleValidator {
+ private static final Log LOG = LogFactory.getLog(RangerValidityScheduleValidator.class);
+
+ private static final ThreadLocal<DateFormat> DATE_FORMATTER = new ThreadLocal<DateFormat>() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat(RangerValiditySchedule.VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION);
+ }
+ };
+
+ private static final Set<String> validTimeZoneIds = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
+
+ private final RangerValiditySchedule validitySchedule;
+ private Date startTime;
+ private Date endTime;
+ private RecurrenceSchedule validityPeriodEstimator;
+ private RangerValiditySchedule normalizedValiditySchedule;
+
+ public RangerValidityScheduleValidator(@Nonnull RangerValiditySchedule validitySchedule) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidityScheduleValidator:: " + validitySchedule);
+ }
+
+ this.validitySchedule = validitySchedule;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidityScheduleValidator:: " + validitySchedule);
+ }
+ }
+
+ public RangerValiditySchedule validate(List<ValidationFailureDetails> validationFailures) {
+ RangerValiditySchedule ret = null;
+
+ if (StringUtils.isEmpty(validitySchedule.getStartTime()) && StringUtils.isEmpty(validitySchedule.getEndTime()) && CollectionUtils.isEmpty(validitySchedule.getRecurrences())) {
+ validationFailures.add(new ValidationFailureDetails(0, "startTime,endTime,recurrences", "", true, true, false, "empty values"));
+ } else {
+
+ if (validitySchedule.getStartTime() != null) {
+ try {
+ startTime = DATE_FORMATTER.get().parse(validitySchedule.getStartTime());
+ } catch (ParseException exception) {
+ LOG.error("Error parsing startTime:[" + validitySchedule.getStartTime() + "]", exception);
+ validationFailures.add(new ValidationFailureDetails(0, "startTime", "", true, true, false, "invalid value"));
+ }
+ } else {
+ startTime = new Date();
+ }
+
+ if (validitySchedule.getEndTime() != null) {
+ try {
+ endTime = DATE_FORMATTER.get().parse(validitySchedule.getEndTime());
+ } catch (ParseException exception) {
+ LOG.error("Error parsing endTime:[" + validitySchedule.getEndTime() + "]", exception);
+ validationFailures.add(new ValidationFailureDetails(0, "endTime", "", true, true, false, "invalid value"));
+ }
+ } else {
+ endTime = new Date(Long.MAX_VALUE);
+ }
+
+ if (startTime != null && endTime != null) {
+ validityPeriodEstimator = new RangerValidityRecurrence.RecurrenceSchedule();
+ normalizedValiditySchedule = new RangerValiditySchedule();
+
+ boolean isValid = validateTimeRangeSpec(validationFailures);
+
+ if (isValid) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("validityPeriodEstimator:[" + validityPeriodEstimator + "]");
+ }
+
+ normalizedValiditySchedule.setStartTime(validitySchedule.getStartTime());
+ normalizedValiditySchedule.setEndTime(validitySchedule.getEndTime());
+ normalizedValiditySchedule.setTimeZone(validitySchedule.getTimeZone());
+
+ ret = normalizedValiditySchedule;
+ } else {
+ normalizedValiditySchedule = null;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ private boolean validateTimeRangeSpec(List<ValidationFailureDetails> validationFailures) {
+ boolean ret;
+ if (startTime.getTime() >= endTime.getTime()) {
+ validationFailures.add(new ValidationFailureDetails(0, "startTime", "", false, true, false, "endTime is not later than startTime"));
+ ret = false;
+ } else {
+ ret = true;
+ }
+ ret = validateTimeZone(validitySchedule.getTimeZone(), validationFailures) && ret;
+
+ for (RangerValidityRecurrence recurrence : validitySchedule.getRecurrences()) {
+ ret = validateValidityInterval(recurrence, validationFailures) && ret;
+
+ if (RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) > 0) {
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, validationFailures) && ret;
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, validationFailures) && ret;
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, validationFailures) && ret;
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, validationFailures) && ret;
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, validationFailures) && ret;
+ ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, validationFailures) && ret;
+ ret = ret && validateIntervalDuration(recurrence, validationFailures);
+
+ if (ret) {
+ RangerValidityRecurrence.RecurrenceSchedule schedule = new RangerValidityRecurrence.RecurrenceSchedule(getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour),
+ getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek),
+ getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year));
+ RangerValidityRecurrence normalizedRecurrence = new RangerValidityRecurrence(schedule, recurrence.getInterval());
+ normalizedValiditySchedule.getRecurrences().add(normalizedRecurrence);
+
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ private boolean validateTimeZone(String timeZone, List<ValidationFailureDetails> validationFailures) {
+ boolean ret = !StringUtils.isNotBlank(timeZone) || validTimeZoneIds.contains(timeZone);
+
+ if (!ret) {
+ validationFailures.add(new ValidationFailureDetails(0, "timeZone", "", false, true, false, "invalid timeZone"));
+ }
+ return ret;
+ }
+
+ private boolean validateValidityInterval(RangerValidityRecurrence recurrence, List<ValidationFailureDetails> validationFailures) {
+ boolean ret = true;
+ RangerValidityRecurrence.ValidityInterval validityInterval = recurrence.getInterval();
+ if (validityInterval != null) {
+ if (validityInterval.getDays() < 0
+ || (validityInterval.getHours() < 0 || validityInterval.getHours() > 23)
+ || (validityInterval.getMinutes() < 0 || validityInterval.getMinutes() > 59)) {
+ validationFailures.add(new ValidationFailureDetails(0, "interval", "", false, true, false, "invalid interval"));
+ ret = false;
+ }
+ }
+ int validityIntervalInMinutes = RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(validityInterval);
+ if (validityIntervalInMinutes > 0) {
+ if (StringUtils.isBlank(recurrence.getSchedule().getDayOfMonth()) && StringUtils.isBlank(recurrence.getSchedule().getDayOfWeek())) {
+ validationFailures.add(new ValidationFailureDetails(0, "validitySchedule", "", false, true, false, "empty dayOfMonth and dayOfWeek"));
+ ret = false;
+ }
+ }
+ return ret;
+ }
+
+ private boolean validateFieldSpec(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field, List<ValidationFailureDetails> validationFailures) {
+ boolean ret = true;
+
+ String fieldValue = recurrence.getSchedule().getFieldValue(field);
+ if (StringUtils.isBlank(fieldValue)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No value provided for [" + field + "]");
+ }
+ if (StringUtils.equals(field.name(), RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.name())
+ || StringUtils.equals(field.name(), RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.name())) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Allow blank value for dayOfWeek or dayOfMonth here. Check for both being null is done elsewhere.");
+ }
+ } else {
+ validationFailures.add(new ValidationFailureDetails(0, field.toString(), "", false, true, false, "No value provided"));
+ }
+ }
+ ret = validateCharacters(fieldValue, field.specialChars);
+
+ if (!ret) {
+ validationFailures.add(new ValidationFailureDetails(0, field.toString(), "", false, true, false, "invalid character(s)"));
+ } else {
+ // Valid month values in java.util.Date are from 1-12, in java.util.Calendar from 0 to 11
+ // Internally we use Calendar values for validation and evaluation
+ int minimum = field == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month ? field.minimum + 1 : field.minimum;
+ int maximum = field == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month ? field.maximum + 1 : field.maximum;
+ ret = validateRanges(recurrence, field, minimum, maximum, validationFailures);
+ }
+ return ret;
+ }
+
+ private boolean validateCharacters(String str, String permittedCharacters) {
+ boolean ret = true;
+ if (StringUtils.isNotBlank(str)) {
+ char[] chars = str.toCharArray();
+ for (char c : chars) {
+ if (!(Character.isDigit(c) || Character.isWhitespace(c) || StringUtils.contains(permittedCharacters, c))) {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
+ private boolean validateIntervalDuration(RangerValidityRecurrence recurrence, List<ValidationFailureDetails> validationFailures) {
+ boolean ret = true;
+
+ if (!validationFailures.isEmpty() || validityPeriodEstimator == null) {
+ ret = false;
+ } else {
+ int minSchedulingInterval = 1; // In minutes
+
+ String minutes = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute);
+ if (!StringUtils.equals(minutes, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ minSchedulingInterval = StringUtils.isBlank(minutes) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1 : Integer.valueOf(minutes);
+
+ if (minSchedulingInterval == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1) {
+ String hours = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour);
+ if (!StringUtils.equals(hours, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ int hour = StringUtils.isBlank(hours) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1 :Integer.valueOf(hours);
+ minSchedulingInterval = hour * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum+1);
+
+ if (hour == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) {
+ String dayOfMonths = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth);
+ String dayOfWeeks = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek);
+
+ int dayOfMonth = 1, dayOfWeek = 1;
+ if (!StringUtils.equals(dayOfMonths, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ dayOfMonth = StringUtils.isBlank(dayOfMonths) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.maximum + 1 : Integer.valueOf(dayOfMonths);
+ }
+ if (!StringUtils.equals(dayOfWeeks, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ dayOfWeek = StringUtils.isBlank(dayOfWeeks) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum + 1 : Integer.valueOf(dayOfWeeks);
+ }
+ if (!StringUtils.equals(dayOfMonths, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD) || !StringUtils.equals(dayOfWeeks, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ int minDays = dayOfMonth > dayOfWeek ? dayOfWeek : dayOfMonth;
+ minSchedulingInterval = minDays*(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum+1)*(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum+1);
+
+ if (dayOfMonth == (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.maximum+1) && dayOfWeek == (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum+1)) {
+ String months = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month);
+ if (!StringUtils.equals(months, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ int month = StringUtils.isBlank(months) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month.maximum + 1 :Integer.valueOf(months);
+ minSchedulingInterval = month * 28 * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1);
+
+ if (month == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month.maximum + 1) {
+ // Maximum interval is 1 year
+ minSchedulingInterval = 365 * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) > minSchedulingInterval) {
+ if (LOG.isDebugEnabled()) {
+ LOG.warn("Specified scheduling interval:" + RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) + " minutes] is more than minimum possible scheduling interval:[" + minSchedulingInterval + " minutes].");
+ LOG.warn("This may turn this (expected to be temporary) policy into effectively permanent policy.");
+ }
+ }
+ }
+ return ret;
+ }
+
+ private boolean validateRanges(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field, int minValidValue, int maxValidValue, List<ValidationFailureDetails> validationFailures) {
+ boolean ret = true;
+
+ String value = null;
+ String fieldName = field.toString();
+
+ String noWhiteSpace = StringUtils.deleteWhitespace(recurrence.getSchedule().getFieldValue(field));
+ String[] specs = StringUtils.split(noWhiteSpace, ",");
+ class Range {
+ private int lower;
+ private int upper;
+ private Range(int lower, int upper) {
+ this.lower = lower;
+ this.upper = upper;
+ }
+ }
+ class RangeComparator implements Comparator<Range>, Serializable {
+ @Override
+ public int compare(Range me, Range other) {
+ int result;
+ result = Integer.compare(me.lower, other.lower);
+ if (result == 0) {
+ result = Integer.compare(me.upper, other.upper);
+ }
+ return result;
+ }
+ }
+
+ List<Range> rangeOfValues = new ArrayList<>();
+
+ List<Integer> values = new ArrayList<>();
+
+ for (String spec : specs) {
+
+ if (StringUtils.isNotEmpty(spec)) {
+ // Range
+ if (spec.startsWith("-") || spec.endsWith("-")) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range spec"));
+ ret = false;
+ } else {
+ String[] ranges = StringUtils.split(spec, "-");
+ if (ranges.length > 2) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range spec"));
+ ret = false;
+ } else if (ranges.length == 2) {
+ int val1 = minValidValue, val2 = maxValidValue;
+ if (!StringUtils.equals(ranges[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ val1 = Integer.valueOf(ranges[0]);
+ if (val1 < minValidValue || val1 > maxValidValue) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect lower range value"));
+ ret = false;
+ }
+ } else {
+ value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD;
+ }
+ if (!StringUtils.equals(ranges[1], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ val2 = Integer.valueOf(ranges[1]);
+ if (val1 < minValidValue || val2 > maxValidValue) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect upper range value"));
+ ret = false;
+ }
+ } else {
+ value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD;
+ }
+ if (ret) {
+ if (val1 >= val2) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range"));
+ ret = false;
+ } else {
+ value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD;
+ for (Range range : rangeOfValues) {
+ if (range.lower == val1 || range.upper == val2) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "duplicate range"));
+ ret = false;
+ break;
+ }
+ }
+ if (ret) {
+ rangeOfValues.add(new Range(val1, val2));
+ }
+ }
+ }
+ } else if (ranges.length == 1) {
+ if (!StringUtils.equals(ranges[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ int val = Integer.valueOf(ranges[0]);
+ if (val < minValidValue || val > maxValidValue) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect value"));
+ ret = false;
+ } else {
+ if (!StringUtils.equals(value, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+ values.add(Integer.valueOf(ranges[0]));
+ }
+ }
+ } else {
+ value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD;
+ }
+ } else {
+ ret = false;
+ }
+ }
+ }
+ }
+ //if (ret) {
+ if (CollectionUtils.isNotEmpty(rangeOfValues)) {
+ rangeOfValues.sort( new RangeComparator());
+ }
+ for (int i = 0; i < rangeOfValues.size(); i++) {
+ Range range = rangeOfValues.get(i);
+ int upper = range.upper;
+ for (int j = i+1; j < rangeOfValues.size(); j++) {
+ Range r = rangeOfValues.get(j);
+ if (upper < r.upper) {
+ validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "overlapping range value"));
+ ret = false;
+ }
+ }
+ }
+ //}
+ if (ret) {
+ if (!StringUtils.equals(value, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) {
+
+ int minDiff = (values.size() <= 1) ? maxValidValue + 1 : Integer.MAX_VALUE;
+
+ if (values.size() > 1) {
+ Collections.sort(values);
+ for (int i = 0; i < values.size() - 1; i++) {
+ int diff = values.get(i + 1) - values.get(i);
+ if (diff < minDiff) {
+ minDiff = diff;
+ }
+ int firstLastDiff = values.get(0) + (maxValidValue - minValidValue + 1) - values.get(values.size() - 1);
+
+ if (minDiff > firstLastDiff) {
+ minDiff = firstLastDiff;
+ }
+ }
+ }
+ if (values.size() > 0) {
+ value = Integer.toString(minDiff);
+ }
+ }
+ validityPeriodEstimator.setFieldValue(field, value);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Set " + field + " to " + value);
+ }
+ }
+ return ret;
+ }
+
+ private String getNormalizedValue(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field) {
+ String ret = null;
+
+ if (RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) > 0) {
+ String noWhiteSpace = StringUtils.deleteWhitespace(recurrence.getSchedule().getFieldValue(field));
+ String[] specs = StringUtils.split(noWhiteSpace, ",");
+
+ List<String> values = new ArrayList<>();
+
+ for (String spec : specs) {
+ if (StringUtils.isNotBlank(spec)) {
+ values.add(spec);
+ }
+ }
+ if (values.size() > 0) {
+ Collections.sort(values);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < values.size(); i++) {
+ if (i != 0) {
+ sb.append(",");
+ }
+ sb.append(values.get(i));
+ }
+ ret = sb.toString();
+ }
+ }
+ return ret;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java
index 1aad049..1d961a1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEvaluatorForTag.java
@@ -26,33 +26,36 @@ import java.io.Serializable;
import java.util.Comparator;
public class PolicyEvaluatorForTag {
- private final RangerPolicyEvaluator evaluator;
- private final RangerTagForEval tag;
-
- PolicyEvaluatorForTag(RangerPolicyEvaluator evaluator, RangerTagForEval tag) {
- this.evaluator = evaluator;
- this.tag = tag;
- }
-
- RangerPolicyEvaluator getEvaluator() {
- return evaluator;
- }
-
- RangerTagForEval getTag() {
- return tag;
- }
-
- public static class PolicyNameComparator implements Comparator<PolicyEvaluatorForTag>, Serializable {
- @Override
- public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) {
- return me.getEvaluator().getPolicy().getName().compareTo(other.getEvaluator().getPolicy().getName());
- }
- }
-
- public static class PolicyEvalOrderComparator implements Comparator<PolicyEvaluatorForTag>, Serializable {
- @Override
- public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) {
- return RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator());
- }
- }
+ public static final Comparator<PolicyEvaluatorForTag> EVAL_ORDER_COMPARATOR = new PolicyEvalOrderComparator();
+ public static final Comparator<PolicyEvaluatorForTag> NAME_COMPARATOR = new PolicyNameComparator();
+
+ private final RangerPolicyEvaluator evaluator;
+ private final RangerTagForEval tag;
+
+ PolicyEvaluatorForTag(RangerPolicyEvaluator evaluator, RangerTagForEval tag) {
+ this.evaluator = evaluator;
+ this.tag = tag;
+ }
+
+ RangerPolicyEvaluator getEvaluator() {
+ return evaluator;
+ }
+
+ RangerTagForEval getTag() {
+ return tag;
+ }
+
+ static class PolicyNameComparator implements Comparator<PolicyEvaluatorForTag>, Serializable {
+ @Override
+ public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) {
+ return RangerPolicyEvaluator.NAME_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator());
+ }
+ }
+
+ static class PolicyEvalOrderComparator implements Comparator<PolicyEvaluatorForTag>, Serializable {
+ @Override
+ public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) {
+ return RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
index 1b01ea4..8e7844f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
@@ -45,6 +45,7 @@ public class RangerAccessResult {
private boolean isAudited;
private long auditPolicyId = -1;
private long policyId = -1;
+ private int policyPriority;
private long evaluatedPoliciesCount;
private String reason;
private Map<String, Object> additionalInfo;
@@ -60,6 +61,7 @@ public class RangerAccessResult {
this.isAudited = false;
this.auditPolicyId = -1;
this.policyId = -1;
+ this.policyPriority = RangerPolicy.POLICY_PRIORITY_NORMAL;
this.evaluatedPoliciesCount = 0;
this.reason = null;
}
@@ -68,6 +70,7 @@ public class RangerAccessResult {
this.isAccessDetermined = other.getIsAccessDetermined();
this.isAllowed = other.getIsAllowed();
this.policyId = other.getPolicyId();
+ this.policyPriority = other.getPolicyPriority();
this.evaluatedPoliciesCount = other.evaluatedPoliciesCount;
this.reason = other.getReason();
this.additionalInfo = other.additionalInfo == null ? new HashMap<String, Object>() : new HashMap<>(other.additionalInfo);
@@ -123,6 +126,9 @@ public class RangerAccessResult {
this.isAllowed = isAllowed;
}
+ public int getPolicyPriority() { return policyPriority;}
+
+ public void setPolicyPriority(int policyPriority) { this.policyPriority = policyPriority; }
/**
* @param reason the reason to set
[2/4] ranger git commit: RANGER-2000: Policy effective dates to
support time-bound and temporary authorization
Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-invalid.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-invalid.json b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-invalid.json
new file mode 100644
index 0000000..ed62828
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-invalid.json
@@ -0,0 +1,146 @@
+[
+ {
+ "name": "Empty validity-schedule",
+ "validitySchedules": [
+ {}
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 1
+ }
+ },
+ {
+ "name": "Invalid characters in validity-schedule",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/12 17:19:00",
+ "recurrences": [
+ {
+ "schedule": {"minute": "MINUTE", "hour": "HOUR", "dayOfMonth": "DAYOFMONTH", "dayOfWeek": "DAYOFWEEK", "month": "MONTH", "year": "YEAR"},
+ "interval": {"days": 10, "hours": 5, "minutes": 5}
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 6
+ }
+ },
+ {
+ "name": "Invalid characters in fields in validity-schedule",
+
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {"minute": "*", "hour": "@", "dayOfMonth": "!", "dayOfWeek": "#", "month": "%", "year": "^&()"},
+ "interval": {"minutes": 10 }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 6
+ }
+ },
+ {
+ "name": "Incorrect validityInterval",
+
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "timeZone":"",
+ "recurrences": [
+ {
+ "schedule": {"minute": "10", "hour": "*", "dayOfMonth": "*", "dayOfWeek": "*", "month": "*", "year": "2018"},
+ "interval": {"days": -1, "hours": 24, "minutes": 60}
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 1
+ }
+ },
+ {
+ "name": "endTime earlier than startTime",
+
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2018/01/02 22:30:00",
+ "recurrences": [
+ {
+ "schedule": {"minute": "45, 30, 1, 14", "hour": "*, 0,20, 21", "dayOfMonth": "1-14, 15,31", "dayOfWeek": "0,4, 6", "month": "11, 0-1", "year": "2018"}
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 1
+ }
+ },
+ {
+ "name": "Overlapping ranges, incorrect range, invalid field value in validity-schedule",
+
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/22 22:30:00",
+ "timeZone":"",
+ "recurrences": [
+ {
+ "schedule": {"minute": "1,10,5", "hour": "0-3, 1-4, 9-8,20, 21", "dayOfMonth": "1-14, 15,31", "dayOfWeek": "0,4, 6", "month": "12, 1-2", "year": "2018"},
+ "interval": {"minutes": 10 }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 3
+ }
+ },
+ {
+ "name": "Both dayOfWeek and dayOfMonth blank",
+
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {"minute": "45, 30, 1, 14", "hour": "*, 0,20, 21", "dayOfMonth": "", "dayOfWeek": "", "month": "12, 1-2", "year": "2018"},
+ "interval": {"minutes": 10 }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": false,
+ "isApplicable": false,
+ "validationFailureCount": 1
+ }
+ }
+]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid-and-applicable.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid-and-applicable.json b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid-and-applicable.json
new file mode 100644
index 0000000..38921d7
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid-and-applicable.json
@@ -0,0 +1,507 @@
+[
+ {
+ "name": "Non-repeating validity-schedule",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2018/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "60",
+ "hour": "*",
+ "dayOfMonth": "*",
+ "dayOfWeek": "5, 7",
+ "month": "*",
+ "year": "2018"
+ },
+ "interval": {
+ "minutes": 0
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180113-14:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable for 9 minutes in a 10 minute interval",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2018/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0, 10, 20, 30, 40, 50",
+ "hour": "*",
+ "dayOfMonth": "*",
+ "dayOfWeek": "5, 7",
+ "month": "*",
+ "year": "2018"
+ },
+ "inteval": {
+ "minutes": 9
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-14:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable every Wednesday or Saturday or 1st of month starting at 10 past noon hour PST for 2 days and 10 hours",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2018/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "10",
+ "hour": "12",
+ "dayOfMonth": "1",
+ "dayOfWeek": "4, 7",
+ "month": "*",
+ "year": "2018"
+ },
+ "interval": {
+ "days": 2,
+ "hours": 10
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180115-19:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable every Wednesday or Saturday or 1st of month starting at 59 minutes past midnight PST for 1 day and 2 minutes",
+ "validitySchedules": [
+ {
+ "startTime": "2017/01/12 14:32:00",
+ "endTime": "2018/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "59",
+ "hour": "0",
+ "dayOfMonth": "1",
+ "dayOfWeek": "4, 7",
+ "month": "*",
+ "year": "2017-2018"
+ },
+ "interval": {
+ "days": 1,
+ "minutes": 2
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180102-01:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable every 31st of month starting at noon Zulu for 1 day, starting from 1/1/18",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "12",
+ "dayOfMonth": "31",
+ "dayOfWeek": "*",
+ "month": "*",
+ "year": "2017-2018"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180301-00:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ }
+ ,
+ {
+ "name": "validity-interval longer than minimum diff in - still not applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "12",
+ "dayOfMonth": "1",
+ "dayOfWeek": "2, 3",
+ "month": "*",
+ "year": "*"
+ },
+ "interval": {
+ "days": 1,
+ "hours": 23,
+ "minutes": 59
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180304-14:40:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "validity-interval longer than minimum diff in schedule - applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "12",
+ "dayOfMonth": "1",
+ "dayOfWeek": "2, 3",
+ "month": "*",
+ "year": "*"
+ },
+ "interval": {
+ "days": 1,
+ "hours": 23,
+ "minutes": 59
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180303-10:40:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek non blank and dayOfMonth blank - applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "",
+ "dayOfWeek": "1",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "hours": 5
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180114-04:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek non blank and dayOfMonth blank - not applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "",
+ "dayOfWeek": "1",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "hours": 5
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180119-04:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek blank and dayOfMonth not blank - applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "15, 20",
+ "dayOfWeek": "",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "days": 5
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180119-04:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek blank and dayOfMonth not blank - not applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "15, 20",
+ "dayOfWeek": "",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "days": 3
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180119-04:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable every 31st of month or every Thursday starting at noon Zulu for 1 day, starting from 1/1/18 - not applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "12",
+ "dayOfMonth": "31",
+ "dayOfWeek": "5",
+ "month": "*",
+ "year": "2017-2018"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180301-00:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable every 31st of month or every Thursday starting at noon Zulu for 1 day, starting from 1/1/18 - applicable",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "12",
+ "dayOfMonth": "31",
+ "dayOfWeek": "5",
+ "month": "*",
+ "year": "2017-2018"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180216-00:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable on Feb 29",
+ "validitySchedules": [
+ {
+ "startTime": "2020/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "*",
+ "dayOfMonth": "29",
+ "dayOfWeek": "",
+ "month": "2",
+ "year": "2020-2026"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20200301-00:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Not Applicable on Mar 29",
+ "validitySchedules": [
+ {
+ "startTime": "2020/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "*",
+ "dayOfMonth": "29",
+ "dayOfWeek": "",
+ "month": "3",
+ "year": "2020-2026"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20200301-00:00:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Applicable on Feb 29 with a timezone specified in the schedule",
+ "validitySchedules": [
+ {
+ "startTime": "2020/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "timeZone": "IST",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "0",
+ "hour": "*",
+ "dayOfMonth": "29",
+ "dayOfWeek": "",
+ "month": "2",
+ "year": "2020-2026"
+ },
+ "interval": {
+ "days": 1
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20200229-23:30:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": true,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Not applicable with a timezone specified in the schedule; no recurrences",
+ "validitySchedules": [
+ {
+ "startTime": "2020/01/01 00:00:00",
+ "endTime": "2050/02/03 12:16:00",
+ "timeZone": "GMT"
+ }
+ ],
+ "accessTime": "20191231-16:00:00.000-0700",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ }
+
+]
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid.json b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid.json
new file mode 100644
index 0000000..d42d3e6
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/validityscheduler/test-validity-schedules-valid.json
@@ -0,0 +1,152 @@
+[
+ {
+ "name": "AccessTime before startTime",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/12 14:32:00"
+ }
+ ],
+ "accessTime": "20170112-14:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "AccessTime after endTime",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2018/02/12 14:32:00"
+ }
+ ],
+ "accessTime": "20180312-14:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Not applicable for minute field",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/12 14:32:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "59, 15, 30",
+ "hour": "*",
+ "dayOfMonth": "*",
+ "dayOfWeek": "*",
+ "month": "*",
+ "year": "2018-2020"
+ },
+ "interval": {
+ "minutes": 10
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180212-14:26:00.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "Not applicable as accessTime earlier than startTime",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/12 14:32:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "3",
+ "hour": "10, 21",
+ "dayOfMonth": "*",
+ "dayOfWeek": "*",
+ "month": "*",
+ "year": "2018-2020"
+ },
+ "interval": {
+ "hours": 2
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20170112-14:26:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek blank and dayOfMonth not blank",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "12",
+ "dayOfWeek": "",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "minutes": 10
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-18:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ },
+ {
+ "name": "dayOfWeek non blank and dayOfMonth blank",
+ "validitySchedules": [
+ {
+ "startTime": "2018/01/12 14:32:00",
+ "endTime": "2020/01/23 06:30:00",
+ "recurrences": [
+ {
+ "schedule": {
+ "minute": "45, 30, 1, 14",
+ "hour": "0,20, 21",
+ "dayOfMonth": "",
+ "dayOfWeek": "1",
+ "month": "12, 1-2",
+ "year": "2018"
+ },
+ "interval": {
+ "minutes": 10
+ }
+ }
+ ]
+ }
+ ],
+ "accessTime": "20180112-18:32:27.000-0800",
+ "result": {
+ "isValid": true,
+ "isApplicable": false,
+ "validationFailureCount": 0
+ }
+ }
+]
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql
----------------------------------------------------------------------
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 d516d64..9e8fcad 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
@@ -551,6 +551,8 @@ CREATE TABLE `x_policy` (
`resource_signature` varchar(128) DEFAULT NULL,
`is_enabled` tinyint(1) NOT NULL DEFAULT '0',
`is_audit_enabled` tinyint(1) NOT NULL DEFAULT '0',
+`options` varchar(4000) NULL DEFAULT NULL,
+`policy_priority` int NOT NULL DEFAULT '0',
primary key (`id`),
KEY `x_policy_added_by_id` (`added_by_id`),
KEY `x_policy_upd_by_id` (`upd_by_id`),
@@ -983,6 +985,7 @@ CREATE TABLE IF NOT EXISTS `x_tag` (
`version` BIGINT(20) NULL DEFAULT NULL,
`type` BIGINT(20) NOT NULL,
`owned_by` SMALLINT DEFAULT 0 NOT NULL,
+`options` varchar(4000) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `x_tag_UK_guid` (`guid`),
KEY `x_tag_IDX_type` (`type`),
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/mysql/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/mysql/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql b/security-admin/db/mysql/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
new file mode 100644
index 0000000..f8bedc4
--- /dev/null
+++ b/security-admin/db/mysql/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
@@ -0,0 +1,44 @@
+-- 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_x_policy_columns_for_time_based_classification;
+delimiter ;;
+
+create procedure add_x_policy_columns_for_time_based_classification() begin
+if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_policy' and column_name='options') then
+ ALTER TABLE x_policy ADD options varchar(4000) NULL DEFAULT NULL;
+end if;
+if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_policy' and column_name='policy_priority') then
+ ALTER TABLE x_policy ADD policy_priority int NOT NULL DEFAULT '0';
+end if;
+end;;
+delimiter ;
+call add_x_policy_columns_for_time_based_classification();
+
+drop procedure if exists add_x_policy_columns_for_time_based_classification;
+
+drop procedure if exists add_x_policy_columns_for_time_based_classification;
+delimiter ;;
+
+create procedure add_x_tag_columns_for_time_based_classification() begin
+if not exists (select * from information_schema.columns where table_schema=database() and table_name = 'x_tag' and column_name='options') then
+ ALTER TABLE x_tag ADD options varchar(4000) NULL DEFAULT NULL;
+end if;
+end;;
+delimiter ;
+call add_x_tag_columns_for_time_based_classification();
+
+drop procedure if exists add_x_tag_columns_for_time_based_classification;
+
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql
----------------------------------------------------------------------
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 abc7d59..55d44a1 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
@@ -455,6 +455,8 @@ description VARCHAR(1024) DEFAULT NULL NULL,
resource_signature VARCHAR(128) DEFAULT NULL NULL,
is_enabled NUMBER(1) DEFAULT '0' NOT NULL,
is_audit_enabled NUMBER(1) DEFAULT '0' NOT NULL,
+options varchar(4000) DEFAULT NULL NULL,
+policy_priority NUMBER(11) DEFAULT 0 NOT NULL,
primary key (id),
CONSTRAINT x_policy_FK_added_by_id FOREIGN KEY (added_by_id) REFERENCES x_portal_user (id),
CONSTRAINT x_policy_FK_upd_by_id FOREIGN KEY (upd_by_id) REFERENCES x_portal_user (id),
@@ -873,6 +875,7 @@ upd_by_id NUMBER(20) DEFAULT NULL NULL,
version NUMBER(20) DEFAULT NULL NULL,
type NUMBER(20) NOT NULL,
owned_by NUMBER(6) DEFAULT 0 NOT NULL,
+options varchar(4000) DEFAULT NULL NULL,
primary key (id),
CONSTRAINT x_tag_UK_guid UNIQUE (guid),
CONSTRAINT x_tag_FK_type FOREIGN KEY (type) REFERENCES x_tag_def (id),
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/oracle/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/oracle/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql b/security-admin/db/oracle/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
new file mode 100644
index 0000000..4183572
--- /dev/null
+++ b/security-admin/db/oracle/patches/032-add-options-to-policy-and-tag-for-time-based-processing.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.
+
+DECLARE
+ v_count number:=0;
+BEGIN
+ select count(*) into v_count from user_tab_cols where table_name='X_POLICY' and column_name='OPTIONS';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_policy ADD options varchar(4000) DEFAULT NULL NULL';
+ end if;
+
+ select count(*) into v_count from user_tab_cols where table_name='X_POLICY' and column_name='POLICY_PRIORITY';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_policy ADD policy_priority NUMBER(11) DEFAULT 0 NOT NULL';
+ end if;
+
+ select count(*) into v_count from user_tab_cols where table_name='X_TAG' and column_name='OPTIONS';
+ if (v_count = 0) then
+ execute immediate 'ALTER TABLE x_tag ADD options varchar(4000) DEFAULT NULL NULL';
+ end if;
+ commit;
+END;/
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql
----------------------------------------------------------------------
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 8862946..ef9ece7 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
@@ -463,6 +463,8 @@ description VARCHAR(1024) DEFAULT NULL NULL,
resource_signature VARCHAR(128) DEFAULT NULL NULL,
is_enabled BOOLEAN DEFAULT '0' NOT NULL,
is_audit_enabled BOOLEAN DEFAULT '0' NOT NULL,
+options VARCHAR(4000) DEFAULT NULL NULL,
+policy_priority INT DEFAULT 0 NOT NULL,
primary key(id),
CONSTRAINT x_policy_FK_added_by_id FOREIGN KEY(added_by_id) REFERENCES x_portal_user(id),
CONSTRAINT x_policy_FK_upd_by_id FOREIGN KEY(upd_by_id) REFERENCES x_portal_user(id),
@@ -951,6 +953,7 @@ upd_by_id BIGINT DEFAULT NULL NULL,
version BIGINT DEFAULT NULL NULL,
type BIGINT NOT NULL,
owned_by SMALLINT DEFAULT 0 NOT NULL,
+options VARCHAR(4000) DEFAULT NULL NULL,
primary key (id),
CONSTRAINT x_tag_UK_guid UNIQUE (guid),
CONSTRAINT x_tag_FK_type FOREIGN KEY (type) REFERENCES x_tag_def (id),
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/postgres/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/postgres/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql b/security-admin/db/postgres/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
new file mode 100644
index 0000000..53ddacc
--- /dev/null
+++ b/security-admin/db/postgres/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
@@ -0,0 +1,53 @@
+-- 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_x_policy_columns_for_time_based_classification
+select 'delimiter start';
+CREATE OR REPLACE FUNCTION add_x_policy_columns_for_time_based_classification()
+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_policy') and attname='options';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_policy ADD COLUMN options VARCHAR(4000) DEFAULT NULL NULL;
+ END IF;
+ select count(*) into v_column_exists from pg_attribute where attrelid in(select oid from pg_class where relname='x_policy') and attname='policy_priority';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_policy ADD COLUMN policy_priority INT DEFAULT 0 NOT NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+select 'delimiter end';
+
+select add_x_policy_columns_for_time_based_classification();
+select 'delimiter end';
+
+select 'delimiter start';
+CREATE OR REPLACE FUNCTION add_x_tag_columns_for_time_based_classification()
+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_tag') and attname='options';
+ IF v_column_exists = 0 THEN
+ ALTER TABLE x_tag ADD COLUMN options VARCHAR(4000) DEFAULT NULL NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+select 'delimiter end';
+
+select add_x_tag_columns_for_time_based_classification();
+select 'delimiter end';
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql
----------------------------------------------------------------------
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 bf3d954..c98d362 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
@@ -341,6 +341,8 @@ create table dbo.x_policy (
resource_signature varchar(128) DEFAULT NULL NULL,
is_enabled tinyint DEFAULT 0 NOT NULL,
is_audit_enabled tinyint DEFAULT 0 NOT NULL,
+ options varchar(4000) DEFAULT NULL NULL,
+ policy_priority int DEFAULT 0 NOT NULL,
CONSTRAINT x_policy_PK_id PRIMARY KEY CLUSTERED(id)
)
GO
@@ -690,6 +692,7 @@ CREATE TABLE dbo.x_tag(
version bigint DEFAULT NULL NULL,
type bigint NOT NULL,
owned_by smallint DEFAULT 0 NOT NULL,
+ options varchar(4000) DEFAULT NULL NULL,
CONSTRAINT x_tag_PK_id PRIMARY KEY CLUSTERED(id),
CONSTRAINT x_tag_UK_guid UNIQUE NONCLUSTERED (guid)
)
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/sqlanywhere/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/sqlanywhere/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql b/security-admin/db/sqlanywhere/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
new file mode 100644
index 0000000..1314ecb
--- /dev/null
+++ b/security-admin/db/sqlanywhere/patches/032-add-options-to-policy-and-tag-for-time-based-processing.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.
+
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_policy' and cname = 'options') THEN
+ ALTER TABLE dbo.x_policy ADD options varchar(4000) DEFAULT NULL NULL;
+END IF;
+GO
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_policy' and cname = 'policy_priority') THEN
+ ALTER TABLE dbo.x_policy ADD policy_priority int DEFAULT 0 NOT NULL;
+END IF;
+GO
+IF NOT EXISTS(select * from SYS.SYSCOLUMNS where tname = 'x_tag' and cname = 'options') THEN
+ ALTER TABLE dbo.x_tag ADD options varchar(4000) DEFAULT NULL NULL;
+END IF;
+GO
+
+exit
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql
----------------------------------------------------------------------
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 56e2e99..61e81a0 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
@@ -1151,6 +1151,8 @@ CREATE TABLE [dbo].[x_policy] (
[resource_signature] [varchar](128) DEFAULT NULL NULL,
[is_enabled] [tinyint] DEFAULT 0 NOT NULL,
[is_audit_enabled] [tinyint] DEFAULT 0 NOT NULL,
+ [options] [varchar](4000) DEFAULT NULL NULL,
+ [policy_priority] [int] DEFAULT 0 NOT NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
@@ -1613,6 +1615,7 @@ CREATE TABLE [dbo].[x_tag](
[version] [bigint] DEFAULT NULL NULL,
[type] [bigint] NOT NULL,
[owned_by] [smallint] DEFAULT 0 NOT NULL,
+ [options] [varchar](4000) DEFAULT NULL NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/db/sqlserver/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/sqlserver/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql b/security-admin/db/sqlserver/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
new file mode 100644
index 0000000..932861c
--- /dev/null
+++ b/security-admin/db/sqlserver/patches/032-add-options-to-policy-and-tag-for-time-based-processing.sql
@@ -0,0 +1,35 @@
+-- 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_policy' and column_name = 'options')
+BEGIN
+ ALTER TABLE [dbo].[x_policy] ADD [options] [varchar](4000) DEFAULT NULL NULL;
+END
+GO
+GO
+IF NOT EXISTS(select * from INFORMATION_SCHEMA.columns where table_name = 'x_policy' and column_name = 'policy_priority')
+BEGIN
+ ALTER TABLE [dbo].[x_policy] ADD [policy_priority] [int] DEFAULT 0 NOT NULL;
+END
+GO
+GO
+IF NOT EXISTS(select * from INFORMATION_SCHEMA.columns where table_name = 'x_tag' and column_name = 'options')
+BEGIN
+ ALTER TABLE [dbo].[x_tag] ADD [options] [varchar](4000) DEFAULT NULL NULL;
+END
+GO
+
+exit
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
index 2c4241d..463957c 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
@@ -26,9 +26,11 @@ import java.util.ListIterator;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.authorization.utils.StringUtil;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.*;
@@ -41,9 +43,10 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator;
import org.apache.ranger.plugin.util.RangerPerfTracer;
-
+import org.apache.ranger.service.RangerPolicyService;
public class RangerPolicyRetriever {
static final Log LOG = LogFactory.getLog(RangerPolicyRetriever.class);
@@ -235,7 +238,7 @@ public class RangerPolicyRetriever {
final Map<Long, String> conditions = new HashMap<Long, String>();
final Map<Long, String> resourceDefs = new HashMap<Long, String>();
final Map<Long, String> dataMasks = new HashMap<Long, String>();
- final Map<Long, String> policyLabels = new HashMap<Long, String>();
+ final Map<Long, String> policyLabels = new HashMap<Long, String>();
String getUserName(Long userId) {
String ret = null;
@@ -257,25 +260,25 @@ public class RangerPolicyRetriever {
return ret;
}
- String getPolicyLabelName(Long policyLabelId) {
- String ret = null;
+ String getPolicyLabelName(Long policyLabelId) {
+ String ret = null;
- if(policyLabelId != null) {
- ret = policyLabels.get(policyLabelId);
+ if (policyLabelId != null) {
+ ret = policyLabels.get(policyLabelId);
- if(ret == null) {
- XXPolicyLabel xxPolicyLabel = daoMgr.getXXPolicyLabels().getById(policyLabelId);
+ if (ret == null) {
+ XXPolicyLabel xxPolicyLabel = daoMgr.getXXPolicyLabels().getById(policyLabelId);
- if(xxPolicyLabel != null) {
- ret = xxPolicyLabel.getPolicyLabel();
+ if (xxPolicyLabel != null) {
+ ret = xxPolicyLabel.getPolicyLabel();
- policyLabels.put(policyLabelId, ret);
- }
- }
- }
+ policyLabels.put(policyLabelId, ret);
+ }
+ }
+ }
- return ret;
- }
+ return ret;
+ }
String getUserScreenName(Long userId) {
String ret = null;
@@ -449,7 +452,7 @@ public class RangerPolicyRetriever {
List<XXPolicyItemCondition> xConditions = daoMgr.getXXPolicyItemCondition().findByServiceId(serviceId);
List<XXPolicyItemDataMaskInfo> xDataMaskInfos = daoMgr.getXXPolicyItemDataMaskInfo().findByServiceId(serviceId);
List<XXPolicyItemRowFilterInfo> xRowFilterInfos = daoMgr.getXXPolicyItemRowFilterInfo().findByServiceId(serviceId);
- List<XXPolicyLabelMap> xxPolicyLabelMap = daoMgr.getXXPolicyLabelMap().findByServiceId(serviceId);
+ List<XXPolicyLabelMap> xxPolicyLabelMap = daoMgr.getXXPolicyLabelMap().findByServiceId(serviceId);
this.service = xService;
this.iterPolicy = xPolicies.listIterator();
@@ -482,7 +485,7 @@ public class RangerPolicyRetriever {
List<XXPolicyItemCondition> xConditions = daoMgr.getXXPolicyItemCondition().findByPolicyId(policyId);
List<XXPolicyItemDataMaskInfo> xDataMaskInfos = daoMgr.getXXPolicyItemDataMaskInfo().findByPolicyId(policyId);
List<XXPolicyItemRowFilterInfo> xRowFilterInfos = daoMgr.getXXPolicyItemRowFilterInfo().findByPolicyId(policyId);
- List<XXPolicyLabelMap> xPolicyLabelMap = daoMgr.getXXPolicyLabelMap().findByPolicyId(policyId);
+ List<XXPolicyLabelMap> xPolicyLabelMap = daoMgr.getXXPolicyLabelMap().findByPolicyId(policyId);
this.service = xService;
this.iterPolicy = xPolicies.listIterator();
@@ -495,7 +498,7 @@ public class RangerPolicyRetriever {
this.iterConditions = xConditions.listIterator();
this.iterDataMaskInfos = xDataMaskInfos.listIterator();
this.iterRowFilterInfos = xRowFilterInfos.listIterator();
- this.iterPolicyLabels = xPolicyLabelMap.listIterator();
+ this.iterPolicyLabels = xPolicyLabelMap.listIterator();
}
RangerPolicy getNextPolicy() {
@@ -518,11 +521,24 @@ public class RangerPolicyRetriever {
ret.setService(service == null ? null : service.getName());
ret.setName(StringUtils.trim(xPolicy.getName()));
ret.setPolicyType(xPolicy.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : xPolicy.getPolicyType());
+ ret.setPolicyPriority(xPolicy.getPolicyPriority() == null ? RangerPolicy.POLICY_PRIORITY_NORMAL : xPolicy.getPolicyPriority());
ret.setDescription(xPolicy.getDescription());
ret.setResourceSignature(xPolicy.getResourceSignature());
ret.setIsAuditEnabled(xPolicy.getIsAuditEnabled());
- getPolicyLabels(ret);
+ Map<String, String> mapOfOptions = JsonUtils.jsonToMapStringString(xPolicy.getOptions());
+
+ if (MapUtils.isNotEmpty(mapOfOptions)) {
+ String validitySchedulesStr = mapOfOptions.get(RangerPolicyService.OPTION_POLICY_VALIDITY_SCHEDULES);
+
+ if (StringUtils.isNotEmpty(validitySchedulesStr)) {
+ List<RangerValiditySchedule> validitySchedules = JsonUtils.jsonToRangerValiditySchedule(validitySchedulesStr);
+
+ ret.setValiditySchedules(validitySchedules);
+ }
+ }
+
+ getPolicyLabels(ret);
getResource(ret);
getPolicyItems(ret);
}
@@ -531,24 +547,24 @@ public class RangerPolicyRetriever {
return ret;
}
- private void getPolicyLabels(RangerPolicy ret) {
- List<String> xPolicyLabels = new ArrayList<String>();
- while(iterPolicyLabels.hasNext()) {
- XXPolicyLabelMap xPolicyLabel = iterPolicyLabels.next();
- if(xPolicyLabel.getPolicyId().equals(ret.getId())) {
- String policyLabel = lookupCache.getPolicyLabelName(xPolicyLabel.getPolicyLabelId());
- if (policyLabel != null) {
- xPolicyLabels.add(policyLabel);
- }
- ret.setPolicyLabels(xPolicyLabels);
- } else {
- if(iterPolicyLabels.hasPrevious()) {
- iterPolicyLabels.previous();
- }
- break;
- }
- }
- }
+ private void getPolicyLabels(RangerPolicy ret) {
+ List<String> xPolicyLabels = new ArrayList<String>();
+ while (iterPolicyLabels.hasNext()) {
+ XXPolicyLabelMap xPolicyLabel = iterPolicyLabels.next();
+ if (xPolicyLabel.getPolicyId().equals(ret.getId())) {
+ String policyLabel = lookupCache.getPolicyLabelName(xPolicyLabel.getPolicyLabelId());
+ if (policyLabel != null) {
+ xPolicyLabels.add(policyLabel);
+ }
+ ret.setPolicyLabels(xPolicyLabels);
+ } else {
+ if (iterPolicyLabels.hasPrevious()) {
+ iterPolicyLabels.previous();
+ }
+ break;
+ }
+ }
+ }
List<RangerPolicy> getAllPolicies() {
List<RangerPolicy> ret = new ArrayList<RangerPolicy>();
@@ -604,8 +620,8 @@ public class RangerPolicyRetriever {
|| iterAccesses.hasNext()
|| iterConditions.hasNext()
|| iterDataMaskInfos.hasNext()
- || iterRowFilterInfos.hasNext()
- || iterPolicyLabels.hasNext();
+ || iterRowFilterInfos.hasNext()
+ || iterPolicyLabels.hasNext();
return !moreToProcess;
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/biz/RangerTagDBRetriever.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerTagDBRetriever.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerTagDBRetriever.java
index 52c1288..5550572 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerTagDBRetriever.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerTagDBRetriever.java
@@ -26,9 +26,12 @@ import java.util.ListIterator;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
+import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.authorization.utils.StringUtil;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.*;
@@ -36,7 +39,6 @@ import org.apache.ranger.plugin.model.*;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.util.RangerPerfTracer;
-
public class RangerTagDBRetriever {
static final Log LOG = LogFactory.getLog(RangerTagDBRetriever.class);
static final Log PERF_LOG = RangerPerfTracer.getPerfLogger("db.RangerTagDBRetriever");
@@ -537,6 +539,18 @@ public class RangerTagDBRetriever {
ret.setUpdateTime(xTag.getUpdateTime());
ret.setVersion(xTag.getVersion());
+ Map<String, String> mapOfOptions = JsonUtils.jsonToMapStringString(xTag.getOptions());
+
+ if (MapUtils.isNotEmpty(mapOfOptions)) {
+ String validityPeriodsStr = mapOfOptions.get(RangerTag.OPTION_TAG_VALIDITY_PERIODS);
+
+ if (StringUtils.isNotEmpty(validityPeriodsStr)) {
+ List<RangerValiditySchedule> validityPeriods = JsonUtils.jsonToRangerValiditySchedule(validityPeriodsStr);
+
+ ret.setValidityPeriods(validityPeriods);
+ }
+ }
+
Map<Long, RangerTagDef> tagDefs = getTagDefs();
if (tagDefs != null) {
RangerTagDef tagDef = tagDefs.get(xTag.getType());
@@ -560,7 +574,6 @@ public class RangerTagDBRetriever {
String attributeName = xTagAttribute.getName();
String attributeValue = xTagAttribute.getValue();
-
tag.getAttributes().put(attributeName, attributeValue);
} else if (xTagAttribute.getTagId().compareTo(tag.getId()) > 0) {
if (iterTagAttribute.hasPrevious()) {
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
index 1583018..8341a73 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
@@ -20,6 +20,7 @@
package org.apache.ranger.biz;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -49,6 +50,8 @@ import org.apache.ranger.entity.XXTagResourceMap;
import org.apache.ranger.plugin.model.*;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerTagDef.RangerTagAttributeDef;
+import org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
import org.apache.ranger.plugin.store.AbstractTagStore;
import org.apache.ranger.plugin.store.PList;
import org.apache.ranger.plugin.store.RangerServiceResourceSignature;
@@ -298,6 +301,8 @@ public class TagDBStore extends AbstractTagStore {
LOG.debug("==> TagDBStore.createTag(" + tag + ")");
}
+ tag = validateTag(tag);
+
RangerTag ret = rangerTagService.create(tag);
createTagAttributes(ret.getId(), tag.getAttributes());
@@ -317,6 +322,8 @@ public class TagDBStore extends AbstractTagStore {
LOG.debug("==> TagDBStore.updateTag(" + tag + ")");
}
+ tag = validateTag(tag);
+
RangerTag existing = rangerTagService.read(tag.getId());
if (existing == null) {
@@ -1088,7 +1095,7 @@ public class TagDBStore extends AbstractTagStore {
}
}
- private List<XXTagAttribute> createTagAttributes(Long tagId, Map<String, String> attributes) {
+ private List<XXTagAttribute> createTagAttributes(Long tagId, Map<String, String> attributes) throws Exception {
List<XXTagAttribute> ret = new ArrayList<XXTagAttribute>();
if(MapUtils.isNotEmpty(attributes)) {
@@ -1281,4 +1288,36 @@ public class TagDBStore extends AbstractTagStore {
LOG.debug("<== TagDBStore.deleteAllTagObjectsForService(" + serviceName + ")");
}
}
+
+ private RangerTag validateTag(RangerTag tag) throws Exception {
+ List<RangerValiditySchedule> validityPeriods = tag.getValidityPeriods();
+
+ if (CollectionUtils.isNotEmpty(validityPeriods)) {
+ List<RangerValiditySchedule> normalizedValidityPeriods = new ArrayList<>();
+ List<ValidationFailureDetails> failures = new ArrayList<>();
+
+ for (RangerValiditySchedule validityPeriod : validityPeriods) {
+ RangerValidityScheduleValidator validator = new RangerValidityScheduleValidator(validityPeriod);
+ RangerValiditySchedule normalizedValidityPeriod = validator.validate(failures);
+
+ if (normalizedValidityPeriod != null && CollectionUtils.isEmpty(failures)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Normalized ValidityPeriod:[" + normalizedValidityPeriod + "]");
+ }
+
+ normalizedValidityPeriods.add(normalizedValidityPeriod);
+ } else {
+ String error = "Incorrect time-specification:[" + Arrays.asList(failures) + "]";
+
+ LOG.error(error);
+
+ throw new Exception(error);
+ }
+ }
+
+ tag.setValidityPeriods(normalizedValidityPeriods);
+ }
+
+ return tag;
+ }
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java
index a2250ec..c6686ff 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java
@@ -64,8 +64,8 @@ public class RangerSearchUtil extends SearchUtil {
ret.setParam(SearchFilter.POL_RESOURCE, request.getParameter(SearchFilter.POL_RESOURCE));
ret.setParam(SearchFilter.RESOURCE_SIGNATURE, request.getParameter(SearchFilter.RESOURCE_SIGNATURE));
ret.setParam(SearchFilter.POLICY_TYPE, request.getParameter(SearchFilter.POLICY_TYPE));
- ret.setParam(SearchFilter.POLICY_LABEL, request.getParameter(SearchFilter.POLICY_LABEL));
- ret.setParam(SearchFilter.POLICY_LABELS_PARTIAL, request.getParameter(SearchFilter.POLICY_LABELS_PARTIAL));
+ ret.setParam(SearchFilter.POLICY_LABEL, request.getParameter(SearchFilter.POLICY_LABEL));
+ ret.setParam(SearchFilter.POLICY_LABELS_PARTIAL, request.getParameter(SearchFilter.POLICY_LABELS_PARTIAL));
ret.setParam(SearchFilter.PLUGIN_HOST_NAME, request.getParameter(SearchFilter.PLUGIN_HOST_NAME));
ret.setParam(SearchFilter.PLUGIN_APP_TYPE, request.getParameter(SearchFilter.PLUGIN_APP_TYPE));
ret.setParam(SearchFilter.PLUGIN_ENTITY_TYPE, request.getParameter(SearchFilter.PLUGIN_ENTITY_TYPE));
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/entity/XXPolicyBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXPolicyBase.java b/security-admin/src/main/java/org/apache/ranger/entity/XXPolicyBase.java
index 69d28bb..2616594 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXPolicyBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXPolicyBase.java
@@ -75,6 +75,14 @@ public abstract class XXPolicyBase extends XXDBBase {
protected Integer policyType;
/**
+ * policyPriority of the XXPolicy
+ * <ul>
+ * </ul>
+ *
+ */
+ @Column(name = "policy_priority")
+ protected Integer policyPriority;
+ /**
* description of the XXPolicy
* <ul>
* </ul>
@@ -110,6 +118,14 @@ public abstract class XXPolicyBase extends XXDBBase {
@Column(name = "is_audit_enabled")
protected boolean isAuditEnabled;
+ /**
+ * options of the XXPolicy
+ * <ul>
+ * </ul>
+ *
+ */
+ @Column(name = "options")
+ protected String options;
/**
* @return the gUID
*/
@@ -233,7 +249,7 @@ public abstract class XXPolicyBase extends XXDBBase {
/**
* Returns the value for the member attribute <b>isEnabled</b>
*
- * @return Date - value of member attribute <b>isEnabled</b> .
+ * @return Value of member attribute <b>isEnabled</b> .
*/
public boolean getIsEnabled() {
return this.isEnabled;
@@ -253,7 +269,7 @@ public abstract class XXPolicyBase extends XXDBBase {
/**
* Returns the value for the member attribute <b>isAuditEnabled</b>
*
- * @return Date - value of member attribute <b>isAuditEnabled</b> .
+ * @return Value of member attribute <b>isAuditEnabled</b> .
*/
public boolean getIsAuditEnabled() {
return this.isAuditEnabled;
@@ -267,6 +283,33 @@ public abstract class XXPolicyBase extends XXDBBase {
this.policyType = policyType;
}
+ public Integer getPolicyPriority() {
+ return policyPriority;
+ }
+
+ public void setPolicyPriority(Integer policyPriority) {
+ this.policyPriority = policyPriority;
+ }
+
+ /**
+ * This method sets the value to the member attribute <b> options</b> .
+ *
+ * @param options
+ * Value to set member attribute <b> options</b>
+ */
+ public void setOptions(String options) {
+ this.options = options;
+ }
+
+ /**
+ * Returns the value for the member attribute <b>options</b>
+ *
+ * @return Value of member attribute <b>options</b> .
+ */
+ public String getOptions() {
+ return this.options;
+ }
+
/*
* (non-Javadoc)
*
@@ -342,6 +385,21 @@ public abstract class XXPolicyBase extends XXDBBase {
} else if (!policyType.equals(other.policyType)) {
return false;
}
+ if (policyPriority == null) {
+ if (other.policyPriority != null) {
+ return false;
+ }
+ } else if (!policyPriority.equals(other.policyPriority)) {
+ return false;
+ }
+ if (options == null) {
+ if (other.options != null) {
+ return false;
+ }
+ } else if (!options.equals(other.options)) {
+ return false;
+ }
+
return true;
}
@@ -355,8 +413,9 @@ public abstract class XXPolicyBase extends XXDBBase {
String str = "XXPolicyBase={";
str += super.toString();
str += " [guid=" + guid + ", version=" + version + ", service=" + service + ", name=" + name
- + ", policyType=" + policyType + ", description=" + description + ", resourceSignature="
- + resourceSignature + ", isEnabled=" + isEnabled + ", isAuditEnabled=" + isAuditEnabled + "]";
+ + ", policyType=" + policyType + ", policyPriority=" + policyPriority + ", description=" + description + ", resourceSignature="
+ + resourceSignature + ", isEnabled=" + isEnabled + ", isAuditEnabled=" + isAuditEnabled
+ + ", options=" + options + "]";
str += "}";
return str;
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/entity/XXTag.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXTag.java b/security-admin/src/main/java/org/apache/ranger/entity/XXTag.java
index 9155385..44d43ef 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXTag.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXTag.java
@@ -60,6 +60,9 @@ public class XXTag extends XXDBBase implements Serializable {
@Column(name = "owned_by")
protected Short owner;
+ @Column(name = "options")
+ protected String options;
+
@Override
public void setId(Long id) {
this.id = id;
@@ -118,7 +121,15 @@ public class XXTag extends XXDBBase implements Serializable {
public Short getOwner() { return owner; }
public void setOwner(Short owner) { this.owner = owner; }
- @Override
+ public void setOptions(String options) {
+ this.options = options;
+ }
+
+ public String getOptions() {
+ return this.options;
+ }
+
+ @Override
public int getMyClassType() {
return AppConstants.CLASS_TYPE_XA_TAG;
}
@@ -137,6 +148,7 @@ public class XXTag extends XXDBBase implements Serializable {
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
+ result = prime * result + ((options == null) ? 0 : options.hashCode());
return result;
}
@@ -179,6 +191,11 @@ public class XXTag extends XXDBBase implements Serializable {
return false;
} else if (!owner.equals(other.owner))
return false;
+ if (options == null) {
+ if (other.options != null)
+ return false;
+ } else if (!options.equals(other.options))
+ return false;
return true;
}
@@ -201,6 +218,7 @@ public class XXTag extends XXDBBase implements Serializable {
sb.append("guid={").append(guid).append("} ");
sb.append("type={").append(type).append("} ");
sb.append("owned_by={").append(owner).append("} ");
+ sb.append("options={").append(options).append("} ");
sb.append(" }");
return sb;
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java
index def5033..8d42165 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerPolicyServiceBase.java
@@ -17,7 +17,9 @@
package org.apache.ranger.service;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.common.GUIDUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.SearchField;
@@ -28,15 +30,22 @@ import org.apache.ranger.common.SortField.SORT_ORDER;
import org.apache.ranger.entity.XXPolicyBase;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.util.SearchFilter;
import org.springframework.beans.factory.annotation.Autowired;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public abstract class RangerPolicyServiceBase<T extends XXPolicyBase, V extends RangerPolicy> extends
RangerBaseModelService<T, V> {
- @Autowired
+ public static final String OPTION_POLICY_VALIDITY_SCHEDULES = "POLICY_VALIDITY_SCHEDULES";
+
+ @Autowired
GUIDUtil guidUtil;
-
+
public RangerPolicyServiceBase() {
super();
searchFields.add(new SearchField(SearchFilter.SERVICE_TYPE, "xSvcDef.name", DATA_TYPE.STRING, SEARCH_TYPE.FULL,
@@ -90,12 +99,28 @@ public abstract class RangerPolicyServiceBase<T extends XXPolicyBase, V extends
xObj.setService(xService.getId());
xObj.setName(StringUtils.trim(vObj.getName()));
xObj.setPolicyType(vObj.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : vObj.getPolicyType());
+ xObj.setPolicyPriority(vObj.getPolicyPriority() == null ? RangerPolicy.POLICY_PRIORITY_NORMAL : vObj.getPolicyPriority());
xObj.setDescription(vObj.getDescription());
xObj.setResourceSignature(vObj.getResourceSignature());
xObj.setIsAuditEnabled(vObj.getIsAuditEnabled());
xObj.setIsEnabled(vObj.getIsEnabled());
- return xObj;
+ String validitySchedules = JsonUtils.listToJson(vObj.getValiditySchedules());
+ Map<String, Object> options = vObj.getOptions();
+
+ if (options == null) {
+ options = new HashMap<>();
+ }
+
+ if (StringUtils.isNotBlank(validitySchedules)) {
+ options.put(OPTION_POLICY_VALIDITY_SCHEDULES, validitySchedules);
+ } else {
+ options.remove(OPTION_POLICY_VALIDITY_SCHEDULES);
+ }
+
+ xObj.setOptions(JsonUtils.mapToJson(options));
+
+ return xObj;
}
@Override
@@ -106,10 +131,26 @@ public abstract class RangerPolicyServiceBase<T extends XXPolicyBase, V extends
vObj.setService(xService.getName());
vObj.setName(StringUtils.trim(xObj.getName()));
vObj.setPolicyType(xObj.getPolicyType() == null ? RangerPolicy.POLICY_TYPE_ACCESS : xObj.getPolicyType());
+ vObj.setPolicyPriority(xObj.getPolicyPriority() == null ? RangerPolicy.POLICY_PRIORITY_NORMAL : xObj.getPolicyPriority());
vObj.setDescription(xObj.getDescription());
vObj.setResourceSignature(xObj.getResourceSignature());
vObj.setIsEnabled(xObj.getIsEnabled());
vObj.setIsAuditEnabled(xObj.getIsAuditEnabled());
+
+ Map<String, Object> options = JsonUtils.jsonToObject(xObj.getOptions(), Map.class);
+
+ if (MapUtils.isNotEmpty(options)) {
+ String optionPolicyValiditySchedule = (String)options.remove(OPTION_POLICY_VALIDITY_SCHEDULES);
+
+ if (StringUtils.isNotBlank(optionPolicyValiditySchedule)) {
+ List<RangerValiditySchedule> validitySchedules = JsonUtils.jsonToRangerValiditySchedule(optionPolicyValiditySchedule);
+
+ vObj.setValiditySchedules(validitySchedules);
+ }
+ }
+
+ vObj.setOptions(options);
+
return vObj;
}
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/security-admin/src/main/java/org/apache/ranger/service/RangerTagServiceBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagServiceBase.java
index e68aa92..2e2c04f 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagServiceBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagServiceBase.java
@@ -25,7 +25,9 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.common.GUIDUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RangerConfigUtil;
@@ -33,6 +35,7 @@ import org.apache.ranger.entity.XXTagAttribute;
import org.apache.ranger.entity.XXTag;
import org.apache.ranger.entity.XXTagDef;
import org.apache.ranger.plugin.model.RangerTag;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.store.PList;
import org.apache.ranger.plugin.util.SearchFilter;
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,6 +66,21 @@ public abstract class RangerTagServiceBase<T extends XXTag, V extends RangerTag>
xObj.setGuid(guid);
xObj.setType(xTagDef.getId());
xObj.setOwner(vObj.getOwner());
+
+ String validityPeriods = JsonUtils.listToJson(vObj.getValidityPeriods());
+ Map<String, Object> options = vObj.getOptions();
+
+ if (options == null) {
+ options = new HashMap<>();
+ }
+
+ if (StringUtils.isNotBlank(validityPeriods)) {
+ options.put(RangerTag.OPTION_TAG_VALIDITY_PERIODS, validityPeriods);
+ } else {
+ options.remove(RangerTag.OPTION_TAG_VALIDITY_PERIODS);
+ }
+
+ xObj.setOptions(JsonUtils.mapToJson(options));
return xObj;
}
@@ -79,6 +97,20 @@ public abstract class RangerTagServiceBase<T extends XXTag, V extends RangerTag>
vObj.setType(xTagDef.getName());
vObj.setOwner(xObj.getOwner());
+ Map<String, Object> options = JsonUtils.jsonToObject(xObj.getOptions(), Map.class);
+
+ if (MapUtils.isNotEmpty(options)) {
+ String optionTagValidityPeriod = (String)options.remove(RangerTag.OPTION_TAG_VALIDITY_PERIODS);
+
+ if (StringUtils.isNotBlank(optionTagValidityPeriod)) {
+ List<RangerValiditySchedule> validityPeriods = JsonUtils.jsonToRangerValiditySchedule(optionTagValidityPeriod);
+
+ vObj.setValidityPeriods(validityPeriods);
+ }
+ }
+
+ vObj.setOptions(options);
+
Map<String, String> attributes = getAttributesForTag(xObj);
vObj.setAttributes(attributes);
http://git-wip-us.apache.org/repos/asf/ranger/blob/844315cd/src/main/assembly/tagsync.xml
----------------------------------------------------------------------
diff --git a/src/main/assembly/tagsync.xml b/src/main/assembly/tagsync.xml
index c929395..0788ac1 100644
--- a/src/main/assembly/tagsync.xml
+++ b/src/main/assembly/tagsync.xml
@@ -60,6 +60,7 @@
<include>com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:${atlas.jackson.version}</include>
<include>com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:${atlas.jackson.version}</include>
<include>org.codehaus.jackson:jackson-core-asl:jar:${codehaus.jackson.version}</include>
+ <include>org.codehaus.jackson:jackson-mapper-asl:jar:${codehaus.jackson.version}</include>
<include>org.codehaus.jackson:jackson-jaxrs:jar:${codehaus.jackson.version}</include>
<include>org.codehaus.jettison:jettison:jar:${jettison.version}</include>
<include>org.scala-lang:scala-library:jar:${scala.version}</include>