enhance: adds truststores to the keycloak cr (#25215)
also generally correcting the misspelling trustore closes: #24798 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
c81b533cf6
commit
08751001db
22 changed files with 298 additions and 32 deletions
|
@ -450,7 +450,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -455,7 +455,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -503,7 +503,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -503,7 +503,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -435,7 +435,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -440,7 +440,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -445,7 +445,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
a way to verify the host of the server they are talking to. This is what the truststore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
|
|
|
@ -6,6 +6,24 @@ The Keycloak JS adapter now uses the https://webpack.js.org/guides/package-expor
|
|||
|
||||
Keycloak introduces an improved truststores configuration options. The Keycloak truststore is now used across the server: for outgoing connections, mTLS, database drivers and more. It's no longer needed to configure separate truststores for individual areas. To configure the truststore, you can put your truststores files or certificates in the default `conf/truststores`, or use the new `truststore-paths` config option. For details refer to the relevant https://www.keycloak.org/server/keycloak-truststore[guide].
|
||||
|
||||
== Keycloak CR Truststores
|
||||
|
||||
You may also take advantage of the new server-side handling of truststores via the Keycloak CR, for example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spec:
|
||||
truststores:
|
||||
mystore:
|
||||
secret:
|
||||
name: mystore-secret
|
||||
myotherstore:
|
||||
secret:
|
||||
name: myotherstore-secret
|
||||
----
|
||||
|
||||
Currently only Secrets are supported.
|
||||
|
||||
= Automatic certificate management for SAML identity providers
|
||||
|
||||
The SAML identity providers can now be configured to automatically download the signing certificates from the IDP entity metadata descriptor endpoint. In order to use the new feature the option `Metadata descriptor URL` should be configured in the provider (URL where the IDP metadata information with the certificates is published) and `Use metadata descriptor URL` needs to be `ON`. The certificates are automatically downloaded and cached in the `public-key-storage` SPI from that URL. The certificates can also be reloaded or imported from the admin console, using the action combo in the provider page.
|
||||
|
|
|
@ -69,5 +69,7 @@ public final class Constants {
|
|||
public static final String INSECURE_DISABLE = "INSECURE-DISABLE";
|
||||
public static final String CERTIFICATES_FOLDER = "/mnt/certificates";
|
||||
|
||||
public static final String TRUSTSTORES_FOLDER = "/opt/keycloak/conf/truststores";
|
||||
|
||||
public static String KEYCLOAK_HTTP_RELATIVE_PATH_KEY = "http-relative-path";
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ import org.keycloak.operator.Utils;
|
|||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.Truststore;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TruststoreSource;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -85,10 +87,16 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
|||
@Override
|
||||
public StatefulSet desired(Keycloak primary, Context<Keycloak> context) {
|
||||
StatefulSet baseDeployment = createBaseDeployment(primary, context);
|
||||
TreeSet<String> allSecrets = new TreeSet<>();
|
||||
if (isTlsConfigured(primary)) {
|
||||
configureTLS(primary, baseDeployment);
|
||||
configureTLS(primary, baseDeployment, allSecrets);
|
||||
}
|
||||
addTruststores(primary, baseDeployment, allSecrets);
|
||||
addEnvVars(baseDeployment, primary, allSecrets);
|
||||
|
||||
if (!allSecrets.isEmpty()) {
|
||||
watchedSecrets.annotateDeployment(new ArrayList<>(allSecrets), primary, baseDeployment);
|
||||
}
|
||||
addEnvVarsAndWatchSecrets(baseDeployment, primary);
|
||||
|
||||
StatefulSet existingDeployment = context.getSecondaryResource(StatefulSet.class).orElse(null);
|
||||
if (existingDeployment == null) {
|
||||
|
@ -109,7 +117,32 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
|||
return baseDeployment;
|
||||
}
|
||||
|
||||
void configureTLS(Keycloak keycloakCR, StatefulSet deployment) {
|
||||
private void addTruststores(Keycloak keycloakCR, StatefulSet deployment, TreeSet<String> allSecrets) {
|
||||
var kcContainer = deployment.getSpec().getTemplate().getSpec().getContainers().get(0);
|
||||
for (Truststore truststore : keycloakCR.getSpec().getTruststores().values()) {
|
||||
// for now we'll assume only secrets, later we can support configmaps
|
||||
TruststoreSource source = truststore.getSecret();
|
||||
String secretName = source.getName();
|
||||
var volume = new VolumeBuilder()
|
||||
.withName("truststore-secret-" + secretName)
|
||||
.withNewSecret()
|
||||
.withSecretName(secretName)
|
||||
.withOptional(source.getOptional())
|
||||
.endSecret()
|
||||
.build();
|
||||
|
||||
var volumeMount = new VolumeMountBuilder()
|
||||
.withName(volume.getName())
|
||||
.withMountPath(Constants.TRUSTSTORES_FOLDER + "/secret-" + secretName)
|
||||
.build();
|
||||
|
||||
deployment.getSpec().getTemplate().getSpec().getVolumes().add(0, volume);
|
||||
kcContainer.getVolumeMounts().add(0, volumeMount);
|
||||
allSecrets.add(secretName);
|
||||
}
|
||||
}
|
||||
|
||||
void configureTLS(Keycloak keycloakCR, StatefulSet deployment, TreeSet<String> allSecrets) {
|
||||
var kcContainer = deployment.getSpec().getTemplate().getSpec().getContainers().get(0);
|
||||
|
||||
var volume = new VolumeBuilder()
|
||||
|
@ -127,6 +160,7 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
|||
|
||||
deployment.getSpec().getTemplate().getSpec().getVolumes().add(0, volume);
|
||||
kcContainer.getVolumeMounts().add(0, volumeMount);
|
||||
allSecrets.add(keycloakCR.getSpec().getHttpSpec().getTlsSecret());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -280,7 +314,7 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
|||
return JGROUPS_DNS_QUERY_PARAM + KeycloakDiscoveryServiceDependentResource.getName(keycloakCR) +"." + keycloakCR.getMetadata().getNamespace();
|
||||
}
|
||||
|
||||
private void addEnvVarsAndWatchSecrets(StatefulSet baseDeployment, Keycloak keycloakCR) {
|
||||
private void addEnvVars(StatefulSet baseDeployment, Keycloak keycloakCR, TreeSet<String> allSecrets) {
|
||||
var firstClasssEnvVars = distConfigurator.configureDistOptions(keycloakCR);
|
||||
|
||||
String adminSecretName = KeycloakAdminSecretDependentResource.getName(keycloakCR);
|
||||
|
@ -301,14 +335,7 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
|||
|
||||
Log.infof("Found config secrets names: %s", serverConfigSecretsNames);
|
||||
|
||||
// add secrets from volume mounts (currently just the tls secret)
|
||||
if (isTlsConfigured(keycloakCR)) {
|
||||
serverConfigSecretsNames.add(keycloakCR.getSpec().getHttpSpec().getTlsSecret());
|
||||
}
|
||||
|
||||
if (!serverConfigSecretsNames.isEmpty()) {
|
||||
watchedSecrets.annotateDeployment(new ArrayList<>(serverConfigSecretsNames), keycloakCR, baseDeployment);
|
||||
}
|
||||
allSecrets.addAll(serverConfigSecretsNames);
|
||||
}
|
||||
|
||||
private List<EnvVar> getDefaultAndAdditionalEnvVars(Keycloak keycloakCR, String adminSecretName) {
|
||||
|
|
|
@ -25,10 +25,13 @@ import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpec;
|
|||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TransactionsSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.Truststore;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
@ -84,6 +87,9 @@ public class KeycloakSpec {
|
|||
@JsonPropertyDescription("In this section you can configure Keycloak hostname and related properties.")
|
||||
private HostnameSpec hostnameSpec;
|
||||
|
||||
@JsonPropertyDescription("In this section you can configure Keycloak truststores.")
|
||||
private Map<String, Truststore> truststores = new LinkedHashMap<>();
|
||||
|
||||
public HttpSpec getHttpSpec() {
|
||||
return httpSpec;
|
||||
}
|
||||
|
@ -182,4 +188,16 @@ public class KeycloakSpec {
|
|||
public void setStartOptimized(Boolean optimized) {
|
||||
this.startOptimized = optimized;
|
||||
}
|
||||
|
||||
public Map<String, Truststore> getTruststores() {
|
||||
return truststores;
|
||||
}
|
||||
|
||||
public void setTruststores(Map<String, Truststore> truststores) {
|
||||
if (truststores == null) {
|
||||
truststores = new LinkedHashMap<>();
|
||||
}
|
||||
this.truststores = truststores;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2023 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.operator.crds.v2alpha1.deployment.spec;
|
||||
|
||||
import io.fabric8.generator.annotation.Required;
|
||||
import io.sundr.builder.annotations.Buildable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
|
||||
public class Truststore {
|
||||
|
||||
@Required
|
||||
private String name;
|
||||
@Required
|
||||
private TruststoreSource secret;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TruststoreSource getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(TruststoreSource secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2023 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.operator.crds.v2alpha1.deployment.spec;
|
||||
|
||||
import io.fabric8.generator.annotation.Required;
|
||||
import io.sundr.builder.annotations.Buildable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
|
||||
public class TruststoreSource {
|
||||
|
||||
@Required
|
||||
private String name;
|
||||
private Boolean optional;
|
||||
|
||||
public Boolean getOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public void setOptional(Boolean optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2022 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.operator.testsuite.integration;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
|
||||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.operator.Constants;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TruststoreBuilder;
|
||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.deployKeycloak;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.getResourceFromFile;
|
||||
|
||||
@QuarkusTest
|
||||
public class KeycloakTruststoresTests extends BaseOperatorTest {
|
||||
@Test
|
||||
public void testTruststoreMissing() {
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var deploymentName = kc.getMetadata().getName();
|
||||
kc.getSpec().getTruststores().put("xyz", new TruststoreBuilder().withName("xyz").withNewSecret().withName("xyz").endSecret().build());
|
||||
|
||||
deployKeycloak(k8sclient, kc, false);
|
||||
Resource<StatefulSet> stsResource = k8sclient.resources(StatefulSet.class).withName(deploymentName);
|
||||
Awaitility.await().ignoreExceptions().untilAsserted(() -> {
|
||||
StatefulSet statefulSet = stsResource.get();
|
||||
assertEquals("true",
|
||||
statefulSet.getMetadata().getAnnotations().get(Constants.KEYCLOAK_MISSING_SECRETS_ANNOTATION));
|
||||
assertTrue(statefulSet.getMetadata().getAnnotations().get(Constants.KEYCLOAK_WATCHING_ANNOTATION)
|
||||
.contains("xyz"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrustroreExists() {
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var deploymentName = kc.getMetadata().getName();
|
||||
|
||||
K8sUtils.set(k8sclient, getResourceFromFile("example-truststore-secret.yaml", Secret.class));
|
||||
kc.getSpec().getTruststores().put("example", new TruststoreBuilder().withName("example").withNewSecret().withName("example-truststore-secret").endSecret().build());
|
||||
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
Resource<StatefulSet> stsResource = k8sclient.resources(StatefulSet.class).withName(deploymentName);
|
||||
StatefulSet statefulSet = stsResource.get();
|
||||
assertEquals("false",
|
||||
statefulSet.getMetadata().getAnnotations().get(Constants.KEYCLOAK_MISSING_SECRETS_ANNOTATION));
|
||||
assertTrue(statefulSet.getSpec().getTemplate().getSpec().getContainers().get(0).getVolumeMounts().stream()
|
||||
.anyMatch(v -> v.getMountPath()
|
||||
.equals("/opt/keycloak/conf/truststores/secret-example-truststore-secret")));
|
||||
}
|
||||
|
||||
}
|
29
operator/src/test/resources/example-truststore-secret.yaml
Normal file
29
operator/src/test/resources/example-truststore-secret.yaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: example-truststore-secret
|
||||
stringData:
|
||||
cert.pem: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDezCCAmOgAwIBAgIEM0VH1DANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQGEwJL
|
||||
QzERMA8GA1UECBMIa2V5Y2xvYWsxETAPBgNVBAcTCGtleWNsb2FrMREwDwYDVQQK
|
||||
EwhrZXljbG9hazERMA8GA1UECxMIa2V5Y2xvYWsxEjAQBgNVBAMTCUtleSBDbG9h
|
||||
azAgFw0yMzExMDkxMjMxNDZaGA8yMDUxMDMyNjEyMzE0NlowbTELMAkGA1UEBhMC
|
||||
S0MxETAPBgNVBAgTCGtleWNsb2FrMREwDwYDVQQHEwhrZXljbG9hazERMA8GA1UE
|
||||
ChMIa2V5Y2xvYWsxETAPBgNVBAsTCGtleWNsb2FrMRIwEAYDVQQDEwlLZXkgQ2xv
|
||||
YWswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv1M8ZiKSONnryBcTy
|
||||
u6u0d/cJ9s0kZAvO+Q62I5W6e6r0zFYlUjheRSTF7PdypAxhJPMRVGZoE0WCKUMn
|
||||
4D1E43ZC8bl8IgzpC8m2hbtJsVcbZs0H4D9jHjHvBiPgdkmTc7F/pU8jk8oD3L+Y
|
||||
olzOFLI/wpwC7kx9O1bzXVpTKOg12JqrKRHIfdvU4mbMlRTRX+AX6Iw5QMiy8vfA
|
||||
77uCkkxPInx18Z4MU6vqjvAWXos5gQE1fVUyHsmWlBp8Eis7jD7d52Th1uK3nJLo
|
||||
4wnKzNXDXq34o25xR6j1BpU+v8iqkcDdpJncQHuo/iHK2WZh8xgQMxGoc33nslxB
|
||||
JvuPAgMBAAGjITAfMB0GA1UdDgQWBBTp2UwAeIxtlKqNFrW4jUVnJ8CgAjANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEANfkQnompu7woA7fCJb5O+WCNTGoAdFO36tjyRczbRO2G
|
||||
W7GqPFupObQhAQTtZ55pBfhZTz30lrM9C6vAMDIhfqjYfdATeflALCZH4lbLRcxf
|
||||
bMq/FVRz1p+hEUGwNeguxCiZ7ZqfqchwiW8oeEeG4MYdYOfdR1pglF6Ak0pkWwqE
|
||||
KqfuTjllGJRkLJco6ApDA6viBnGUX9T4Xb+xsfzTiOj93k9Z1aWzLB4MCupS+Z1h
|
||||
VC39DBEUe04OEczu8ZT4A20hiOp+wA2YuToxVVncpnMdZhe1hbzKrTTflM22mcs1
|
||||
6Fqjo2BBJQ/sfhWMB7KYpnI78n/bkVP2S4hE3JChXA==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
type: Opaque
|
|
@ -219,11 +219,11 @@ public class FileTruststoreProviderFactory implements TruststoreProviderFactory
|
|||
if (isSelfSigned(cax509cert)) {
|
||||
X500Principal principal = cax509cert.getSubjectX500Principal();
|
||||
trustedRootCerts.put(principal, cax509cert);
|
||||
log.debug("Trusted root CA found in trustore : alias : " + alias + " | Subject DN : " + principal);
|
||||
log.debug("Trusted root CA found in truststore : alias : " + alias + " | Subject DN : " + principal);
|
||||
} else {
|
||||
X500Principal principal = cax509cert.getSubjectX500Principal();
|
||||
intermediateCerts.put(principal, cax509cert);
|
||||
log.debug("Intermediate CA found in trustore : alias : " + alias + " | Subject DN : " + principal);
|
||||
log.debug("Intermediate CA found in truststore : alias : " + alias + " | Subject DN : " + principal);
|
||||
}
|
||||
} else
|
||||
log.info("Skipping certificate with alias [" + alias + "] from truststore, because it's not an X509Certificate");
|
||||
|
|
|
@ -419,7 +419,7 @@ public interface TestingResource {
|
|||
void disableTruststoreSpi();
|
||||
|
||||
/**
|
||||
* Temporarily changes the trustore SPI with another hostname verification policy. Call reenableTruststoreSpi to revert.
|
||||
* Temporarily changes the truststore SPI with another hostname verification policy. Call reenableTruststoreSpi to revert.
|
||||
* @param hostnamePolicy The hostname verification policy to set
|
||||
*/
|
||||
@GET
|
||||
|
|
|
@ -119,10 +119,10 @@ public class AdminClientUtil {
|
|||
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder) ResteasyClientBuilder.newBuilder();
|
||||
|
||||
if ("true".equals(System.getProperty("auth.server.ssl.required"))) {
|
||||
File trustore = new File(PROJECT_BUILD_DIRECTORY, "dependency/keystore/keycloak.truststore");
|
||||
resteasyClientBuilder.sslContext(getSSLContextWithTrustore(trustore, "secret"));
|
||||
File truststore = new File(PROJECT_BUILD_DIRECTORY, "dependency/keystore/keycloak.truststore");
|
||||
resteasyClientBuilder.sslContext(getSSLContextWithTruststore(truststore, "secret"));
|
||||
|
||||
System.setProperty("javax.net.ssl.trustStore", trustore.getAbsolutePath());
|
||||
System.setProperty("javax.net.ssl.trustStore", truststore.getAbsolutePath());
|
||||
}
|
||||
|
||||
// We need to ignore unknown JSON properties e.g. in the adapter configuration representation
|
||||
|
@ -145,7 +145,7 @@ public class AdminClientUtil {
|
|||
return resteasyClientBuilder.build();
|
||||
}
|
||||
|
||||
private static SSLContext getSSLContextWithTrustore(File file, String password) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
|
||||
private static SSLContext getSSLContextWithTruststore(File file, String password) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
|
||||
if (!file.isFile()) {
|
||||
throw new RuntimeException("Truststore file not found: " + file.getAbsolutePath());
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public class MutualTLSUtils {
|
|||
}
|
||||
}
|
||||
|
||||
// load the trustore
|
||||
// load the truststore
|
||||
KeyStore truststore = null;
|
||||
if (trustStorePath != null) {
|
||||
try {
|
||||
|
|
|
@ -446,7 +446,7 @@ public class OAuthClient {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// load the trustore
|
||||
// load the truststore
|
||||
KeyStore truststore = null;
|
||||
try {
|
||||
truststore = KeystoreUtil.loadKeyStore(trustStorePath, trustStorePassword);
|
||||
|
|
Loading…
Reference in a new issue