Skip to content

Commit 692e6f8

Browse files
dansanduleacrobert3005
authored andcommitted
Redact passwords from conda output (apache#243)
1 parent f623f54 commit 692e6f8

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

core/src/main/scala/org/apache/spark/api/conda/CondaEnvironmentManager.scala

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import java.nio.file.Files
2020
import java.nio.file.Path
2121
import java.nio.file.Paths
2222
import java.nio.file.attribute.PosixFilePermission
23+
import java.util.regex.Pattern
2324

2425
import scala.collection.JavaConverters._
2526
import scala.sys.process.BasicIO
@@ -160,16 +161,21 @@ final class CondaEnvironmentManager(condaBinaryPath: String,
160161
* @return the stdout of the process
161162
*/
162163
private[this] def runOrFail(command: ProcessBuilder, description: String): String = {
164+
import CondaEnvironmentManager.redactCredentials
163165
val out = new StringBuffer
164166
val err = new StringBuffer
165167
val collectErrOutToBuffer = new ProcessIO(
166-
BasicIO.input(false),
167-
BasicIO.processFully(out),
168-
BasicIO.processFully(line => {
169-
err append line
170-
err append BasicIO.Newline
171-
log.info(s"<conda> $line")
172-
}))
168+
BasicIO.input(false),
169+
BasicIO.processFully((redactCredentials _).andThen(line => {
170+
out.append(line)
171+
out.append(BasicIO.Newline)
172+
()
173+
})),
174+
BasicIO.processFully((redactCredentials _).andThen(line => {
175+
err.append(line)
176+
err.append(BasicIO.Newline)
177+
log.info(s"<conda> $line")
178+
})))
173179
val exitCode = command.run(collectErrOutToBuffer).exitValue()
174180
if (exitCode != 0) {
175181
throw new SparkException(s"Attempt to $description exited with code: "
@@ -196,6 +202,13 @@ object CondaEnvironmentManager extends Logging {
196202
sparkConf.contains(CONDA_BINARY_PATH)
197203
}
198204

205+
private[this] val httpUrlToken =
206+
Pattern.compile("(\\b\\w+://[^:/@]*:)([^/@]+)(?=@([\\w-.]+)(:\\d+)?\\b)")
207+
208+
private[conda] def redactCredentials(line: String): String = {
209+
httpUrlToken.matcher(line).replaceAll("$1<password>")
210+
}
211+
199212
def fromConf(sparkConf: SparkConf): CondaEnvironmentManager = {
200213
val condaBinaryPath = sparkConf.get(CONDA_BINARY_PATH).getOrElse(
201214
sys.error(s"Expected config ${CONDA_BINARY_PATH.key} to be set"))

core/src/test/scala/org/apache/spark/api/conda/CondaEnvironmentManagerTest.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,19 @@ class CondaEnvironmentManagerTest extends org.apache.spark.SparkFunSuite with Te
2828
CondaEnvironmentManager.ensureExecutable(path.toString)
2929
assert(Files.isExecutable(path), "File should now be executable")
3030
}
31+
32+
test("CondaEnvironmentManager.redactCredentials") {
33+
val original = "24u0f8 adfghjfouh https://:[email protected]" +
34+
".baz:12345/whatever/else"
35+
val redacted = "24u0f8 adfghjfouh https://:<password>@my-host-name-5.foo.bar" +
36+
".baz:12345/whatever/else"
37+
assert(CondaEnvironmentManager.redactCredentials(original) == redacted)
38+
}
39+
40+
test("CondaEnvironmentManager.redactTwoCredentials") {
41+
val original = "random:https://:[email protected]/whatever/else][http://us_r:[email protected]:222"
42+
val redacted = "random:https://:<password>@x-5.bar/whatever/else]" +
43+
"[http://us_r:<password>@yy.bar:222"
44+
assert(CondaEnvironmentManager.redactCredentials(original) == redacted)
45+
}
3146
}

0 commit comments

Comments
 (0)