Skip to content

Commit

Permalink
Quarkus Gradle Plugin: allow encrypted configuration
Browse files Browse the repository at this point in the history
As decribed in quarkusio#33135, using encrypted configuration values does not
work with the current Gradle plugin since Quarkus 3.0.0.

`smallrye-config-crypto` requires the
`smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key` to be
present for _all_ builds, even those that do not use encrypted config
values.

It is probably not necessary to actually know the decrypted
configuration values in the Gradle build, it might practically be a
security risk, because the secret key could leak into build log files
(could be prevented of course) and the Gradle cache, which has a high
chance of being shared with others, likely publicly.

This PR adds a "fake" secret keys handler that just returns the string
`<REDACTED>` for all encrypted values.

Fixes quarkusio#33135
  • Loading branch information
snazy committed May 6, 2023
1 parent 8670bba commit b599a7a
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.smallrye.config.AbstractLocationConfigSourceLoader;
import io.smallrye.config.EnvConfigSource;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.SecretKeysHandler;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.common.utils.ConfigSourceUtil;
import io.smallrye.config.source.yaml.YamlConfigSource;
Expand Down Expand Up @@ -118,6 +119,7 @@ static SmallRyeConfig buildConfig(String profile, List<ConfigSource> configSourc
return ConfigUtils.emptyConfigBuilder()
.withSources(configSources)
.withProfile(profile)
.withSecretKeysHandlers(new FakeSecretKeysHandler("aes-gcm-nopadding"))
.build();
}

Expand Down Expand Up @@ -225,4 +227,22 @@ public List<ConfigSource> getConfigSources(final ClassLoader classLoader) {
return loadConfigSources(getFileExtensions(), ordinal, classLoader);
}
}

static final class FakeSecretKeysHandler implements SecretKeysHandler {
private final String name;

FakeSecretKeysHandler(String name) {
this.name = name;
}

@Override
public String decode(String secret) {
return "<REDACTED>";
}

@Override
public String getName() {
return name;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkus.gradle.tasks;

import java.io.File;
import java.net.URL;
import java.nio.file.Path;

import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

public class CryptoConfigTest {

@TempDir
Path testProjectDir;

@Test
void smallryeCrypto() throws Exception {
URL url = getClass().getClassLoader().getResource("io/quarkus/gradle/tasks/crypto/main");
FileUtils.copyDirectory(new File(url.toURI()), testProjectDir.toFile());
FileUtils.copyFile(new File("../gradle.properties"), testProjectDir.resolve("gradle.properties").toFile());

GradleRunner.create()
.withPluginClasspath()
.withProjectDir(testProjectDir.toFile())
.withArguments("build", "--info", "--stacktrace", "--build-cache", "--configuration-cache")
// .build() checks whether the build failed, which is good enough for this test
.build();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ void fromForcedProperties() {
soft.assertThat(effectiveConfig.configMap()).containsEntry("quarkus.foo", "bar");
}

@Test
void crypto() {
EffectiveConfig effectiveConfig = EffectiveConfig.builder()
.withTaskProperties(Map.of("quarkus.foo", "${aes-gcm-nopadding::superSecret}")).build();

soft.assertThat(effectiveConfig.configMap()).containsEntry("quarkus.foo", "<REDACTED>");
}

@ParameterizedTest
@ValueSource(strings = {
"app-props-and-yaml",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
java
id("io.quarkus")
}

buildscript {
repositories {
mavenLocal()
mavenCentral()
}
}

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
implementation(enforcedPlatform("io.quarkus:quarkus-bom:${project.property("version")}"))
implementation("jakarta.inject:jakarta.inject-api:2.0.1")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = "gradle-build-caching"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.acme;

public class Foo {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
someValue = ${aes-gcm-nopadding::superSecret}

0 comments on commit b599a7a

Please sign in to comment.