Skip to content

Commit

Permalink
Add more details to the list --paths subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
en-milie committed Oct 13, 2023
1 parent 4d26fa5 commit 8150a94
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 26 deletions.
9 changes: 5 additions & 4 deletions src/main/java/com/endava/cats/ReflectionConfig.java

Large diffs are not rendered by default.

15 changes: 1 addition & 14 deletions src/main/java/com/endava/cats/command/CatsCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.fusesource.jansi.Ansi.ansi;

Expand Down Expand Up @@ -324,21 +322,10 @@ private void printConfiguration(OpenAPI openAPI) {
logger.config(ansi().bold().a("Total number of OpenAPI paths: {}").reset().toString(), ansi().fg(Ansi.Color.YELLOW).a(openAPI.getPaths().size()));
logger.config(ansi().bold().a("HTTP methods in scope: {}").reset().toString(), ansi().fg(Ansi.Color.YELLOW).a(filterArguments.getHttpMethods()).reset());

int nofOfOperations = openAPI.getPaths()
.values()
.stream()
.mapToInt(CatsCommand::countPathOperations)
.sum();
int nofOfOperations = OpenApiUtils.getNumberOfOperations(openAPI);
logger.config(ansi().bold().a("Total number of OpenAPI operations: {}").reset().toString(), ansi().fg(Ansi.Color.YELLOW).a(nofOfOperations));
}

private static int countPathOperations(PathItem pathItem) {
return Stream.of(pathItem.getGet(), pathItem.getPost(), pathItem.getPut(), pathItem.getDelete(),
pathItem.getPatch(), pathItem.getOptions(), pathItem.getHead())
.filter(Objects::nonNull)
.mapToInt(sum -> 1)
.sum();
}

