Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/include #59

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
19 changes: 5 additions & 14 deletions activities/fellowship of the ring/gandalf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,10 @@ settings:
application: "gandalf" # e.g. from deployment
team: "fellowship of the ring"

# TODO optional fields results in null values in the output is good?
includes:
- infrastructure/infrastructure.yaml

activities:
Source Control Protection:
components:
- url: "https://test1.com"
date: 2023-01-01
- date: 2022-05-01
url: "https://test1.com"
- date: 2021-05-01
url: "https://test1.com"
- date: 2023-12-19
url: "https://test1.com"


Conduction of simple threat modeling on technical level:
components:
- date: "2008-11-01"
Expand All @@ -42,4 +31,6 @@ activities:
links:
- title: "testtitle"
url: "https://test1.com"

Reduction of the attack surface:
components:
- date: "2024-01-01"
18 changes: 18 additions & 0 deletions activities/infrastructure/infrastructure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: application
settings:
desired level: Level 2
application: "kube"
team: "ops"

activities:
Source Control Protection:
components:
- url: "https://test1.com"
date: 2023-01-01
- date: 2022-05-01
url: "https://test1.com"
- date: 2021-05-01
url: "https://test1.com"
- date: 2023-12-19
url: "https://test1.com"
38 changes: 38 additions & 0 deletions activities/infrastructure/team.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: v1
kind: team

settings:
team: "ops"

activities:
Security requirements:
components:
- url: "https://test1.com"
date: 2023-01-01
- date: 2022-05-01
url: "https://test1.com"
- date: 2021-05-01
url: "https://test1.com"
- date: 2023-12-19
url: "https://test1.com"

Data privacy requirements:
components:
- date: 2022-05-01
- date: 2021-05-01
- date: 2023-12-19

Security champion:
components:
- firstname: "Max"
lastname: "Mustermann"
date: "2020-11-01"

Security Training:
components:
- date: "2020-11-01"
people: 2
hours: 5
- date: "2023-11-01"
people: 2
hours: 5
24 changes: 16 additions & 8 deletions activities/two towers/sauron.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,32 @@ settings:
application: "sauron" # e.g. from deployment
team: "two towers"

includes:
- infrastructure/infrastructure.yaml

activities:
Source Control Protection:
components:
- url: "https://test1.com"
date: 2023-01-01
- date: 2022-10-01
- date: 2022-05-01
url: "https://test1.com"
- date: 2000-01-01
- date: 2021-05-01
url: "https://test1.com"
- date: 2023-12-19
url: "https://test1.com"

Defined build process:
components:
- url: "https://test1.com"
date: 2023-01-01
- date: 2022-05-01
url: "https://test2.com"
url: "https://test1.com"
- date: 2021-05-01
url: "https://test1.com"
- date: 2023-12-19
url: "https://test2.com"
url: "https://test1.com"

Conduction of simple threat modeling on technical level:
components:
- date: "2009-11-01"
Expand All @@ -44,10 +55,7 @@ activities:
links:
- title: "testtitle"
url: "https://test1.com"
Reduction of the attack surface:
components:
- date: "2023-01-01"
# sast:
# confirmation:
# - confirmed by: "Max Mustermann"
# confirmed date: "2020-01-01"
# confirmed date: "2020-01-01"
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private List<SkeletonActivity> getDeserializeSkeletons() throws IOException, Git

