Пустой DN эмитента не допускается в X509CertificatesJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Пустой DN эмитента не допускается в X509Certificates

Сообщение Anonymous »

Я пытаюсь реализовать Spring Security против Keycloak, который развернут в локальном кластере K3D, конфигурация которого приведена ниже:
application.yml:

Код: Выделить всё

spring:
application:
name: backend

security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth.photoatom.local/realms/PhotoAtom
SecurityConfiguration.java:

Код: Выделить всё

package com.photoatom.backend.Configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.client.RestTemplate;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.Collection;
import java.util.List;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfiguration {

@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
String issuerUri;

interface AuthoritiesConverter extends Converter {
}

@Bean
AuthoritiesConverter realmRolesAuthoritiesConverter() {
return claims -> {
final var realmAccess = Optional.ofNullable((Map) claims.get("realm_access"));
final var roles = realmAccess.flatMap(map -> Optional.ofNullable((List) map.get("roles")));
return roles.map(List::stream).orElse(Stream.empty()).map(SimpleGrantedAuthority::new)
.map(GrantedAuthority.class::cast).toList();
};
}

@Bean
JwtAuthenticationConverter authenticationConverter(
Converter authoritiesConverter) {

var authenticationConverter = new JwtAuthenticationConverter();

authenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> {
return authoritiesConverter.convert(jwt.getClaims());
});

return authenticationConverter;
}

@Bean
JwtDecoder jwtDecoder() throws IOException, GeneralSecurityException {

SSLContext sslSocket = createSslSocketFactory("certificates/keycloak/truststore.jks", "changeit",
"certificates/keycloak/keystore.p12", "changeit");

RestTemplate restOperations = new RestTemplate(new CustomRequestFactory(sslSocket));

return NimbusJwtDecoder.withIssuerLocation(issuerUri)
.restOperations(restOperations).build();
}

@Bean
public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http,
Converter authenticationConverter) throws Exception {

http.oauth2ResourceServer(resourceServer -> {
resourceServer.jwt(jwtDecoder -> {
jwtDecoder.jwtAuthenticationConverter(authenticationConverter);
});
});

http.sessionManagement(sessions -> {
sessions.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}).csrf(csrf -> {
csrf.disable();
});

http.authorizeHttpRequests(requests ->  {
requests.requestMatchers("/dummy").authenticated();
requests.anyRequest().denyAll();
});

return http.build();
}

/**
* Generate SSL Socket Factory for the provided certificates path and passwords.
*
* @param caCertPath       CA Certificate Path
* @param caCertPassword   CA Certificate Password
* @param userCertPath     User Certificate Path
* @param userCertPassword User Certificate Password
* @return SSLSocketFactory
* @throws IOException
* @throws GeneralSecurityException
*/
private SSLContext createSslSocketFactory(
String caCertPath, String caCertPassword, String userCertPath, String userCertPassword)
throws IOException, GeneralSecurityException {

KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(new FileInputStream(userCertPath), userCertPassword.toCharArray());

KeyStore trustStore = KeyStore.getInstance("jks");
trustStore.load(new FileInputStream(caCertPath), caCertPassword.toCharArray());

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
trustManagerFactory.init(trustStore);

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(keyStore, userCertPassword.toCharArray());

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

return sslContext;
}

}
CustomRequestFactory.java:

Код: Выделить всё

package com.photoatom.backend.Configuration;

import java.io.IOException;
import javax.net.ssl.SSLContext;

import org.springframework.http.client.SimpleClientHttpRequestFactory;

