diff options
author | Rodrigo Lima <rodrigo.lima@yoppworks.com> | 2020-09-09 14:54:15 -0400 |
---|---|---|
committer | Rodrigo Lima <rodrigo.lima@yoppworks.com> | 2020-09-10 15:08:25 -0400 |
commit | c35c896ba3cf8ea670c9a3a87e77be0b3dedb2b3 (patch) | |
tree | ed7c20c179fe6b82ddb3f0064bef68624192292b /aai-core/src | |
parent | 87925eec3e39fc79540e034622705ff9ee663343 (diff) |
Add side effect to check pnf owning entity
- Create side effect to check : user's groups contains pnf's owning entity name
- Create unit tests for side effect
- Add new process method in HttpEntry to pass set of groups
- Pass set of groups to db serializer
Issue-ID: AAI-3176
Signed-off-by: Rodrigo Lima <rodrigo.lima@yoppworks.com>
Change-Id: I4bc7ab6e22bce8cbe60bd7ef6bb5db73dac3a1c4
Diffstat (limited to 'aai-core/src')
6 files changed, 416 insertions, 4 deletions
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/OwnerCheck.java b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/OwnerCheck.java new file mode 100644 index 00000000..a32c4ecc --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/introspection/sideeffect/OwnerCheck.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.introspection.sideeffect; + +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; + +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.edges.exceptions.AmbiguousRuleChoiceException; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.schema.enums.PropertyMetadata; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; + +public class OwnerCheck extends SideEffect { + + public OwnerCheck(Introspector obj, Vertex self, TransactionalGraphEngine dbEngine, DBSerializer serializer) { + super(obj, self, dbEngine, serializer); + } + + @Override + protected void processURI(Optional<String> completeUri, Entry<String, String> entry) + throws AAIException { + if (serializer.getGroups() != null && !serializer.getGroups().isEmpty()) { + List<Vertex> owningEntity = self.graph().traversal() + .V(self) + .inE("org.onap.relationships.inventory.BelongsTo") + .outV() + .has("aai-node-type", "owning-entity") + .toList(); + + if(!owningEntity.isEmpty()) { + VertexProperty owningEntityName = owningEntity.get(0).property("owning-entity-name"); + + if(!serializer.getGroups().contains(owningEntityName.orElseGet(null))) { + throw new AAIException("AAI_3304", + "Group(s) :" + serializer.getGroups() + " not authorized to perform function"); + } + } + } //else skip processing because no required properties were specified + + } + + @Override + protected PropertyMetadata getPropertyMetadata() { + return PropertyMetadata.OWNER_CHECK; + } + + @Override + protected boolean replaceWithWildcard() { + return false; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java index 2899a812..aa4fb8c8 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java +++ b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java @@ -243,6 +243,13 @@ public class HttpEntry { return dbEngine; } + public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, + String sourceOfTruth, + Set<String> groups) + throws AAIException { + return this.process(requests, sourceOfTruth, groups, true); + } + public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth) throws AAIException { return this.process(requests, sourceOfTruth, true); @@ -339,14 +346,21 @@ public class HttpEntry { * @throws AAIException the AAI exception */ public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth, - boolean enableResourceVersion) throws AAIException { + boolean enableResourceVersion) throws AAIException { + return this.process(requests, sourceOfTruth, Collections.EMPTY_SET, enableResourceVersion); + } + + private Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, + String sourceOfTruth, + Set<String> groups, + boolean enableResourceVersion) throws AAIException { DBSerializer serializer = null; if(serverBase != null){ - serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth, notificationDepth, serverBase); + serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth, groups, notificationDepth, serverBase); } else { - serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth, notificationDepth); + serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth, groups, notificationDepth); } Response response; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java index 7cd0e785..5b274ee2 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java @@ -96,6 +96,7 @@ public class DBSerializer { private final TransactionalGraphEngine engine; private final String sourceOfTruth; + private final Set<String> groups; private final ModelType introspectionType; private final SchemaVersion version; private final Loader latestLoader; @@ -128,6 +129,7 @@ public class DBSerializer { String sourceOfTruth) throws AAIException { this.engine = engine; this.sourceOfTruth = sourceOfTruth; + this.groups = Collections.EMPTY_SET; this.introspectionType = introspectionType; this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); @@ -144,6 +146,27 @@ public class DBSerializer { initBeans(); } + public DBSerializer(SchemaVersion version, TransactionalGraphEngine engine, ModelType introspectionType, + String sourceOfTruth, Set<String> groups) throws AAIException { + this.engine = engine; + this.sourceOfTruth = sourceOfTruth; + this.groups = groups; + this.introspectionType = introspectionType; + this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); + this.latestLoader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, latestVersion); + this.version = version; + this.loader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); + this.namedPropNodes = this.latestLoader.getNamedPropNodes(); + this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE); + this.currentTimeMillis = System.currentTimeMillis(); + // If creating the DBSerializer the old way then set the notification depth to maximum + this.notificationDepth = AAIProperties.MAXIMUM_DEPTH; + initBeans(); + } + public DBSerializer(SchemaVersion version, TransactionalGraphEngine engine, ModelType introspectionType, @@ -151,6 +174,31 @@ public class DBSerializer { int notificationDepth) throws AAIException { this.engine = engine; this.sourceOfTruth = sourceOfTruth; + this.groups = Collections.EMPTY_SET; + this.introspectionType = introspectionType; + this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); + this.latestLoader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, latestVersion); + this.version = version; + this.loader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); + this.namedPropNodes = this.latestLoader.getNamedPropNodes(); + this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE); + this.currentTimeMillis = System.currentTimeMillis(); + this.notificationDepth = notificationDepth; + initBeans(); + } + + public DBSerializer(SchemaVersion version, + TransactionalGraphEngine engine, + ModelType introspectionType, + String sourceOfTruth, + Set<String> groups, + int notificationDepth) throws AAIException { + this.engine = engine; + this.sourceOfTruth = sourceOfTruth; + this.groups = groups; this.introspectionType = introspectionType; this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); @@ -174,6 +222,32 @@ public class DBSerializer { String serverBase) throws AAIException { this.engine = engine; this.sourceOfTruth = sourceOfTruth; + this.groups = Collections.EMPTY_SET; + this.introspectionType = introspectionType; + this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); + this.latestLoader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, latestVersion); + this.version = version; + this.loader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); + this.namedPropNodes = this.latestLoader.getNamedPropNodes(); + this.baseURL = serverBase; + this.currentTimeMillis = System.currentTimeMillis(); + this.notificationDepth = notificationDepth; + initBeans(); + } + + public DBSerializer(SchemaVersion version, + TransactionalGraphEngine engine, + ModelType introspectionType, + String sourceOfTruth, + Set<String> groups, + int notificationDepth, + String serverBase) throws AAIException { + this.engine = engine; + this.sourceOfTruth = sourceOfTruth; + this.groups = groups; this.introspectionType = introspectionType; this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); SchemaVersion latestVersion = schemaVersions.getDefaultVersion(); @@ -223,6 +297,10 @@ public class DBSerializer { return impliedDeleteUriObjectPair; } + public Set<String> getGroups() { + return this.groups; + } + /** * Touch standard vertex properties. * @param v the v @@ -2193,7 +2271,7 @@ public class DBSerializer { private void executePreSideEffects(Introspector obj, Vertex self) throws AAIException { SideEffectRunner runner = new SideEffectRunner.Builder(this.engine, this).addSideEffect(DataCopy.class) - .addSideEffect(PrivateEdge.class).build(); + .addSideEffect(PrivateEdge.class).addSideEffect(OwnerCheck.class).build(); runner.execute(obj, self); } diff --git a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/OwnerCheckTest.java b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/OwnerCheckTest.java new file mode 100644 index 00000000..0e33f6c7 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/OwnerCheckTest.java @@ -0,0 +1,229 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.introspection.sideeffect; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphFactory; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.edges.enums.EdgeProperty; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; + +@RunWith(value = Parameterized.class) + +public class OwnerCheckTest extends AAISetup { + + private static JanusGraph graph; + private final static ModelType introspectorFactoryType = ModelType.MOXY; + private static Loader loader; + private static TransactionalGraphEngine dbEngine; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Parameterized.Parameter + public QueryStyle queryStyle; + + @Parameterized.Parameters(name = "QueryStyle.{0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}}); + } + + @BeforeClass + public static void setup() { + graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + System.setProperty("AJSC_HOME", "."); + System.setProperty("BUNDLECONFIG_DIR", "src/test/resources/bundleconfig-local"); + + graph.traversal() + .addV("pnf") + .property("aai-node-type", "pnf") + .property("pnf-name", "my-pnf") + .property(AAIProperties.AAI_URI, "/network/pnfs/pnf/my-pnf") + .property("model-invariant-id", "key1") + .as("v1") + .addV("owning-entity") + .property("aai-node-type", "owning-entity") + .property("owning-entity-name", "OE-Generic") + .property("owning-entity-id", "367c897c-8cec-47ba-b7f5-4b6139f06691") + .property(AAIProperties.AAI_URI,"/network/pnfs/pnf/my-pnf/business/owning-entities/owning-entity/367c897c-8cec-47ba-b7f5-4b6139f06691") + .as("oe") + .addE("org.onap.relationships.inventory.BelongsTo").to("v1").from("oe") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV("model-ver") + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key2") + .property("model-version", "testValue") + .property(AAIProperties.AAI_URI, "/network/pnfs/pnf/my-pnf/model-vers/model-ver/key2") + .as("v2") + .addE("org.onap.relationships.inventory.BelongsTo").to("v1").from("v2") + .property(EdgeProperty.CONTAINS.toString(), true) + .addV("model") + .property("aai-node-type", "model") + .property("model-invariant-id", "key3") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3") + .as("v3") + .addV() + .property("aai-node-type", "model-ver") + .property("model-ver", "myValue") + .property("model-version-id", "key4") + .property(AAIProperties.AAI_URI, "/service-design-and-creation/models/model/key3/model-vers/model-ver/key4") + .as("v4") + .addE("org.onap.relationships.inventory.BelongsTo").to("v3").from("v4") + .property(EdgeProperty.CONTAINS.toString(), true) + .next(); + graph.tx().commit(); + } + + @AfterClass + public static void tearDown() { + graph.tx().rollback(); + graph.close(); + } + + @Before + public void initMock() { + loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion()); + MockitoAnnotations.initMocks(this); + dbEngine = new JanusGraphDBEngine(queryStyle, loader); + } + + @Test + public void shouldFailComparisonWithDiffOwningEntity() throws Exception { + + final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + final Introspector obj = loader.introspectorFromName("pnf"); + obj.setValue("pnf-name", "my-pnf"); + obj.setValue("model-invariant-id", "key1"); + obj.setValue("model-version-id", "key2"); + //obj.setValue("owning-entity-id", "367c897c-8cec-47ba-b7f5-4b6139f06691"); + TransactionalGraphEngine spy = spy(dbEngine); + TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); + Graph g = graph.newTransaction(); + GraphTraversalSource traversal = g.traversal(); + when(spy.asAdmin()).thenReturn(adminSpy); + when(adminSpy.getTraversalSource()).thenReturn(traversal); + DBSerializer serializer = + new DBSerializer(schemaVersions.getDefaultVersion(), + spy, introspectorFactoryType, + "AAI_TEST", new HashSet<>(Arrays.asList("OE-GenericI", "OE-GenericII"))); + + Vertex selfV = g.traversal().V().has("aai-node-type", "pnf").next(); + + OwnerCheck ownerCheck = new OwnerCheck(obj, selfV, spy, serializer); + + thrown.expect(AAIException.class); + thrown.expectMessage("Group(s) :[OE-GenericI, OE-GenericII] not authorized to perform function"); + ownerCheck.execute(); + g.tx().rollback(); + + } + + @Test + public void shouldPassIfOwningEntityEqual() throws Exception { + + final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + final Introspector obj = loader.introspectorFromName("pnf"); + obj.setValue("pnf-name", "my-pnf"); + obj.setValue("model-invariant-id", "key1"); + obj.setValue("model-version-id", "key2"); + //obj.setValue("owning-entity-id", "367c897c-8cec-47ba-b7f5-4b6139f06691"); + TransactionalGraphEngine spy = spy(dbEngine); + TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); + Graph g = graph.newTransaction(); + GraphTraversalSource traversal = g.traversal(); + when(spy.tx()).thenReturn(g); + when(spy.asAdmin()).thenReturn(adminSpy); + when(adminSpy.getTraversalSource()).thenReturn(traversal); + + Vertex selfV = g.traversal().V().has("aai-node-type", "pnf").next(); + + DBSerializer serializer = + new DBSerializer(schemaVersions.getDefaultVersion(), + spy, introspectorFactoryType, + "AAI_TEST", new HashSet<>(Arrays.asList("OE-Generic", "OE-GenericII"))); + + OwnerCheck ownerCheck = new OwnerCheck(obj, selfV, spy, serializer); + + ownerCheck.execute(); + + + g.tx().rollback(); + } + + @Test + public void shouldPassIfUserOwningEntityEmptyl() throws Exception { + + final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + final Introspector obj = loader.introspectorFromName("pnf"); + obj.setValue("pnf-name", "my-pnf"); + obj.setValue("model-invariant-id", "key1"); + obj.setValue("model-version-id", "key2"); + //obj.setValue("owning-entity-id", "367c897c-8cec-47ba-b7f5-4b6139f06691"); + TransactionalGraphEngine spy = spy(dbEngine); + TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin()); + Graph g = graph.newTransaction(); + GraphTraversalSource traversal = g.traversal(); + when(spy.asAdmin()).thenReturn(adminSpy); + when(adminSpy.getTraversalSource()).thenReturn(traversal); + DBSerializer serializer = + new DBSerializer(schemaVersions.getDefaultVersion(), + spy, introspectorFactoryType, + "AAI_TEST"); + + Vertex selfV = g.traversal().V().has("aai-node-type", "pnf").next(); + + OwnerCheck ownerCheck = new OwnerCheck(obj, selfV, spy, serializer); + + ownerCheck.execute(); + g.tx().rollback(); + } +} diff --git a/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json b/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json index 7b5c26a7..0480bb8e 100644 --- a/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json +++ b/aai-core/src/test/resources/onap/dbedgerules/v14/DbEdgeRules_v14.json @@ -1570,6 +1570,18 @@ "default": "true", "description":"" }, + { + "from": "pnf", + "to": "owning-entity", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, { "from": "cvlan-tag", "to": "port-group", diff --git a/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml b/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml index 8436fac2..b08e4fb1 100644 --- a/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml +++ b/aai-core/src/test/resources/onap/oxm/v14/aai_oxm_v14.xml @@ -5128,6 +5128,7 @@ <xml-element java-attribute="pnfName" name="pnf-name" required="true" type="java.lang.String" xml-key="true"> <xml-properties> <xml-property name="description" value="unique name of Physical Network Function."/> + <xml-property name="ownerCheck" value="N/A"/> </xml-properties> </xml-element> <xml-element java-attribute="pnfName2" name="pnf-name2" type="java.lang.String"> |