private void processLogLevelArgument() {
reportingArguments.processLogData();
Expand Down
42 changes: 39 additions & 3 deletions src/main/java/com/endava/cats/command/ListCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import com.endava.cats.annotations.ValidateAndSanitize;
import com.endava.cats.annotations.ValidateAndTrim;
import com.endava.cats.command.model.FuzzerListEntry;
import com.endava.cats.command.model.PathListEntry;
import com.endava.cats.fuzzer.api.Fuzzer;
import com.endava.cats.generator.format.api.OpenAPIFormat;
import com.endava.cats.http.HttpMethod;
import com.endava.cats.json.JsonUtils;
import com.endava.cats.model.FuzzingData;
import com.endava.cats.openapi.OpenApiUtils;
Expand All @@ -26,9 +28,11 @@

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import static org.fusesource.jansi.Ansi.ansi;

Expand Down Expand Up @@ -89,11 +93,17 @@ void listFormats() {
void listContractPaths() {
try {
OpenAPI openAPI = OpenApiUtils.readOpenApi(listCommandGroups.listContractOptions.contract);
PathListEntry pathListEntry = createPathEntryList(openAPI);

if (json) {
PrettyLoggerFactory.getConsoleLogger().noFormat(JsonUtils.GSON.toJson(openAPI.getPaths().keySet()));
PrettyLoggerFactory.getConsoleLogger().noFormat(JsonUtils.GSON.toJson(pathListEntry));
} else {
logger.noFormat("Available paths:");
openAPI.getPaths().keySet().stream().sorted().map(item -> " ◼ " + item).forEach(logger::noFormat);
logger.noFormat("{} paths and {} operations:", pathListEntry.getNumberOfPaths(), pathListEntry.getNumberOfOperations());
pathListEntry.getPathDetailsList()
.stream()
.sorted()
.map(item -> " ◼ " + item.getPath() + ": " + item.getMethods())
.forEach(logger::noFormat);
}
} catch (IOException e) {
logger.debug("Exception while reading contract!", e);
Expand All @@ -102,6 +112,32 @@ void listContractPaths() {
}
}

private static PathListEntry createPathEntryList(OpenAPI openAPI) {
int numberOfPaths = openAPI.getPaths().size();
int numberOfOperations = OpenApiUtils.getNumberOfOperations(openAPI);
List<PathListEntry.PathDetails> pathDetailsList = new ArrayList<>();

openAPI.getPaths()
.forEach((pathName, pathItem) -> {
List<HttpMethod> httpMethods = HttpMethod.OPERATIONS.entrySet()
.stream()
.filter(entry -> entry.getValue().apply(pathItem) != null)
.map(Map.Entry::getKey)
.toList();

pathDetailsList.add(PathListEntry.PathDetails
.builder()
.methods(httpMethods)
.path(pathName)
.build());
});
return PathListEntry.builder()
.numberOfPaths(numberOfPaths)
.numberOfOperations(numberOfOperations)
.pathDetailsList(pathDetailsList)
.build();
}

void listFuzzerStrategies() {
logger.noFormat("Registered fieldsFuzzerStrategies: {}", Arrays.asList(FuzzingData.SetFuzzingStrategy.values()));
}
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/com/endava/cats/command/model/PathListEntry.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
package com.endava.cats.command.model;

import com.endava.cats.http.HttpMethod;
import lombok.Builder;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.List;

@Builder
@Getter
public class PathListEntry {
private String method;
private String path;
private int numberOfPaths;
private int numberOfOperations;
private List<PathDetails> pathDetailsList;

@Builder
@Getter
public static class PathDetails implements Comparable<PathDetails> {
private List<HttpMethod> methods;
private String path;

@Override
public int compareTo(@NotNull PathListEntry.PathDetails o) {
return this.getPath().compareTo(o.getPath());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
public class CheckSecurityHeadersFuzzer implements Fuzzer {

protected static final String SECURITY_HEADERS_AS_STRING;
public static final Map<String, List<KeyValuePair<String, String>>> SECURITY_HEADERS = new HashMap<>();
protected static final Map<String, List<KeyValuePair<String, String>>> SECURITY_HEADERS = new HashMap<>();

static {
SECURITY_HEADERS.put("Cache-Control", Collections.singletonList(new KeyValuePair<>("Cache-Control", "no-store")));
Expand Down Expand Up @@ -93,7 +93,7 @@ private List<KeyValuePair<String, String>> getMissingSecurityHeaders(CatsRespons
return responseHeader != null &&
possibleValues.stream().noneMatch(possibleHeader -> this.matchesSecurityHeader(possibleHeader, responseHeader));
}).flatMap(entry -> entry.getValue().stream())
.collect(Collectors.toList());
.toList();
}

private boolean matchesSecurityHeader(KeyValuePair<String, String> expected, KeyValuePair<String, String> actual) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/endava/cats/http/HttpMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum HttpMethod {
BIND, UNBIND, REBIND, MKREDIRECTREF,
UPDATEREDIRECTREF, ORDERPATCH, ACL, REPORT);

private static final EnumMap<HttpMethod, Function<PathItem, Operation>> OPERATIONS = new EnumMap<>(HttpMethod.class);
public static final EnumMap<HttpMethod, Function<PathItem, Operation>> OPERATIONS = new EnumMap<>(HttpMethod.class);
private static final EnumMap<HttpMethod, List<String>> RECOMMENDED_CODES = new EnumMap<>(HttpMethod.class);
private static final String TWOXX = "200|201|202|204";

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/endava/cats/openapi/OpenApiUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.github.ludovicianul.prettylogger.PrettyLogger;
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Content;
Expand All @@ -21,7 +22,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

public abstract class OpenApiUtils {
private static final PrettyLogger LOGGER = PrettyLoggerFactory.getLogger(OpenApiUtils.class);
Expand Down Expand Up @@ -106,4 +109,20 @@ public static boolean hasContentType(Content content, List<String> contentType)
.anyMatch(contentItem -> contentKey.matches(contentItem) || contentKey.equalsIgnoreCase(contentItem))
);
}

public static int getNumberOfOperations(OpenAPI openAPI) {
return openAPI.getPaths()
.values()
.stream()
.mapToInt(OpenApiUtils::countPathOperations)
.sum();
}

private static int countPathOperations(PathItem pathItem) {
return Stream.of(pathItem.getGet(), pathItem.getPost(), pathItem.getPut(), pathItem.getDelete(),
pathItem.getPatch(), pathItem.getOptions(), pathItem.getHead())
.filter(Objects::nonNull)
.mapToInt(sum -> 1)
.sum();
}
}

0 comments on commit 8150a94

Please sign in to comment.