Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
56 changes: 5 additions & 51 deletions .replit
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ modules = ["java", "java-17"]
[nix]
channel = "stable-24_05"

# Zipkin is intentionally not bootstrapped by Replit. Use the repository's Docker Compose
# topology for the supported, reviewable observability runtime.
[workflows]
runButton = "Project"

Expand All @@ -23,18 +25,6 @@ args = "Java Version Check"
task = "workflow.run"
args = "Build Project"

[[workflows.workflow.tasks]]
task = "workflow.run"
args = "Run Zipkin Server"

[[workflows.workflow.tasks]]
task = "workflow.run"
args = "Run Zipkin"

[[workflows.workflow.tasks]]
task = "workflow.run"
args = "Run Eureka Server"

[[workflows.workflow.tasks]]
task = "workflow.run"
args = "Run All Tests"
Expand All @@ -43,10 +33,6 @@ args = "Run All Tests"
task = "workflow.run"
args = "Check Test Status"

[[workflows.workflow.tasks]]
task = "workflow.run"
args = "Build and Run Microservices"

[[workflows.workflow]]
name = "Run Microservices"
author = "agent"
Expand All @@ -56,8 +42,8 @@ agentRequireRestartOnSave = false

[[workflows.workflow.tasks]]
task = "shell.exec"
args = "mvn clean install && java -jar eureka-server/target/eureka-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar config-server/target/config-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar zipkin.jar & sleep 30 && java -jar etl-service/target/etl-service-1.0-SNAPSHOT.jar & java -jar cdc-service/target/cdc-service-1.0-SNAPSHOT.jar & java -jar zuul-gateway/target/zuul-gateway-1.0-SNAPSHOT.jar"
waitForPort = 9411
args = "mvn clean install && java -jar eureka-server/target/eureka-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar config-server/target/config-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar etl-service/target/etl-service-1.0-SNAPSHOT.jar & java -jar cdc-service/target/cdc-service-1.0-SNAPSHOT.jar & java -jar zuul-gateway/target/zuul-gateway-1.0-SNAPSHOT.jar"
waitForPort = 8761

[[workflows.workflow]]
name = "Java Version Check"
Expand All @@ -81,30 +67,6 @@ agentRequireRestartOnSave = false
task = "shell.exec"
args = "mvn clean install"

[[workflows.workflow]]
name = "Run Zipkin Server"
author = "agent"

[workflows.workflow.metadata]
agentRequireRestartOnSave = false

[[workflows.workflow.tasks]]
task = "shell.exec"
args = "curl -sSL https://zipkin.io/quickstart.sh | bash -s && java -jar zipkin.jar"
waitForPort = 9411

[[workflows.workflow]]
name = "Run Zipkin"
author = "agent"

[workflows.workflow.metadata]
agentRequireRestartOnSave = false

[[workflows.workflow.tasks]]
task = "shell.exec"
args = "java -jar zipkin.jar --server.port=9412"
waitForPort = 9412

[[workflows.workflow]]
name = "Run Eureka Server"
author = "agent"
Expand Down Expand Up @@ -152,16 +114,8 @@ args = "mvn clean install && java -jar eureka-server/target/eureka-server-1.0-SN
waitForPort = 8761

[deployment]
run = ["sh", "-c", "mvn clean install && java -jar eureka-server/target/eureka-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar config-server/target/config-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar zipkin.jar & sleep 30 && java -jar etl-service/target/etl-service-1.0-SNAPSHOT.jar & java -jar cdc-service/target/cdc-service-1.0-SNAPSHOT.jar & java -jar zuul-gateway/target/zuul-gateway-1.0-SNAPSHOT.jar"]
run = ["sh", "-c", "mvn clean install && java -jar eureka-server/target/eureka-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar config-server/target/config-server-1.0-SNAPSHOT.jar & sleep 30 && java -jar etl-service/target/etl-service-1.0-SNAPSHOT.jar & java -jar cdc-service/target/cdc-service-1.0-SNAPSHOT.jar & java -jar zuul-gateway/target/zuul-gateway-1.0-SNAPSHOT.jar"]

[[ports]]
localPort = 8761
externalPort = 3001

[[ports]]
localPort = 9411
externalPort = 80

[[ports]]
localPort = 9412
externalPort = 3000
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.xtrmetl.etl.security;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Guards repository-owned developer launch configuration against unsafe or conflicting
* developer-runtime authority paths.
*/
class RepositoryRuntimeSupplyChainTest {

private static final Path PROJECT_ROOT = projectRoot();
private static final Pattern REMOTE_SHELL_PIPE = Pattern.compile(
"(?im)\\bcurl\\b[^\\r\\n|]*\\|\\s*(?:bash|sh)\\b"
);

@Test
void replitDoesNotExecuteTrackedZipkinJar() throws IOException {
String replit = readReplit();
assertFalse(
replit.contains("java -jar zipkin.jar"),
"Replit launch configuration must not execute the repository-tracked opaque Zipkin JAR"
);
}

@Test
void replitDoesNotPipeMutableRemoteContentIntoAShell() throws IOException {
String replit = readReplit();
assertFalse(
REMOTE_SHELL_PIPE.matcher(replit).find(),
"Replit launch configuration must not pipe mutable remote content directly into a shell"
);
}

@Test
void projectRunButtonDelegatesToOneMicroserviceTopology() throws IOException {
String projectWorkflow = workflowBlock(readReplit(), "Project");
int serviceTopologyDelegates = countOccurrences(projectWorkflow, "args = \"Run Microservices\"")
+ countOccurrences(projectWorkflow, "args = \"Run Eureka Server\"")
+ countOccurrences(projectWorkflow, "args = \"Build and Run Microservices\"");

assertEquals(
1,
serviceTopologyDelegates,
"The Replit run button must not launch overlapping copies of the same microservice topology"
);
assertTrue(
projectWorkflow.contains("args = \"Run Microservices\""),
"The Replit run button must delegate service startup to the canonical Run Microservices workflow"
);
}

private static String readReplit() throws IOException {
return Files.readString(PROJECT_ROOT.resolve(".replit"), StandardCharsets.UTF_8);
}

private static String workflowBlock(String replit, String workflowName) {
String normalizedReplit = replit.replace("\r\n", "\n").replace('\r', '\n');
String marker = "[[workflows.workflow]]\nname = \"" + workflowName + "\"";
int start = normalizedReplit.indexOf(marker);
if (start < 0) {
throw new AssertionError("Missing Replit workflow: " + workflowName);
}
int end = normalizedReplit.indexOf("[[workflows.workflow]]", start + marker.length());
return end < 0 ? normalizedReplit.substring(start) : normalizedReplit.substring(start, end);
}

private static int countOccurrences(String text, String needle) {
int count = 0;
int cursor = 0;
while ((cursor = text.indexOf(needle, cursor)) >= 0) {
count++;
cursor += needle.length();
}
return count;
}

private static Path projectRoot() {
Path current = Paths.get(System.getProperty("user.dir")).toAbsolutePath();
while (current != null) {
if (Files.isRegularFile(current.resolve("pom.xml"))
&& Files.isRegularFile(current.resolve(".replit"))) {
return current;
}
current = current.getParent();
}
throw new IllegalStateException("Could not locate mightyETL repository root");
}
}
Loading