public class CustomRequestFactory extends SimpleClientHttpRequestFactory {

private final SSLContext sslContext;

public CustomRequestFactory(SSLContext sslContext) {
this.sslContext = sslContext;
}

@Override
protected void prepareConnection(java.net.HttpURLConnection connection, String httpMethod) throws IOException {
if (connection instanceof javax.net.ssl.HttpsURLConnection) {
((javax.net.ssl.HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
}
super.prepareConnection(connection, httpMethod);
}
}
Итак, я пытаюсь загрузить свои самозаверяющие сертификаты для моего кластера Keycloak, чтобы убедиться, что я использую SSL-соединение при запуске аутентификации в моем бэкэнде. Но я столкнулся с ошибкой, которая выглядит следующим образом:

Код: Выделить всё

Caused by: java.lang.IllegalArgumentException: Unable to resolve the Configuration with the provided Issuer of "https://auth.photoatom.local/realms/PhotoAtom"
at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getConfiguration(JwtDecoderProviderConfigurationUtils.java:178) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getConfigurationForIssuerLocation(JwtDecoderProviderConfigurationUtils.java:90) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.lambda$withIssuerLocation$2(NimbusJwtDecoder.java:226) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder$JwkSetUriJwtDecoderBuilder.processor(NimbusJwtDecoder.java:389) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder$JwkSetUriJwtDecoderBuilder.build(NimbusJwtDecoder.java:405) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
at com.photoatom.backend.Configuration.SecurityConfiguration.jwtDecoder(SecurityConfiguration.java:79) ~[classes/:na]
at com.photoatom.backend.Configuration.SecurityConfiguration$$SpringCGLIB$$0.CGLIB$jwtDecoder$2() ~[classes/:na]
at com.photoatom.backend.Configuration.SecurityConfiguration$$SpringCGLIB$$FastClass$$1.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.1.14.jar:6.1.14]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:348) ~[spring-context-6.1.14.jar:6.1.14]
at com.photoatom.backend.Configuration.SecurityConfiguration$$SpringCGLIB$$0.jwtDecoder() ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146) ~[spring-beans-6.1.14.jar:6.1.14]
... 74 common frames omitted
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://auth.photoatom.local/realms/PhotoAtom/.well-known/openid-configuration": Failed to parse server certificates
at org.springframework.web.client.RestTemplate.createResourceAccessException(RestTemplate.java:915) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:895) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:740) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getConfiguration(JwtDecoderProviderConfigurationUtils.java:167) ~[spring-security-oauth2-jose-6.3.4.jar:6.3.4]
...  87 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: Failed to parse server certificates
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1282) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1195) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1138) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:393) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:476) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:447) ~[na:na]
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201) ~[na:na]
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:586) ~[na:na]
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:141) ~[na:na]
at org.springframework.http.client.SimpleClientHttpRequest.executeInternal(SimpleClientHttpRequest.java:79) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:889) ~[spring-web-6.1.14.jar:6.1.14]
... 89 common frames omitted
Caused by: java.security.cert.CertificateParsingException: Empty issuer DN not allowed in X509Certificates
at java.base/sun.security.x509.X509CertInfo.parse(X509CertInfo.java:367) ~[na:na]
at java.base/sun.security.x509.X509CertInfo.(X509CertInfo.java:137) ~[na:na]
at java.base/sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1456) ~[na:na]
at java.base/sun.security.x509.X509CertImpl.(X509CertImpl.java:143) ~[na:na]
at java.base/sun.security.provider.X509Factory.cachedGetX509Cert(X509Factory.java:113) ~[na:na]
at java.base/sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:97) ~[na:na]
at java.base/java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:355) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1278) ~[na:na]
... 107 common frames omitted
Я не совсем понимаю, что делаю неправильно. Я заметил ошибку «Отсутствует DN эмитента» и после некоторого поиска в Google обнаружил, что в соответствии с этой проблемой в диспетчере сертификатов (я генерирую самоподписанные сертификаты с помощью диспетчера сертификатов), и кажется, что добавление commonName должно помочь, но это не так. Я также прилагаю сертификаты, которые я сгенерировал локально для декодирования:
tls.crt:

Код: Выделить всё

-----BEGIN CERTIFICATE-----
MIICdDCCAhqgAwIBAgIQaN6oSHS/ll6Kkb72VGEmhTAKBggqhkjOPQQDAjAWMRQw
EgYDVQQDEwtrZXljbG9hay1jYTAeFw0yNDExMjcxMDE2MjJaFw0yNTAyMjUxMDE2
MjJaMDMxEjAQBgNVBAsTCXBob3RvYXRvbTEdMBsGA1UEAxMUYXV0aC5waG90b2F0
b20ubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJq8ZAR46w
Hr8TM1w5QgcgA7ogIUpCC+xeTI4cQYUniL73KpCKsC3D4f3JZ6wbSBRh0Rz6d7QX
KEYyDJO945t6T/QlLsVnTFeJLnYAwpKXxKQ0e+5A3wNygXu4OoP5/mwXpGhEad1d
6E7794hHLPRsj9nRoCkRSrQZxGNn9TlgF1ZJ6EDfjPPAbmtNdLKRm7NNEmRDReuL
pJ4kg67Bd4R3hazGOpBT+kHTW6o9h6A1+VpTDGHffGKyQrFMA+C2Av7p5B2qN5Ae
a9jSOYH2XVl4CWNPZRkNgYJzHcMZibUYLpiPZ0j1wfiF8uM6CsquJqZW609U2SaH
e7+CfC5z6U9tAgMBAAGjYjBgMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAA
MB8GA1UdIwQYMBaAFDmmzF/TIlHr9rKBEOly+TSTzekuMB8GA1UdEQQYMBaCFGF1
dGgucGhvdG9hdG9tLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIQDqaCG6Jz46sS7M
p6UDzsRfbqnsYd0tMCIjPKakcnXq7AIgT4vfDOGl98qxehUL2AS/+WitZF3oaUrx
wAXKOJjxPZE=
-----END CERTIFICATE-----
tls.key:

