From d28b54e5d5c2ea4e4fffc6b5988af19ec0f247e8 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Tue, 25 Jan 2022 10:24:35 -0300 Subject: [PATCH] Hide Hasicorp Vault from CLI (#9700) Closes #9688 --- .../quarkus/deployment/KeycloakProcessor.java | 4 +- .../mappers/VaultPropertyMappers.java | 34 +++++++++++---- .../FilesPlainTextVaultProviderFactory.java | 43 +++++++++++++++++++ .../vault/QuarkusVaultProviderFactory.java | 3 +- .../org.keycloak.vault.VaultProviderFactory | 3 +- .../configuration/test/ConfigurationTest.java | 13 +++--- ...HelpCommandTest.testBuildHelp.approved.txt | 6 +-- ...pCommandTest.testStartDevHelp.approved.txt | 5 +++ ...mmandTest.testStartDevHelpAll.approved.txt | 8 ++-- ...HelpCommandTest.testStartHelp.approved.txt | 5 +++ .../src/main/content/conf/keycloak.conf | 3 +- 11 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/FilesPlainTextVaultProviderFactory.java diff --git a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java index ef8f3d8c6d95..6727d1309672 100644 --- a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java +++ b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java @@ -127,6 +127,7 @@ import org.keycloak.url.FixedHostnameProviderFactory; import org.keycloak.url.RequestHostnameProviderFactory; import org.keycloak.util.JsonSerialization; +import org.keycloak.vault.FilesPlainTextVaultProviderFactory; class KeycloakProcessor { @@ -146,7 +147,8 @@ class KeycloakProcessor { LiquibaseJpaUpdaterProviderFactory.class, DefaultHostnameProviderFactory.class, FixedHostnameProviderFactory.class, - RequestHostnameProviderFactory.class); + RequestHostnameProviderFactory.class, + FilesPlainTextVaultProviderFactory.class); static { DEPLOYEABLE_SCRIPT_PROVIDERS.put(AUTHENTICATORS, KeycloakProcessor::registerScriptAuthenticator); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/VaultPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/VaultPropertyMappers.java index 260b6bec789d..6b7c853cbff8 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/VaultPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/VaultPropertyMappers.java @@ -8,26 +8,44 @@ private VaultPropertyMappers() { public static PropertyMapper[] getVaultPropertyMappers() { return new PropertyMapper[] { builder() - .from("vault-file-path") - .to("kc.spi-vault-files-plaintext-dir") - .description("If set, secrets can be obtained by reading the content of files within the given path.") + .from("vault") + .description("Enables a vault provider.") + .expectedValues("file", "hashicorp") + .paramLabel("provider") + .isBuildTimeProperty(true) + .build(), + builder() + .from("vault-dir") + .to("kc.spi-vault-file-dir") + .description("If set, secrets can be obtained by reading the content of files within the given directory.") .paramLabel("dir") .build(), builder() - .from("vault-hashicorp-") + .from("vault-") .to("quarkus.vault.") - .description("If set, secrets can be obtained from Hashicorp Vault.") + .description("Maps any vault option to their corresponding properties in quarkus-vault extension.") + .hidden(true) + .isBuildTimeProperty(true) + .build(), + builder() + .from("vault-url") + .to("quarkus.vault.url") + .description("The vault server url.") + .paramLabel("paths") + .hidden(true) + .isBuildTimeProperty(true) .build(), builder() - .from("vault-hashicorp-paths") + .from("vault-kv-paths") .to("kc.spi-vault-hashicorp-paths") - .description("A set of one or more paths that should be used when looking up secrets.") + .description("A set of one or more key/value paths that should be used when looking up secrets.") .paramLabel("paths") + .hidden(true) .build() }; } private static PropertyMapper.Builder builder() { - return PropertyMapper.builder(ConfigCategory.VAULT).isBuildTimeProperty(true); + return PropertyMapper.builder(ConfigCategory.VAULT); } } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/FilesPlainTextVaultProviderFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/FilesPlainTextVaultProviderFactory.java new file mode 100644 index 000000000000..df977ccf3abc --- /dev/null +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/FilesPlainTextVaultProviderFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.quarkus.runtime.vault; + +import org.keycloak.Config; +import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.quarkus.runtime.configuration.Configuration; + +public class FilesPlainTextVaultProviderFactory extends org.keycloak.vault.FilesPlainTextVaultProviderFactory + implements EnvironmentDependentProviderFactory { + + public static final String ID = "file"; + + @Override + public String getId() { + return ID; + } + + @Override + public boolean isSupported() { + return false; + } + + @Override + public boolean isSupported(Config.Scope config) { + return getId().equals(Configuration.getRawValue("kc.vault")); + } +} diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/QuarkusVaultProviderFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/QuarkusVaultProviderFactory.java index 8b44d77c07ec..06a50eb99599 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/QuarkusVaultProviderFactory.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/vault/QuarkusVaultProviderFactory.java @@ -21,6 +21,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.vault.AbstractVaultProviderFactory; import org.keycloak.vault.VaultProvider; @@ -77,7 +78,7 @@ public int order() { @Override public boolean isSupported(Config.Scope config) { - return !config.getPropertyNames().isEmpty(); + return getId().equals(Configuration.getRawValue("kc.vault")); } @Override diff --git a/quarkus/runtime/src/main/resources/META-INF/services/org.keycloak.vault.VaultProviderFactory b/quarkus/runtime/src/main/resources/META-INF/services/org.keycloak.vault.VaultProviderFactory index 6ebce29f8f60..0aa47df231d6 100644 --- a/quarkus/runtime/src/main/resources/META-INF/services/org.keycloak.vault.VaultProviderFactory +++ b/quarkus/runtime/src/main/resources/META-INF/services/org.keycloak.vault.VaultProviderFactory @@ -1 +1,2 @@ -org.keycloak.quarkus.runtime.vault.QuarkusVaultProviderFactory \ No newline at end of file +org.keycloak.quarkus.runtime.vault.FilesPlainTextVaultProviderFactory +org.keycloak.quarkus.runtime.vault.QuarkusVaultProviderFactory diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java index dc7148aee913..655f95d4d76a 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/test/ConfigurationTest.java @@ -23,7 +23,6 @@ import java.io.File; import java.lang.reflect.Field; -import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -45,7 +44,7 @@ import io.quarkus.runtime.configuration.ConfigUtils; import io.smallrye.config.SmallRyeConfigProviderResolver; import org.keycloak.quarkus.runtime.Environment; -import org.keycloak.vault.FilesPlainTextVaultProviderFactory; +import org.keycloak.quarkus.runtime.vault.FilesPlainTextVaultProviderFactory; import org.mariadb.jdbc.MySQLDataSource; import org.postgresql.xa.PGXADataSource; @@ -124,11 +123,11 @@ public void testEnvVarPriorityOverPropertiesFile() { @Test public void testEnvVarAvailableFromPropertyNames() { - putEnvVar("KC_VAULT_FILE_PATH", "/foo/bar"); - Config.Scope config = initConfig("vault", FilesPlainTextVaultProviderFactory.PROVIDER_ID); + putEnvVar("KC_VAULT_DIR", "/foo/bar"); + Config.Scope config = initConfig("vault", FilesPlainTextVaultProviderFactory.ID); assertEquals("/foo/bar", config.get("dir")); assertTrue(config.getPropertyNames() - .contains("kc.spi-vault-".concat(FilesPlainTextVaultProviderFactory.PROVIDER_ID).concat("-dir"))); + .contains("kc.spi-vault-".concat(FilesPlainTextVaultProviderFactory.ID).concat("-dir"))); } @Test @@ -197,8 +196,8 @@ public void testPropertyNamesFromConfig() { assertEquals(1, config.getPropertyNames().size()); assertEquals("http://c.jwk.url", config.get("static-jwk-url")); - System.setProperty(CLI_ARGS, "--vault-file-path=secrets"); - config = initConfig("vault", FilesPlainTextVaultProviderFactory.PROVIDER_ID); + System.setProperty(CLI_ARGS, "--vault-dir=secrets"); + config = initConfig("vault", FilesPlainTextVaultProviderFactory.ID); assertEquals(1, config.getPropertyNames().size()); assertEquals("secrets", config.get("dir")); diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testBuildHelp.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testBuildHelp.approved.txt index 990fe717d3f9..126c430a36f1 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testBuildHelp.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testBuildHelp.approved.txt @@ -94,11 +94,7 @@ Metrics: Vault: ---vault-file-path - If set, secrets can be obtained by reading the content of files within the - given path. ---vault-hashicorp-paths - A set of one or more paths that should be used when looking up secrets. +--vault Enables a vault provider. Examples: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.approved.txt index 6ab3e461ec46..e45a052ea1a5 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.approved.txt @@ -95,6 +95,11 @@ Proxy: --proxy The proxy address forwarding mode if the server is behind a reverse proxy. Possible values are: none,edge,reencrypt,passthrough Default: none. +Vault: + +--vault-dir If set, secrets can be obtained by reading the content of files within the + given directory. + Do NOT start the server using this command when deploying to production. Use 'kc.sh start-dev --help-all' to list all available options, including build diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.approved.txt index c9d48703f0c7..76be0df1d3e9 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.approved.txt @@ -161,11 +161,9 @@ Proxy: Vault: ---vault-file-path - If set, secrets can be obtained by reading the content of files within the - given path. ---vault-hashicorp-paths - A set of one or more paths that should be used when looking up secrets. +--vault Enables a vault provider. +--vault-dir If set, secrets can be obtained by reading the content of files within the + given directory. Do NOT start the server using this command when deploying to production. diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.approved.txt index 0c207a6be7fc..326a54f8173e 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.approved.txt @@ -98,6 +98,11 @@ Proxy: --proxy The proxy address forwarding mode if the server is behind a reverse proxy. Possible values are: none,edge,reencrypt,passthrough Default: none. +Vault: + +--vault-dir If set, secrets can be obtained by reading the content of files within the + given directory. + You may use the "--auto-build" option when starting the server to avoid running the "build" command everytime you need to change a static property: diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.conf b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.conf index d9e77cbffe33..fed3044098ba 100644 --- a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.conf +++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.conf @@ -45,4 +45,5 @@ spi-events-store-jpa-max-detail-length=2000 spi-login-protocol-saml-known-protocols=http=8180,https=8543 # File-Based Vault -vault-file-path=${kc.home.dir}secrets +vault=file +vault-dir=${kc.home.dir}secrets