Merge "b/162508047 Add Path Traversal"
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
index 701ba8a..58e4e14 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
@@ -15,6 +15,7 @@
import org.openapi4j.parser.model.v3.OpenApi3;
import org.openapi4j.parser.model.v3.Operation;
import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.Path;
import org.openapi4j.parser.model.v3.Response;
import org.openapi4j.parser.model.v3.SecurityRequirement;
import org.openapi4j.parser.model.v3.Server;
@@ -116,6 +117,17 @@
}
@Override
+ public void sendPathTraversals(ImmutableMap<String, Path> pathMap) {
+ Optional.ofNullable(pathMap)
+ .ifPresent(
+ paths ->
+ paths.forEach(
+ (name, path) ->
+ coordinator.handleTraversalCommand(
+ factory.create(path, traversalPath, name))));
+ }
+
+ @Override
public void sendResponseTraversals(ImmutableMap<String, Response> responses) {
Optional.ofNullable(responses)
.ifPresent(
@@ -139,8 +151,8 @@
}
@Override
- public void sendServerTraversals(ImmutableList<Server> serversList) {
- Optional.ofNullable(serversList)
+ public void sendServerTraversals(ImmutableList<Server> serverList) {
+ Optional.ofNullable(serverList)
.ifPresent(
servers ->
servers.forEach(
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/CallbackTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/CallbackTraversal.java
index ca89f3c..7ed41fc 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/CallbackTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/CallbackTraversal.java
@@ -29,6 +29,10 @@
@Override
public void traverse() {
// TODO(b/161441872): Process extensions.
- // TODO(b/162508047): Add path object traversal and callback object traversal logic.
+
+ TraversalHelper traversalHelper = traversalHelperFactory.create(getUpdatedTraversalPath());
+
+ traversalHelper.sendPathTraversals(
+ Immutables.toImmutableMap(openApiSchemaObj.getCallbackPaths()));
}
}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
index 1709d93..07b547f 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
@@ -1,6 +1,7 @@
package com.apigee.security.oas.extendedvalidator;
import static com.apigee.security.oas.extendedvalidator.Immutables.toImmutableList;
+import static com.apigee.security.oas.extendedvalidator.Immutables.toImmutableMap;
import com.google.common.collect.ImmutableList;
import com.google.inject.assistedinject.Assisted;
@@ -29,6 +30,8 @@
traversalHelper.sendInfoTraversal(openApiSchemaObj.getInfo());
traversalHelper.sendServerTraversals(toImmutableList(openApiSchemaObj.getServers()));
traversalHelper.sendTagTraversals(toImmutableList(openApiSchemaObj.getTags()));
- // TODO(b/162508047): Add path object traversal and callback object traversal logic.
+ traversalHelper.sendPathTraversals(toImmutableMap(openApiSchemaObj.getPaths()));
+ // TODO(b/162682119): Send OpenApiSpecification SecurityRequirements to TraversalHelper.
+ // TODO(b/162677159): Send Components traversal.
}
}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversal.java
new file mode 100644
index 0000000..5ba0797
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversal.java
@@ -0,0 +1,42 @@
+package com.apigee.security.oas.extendedvalidator;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.assistedinject.Assisted;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import org.openapi4j.parser.model.OpenApiSchema;
+import org.openapi4j.parser.model.v3.Path;
+
+/** A {@link Traversal} that traverses a {@link Path} object. */
+final class PathTraversal extends Traversal<Path> implements PathTraversalCommand {
+
+ @Inject
+ PathTraversal(
+ TraversalHelperFactory traversalHelperFactory,
+ ExtensionValidationIntegrator extensionValidationIntegrator,
+ @Assisted
+ ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+ @Assisted Path openApiSchemaObj,
+ @Assisted String name) {
+ super(
+ traversalHelperFactory,
+ extensionValidationIntegrator,
+ traversalPath,
+ openApiSchemaObj,
+ name);
+ }
+
+ @Override
+ public void traverse() {
+ // TODO(b/161441872): Process extensions.
+
+ TraversalHelper traversalHelper = traversalHelperFactory.create(getUpdatedTraversalPath());
+
+ traversalHelper.sendParameterTraversals(
+ Immutables.toImmutableList(openApiSchemaObj.getParameters()));
+ traversalHelper.sendServerTraversals(Immutables.toImmutableList(openApiSchemaObj.getServers()));
+ traversalHelper.sendOperationTraversals(
+ Immutables.toImmutableMap(openApiSchemaObj.getOperations()));
+ }
+}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversalCommand.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversalCommand.java
new file mode 100644
index 0000000..0a3db17
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/PathTraversalCommand.java
@@ -0,0 +1,4 @@
+package com.apigee.security.oas.extendedvalidator;
+
+/** A {@link TraversalCommand} interface for {@link PathTraversal}. */
+public interface PathTraversalCommand extends TraversalCommand {}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
index 1300951..c6e9a40 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
@@ -26,6 +26,7 @@
// TODO(b/161441872): Process extensions.
TraversalHelper traversalHelper = traversalHelperFactory.create(getUpdatedTraversalPath());
+
traversalHelper.sendExternalDocsTraversal(openApiSchemaObj.getExternalDocs());
}
}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
index 2167c17..654187b 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
@@ -12,6 +12,7 @@
import org.openapi4j.parser.model.v3.OpenApi3;
import org.openapi4j.parser.model.v3.Operation;
import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.Path;
import org.openapi4j.parser.model.v3.Response;
import org.openapi4j.parser.model.v3.SecurityRequirement;
import org.openapi4j.parser.model.v3.Server;
@@ -56,6 +57,11 @@
Parameter parameter,
ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
+ PathTraversalCommand create(
+ Path path,
+ ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+ String name);
+
ResponseTraversalCommand create(
Response response,
ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
index fb3d8a7..a226e1a 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
@@ -18,6 +18,7 @@
OpenApiSpecificationTraversalCommand.class, OpenApiSpecificationTraversal.class)
.implement(OperationTraversalCommand.class, OperationTraversal.class)
.implement(ParameterTraversalCommand.class, ParameterTraversal.class)
+ .implement(PathTraversalCommand.class, PathTraversal.class)
.implement(ResponseTraversalCommand.class, ResponseTraversal.class)
.implement(
SecurityRequirementTraversalCommand.class, SecurityRequirementTraversal.class)
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
index c2c6c94..1f6ea32 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
@@ -10,6 +10,7 @@
import org.openapi4j.parser.model.v3.OpenApi3;
import org.openapi4j.parser.model.v3.Operation;
import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.Path;
import org.openapi4j.parser.model.v3.Response;
import org.openapi4j.parser.model.v3.SecurityRequirement;
import org.openapi4j.parser.model.v3.Server;
@@ -35,6 +36,8 @@
void sendParameterTraversals(ImmutableList<Parameter> parameters);
+ void sendPathTraversals(ImmutableMap<String, Path> paths);
+
void sendResponseTraversals(ImmutableMap<String, Response> responses);
void sendSecurityRequirementTraversals(ImmutableList<SecurityRequirement> securityRequirements);
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/CallbackTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/CallbackTraversalTest.java
new file mode 100644
index 0000000..dc4944d
--- /dev/null
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/CallbackTraversalTest.java
@@ -0,0 +1,67 @@
+package com.apigee.security.oas.extendedvalidator;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.openapi4j.parser.model.v3.Callback;
+import org.openapi4j.parser.model.v3.Path;
+
+@RunWith(JUnit4.class)
+public class CallbackTraversalTest {
+
+ private final ImmutableMap<String, Path> callbackPaths =
+ ImmutableMap.of("one", new Path(), "two", new Path(), "three", new Path());
+
+ private CallbackTraversal callbackTraversal;
+
+ @Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+ @Mock private TraversalHelperFactory traversalHelperFactory;
+ @Mock private TraversalHelper traversalHelper;
+ @Mock private ExtensionValidationIntegrator extensionValidationIntegrator;
+ @Mock private Callback callback;
+
+ /** Sets up live and mocked instances for testing. */
+ @Before
+ public void setup() {
+ callbackTraversal =
+ new CallbackTraversal(
+ traversalHelperFactory,
+ extensionValidationIntegrator,
+ ImmutableList.of(),
+ callback,
+ "name");
+
+ when(callback.getCallbackPaths()).thenReturn(callbackPaths);
+
+ when(traversalHelperFactory.create(any(ImmutableList.class))).thenReturn(traversalHelper);
+ }
+
+ @Test
+ public void traverse_sendsCallbackPathsToTraversalHelper() {
+ callbackTraversal.traverse();
+
+ verify(traversalHelper).sendPathTraversals(callbackPaths);
+ }
+
+ @Test
+ public void traverse_nullCallbackPathsMember_doesNotFail() {
+ when(callback.getCallbackPaths()).thenReturn(null);
+
+ callbackTraversal.traverse();
+
+ verify(traversalHelper, atLeastOnce()).sendPathTraversals(any());
+ }
+}
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
index 4df4f5d..efe1ae1 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
@@ -6,6 +6,7 @@
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -18,6 +19,7 @@
import org.openapi4j.parser.model.v3.ExternalDocs;
import org.openapi4j.parser.model.v3.Info;
import org.openapi4j.parser.model.v3.OpenApi3;
+import org.openapi4j.parser.model.v3.Path;
import org.openapi4j.parser.model.v3.Server;
import org.openapi4j.parser.model.v3.Tag;
@@ -38,6 +40,9 @@
ImmutableList.of(new Server(), new Server(), new Server());
private final ImmutableList<Tag> tags = ImmutableList.of(new Tag(), new Tag(), new Tag());
+ private final ImmutableMap<String, Path> paths =
+ ImmutableMap.of("one", new Path(), "two", new Path(), "three", new Path());
+
private OpenApiSpecificationTraversal openApiSpecificationTraversal;
/** Sets up live and mocked instances for testing. */
@@ -48,33 +53,45 @@
traversalHelperFactory, extensionValidationIntegrator, openApiSpec);
when(openApiSpec.getServers()).thenReturn(servers);
-
when(openApiSpec.getTags()).thenReturn(tags);
-
when(openApiSpec.getInfo()).thenReturn(info);
-
when(openApiSpec.getExternalDocs()).thenReturn(externalDocs);
+ when(openApiSpec.getPaths()).thenReturn(paths);
when(traversalHelperFactory.create(any(ImmutableList.class))).thenReturn(traversalHelper);
}
@Test
- public void traverse_sendsInfoToTraversalHelper() {
- openApiSpecificationTraversal.traverse();
-
- verify(traversalHelperFactory, atLeastOnce()).create(any(ImmutableList.class));
- verify(traversalHelper).sendInfoTraversal(info);
- }
-
- @Test
public void traverse_sendsExternalDocsToTraversalHelper() {
openApiSpecificationTraversal.traverse();
- verify(traversalHelperFactory, atLeastOnce()).create(any(ImmutableList.class));
verify(traversalHelper).sendExternalDocsTraversal(externalDocs);
}
@Test
+ public void traverse_sendsInfoToTraversalHelper() {
+ openApiSpecificationTraversal.traverse();
+
+ verify(traversalHelper).sendInfoTraversal(info);
+ }
+
+ @Test
+ public void traverse_sendsPathsToTraversalHelper() {
+ openApiSpecificationTraversal.traverse();
+
+ verify(traversalHelper).sendPathTraversals(paths);
+ }
+
+ @Test
+ public void traverse_nullPathsMember_doesNotFail() {
+ when(openApiSpec.getPaths()).thenReturn(null);
+
+ openApiSpecificationTraversal.traverse();
+
+ verify(traversalHelper, atLeastOnce()).sendPathTraversals(any());
+ }
+
+ @Test
public void traverse_sendsServersToTraversalHelper() {
openApiSpecificationTraversal.traverse();
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/PathTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/PathTraversalTest.java
new file mode 100644
index 0000000..042f0a4
--- /dev/null
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/PathTraversalTest.java
@@ -0,0 +1,108 @@
+package com.apigee.security.oas.extendedvalidator;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.openapi4j.parser.model.v3.Operation;
+import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.Path;
+import org.openapi4j.parser.model.v3.Server;
+
+@RunWith(JUnit4.class)
+public class PathTraversalTest {
+
+ private final ImmutableList<Parameter> parameters =
+ ImmutableList.of(new Parameter(), new Parameter(), new Parameter(), new Parameter());
+ private final ImmutableList<Server> servers =
+ ImmutableList.of(new Server(), new Server(), new Server());
+
+ private final ImmutableMap<String, Operation> operations =
+ ImmutableMap.of("one", new Operation(), "two", new Operation(), "three", new Operation());
+
+ private PathTraversal pathTraversal;
+
+ @Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+ @Mock private TraversalHelperFactory traversalHelperFactory;
+ @Mock private TraversalHelper traversalHelper;
+ @Mock private ExtensionValidationIntegrator extensionValidationIntegrator;
+ @Mock private Path path;
+
+ /** Sets up live and mocked instances for testing. */
+ @Before
+ public void setup() {
+ pathTraversal =
+ new PathTraversal(
+ traversalHelperFactory,
+ extensionValidationIntegrator,
+ ImmutableList.of(),
+ path,
+ "name");
+
+ when(path.getOperations()).thenReturn(operations);
+ when(path.getParameters()).thenReturn(parameters);
+ when(path.getServers()).thenReturn(servers);
+
+ when(traversalHelperFactory.create(any(ImmutableList.class))).thenReturn(traversalHelper);
+ }
+
+ @Test
+ public void traverse_sendsOperationsToTraversalHelper() {
+ pathTraversal.traverse();
+
+ verify(traversalHelper).sendOperationTraversals(operations);
+ }
+
+ @Test
+ public void traverse_nullOperationsMember_doesNotFail() {
+ when(path.getOperations()).thenReturn(null);
+
+ pathTraversal.traverse();
+
+ verify(traversalHelper, atLeastOnce()).sendOperationTraversals(any());
+ }
+
+ @Test
+ public void traverse_sendsParametersToTraversalHelper() {
+ pathTraversal.traverse();
+
+ verify(traversalHelper).sendParameterTraversals(parameters);
+ }
+
+ @Test
+ public void traverse_nullParametersMember_doesNotFail() {
+ when(path.getParameters()).thenReturn(null);
+
+ pathTraversal.traverse();
+
+ verify(traversalHelper, atLeastOnce()).sendParameterTraversals(any());
+ }
+
+ @Test
+ public void traverse_sendsServersToTraversalHelper() {
+ pathTraversal.traverse();
+
+ verify(traversalHelper).sendServerTraversals(servers);
+ }
+
+ @Test
+ public void traverse_nullServersMember_doesNotFail() {
+ when(path.getServers()).thenReturn(null);
+
+ pathTraversal.traverse();
+
+ verify(traversalHelper, atLeastOnce()).sendServerTraversals(any());
+ }
+}
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
index 9f8e177..455543d 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
@@ -19,6 +19,7 @@
import org.openapi4j.parser.model.v3.OpenApi3;
import org.openapi4j.parser.model.v3.Operation;
import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.Path;
import org.openapi4j.parser.model.v3.Response;
import org.openapi4j.parser.model.v3.SecurityRequirement;
import org.openapi4j.parser.model.v3.Server;
@@ -75,6 +76,11 @@
}
@Test
+ public void create_pathAndNamePassed_returnsNonNullObject() {
+ assertThat(traversalCommandFactory.create(new Path(), traversalPath, "name")).isNotNull();
+ }
+
+ @Test
public void create_responseAndNamePassed_returnsNonNullObject() {
assertThat(traversalCommandFactory.create(new Response(), traversalPath, "name")).isNotNull();
}