Код: Выделить всё

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyavGQEeOsB6/EzNcOUIHIAO6ICFKQgvsXkyOHEGFJ4i+9yqQ
irAtw+H9yWesG0gUYdEc+ne0FyhGMgyTveObek/0JS7FZ0xXiS52AMKSl8SkNHvu
QN8DcoF7uDqD+f5sF6RoRGndXehO+/eIRyz0bI/Z0aApEUq0GcRjZ/U5YBdWSehA
34zzwG5rTXSykZuzTRJkQ0Xri6SeJIOuwXeEd4WsxjqQU/pB01uqPYegNflaUwxh
33xiskKxTAPgtgL+6eQdqjeQHmvY0jmB9l1ZeAljT2UZDYGCcx3DGYm1GC6Yj2dI
9cH4hfLjOgrKriamVutPVNkmh3u/gnwuc+lPbQIDAQABAoIBACV+IeVhaE2l6bAQ
JF0gwWJaTwgaKEwPG2qMoP7vz2mCKr6Y0zZ1eoyoPx5qf7yysdddoR2Pk5OakTJM
1ErBPe6HXsRq5ZhGwR9n29hYVBiTHlQDlk/JJkLrf6zIdDDN9BqRHjFZ3SXQQp7l
bhiNawOj2sL2G6xzTvhbYn+5P2l1mFxQWkfJjVdQsFLx4ZoFxHPMfHLHpL8Het8o
ns0ZNrYm73f9leGkC9X2moSSYF6hXwS4vXtw6dGiy7hlNOp39d4N+bkfnqEWRxdK
/WldGF5R19I22klTULqJ3z5q7sJPzgPJac8M3DPtRqgSm5Hikaki+Rf7cC5Zc8M4
z6SZs6ECgYEA+jgBFnhdcewl4H/CcwVljGnHpgLcnwBGdtLo/CeF2GwlGW/4Sfi1
Og0kJP5cGEavQto5fT8g9GsUSsUrww2y8B+ehg62dVwElelIbPJzEKjhpLCQ1ShQ
OW+n2b/UTIT079WHkuDQ7S+warrNru0ucg0Fxc+jysCa5LKjRrLf2vcCgYEAzlSe
lKHvsYxh7mdzn5zdmdP54xQeLEyU6SeCMxHKmGQthsC4p4dEv0kbcIFLXTgJFy0F
RgfECjYbdkKUmbbVg3xdojdLfT6vtEDPB3oHfty5WVhtd9TFKR8kA7v+wTdPgPtF
yr8+dxDOxV6aUknVVdQjAtGYBgOGNdFunNcyS7sCgYEAsSKSipC9Plf53Hs1ce3h
HM0JvFmMS7eLKrVWoKNuGm88uExPDjbWPPlunA3BrqHjksUgK61ULBPd8qywtU3u
XhVUSP0DaAOzb1kNn6rnkGSuEMO6VFxMpsyHnBw0M9Nv/pVAe9dRsIexMW17DJn1
5mGXs5iyEGfXf42DDxq0ZLMCgYByR8Yp1uOW+IVJcb1F27GVwSX4Ey1/Jc+YsAxa
UvFepKXerCHakH6QYGK1VreyYxYN4x63ohd//GYLg2chGHZ8REbsUSobrbvN39OL
dZhvOLvkc6j2JUAqvZfKBbddt0/uxb3rRS/I7ONJyFM7Xq+twTi/F+3W7t7IMj7M
2hh+fwKBgDhgYfiTWkMbFg1jShsERnP2Wom15JGVisG98hy4h4XxsUZiUldHxHDK
QgY/xWbymKoqnVNHOMdkd46iqCtQ214Kz0HPeyLWGNnGYrBEf0Sm99zI6MaMO9aE
Bz2w2/4nJlJgOPeXMNfGheM4LdlXP+DwSp2C3rM6vbVWf+KFcogM
-----END RSA PRIVATE KEY-----
ca.crt:

Код: Выделить всё

-----BEGIN CERTIFICATE-----
MIIBazCCARKgAwIBAgIQPgIxsF4n5MlqzY/IoTe3YTAKBggqhkjOPQQDAjAWMRQw
EgYDVQQDEwtrZXljbG9hay1jYTAeFw0yNDExMjcxMDE2MjBaFw0zMjExMjcxMDE2
MjBaMBYxFDASBgNVBAMTC2tleWNsb2FrLWNhMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEJrTYx58qpmeRTpwgAcSWyMsZHshECyaLuyZzXWbHNYwWLepST9e7CxYQ
giuytx9cgOSDzZuA/yVJRKSWeSoyWaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1Ud
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFDmmzF/TIlHr9rKBEOly+TSTzekuMAoGCCqG
SM49BAMCA0cAMEQCIBzTHUr8sUNi0/6x4IJl2k/fjYvr/jxAXfNZ4L8qPbl4AiAS
q9JGd8W3B5pl4BGd0YGY7V/XLDc72bEDhpjBtwhr3w==
-----END CERTIFICATE-----
Также отметим, что я преобразовал эти сертификаты в файлы хранилища доверенных сертификатов и хранилища ключей, используя следующие команды:

Код: Выделить всё

openssl pkcs12 -export -in certificates/keycloak/tls.crt -inkey certificates/keycloak/tls.key -out certificates/keycloak/keystore.p12 -CAfile certificates/keycloak/ca.crt -caname keycloak-ca -name "keycloak"

keytool -importcert -keystore certificates/cache/truststore.jks -storepass changeit -file certificates/cache/ca.crt
Любая помощь в этом будет очень признательна, заранее большое спасибо!

Подробнее здесь: https://stackoverflow.com/questions/792 ... rtificates
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»