Как переопределить Spring boot keystore / truststore для взаимного SSL

У меня есть приложение Spring Boot. Его application.yml взят с онлайн-ресурса. Он содержит следующую конфигурацию для взаимного SSL:

server:
  ssl:
    enabled: true
    client-auth: need
    key-store-type: PKCS12
    key-store: http://{config server url}/keystore.p12
    key-store-password: {keystore password}
    trust-store-type: JKS
    trust-store: http://{config server url}/truststore.jks
    trust-store-password: {truststore password}
  port: 8443

При запуске приложения у меня такая ошибка:

java.io.IOException: DerInputStream.getLength(): lengthTag=111, too big.
    at sun.security.util.DerInputStream.getLength(DerInputStream.java:599)
    at sun.security.util.DerValue.init(DerValue.java:391)
    at sun.security.util.DerValue.<init>(DerValue.java:332)
    at sun.security.util.DerValue.<init>(DerValue.java:345)
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1938)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at org.apache.tomcat.util.security.KeyStoreUtil.load(KeyStoreUtil.java:69)
    at org.apache.tomcat.util.net.SSLUtilBase.getStore(SSLUtilBase.java:209)
    at org.apache.tomcat.util.net.SSLHostConfigCertificate.getCertificateKeystore(SSLHostConfigCertificate.java:206)
    at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:272)
    at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:239)
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
    ... 23 common frames omitted

Но я могу нормально открыть хранилище ключей и хранилище доверенных сертификатов, сделав это программно. (Показано ниже)

private KeyStore getKeyStore() {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    try (InputStream is = readCertificateFromURL(new URI(keyStoreURL))) {
        keyStore.load(is, keyStorePassword.toCharArray());
    }
    return keyStore();
}

private InputStream readCertificateFromURL(URI uri) throws IOException {
    RequestEntity<Void> requestEntity = RequestEntity.get(uri)
         .accept(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM)
         .build();
    Resource resource = new RestTemplate().exchange(requestEntity,Resource.class).getBody();
    return resource.getInputStream();
}

Как я могу сказать, что Spring boot выбирает эти ключи / доверенные хранилища вместо тех, которые определены в application.yml?

Единственное, что я нашел в Интернете, касалось переопределения путей хранилища ключей / доверенных сертификатов, а не самих объектов хранилища ключей.


person jerthiry    schedule 19.07.2019    source источник


Ответы (2)


Значения для javax.net.ssl.trustStore и javax.net.ssl.keyStore и их соответствующие значения в свойствах Spring должны быть путями файловой системы. Работает ли ваш подход, если вы копируете их в локальную файловую систему и вместо этого ссылаетесь на них?

person Toby    schedule 23.07.2019

Он действительно работает с локальными файлами, как спросил @Toby. Дело в том, что магазины были загружены с конфиг-сервера, а не как бинарные. В итоге я реализовал собственный SslStoreProvider:

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatSslCustomizer() {
    return tomcat -> tomcat.setSslStoreProvider(new SslStoreProvider() {

        @Override
        public KeyStore getKeyStore() throws Exception {
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            try (InputStream is = readStoreFromURL(new URI(keyStoreURL))) {
                keyStore.load(is, keyStorePassword.toCharArray());
            }
            return keyStore;
        }

        @Override
        public KeyStore getTrustStore() throws Exception {
            KeyStore truststore = KeyStore.getInstance(trustStoreType);
            try (InputStream is = readStoreFromURL(new URI(trustStoreURL))) {
                truststore.load(is, trustStorePassword.toCharArray());
            }
            return truststore;
        }

        private InputStream readStoreFromURL(URI uri) {
            // Download the stores as binary from the config server
        }

    });
}
person jerthiry    schedule 23.07.2019