Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,24 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.util.ConcurrentReferenceHashMap;

@Component
@Profile({ "simple-cache" })
public class InMemoryPolicyEvaluationCache extends AbstractPolicyEvaluationCache {

private final Map<String, String> evalCache = Collections.synchronizedMap(new HashMap<String, String>());
private final Map<String, Set<String>> resourceTranslations = Collections
.synchronizedMap(new HashMap<String, Set<String>>());
// For security reasons we can't evict time stamps used to invalidate cached evaluation results.
private final Map<String, String> timestampCache = Collections.synchronizedMap(new HashMap<String, String>());
private final Map<String, String> evalCache = new ConcurrentReferenceHashMap<String, String>();

@Override
void delete(final String key) {
this.evalCache.remove(key);
this.timestampCache.remove(key);
}

@Override
Expand All @@ -55,16 +48,6 @@ void delete(final Collection<String> keys) {
@Override
void flushAll() {
this.evalCache.clear();
this.timestampCache.clear();
}

@Override
Set<String> getResourceTranslations(final String fromKey) {
Set<String> results = this.resourceTranslations.get(fromKey);
if (null == results) {
return Collections.emptySet();
}
return results;
}

@Override
Expand All @@ -76,28 +59,11 @@ Set<String> keys(final String key) {
List<String> multiGet(final List<String> keys) {
List<String> results = new ArrayList<>();
for (String key : keys) {
String value = this.timestampCache.get(key);
if (null == value) {
value = this.evalCache.get(key);
}
results.add(value);
results.add(this.evalCache.get(key));
}
return results;
}

@Override
List<Object> multiGetResourceTranslations(final List<String> fromKeys) {
List<Object> result = new ArrayList<>();
for (String fromKey : fromKeys) {
Set<String> toKeys = this.resourceTranslations.get(fromKey);
if (null == toKeys) {
toKeys = Collections.emptySet();
}
result.add(toKeys);
}
return result;
}

@Override
void multiSet(final Map<String, String> map) {
for (Entry<String, String> entry : map.entrySet()) {
Expand All @@ -107,34 +73,18 @@ void multiSet(final Map<String, String> map) {

@Override
void set(final String key, final String value) {
if (isPolicySetChangedKey(key) || isResourceChangedKey(key) || isSubjectChangedKey(key)) {
this.timestampCache.put(key, value);
} else if (isPolicyEvalResultKey(key)) {
if (isPolicySetChangedKey(key) || isResourceChangedKey(key) || isSubjectChangedKey(key)
|| isPolicyEvalResultKey(key)) {
this.evalCache.put(key, value);
} else {
throw new IllegalArgumentException("Unsupported key format.");
}
}

@Override
void setResourceTranslation(final String fromKey, final String toKey) {
Set<String> toKeys = this.resourceTranslations.get(fromKey);
if (null == toKeys) {
toKeys = new HashSet<>();
}
toKeys.add(toKey);
this.resourceTranslations.put(fromKey, toKeys);
}

@Override
void setResourceTranslations(final Set<String> fromKeys, final String toKey) {
for (String fromKey : fromKeys) {
Set<String> toKeysLocal = this.resourceTranslations.get(fromKey);
if (null == toKeysLocal) {
toKeysLocal = new HashSet<>();
}
toKeysLocal.add(toKey);
this.resourceTranslations.put(fromKey, toKeysLocal);
void setIfNotExists(final String key, final String value) {
if (!this.evalCache.containsKey(key)) {
this.evalCache.put(key, value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,6 @@ public void set(final PolicyEvaluationRequestCacheKey key, final PolicyEvaluatio
// Purposely empty since it's required by the PolicyEvaluationCache interface but unused here
}

@Override
public void setResourceTranslation(final String zoneId, final String fromResourceId, final String toResourceId) {
// Purposely empty since it's required by the PolicyEvaluationCache interface but unused here
}

@Override
public void setResourceTranslations(final String zoneId, final Set<String> fromResourceIds,
final String toResourceId) {
// Purposely empty since it's required by the PolicyEvaluationCache interface but unused here
}

@Override
public void reset() {
// Purposely empty since it's required by the PolicyEvaluationCache interface but unused here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ public interface PolicyEvaluationCache {

void set(PolicyEvaluationRequestCacheKey key, PolicyEvaluationResult value);

void setResourceTranslation(String zoneId, String fromResourceId, String toResourceId);

void setResourceTranslations(String zoneId, Set<String> fromResourceIds, String toResourceId);

void reset();

void reset(PolicyEvaluationRequestCacheKey key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public PolicyEvaluationRequestCacheKey(final LinkedHashSet<String> policySetIds,
this.zoneId = zoneId;
}

public String toRedisKey() {
public String toDecisionKey() {
StringBuilder keyBuilder = new StringBuilder();
if (null == this.zoneId) {
keyBuilder.append("*:");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

@Component
Expand Down Expand Up @@ -74,11 +69,6 @@ void flushAll() {
this.redisTemplate.getConnectionFactory().getConnection().flushAll();
}

@Override
Set<String> getResourceTranslations(final String fromKey) {
return this.redisTemplate.opsForSet().members(fromKey);
}

@Override
Set<String> keys(final String key) {
return this.redisTemplate.keys(key);
Expand All @@ -89,22 +79,6 @@ List<String> multiGet(final List<String> keys) {
return this.redisTemplate.opsForValue().multiGet(keys);
}

@Override
List<Object> multiGetResourceTranslations(final List<String> fromKeys) {
// Pipelining makes sure we don't pay excessive RTT penalties.
return this.redisTemplate.executePipelined(new RedisCallback<List<Object>>() {
@Override
public List<Object> doInRedis(final RedisConnection connection) {
StringRedisConnection stringRedisConn = new DefaultStringRedisConnection(connection);
for (String fromKey : fromKeys) {
stringRedisConn.sMembers(fromKey);
}
return null;
}
}, new StringRedisSerializer());
}

@Override
void multiSet(final Map<String, String> map) {
this.redisTemplate.opsForValue().multiSet(map);
}
Expand All @@ -122,22 +96,7 @@ public void setCachedEvalTimeToLiveSeconds(final long cachedEvalTimeToLiveSecond
this.cachedEvalTimeToLiveSeconds = cachedEvalTimeToLiveSeconds;
}

@Override
void setResourceTranslation(final String fromKey, final String toKey) {
this.redisTemplate.opsForSet().add(fromKey, toKey);
}

@Override
void setResourceTranslations(final Set<String> fromKeys, final String toKey) {
this.redisTemplate.execute(new RedisCallback<List<Object>>() {
@Override
public List<Object> doInRedis(final RedisConnection connection) {
StringRedisConnection stringRedisConn = new DefaultStringRedisConnection(connection);
for (String fromKey : fromKeys) {
stringRedisConn.sAdd(fromKey, toKey);
}
return null;
}
});
void setIfNotExists(final String key, final String value) {
this.redisTemplate.boundValueOps(key).setIfAbsent(value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we set an expiration timeout on the key similar to what's done in line #89? The same comment applies to set function above. Timeout is only set on the key for eval result and not for any other.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeout should not be set for anything other then Policy Evaluation. This is because we would then be unnecessarily reevaluating requests when entities have no changed.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,21 @@ public PolicyEvaluationResult evalPolicy(final PolicyEvaluationRequestV1 request
// Fixing policy evaluation order so we could build a cache key.
PolicyEvaluationRequestCacheKey key;
if (policySetsEvaluationOrder.isEmpty()) {
key = new Builder().zoneId(zone.getName()).policySetIds(
Stream.of(filteredPolicySets.iterator().next().getName())
.collect(Collectors.toCollection(LinkedHashSet::new))).request(request).build();
key = new Builder().zoneId(zone.getName())
.policySetIds(Stream.of(filteredPolicySets.iterator().next().getName())
.collect(Collectors.toCollection(LinkedHashSet::new)))
.request(request).build();
} else {
key = new Builder().zoneId(zone.getName()).request(request).build();
}

PolicyEvaluationResult result = this.cache.get(key);
PolicyEvaluationResult result = null;
try {
result = this.cache.get(key);
} catch (Exception e) {
LOGGER.error(String.format("Unable to get cache key '%s'", key), e);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a unit test that policy evaluation returns expected result if cache get or set fails

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

if (null == result) {
result = new PolicyEvaluationResult(Effect.NOT_APPLICABLE);

Expand All @@ -141,7 +148,12 @@ public PolicyEvaluationResult evalPolicy(final PolicyEvaluationRequestV1 request

LOGGER.info("Processed Policy Evaluation for: " + "resourceUri='{}', subjectIdentifier='{}', action='{}',"
+ " result='{}'", uri, subjectIdentifier, action, result.getEffect());
this.cache.set(key, result);
try {
this.cache.set(key, result);
} catch (Exception e) {
LOGGER.error(String.format("Unable to set cache key '%s' to value '%s' due to exception", key, result),
e);
}
}
return result;
}
Expand All @@ -152,7 +164,8 @@ LinkedHashSet<PolicySet> filterPolicySetsByPriority(final String subjectIdentifi

if (policySetsEvaluationOrder.isEmpty()) {
if (allPolicySets.size() > 1) {
LOGGER.error("Found more than one policy set during policy evaluation and "
LOGGER.error(
"Found more than one policy set during policy evaluation and "
+ "no evaluation order is provided. subjectIdentifier='{}', resourceURI='{}'",
subjectIdentifier, uri);
throw new IllegalArgumentException("More than one policy set exists for this zone. "
Expand Down Expand Up @@ -192,9 +205,6 @@ private PolicyEvaluationResult evalPolicySet(final PolicySet policySet, final St

Effect effect = Effect.NOT_APPLICABLE;
Set<String> resolvedResourceUris = matchResult.getResolvedResourceUris();
if (null == resolvedResourceUris) {
resolvedResourceUris = new HashSet<>();
}
resolvedResourceUris.add(resourceURI);

Set<Attribute> resourceAttributes = Collections.emptySet();
Expand Down Expand Up @@ -264,8 +274,8 @@ boolean evaluateConditions(final Set<Attribute> subjectAttributes, final Set<Att

debugAttributes(subjectAttributes, resourceAttributes);

Map<String, Object> attributeBindingsMap = this
.getAttributeBindingsMap(subjectAttributes, resourceAttributes, resourceURI, resourceURITemplate);
Map<String, Object> attributeBindingsMap = this.getAttributeBindingsMap(subjectAttributes, resourceAttributes,
resourceURI, resourceURITemplate);

boolean result = true;
for (int i = 0; i < validatedConditionScripts.size(); i++) {
Expand Down
Loading