Skip to content

Commit 5f3bbf4

Browse files
authored
feat(secrets): secret management (#1605)
* feat(secrets): initial draft Signed-off-by: melodicore <[email protected]> * feat(secrets): use DI Signed-off-by: melodicore <[email protected]> * fmt(secrets): use project conventions Signed-off-by: melodicore <[email protected]> * feat(secrets): various changes Signed-off-by: melodicore <[email protected]> * feat(secrets): next revision Signed-off-by: melodicore <[email protected]> * feat(secrets): initial integration with runtime and manifest Signed-off-by: melodicore <[email protected]> * feat(secrets): refactoring, reformatting, bug squashing and quality of life features Signed-off-by: melodicore <[email protected]> * feat(secrets): apply secret environment variables Signed-off-by: melodicore <[email protected]> * feat(secrets): secrets package tests Signed-off-by: melodicore <[email protected]> * fmt(secrets): correct detekt and spotless issues Signed-off-by: melodicore <[email protected]> * feat(secrets): final additions Signed-off-by: melodicore <[email protected]> * fix(secrets): make native build work Signed-off-by: melodicore <[email protected]> * fix(secrets): fix crashes when loading secrets and things go wrong Signed-off-by: melodicore <[email protected]> * fix(secrets): reset initialized state in tests Signed-off-by: melodicore <[email protected]> * docs(secrets): add api comments, fix formatting Signed-off-by: melodicore <[email protected]> * feat(secrets): regenerate api pins Signed-off-by: melodicore <[email protected]> * feat(secrets): add new api pins Signed-off-by: melodicore <[email protected]> * fix(secrets): fix some displayed messages Signed-off-by: melodicore <[email protected]> * fix(secrets): fix unused import Signed-off-by: melodicore <[email protected]> * feat(secrets): allow changing encryption details and regenerating profile keys Signed-off-by: melodicore <[email protected]> * feat(secrets): python module Signed-off-by: melodicore <[email protected]> * chore(secrets): spotless Signed-off-by: melodicore <[email protected]> * chore(secrets): api dump Signed-off-by: melodicore <[email protected]> * fix(secrets): review fixes Signed-off-by: melodicore <[email protected]> * fix(secrets): api dump again Signed-off-by: melodicore <[email protected]> --------- Signed-off-by: melodicore <[email protected]>
1 parent cac7c1f commit 5f3bbf4

File tree

95 files changed

+6499
-613
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+6499
-613
lines changed

gradle/elide.versions.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,10 @@ kotlinx-io-bytestring-jvm = { group = "org.jetbrains.kotlinx", name = "kotlinx-i
639639
kotlinx-knit = { group = "org.jetbrains.kotlinx", name = "kotlinx-knit", version.ref = "kotlinx-knit" }
640640
kotlinx-metadata-jvm = { group = "org.jetbrains.kotlinx", name = "kotlinx-metadata-jvm", version.ref = "kotlinx-metadata-jvm" }
641641
kotlinx-nodejs = { group = "org.jetbrains.kotlinx", name = "kotlinx-nodejs", version.ref = "kotlinx-nodejs" }
642+
kotlinx-serialization-cbor = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-cbor", version.ref = "kotlinx-serialization" }
643+
kotlinx-serialization-cbor-js = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-cbor-js", version.ref = "kotlinx-serialization" }
644+
kotlinx-serialization-cbor-jvm = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-cbor-jvm", version.ref = "kotlinx-serialization" }
645+
kotlinx-serialization-cbor-wasm = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-cbor-wasm", version.ref = "kotlinx-serialization" }
642646
kotlinx-serialization-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
643647
kotlinx-serialization-core-js = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core-js", version.ref = "kotlinx-serialization" }
644648
kotlinx-serialization-core-jvm = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core-jvm", version.ref = "kotlinx-serialization" }
@@ -691,6 +695,10 @@ kotlinx-wrappers-web = { group = "org.jetbrains.kotlin-wrappers", name = "kotlin
691695
ksp = { group = "com.google.devtools.ksp", name = "symbol-processing", version.ref = "ksp" }
692696
ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" }
693697
ksp-cmdline = { group = "com.google.devtools.ksp", name = "symbol-processing-cmdline", version.ref = "ksp" }
698+
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
699+
ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
700+
ktor-client-contentNegotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
701+
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" }
694702
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
695703
ktor-server-cio = { group = "io.ktor", name = "ktor-server-cio", version.ref = "ktor" }
696704
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
@@ -1024,3 +1032,9 @@ ktor-server = [
10241032
"ktor-server-hsts",
10251033
"ktor-server-websockets",
10261034
]
1035+
1036+
ktor-client = [
1037+
"ktor-client-core",
1038+
"ktor-client-contentNegotiation",
1039+
"ktor-serialization-kotlinx-json",
1040+
]

packages/cli/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,9 @@ dependencies {
604604
// TODO: patched
605605
// implementation(libs.graalvm.tools.coverage)
606606

607+
// Secrets
608+
implementation(projects.packages.secrets)
609+
607610
// KotlinX
608611
implementation(libs.kotlinx.serialization.core)
609612
implementation(libs.kotlinx.serialization.json)
@@ -1805,6 +1808,7 @@ val linuxOnlyArgs = defaultPlatformArgs.plus(
18051808
"--initialize-at-run-time=io.netty.channel.kqueue.KQueue",
18061809
"--initialize-at-run-time=io.netty.channel.kqueue.KQueueIoHandler",
18071810
"--initialize-at-run-time=io.netty.channel.kqueue.AbstractKQueueChannel",
1811+
"--initialize-at-run-time=io.netty.internal.tcnative.CertificateCompressionAlgo",
18081812
).plus(
18091813
listOfNotNull(
18101814
onlyIf(enableStatic, "--libc=musl"),

packages/cli/src/main/kotlin/elide/tool/cli/Elide.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import elide.tool.cli.cmd.pkl.ToolPklCommand
5656
import elide.tool.cli.cmd.project.ToolProjectCommand
5757
import elide.tool.cli.cmd.tool.ToolInvokeCommand
5858
import elide.tool.cli.cmd.repl.ToolShellCommand
59+
import elide.tool.cli.cmd.secrets.ToolSecretsCommand
5960
import elide.tool.cli.cmd.tool.jar.JarToolAdapter
6061
import elide.tool.cli.cmd.tool.javac.JavaCompilerAdapter
6162
import elide.tool.cli.cmd.tool.javadoc.JavadocToolAdapter
@@ -130,6 +131,7 @@ internal const val ELIDE_HEADER = ("@|bold,fg(magenta)%n" +
130131
LspCommand::class,
131132
McpCommand::class,
132133
Elide.Completions::class,
134+
ToolSecretsCommand::class,
133135
],
134136
customSynopsis = [
135137
"",

packages/cli/src/main/kotlin/elide/tool/cli/cmd/repl/ToolShellCommand.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ import elide.runtime.precompiler.Precompiler
105105
import elide.runtime.runner.JvmRunner
106106
import elide.runtime.runner.RunnerOutcome
107107
import elide.runtime.runner.Runners
108+
import elide.secrets.Secrets
108109
import elide.tool.cli.*
109110
import elide.tool.cli.GuestLanguage.*
110111
import elide.tool.cli.cmd.builder.emitCommand
@@ -2454,6 +2455,7 @@ internal class ToolShellCommand : ProjectAwareSubcommand<ToolState, CommandConte
24542455
appEnvironment.apply(
24552456
project,
24562457
this,
2458+
beanContext.getBean(Secrets::class.java).getEnv(),
24572459
host = accessControl.allowAll || accessControl.allowEnv,
24582460
dotenv = appEnvironment.dotenv,
24592461
)
@@ -2762,6 +2764,27 @@ internal class ToolShellCommand : ProjectAwareSubcommand<ToolState, CommandConte
27622764

27632765
val effectiveInitLangs = onByDefaultLangs + projectLangs
27642766

2767+
// initialize secrets
2768+
val secretsResolution = launch {
2769+
run {
2770+
projectResolution.join()
2771+
2772+
val secrets = beanContext.getBean(Secrets::class.java)
2773+
try {
2774+
secrets.init(projectPath, activeProject.value?.manifest)
2775+
} catch (t: Throwable) {
2776+
logging.warn { "Secrets were not initialized with message: ${t.message}" }
2777+
}
2778+
if(secrets.initialized) {
2779+
if (secrets.getProfile() == null) {
2780+
val profiles = secrets.listProfiles()
2781+
if (profiles.size != 1) logging.warn { "No secret profile will be loaded" }
2782+
else secrets.loadProfile(profiles.first())
2783+
}
2784+
}
2785+
}
2786+
}
2787+
27652788
// if no entrypoint was specified, attempt to use the one in the project manifest, or try resolving the runnable as
27662789
// a script name in either `elide.pkl` or a foreign manifest.
27672790
when (val tgt = runnable) {
@@ -2892,6 +2915,7 @@ internal class ToolShellCommand : ProjectAwareSubcommand<ToolState, CommandConte
28922915
try {
28932916
projectResolution.join()
28942917
lockfileResolution.join()
2918+
secretsResolution.join()
28952919

28962920
resolveEngine(effectiveInitLangs).unwrap().use {
28972921
withDeferredContext(effectiveInitLangs) {

packages/cli/src/main/kotlin/elide/tool/cli/cmd/runner/EnvironmentConfig.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import elide.tooling.project.ElideProject
4545
internal fun apply(
4646
project: ElideProject?,
4747
config: PolyglotEngineConfiguration,
48+
secretsEnv: Map<String, String>,
4849
host: Boolean = false,
4950
dotenv: Boolean = true,
5051
) = config.environment {
@@ -59,7 +60,10 @@ import elide.tooling.project.ElideProject
5960
mapToHostEnv(it.key)
6061
}
6162

62-
// apply project-level environment variables first (if applicable)
63+
// apply secret environment variables first
64+
secretsEnv.forEach { environment(it.key, it.value) }
65+
66+
// apply project-level environment variables (if applicable)
6367
project?.env?.vars?.forEach {
6468
if (it.value.isPresent) {
6569
if (it.value.source == EnvVariableSource.DOTENV && !dotenv) {

0 commit comments

Comments
 (0)