private List<Application> getDeserializedApplications(List<SkeletonActivity> skeletonActivities) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, GitAPIException {
List<Application> applications = new ArrayList<>();
YamlApplicationNodes yamlApplicationNodes = new YamlApplicationNodes();
YamlApplicationNodes yamlApplicationNodes = new YamlApplicationNodes(yamlScanner.getYamlApplicationFolderPath());
HashMap<String, List<Activity>> teamActivities = new HashMap<>();
for (File yamlApplicationFilePath : yamlScanner.getApplicationYamls()) {
logger.info("yamlApplicationFilePath: " + yamlApplicationFilePath.getPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

Expand All @@ -12,9 +13,15 @@ public class YamlApplicationNodes {
// Key: Team name
protected HashMap<String, ArrayList<JsonNode>> nodes;

protected String yamlBasePath = "";

public YamlApplicationNodes() {
this.nodes = new HashMap<String, ArrayList<JsonNode>>();
}
public YamlApplicationNodes(String yamlBasePath) {
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
this.yamlBasePath = yamlBasePath;
this.nodes = new HashMap<String, ArrayList<JsonNode>>();
}

public void addJsonNode(JsonNode node) {
JsonNode settings = node.get("settings");
Expand Down Expand Up @@ -45,14 +52,19 @@ public ArrayList<JsonNode> getNodesForTeam(String team) {
return allNodes;
}

public ArrayList<JsonNode> getNodes(String team, String kind) {
public ArrayList<JsonNode> getNodes(String team, String kind) throws IOException {
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
ArrayList<JsonNode> applicationNodes = new ArrayList<JsonNode>();

for (JsonNode node : getNodesForTeam(team)) {
if (node.get("kind").asText().equals(kind)) {
if(yamlBasePath != null && !yamlBasePath.isEmpty()) {
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
YamlScannerIncludes yamlScannerIncludes = new YamlScannerIncludes(node, yamlBasePath);
node = yamlScannerIncludes.getNode();
}
applicationNodes.add(node);
}
}

return applicationNodes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private String getYamlSkeletonFilePath() {
return yamlSkeletonFilePath;
}

private String getYamlApplicationFolderPath() {
public String getYamlApplicationFolderPath() {
logger.info("yamlApplicationFolderPath() " + yamlApplicationFolderPath);
if (isGit()) {
return yamlGitTargetPath + "/" + yamlApplicationFolderPath;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.owasp.dsomm.metricca.analyzer.deserialization;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

import java.io.File;
import java.io.IOException;

public class YamlScannerIncludes {
private ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
private String yamlBasePath;
private JsonNode applicationJsonNode;

public YamlScannerIncludes(JsonNode applicationJsonNode, String basePath) {
this.applicationJsonNode = applicationJsonNode;
this.yamlBasePath = basePath;
}

public JsonNode getNode() throws IOException {
processIncludes(applicationJsonNode);
return applicationJsonNode;
}

private void processIncludes(JsonNode node) throws IOException {
if (node.has("includes")) {
ArrayNode includesArray = (ArrayNode) node.get("includes");
for (JsonNode includeNode : includesArray) {
if (includeNode.isTextual()) {
String includePath = includeNode.asText();
File includeFile = new File(yamlBasePath + File.separator + includePath);
JsonNode includeContent = mapper.readTree(includeFile);
if (includeContent.has("includes")) {
processIncludes(includeContent);
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
}
mergeJsonNodes(node, includeContent);
}
}
((ObjectNode) node).remove("includes");
}


}

private void mergeJsonNodes(JsonNode destinationNode, JsonNode sourceNode) {
if (destinationNode instanceof ObjectNode && sourceNode instanceof ObjectNode) {
ObjectNode destObjectNode = (ObjectNode) destinationNode;
ObjectNode srcObjectNode = (ObjectNode) sourceNode;

// Merge fields from source node to destination node
srcObjectNode.fieldNames().forEachRemaining(fieldName -> {
JsonNode srcFieldValue = srcObjectNode.get(fieldName);
JsonNode destFieldValue = destObjectNode.get(fieldName);

if (destFieldValue != null && destFieldValue.isObject() && srcFieldValue.isObject()) {
// Recursive deep merge for nested objects
mergeJsonNodes(destFieldValue, srcFieldValue);
} else {
// If the field exists in the destination node but not in the source node, or if the field is null in the destination
// and exists in the source node, or if the included YAML is overriding the including YAML, override the value in the destination
if (destFieldValue == null || (!destObjectNode.has(fieldName) && srcObjectNode.has(fieldName))) {
destObjectNode.set(fieldName, srcFieldValue);
}
}
});
} else {
throw new IllegalArgumentException("Both nodes must be ObjectNodes");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ private UrlActivity getSecurityRequirementsActivity() throws GitAPIException, IO
List<Application> actualApplications = applicationDirector.getApplications();
for (Application application : actualApplications) {
if (application.getName().equals("sauron")) {
Date date = ((UrlActivity) application.getActivities().get(0)).getDateComponents().get(0).getDate();
logger.error("date" + date);
return (UrlActivity) application.getActivities().get(0);
}
}
Expand Down Expand Up @@ -70,9 +72,9 @@ public void testShowEndDateWithEndDateToShowForSingleDate() throws Exception {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd");
isoFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));

Date existingDate = isoFormat.parse("2000-01-01");
Date existingDate = isoFormat.parse("2023-12-19");
DatePeriod endDateForExistingDate = activity.getThresholdDatePeriodMap().get("Level 1").getDatePeriodForDate(existingDate);
assertNotNull(endDateForExistingDate);
assertTrue(endDateForExistingDate.getShowEndDate());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.owasp.dsomm.metricca.analyzer.deserialization.YamlApplicationNodes;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

Expand Down Expand Up @@ -91,7 +92,7 @@ void shouldGetNodesForTeam() {
}

@Test
void testGetNodesForTeam() throws JsonProcessingException {
void testGetNodesForTeam() throws IOException {
HashMap<String, ArrayList<JsonNode>> nodes = new HashMap<>();
ArrayList<JsonNode> jsonNodes = new ArrayList<>();
jsonNodes.add(objectMapper.readTree(jsonNodeString));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.owasp.dsomm.metricca.analyzer.deserialization;
import com.fasterxml.jackson.databind.JsonNode;
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.nio.file.Paths;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class YamlScannerIncludesTest {

@Test
void testSingleNodeInclude() throws Exception {
// Arrange
String basePath = Paths.get("src", "test", "resources", "include").toString();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode applicationJsonNode = objectMapper.readTree("{ \"key\": \"value\", \"includes\": [\"include1.yaml\"] }");
JsonNode expected = objectMapper.readTree("{ \"key\": \"value\", \"includedKey\": \"includedValue\" }");

// Act
YamlScannerIncludes yamlScannerIncludes = new YamlScannerIncludes(applicationJsonNode, basePath);
JsonNode result = yamlScannerIncludes.getNode();

// Assert
assertEquals(expected, result);
}

@Test
void testMultipleNodeInclude() throws Exception {
// Arrange
String basePath = Paths.get("src", "test", "resources", "include").toString();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode applicationJsonNode = objectMapper.readTree("{ \"key\": \"value\", \"includes\": [\"include2.yaml\"] }");
JsonNode expected = objectMapper.readTree("{ \"key\": \"value\", \"includedKey2\": \"includedValue2\" }");

// Act
YamlScannerIncludes yamlScannerIncludes = new YamlScannerIncludes(applicationJsonNode, basePath);
JsonNode result = yamlScannerIncludes.getNode();

// Assert
assertEquals(expected, result);
}

@Test
void testNestedIncludes() throws Exception {
// Arrange
String basePath = Paths.get("src", "test", "resources", "include").toString();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode applicationJsonNode = objectMapper.readTree("{ \"key\": \"value\", \"includes\": [\"nestedInclude.yaml\"] }");
JsonNode expected = objectMapper.readTree("{ \"key\": \"value\", \"includedKey1\": \"includedValue1\", \"nestedKey2\": \"nestedValue2\"}");
// Act
YamlScannerIncludes yamlScannerIncludes = new YamlScannerIncludes(applicationJsonNode, basePath);
JsonNode result = yamlScannerIncludes.getNode();

// Assert
assertEquals(expected, result);
}
@Test
wurstbrot marked this conversation as resolved.
Show resolved Hide resolved
void testIncludesWithActivities() throws Exception {
// Arrange
String basePath = Paths.get("src", "test", "resources", "include").toString();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode applicationJsonNode = objectMapper.readTree("{ \"activities\": {\"key\": \"value\"}, \"includes\": [\"includeWithActivities.yaml\"]}");
JsonNode expected = objectMapper.readTree("{ \"activities\": {\"key\": \"value\", \"includedKey\": \"includedValue\"}}");
// Act
YamlScannerIncludes yamlScannerIncludes = new YamlScannerIncludes(applicationJsonNode, basePath);
JsonNode result = yamlScannerIncludes.getNode();

// Assert
assertEquals(expected, result);
}
}
5 changes: 5 additions & 0 deletions src/test/resources/include/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
includes:
- include1.yaml
- include2.yaml
- nestedInclude.yaml
key: value
1 change: 1 addition & 0 deletions src/test/resources/include/include1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
includedKey: includedValue
1 change: 1 addition & 0 deletions src/test/resources/include/include2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
includedKey2: includedValue2
2 changes: 2 additions & 0 deletions src/test/resources/include/includeWithActivities.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
activities:
includedKey: includedValue
Loading