From 2f8a1055f047cf12fc03e5dc2a0667c76d68a107 Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Thu, 3 Feb 2022 18:01:50 +0000 Subject: [PATCH] Do not force mp.jwt.verify.publickey.location to be a build time property --- .../jwt/deployment/SmallRyeJwtProcessor.java | 32 +++++++++++++---- ...yLocationBuildTimeConfigSourceFactory.java | 26 ++++++++++++++ .../jwt/test/PublicKeyLocationConfigTest.java | 36 +++++++++++++++++++ 3 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationBuildTimeConfigSourceFactory.java create mode 100644 extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationConfigTest.java diff --git a/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java b/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java index 0535e0d0dd1f6..2dd1bb870313b 100644 --- a/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java +++ b/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java @@ -1,9 +1,11 @@ package io.quarkus.smallrye.jwt.deployment; import java.util.HashSet; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.function.BooleanSupplier; +import java.util.function.Supplier; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; @@ -30,6 +32,7 @@ import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.pkg.steps.NativeBuild; import io.quarkus.security.deployment.JCAProviderBuildItem; import io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism; import io.quarkus.smallrye.jwt.runtime.auth.JsonWebTokenCredentialProducer; @@ -37,6 +40,7 @@ import io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator; import io.quarkus.smallrye.jwt.runtime.auth.RawOptionalClaimCreator; import io.quarkus.vertx.http.deployment.SecurityInformationBuildItem; +import io.smallrye.config.Expressions; import io.smallrye.jwt.algorithm.KeyEncryptionAlgorithm; import io.smallrye.jwt.algorithm.SignatureAlgorithm; import io.smallrye.jwt.auth.cdi.ClaimValueProducer; @@ -115,16 +119,30 @@ FeatureBuildItem feature() { * * @return NativeImageResourceBuildItem */ - @BuildStep + @BuildStep(onlyIf = NativeBuild.class) NativeImageResourceBuildItem registerNativeImageResources() { final Config config = ConfigProvider.getConfig(); - Optional publicKeyLocationOpt = config.getOptionalValue("mp.jwt.verify.publickey.location", String.class); - if (publicKeyLocationOpt.isPresent()) { - final String publicKeyLocation = publicKeyLocationOpt.get(); - if (publicKeyLocation.indexOf(':') < 0 || publicKeyLocation.startsWith("classpath:")) { - log.infof("Adding %s to native image", publicKeyLocation); - return new NativeImageResourceBuildItem(publicKeyLocation); + try { + Optional publicKeyLocationOpt = config.getOptionalValue("mp.jwt.verify.publickey.location", String.class); + if (publicKeyLocationOpt.isPresent()) { + final String publicKeyLocation = publicKeyLocationOpt.get(); + if (publicKeyLocation.indexOf(':') < 0 || publicKeyLocation.startsWith("classpath:")) { + log.infof("Adding %s to native image", publicKeyLocation); + return new NativeImageResourceBuildItem(publicKeyLocation); + } } + } catch (NoSuchElementException e) { + // The Config may contain expansion variables. Don't fail in this case because the config is not build time. + // The user will have to provide the config for runtime and register the resource manually + String publicKeyRawValue = Expressions.withoutExpansion(new Supplier() { + @Override + public String get() { + return config.getConfigValue("mp.jwt.verify.publickey.location").getRawValue(); + } + }); + log.warnf("Cannot determine %s of mp.jwt.verify.publickey.location to register with the native image", + publicKeyRawValue); + return null; } return null; } diff --git a/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationBuildTimeConfigSourceFactory.java b/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationBuildTimeConfigSourceFactory.java new file mode 100644 index 0000000000000..301f742ea2f03 --- /dev/null +++ b/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationBuildTimeConfigSourceFactory.java @@ -0,0 +1,26 @@ +package io.quarkus.jwt.test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.eclipse.microprofile.config.spi.ConfigSource; + +import io.smallrye.config.ConfigSourceContext; +import io.smallrye.config.ConfigSourceFactory; +import io.smallrye.config.ConfigValue; +import io.smallrye.config.common.MapBackedConfigSource; + +public class PublicKeyLocationBuildTimeConfigSourceFactory implements ConfigSourceFactory { + @Override + public Iterable getConfigSources(final ConfigSourceContext context) { + // This property is only available in runtime. + ConfigValue value = context.getValue("quarkus.uuid"); + if (value == null || value.getValue() == null) { + return List.of(new MapBackedConfigSource(PublicKeyLocationBuildTimeConfigSourceFactory.class.getName(), + Map.of("mp.jwt.verify.publickey.location", "${invalid}"), 1000) { + }); + } + return Collections.emptyList(); + } +} diff --git a/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationConfigTest.java b/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationConfigTest.java new file mode 100644 index 0000000000000..6b0eb8bc45234 --- /dev/null +++ b/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/PublicKeyLocationConfigTest.java @@ -0,0 +1,36 @@ +package io.quarkus.jwt.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.logging.Level; + +import javax.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.smallrye.config.ConfigSourceFactory; +import io.smallrye.config.SmallRyeConfig; + +public class PublicKeyLocationConfigTest { + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest().withApplicationRoot((jar) -> jar.addAsResource("publicKey.pem") + .addClass(PublicKeyLocationBuildTimeConfigSourceFactory.class) + .addAsServiceProvider(ConfigSourceFactory.class, PublicKeyLocationBuildTimeConfigSourceFactory.class)) + .overrideConfigKey("mp.jwt.verify.publickey.location", "publicKey.pem") + .overrideConfigKey("quarkus.package.type", "native") + .setLogRecordPredicate(record -> record.getLevel().intValue() >= Level.WARNING.intValue()) + .assertLogRecords(logRecords -> { + assertEquals("Cannot determine %s of mp.jwt.verify.publickey.location to register with the native image", + logRecords.get(0).getMessage()); + }); + + @Inject + SmallRyeConfig config; + + @Test + void config() { + assertEquals("publicKey.pem", config.getRawValue("mp.jwt.verify.publickey.location")); + } +}