aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Santos <eric.santos@yoppworks.com>2021-03-22 13:29:48 -0400
committerEric Santos <eric.santos@yoppworks.com>2021-04-19 12:02:22 -0400
commit7b0b01a41e7eacd40ba296dda474b7fcbc54a1cd (patch)
tree949ed8e408205500c767c5034e4c63bdea0f5dcf
parent3e1571574eff898b9dcce3ce9a605f83dc4aa57a (diff)
Add multitenancy filter with data-owner
Issue-ID: AAI-3299 Signed-off-by: Santos, Eric <eric.santos@yoppworks.com> Change-Id: Ia22001af5a1701bf70d8be6dbf8d09273ebd5575
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java8
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java8
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java49
3 files changed, 56 insertions, 9 deletions
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
index b9295a9..41a3a3c 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
@@ -104,6 +104,8 @@ public class DslConsumer extends TraversalConsumer {
@Context UriInfo info,
@DefaultValue("-1") @QueryParam("resultIndex") String resultIndex,
@DefaultValue("-1") @QueryParam("resultSize") String resultSize) {
+ Set<String> roles = this.getRoles(req.getUserPrincipal());
+
return runner(TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_ENABLED,
TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_APP,
TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_LIMIT,
@@ -114,7 +116,7 @@ public class DslConsumer extends TraversalConsumer {
@Override
public Response process() throws Exception {
return (processExecuteQuery(content, req, versionParam, queryFormat, subgraph, validate, headers, info,
- resultIndex, resultSize));
+ resultIndex, resultSize, roles));
}
}
);
@@ -122,7 +124,7 @@ public class DslConsumer extends TraversalConsumer {
public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, String queryFormat, String subgraph,
String validate, HttpHeaders headers, UriInfo info, String resultIndex,
- String resultSize) {
+ String resultSize, Set<String> roles) {
String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride");
@@ -172,7 +174,7 @@ public class DslConsumer extends TraversalConsumer {
validateHistoryParams(format, info.getQueryParameters());
}
- GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info);
+ GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info, roles);
GenericQueryProcessor processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton)
.queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion).processWith(processorType)
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
index 5297de5..affee3a 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
@@ -101,6 +101,8 @@ public class QueryConsumer extends TraversalConsumer {
@Context UriInfo info,
@DefaultValue("-1") @QueryParam("resultIndex") String resultIndex,
@DefaultValue("-1") @QueryParam("resultSize") String resultSize) {
+ Set<String> roles = this.getRoles(req.getUserPrincipal());
+
return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED,
TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP,
TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT,
@@ -110,14 +112,14 @@ public class QueryConsumer extends TraversalConsumer {
new AaiCallable<Response>() {
@Override
public Response process() {
- return processExecuteQuery(content, req, versionParam, queryFormat, subgraph, headers, info, resultIndex, resultSize);
+ return processExecuteQuery(content, req, versionParam, queryFormat, subgraph, headers, info, resultIndex, resultSize, roles);
}
});
}
public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, String queryFormat, String subgraph,
HttpHeaders headers, UriInfo info, String resultIndex,
- String resultSize) {
+ String resultSize, Set<String> roles) {
String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor");
@@ -193,7 +195,7 @@ public class QueryConsumer extends TraversalConsumer {
if(isHistory(format)){
validateHistoryParams(format, info.getQueryParameters());
}
- GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info);
+ GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info, roles);
QueryStyle queryStyle = getQueryStyle(format, traversalUriHttpEntry);
if (!startURIs.isEmpty()) {
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java
index 059d2c8..a8f88ec 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java
@@ -19,13 +19,18 @@
*/
package org.onap.aai.rest;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
+import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.onap.aai.config.SpringContextAware;
import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.introspection.sideeffect.OwnerCheck;
import org.onap.aai.rest.db.HttpEntry;
import org.onap.aai.restcore.RESTAPI;
import org.onap.aai.serialization.engines.QueryStyle;
@@ -34,12 +39,17 @@ import org.onap.aai.serialization.queryformats.Format;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
public abstract class TraversalConsumer extends RESTAPI {
private static final String HISTORICAL_FORMAT = "state,lifecycle";
private final boolean historyEnabled;
+ private final boolean multiTenancyEnabled;
private final int historyTruncateWindow;
private final long currentTime = System.currentTimeMillis();
private Long startTime = null;
@@ -51,6 +61,8 @@ public abstract class TraversalConsumer extends RESTAPI {
SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.truncate.window.days", "365"));
this.historyEnabled = Boolean.parseBoolean(
SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.enabled", "false"));
+ this.multiTenancyEnabled = Boolean.parseBoolean(
+ SpringContextAware.getApplicationContext().getEnvironment().getProperty("multi.tenancy.enabled", "false"));
}
public boolean isHistory(Format queryFormat) {
@@ -137,15 +149,46 @@ public abstract class TraversalConsumer extends RESTAPI {
).create();
}
+ private SubgraphStrategy getDataOwnerSubgraphStrategy(Set<String> roles) {
+ return SubgraphStrategy.build()
+ .vertices(
+ __.or(__.has("data-owner", P.within(roles)), __.hasNot("data-owner"))
+ ).create();
+ }
+ protected GraphTraversalSource getTraversalSource(TransactionalGraphEngine dbEngine, Format format, UriInfo info, Set<String> roles) throws AAIException {
+ GraphTraversalSource traversalSource;
- protected GraphTraversalSource getTraversalSource(TransactionalGraphEngine dbEngine, Format format, UriInfo info) throws AAIException {
if (isHistory(format)) {
long localStartTime = this.getStartTime(format, info.getQueryParameters());
long localEndTime = this.getEndTime(info.getQueryParameters());
- return dbEngine.asAdmin().getTraversalSource().withStrategies(getSubgraphStrategy(localStartTime, localEndTime, format));
+ traversalSource = dbEngine.asAdmin().getTraversalSource().withStrategies(getSubgraphStrategy(localStartTime, localEndTime, format));
+ } else {
+ traversalSource = dbEngine.asAdmin().getTraversalSource();
+
+ if (multiTenancyEnabled) {
+ return traversalSource.withStrategies(this.getDataOwnerSubgraphStrategy(roles));
+ }
}
- return dbEngine.asAdmin().getTraversalSource();
+
+ return traversalSource;
+ }
+
+ protected Set<String> getRoles(Principal userPrincipal) {
+ KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) userPrincipal;
+ if (ObjectUtils.isEmpty(token)) {
+ return Collections.EMPTY_SET;
+ }
+
+ SimpleKeycloakAccount account = (SimpleKeycloakAccount) token.getDetails();
+ if (ObjectUtils.isEmpty(account)) {
+ return Collections.EMPTY_SET;
+ }
+
+ return account.getRoles()
+ .stream()
+ .map(role -> StringUtils.removeEnd(role, OwnerCheck.READ_ONLY_SUFFIX))
+ .collect(Collectors.toSet());
}
protected void validateHistoryParams(Format format, MultivaluedMap<String, String> params) throws AAIException {