From a70ae91ce48cadf35c955fa5eef1128dcfb8b25f Mon Sep 17 00:00:00 2001 From: Josha von Gizycki Date: Sun, 17 Aug 2025 19:25:49 +0200 Subject: [PATCH] sanitize env for processes, restructure log file --- .../kotlin/alfred/web/core/build/Builds.kt | 1 - .../kotlin/alfred/web/core/build/LogFile.kt | 2 + .../web/core/process/ProcessEnvironment.kt | 24 +++++++++++ .../web/core/{ => process}/Processes.kt | 12 +++--- .../alfred/web/core/runner/GitRunner.kt | 14 +++---- .../alfred/web/core/runner/ScriptRunner.kt | 3 +- .../core/process/ProcessEnvironmentTest.kt | 40 +++++++++++++++++++ src/test/resources/application.properties | 18 +++++++++ 8 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/alfred/web/core/process/ProcessEnvironment.kt rename src/main/kotlin/alfred/web/core/{ => process}/Processes.kt (75%) create mode 100644 src/test/kotlin/alfred/web/core/process/ProcessEnvironmentTest.kt create mode 100644 src/test/resources/application.properties diff --git a/src/main/kotlin/alfred/web/core/build/Builds.kt b/src/main/kotlin/alfred/web/core/build/Builds.kt index 429372b..f30a928 100644 --- a/src/main/kotlin/alfred/web/core/build/Builds.kt +++ b/src/main/kotlin/alfred/web/core/build/Builds.kt @@ -40,7 +40,6 @@ class Builds( .filter { it.key.toString() == it.key.toString().uppercase() } .associate { Pair(it.key.toString(), it.value.toString()) } - // diverge into ScriptedBasedConfig and GitBasedConfig return props.toBuildConfig(env) } diff --git a/src/main/kotlin/alfred/web/core/build/LogFile.kt b/src/main/kotlin/alfred/web/core/build/LogFile.kt index 095487c..b970826 100644 --- a/src/main/kotlin/alfred/web/core/build/LogFile.kt +++ b/src/main/kotlin/alfred/web/core/build/LogFile.kt @@ -21,9 +21,11 @@ class LogFile( append("At your service.") append("Build $buildId, rev [${rev ?: "-none-"}] started at ${ZonedDateTime.now()}") append("Workspace directory is: ${workspace.toFile().absolutePath}") + append("------------------------------------------------------------") } fun footer() { + append("------------------------------------------------------------") append("Build finished at ${ZonedDateTime.now()}") } diff --git a/src/main/kotlin/alfred/web/core/process/ProcessEnvironment.kt b/src/main/kotlin/alfred/web/core/process/ProcessEnvironment.kt new file mode 100644 index 0000000..6c1436e --- /dev/null +++ b/src/main/kotlin/alfred/web/core/process/ProcessEnvironment.kt @@ -0,0 +1,24 @@ +package alfred.web.core.process + +import alfred.web.core.build.BuildConfig +import alfred.web.core.build.LogFile +import org.springframework.stereotype.Service + +@Service +class ProcessEnvironment { + + fun forBuild( + config: BuildConfig, + logFile: LogFile, + rev: String?, + useEnv: MutableMap = System.getenv() + ) = + useEnv.let { env -> + env.filter { it.key.contains("ALFRED") }.forEach { env.remove(it.key) } + env.putAll(config.env) + env["ALFRED_LOG_FILE"] = logFile.backingFile.absolutePath + env["ALFRED_REV"] = rev ?: "" + env + } + +} diff --git a/src/main/kotlin/alfred/web/core/Processes.kt b/src/main/kotlin/alfred/web/core/process/Processes.kt similarity index 75% rename from src/main/kotlin/alfred/web/core/Processes.kt rename to src/main/kotlin/alfred/web/core/process/Processes.kt index 32fc48a..6963c4a 100644 --- a/src/main/kotlin/alfred/web/core/Processes.kt +++ b/src/main/kotlin/alfred/web/core/process/Processes.kt @@ -1,21 +1,23 @@ -package alfred.web.core +package alfred.web.core.process import alfred.web.core.build.BuildConfig import alfred.web.core.build.BuildContext import alfred.web.core.build.LogFile import org.springframework.stereotype.Service +import kotlin.apply @Service -class Processes { +class Processes( + val env: ProcessEnvironment +) { fun builder(config: BuildConfig, logFile: LogFile, rev: String?): ProcessBuilder = ProcessBuilder() .redirectOutput(ProcessBuilder.Redirect.appendTo(logFile.backingFile)) .redirectError(ProcessBuilder.Redirect.appendTo(logFile.backingFile)) .apply { - environment().putAll(config.env) - environment()["ALFRED_LOG_FILE"] = logFile.backingFile.absolutePath - environment()["ALFRED_REV"] = rev + environment().clear() + environment().putAll(env.forBuild(config, logFile, rev)) } fun builder(ctx: BuildContext) = diff --git a/src/main/kotlin/alfred/web/core/runner/GitRunner.kt b/src/main/kotlin/alfred/web/core/runner/GitRunner.kt index d0e4799..8d806a3 100644 --- a/src/main/kotlin/alfred/web/core/runner/GitRunner.kt +++ b/src/main/kotlin/alfred/web/core/runner/GitRunner.kt @@ -2,7 +2,6 @@ package alfred.web.core.runner import alfred.web.core.Handle import alfred.web.core.Handles -import alfred.web.core.Processes import alfred.web.core.build.BuildContext import alfred.web.core.build.BuildId import alfred.web.core.build.Builds @@ -10,6 +9,7 @@ import alfred.web.core.build.ProcessInfo import alfred.web.core.build.Workspace import alfred.web.core.build.Workspaces import alfred.web.core.event.BuildFinished +import alfred.web.core.process.Processes import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.context.ApplicationEventPublisher @@ -63,7 +63,7 @@ class GitRunner( } private fun clone(ctx: BuildContext, ws: Workspace) { - ctx.log("build ${ctx.buildId}: cloning ${ctx.config.gitRepo} into $ws") + ctx.log("cloning ${ctx.config.gitRepo} into $ws") val proc = processes.builder(ctx.config, ctx.logFile, "") .command("git", "clone", ctx.config.gitRepo, ".") @@ -78,7 +78,7 @@ class GitRunner( } private fun checkout(ctx: BuildContext, ws: Workspace) { - ctx.log("build ${ctx.buildId}: checkout rev ${ctx.rev}") + ctx.log("checkout rev ${ctx.rev}") val proc = processes.builder(ctx.config, ctx.logFile, "") .command("git", "checkout", ctx.rev) @@ -93,12 +93,12 @@ class GitRunner( } private fun execScripts(ctx: BuildContext, ws: Workspace) { - ctx.log("build ${ctx.buildId}: looking for scripts $scriptFiles in $scriptsDir/") + ctx.log("looking for scripts $scriptFiles in $scriptsDir/") scriptFiles.forEach { script -> val scriptFile = shFile(ws, script) if (scriptFile.exists()) { - ctx.log("build ${ctx.buildId}: found script $script, running it") + ctx.log("found script $script, running it") ctx.log("Running build file: $script") @@ -109,7 +109,7 @@ class GitRunner( handles.add(Handle(scriptProcess.toHandle(), ctx.buildId)) val ret = scriptProcess.waitFor() - ctx.log("build ${ctx.buildId}: script $script returned $ret") + ctx.log("script $script returned $ret") ctx.log("$script returned $ret") } else { @@ -130,7 +130,7 @@ class FailedToClone( buildId: BuildId, gitRepo: String ) : RuntimeException( - "${FailedToClone::class}: failed to clone $gitRepo for build id $buildId" + "failed to clone $gitRepo for build id $buildId" ) class FailedToCheckout( diff --git a/src/main/kotlin/alfred/web/core/runner/ScriptRunner.kt b/src/main/kotlin/alfred/web/core/runner/ScriptRunner.kt index 7fc5b2d..4561643 100644 --- a/src/main/kotlin/alfred/web/core/runner/ScriptRunner.kt +++ b/src/main/kotlin/alfred/web/core/runner/ScriptRunner.kt @@ -2,9 +2,9 @@ package alfred.web.core.runner import alfred.web.core.Handle import alfred.web.core.Handles -import alfred.web.core.Processes import alfred.web.core.build.* import alfred.web.core.event.BuildFinished +import alfred.web.core.process.Processes import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.context.ApplicationEventPublisher @@ -47,6 +47,7 @@ class ScriptRunner( val wsDir = workspaces.prepare(ctx) ctx.logFile.header(ctx.buildId, ctx.rev, wsDir) + ctx.log("running ${ctx.config.script} in ${wsDir.toAbsolutePath()}") val process = processes.builder(ctx) .command(ctx.config.script) .directory(wsDir.toFile()) diff --git a/src/test/kotlin/alfred/web/core/process/ProcessEnvironmentTest.kt b/src/test/kotlin/alfred/web/core/process/ProcessEnvironmentTest.kt new file mode 100644 index 0000000..1c6232e --- /dev/null +++ b/src/test/kotlin/alfred/web/core/process/ProcessEnvironmentTest.kt @@ -0,0 +1,40 @@ +package alfred.web.core.process + +import alfred.web.core.build.BuildConfig +import alfred.web.core.build.LogFile +import org.junit.jupiter.api.Test +import java.nio.file.Files +import kotlin.test.assertEquals + +class ProcessEnvironmentTest { + + @Test + fun `removes all previous ALFRED vars`(){ + val processEnvironment = ProcessEnvironment() + val cfg = BuildConfig( + user = "Gandalf", + apikey = "Mellon", + script = "", + gitRepo = "", + gitCloneTimeout = 0, + workspace = "", + mailReportTo = "", + env = mapOf( + "ENV1" to "ENV-VAL-1" + ) + ) + val logFile = LogFile(Files.createTempFile("alfred-test", "").toFile()) + + val env = processEnvironment.forBuild( + config = cfg, + logFile = logFile, + rev = "", + useEnv = mutableMapOf( + "ALFRED_TOP_SECRET" to "You-Don't-Know-Jack" + ) + ) + + assertEquals(setOf("ENV1", "ALFRED_LOG_FILE", "ALFRED_REV"), env.keys) + } + +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..08a92d1 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,18 @@ +ALFRED_MAIL_HOST=testing.host +ALFRED_MAIL_PORT=1337 +ALFRED_MAIL_USERNAME=testing.username +ALFRED_MAIL_PASSWORD=testing.password + +ALFRED_HOME=/tmp/alfred +ALFRED_PORT=8080 + +server.port=${ALFRED_PORT} +spring.application.name=Alfred - RCE AAS + +spring.mail.host=${ALFRED_MAIL_HOST} +spring.mail.port=${ALFRED_MAIL_PORT} +spring.mail.username=${ALFRED_MAIL_USERNAME} +spring.mail.password=${ALFRED_MAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=${ALFRED_MAIL_SMTP_AUTH : true} +spring.mail.properties.mail.smtp.starttls.enable=${ALFRED_MAIL_STARTTLS : true} +ALFRED_MAIL_FROM=alfred@your.service