2014-12-31 8 views
29

Sto utilizzando springBootVersion 1.2.0.RELEASE. Sto tentando di configurare il keystore e il truststore tramite application.properties.Specifica delle informazioni dell'archivio trust in primavera boot.properties

Quando aggiungo le seguenti impostazioni, posso far funzionare il keystore, ma non il truststore.

server.ssl.key-store=classpath:foo.jks 
server.ssl.key-store-password=password 
server.ssl.key-password=password 
server.ssl.trust-store=classpath:foo.jks 
server.ssl.trust-store-password=password 

Tuttavia, se aggiungo il truststore se

bootRun { 
    jvmArgs = [ "-Djavax.net.ssl.trustStore=c://foo.jks", "-Djavax.net.ssl.trustStorePassword=password"] 
} 

funziona bene.

Qualcuno ha utilizzato le proprietà application.properties per gli archivi fiduciari?

+0

Quali incorporato contenitore stai usando e come hai deciso che non funziona? –

risposta

6

Ho lo stesso problema, proverò a spiegarlo un po 'più in dettaglio.

Sto usando spring-boot 1.2.2-RELEASE e l'ho provato su Tomcat e Undertow con lo stesso risultato.

Definire la fiducia-store in application.yml come:

server: 
    ssl: 
    trust-store: path-to-truststore... 
    trust-store-password: my-secret-password... 

non funziona, mentre:

$ java -Djavax.net.debug=ssl -Djavax.net.ssl.trustStore=path-to-truststore... -Djavax.net.ssl.trustStorePassword=my-secret-password... -jar build/libs/*.jar 

opere perfettamente bene.

Il modo più semplice per vedere la differenza in rutime è abilitare ssl-debug nel client. Quando si lavora (vale a dire utilizzando -D bandiere) qualcosa di simile al seguente viene scritto nella console (durante l'elaborazione della prima richiesta):

trustStore is: path-to-truststore... 
trustStore type is : jks 
trustStore provider is : 
init truststore 
adding as trusted cert: 
    Subject: C=..., ST=..., O=..., OU=..., CN=... 
    Issuer: C=..., ST=..., O=..., OU=..., CN=... 
    Algorithm: RSA; Serial number: 0x4d2 
    Valid from Wed Oct 16 17:58:35 CEST 2013 until Tue Oct 11 17:58:35 CEST 2033 

Senza le bandiere -D ottengo:

trustStore is: /Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/security/cacerts 
trustStore type is : jks 
trustStore provider is : 
init truststore 
adding as trusted cert: ... (one for each CA-cert in the defult truststore) 

. ..e quando si esegue una richiesta ottengo l'eccezione:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

Spero che aiuti a capire meglio il problema!

+0

qualcuno sa perché il modo 'application.yml' non funziona? –

+0

Vedere [Impostazione di un truststore senza un keystore] (https://github.com/spring-projects/spring-boot/issues/6493) –

3

Avevo anche lo stesso problema con Spring Boot e Tomcat incorporato.

Da quelle che ho capito, queste proprietà impostano solo i parametri di configurazione Tomcat. Secondo la documentazione di Tomcat questo viene utilizzato solo per l'autenticazione del client (vale a dire per due vie SSL) e non per la verifica dei certificati remoti:

truststoreFile - Il file negozio di fiducia da utilizzare per convalidare cliente certificati.

https://tomcat.apache.org/tomcat-8.0-doc/config/http.html

Per configurare il negozio di fiducia per HttpClient esso dipende in gran parte l'attuazione HttpClient si utilizza. Ad esempio per RestTemplate per impostazione predefinita Spring Boot utilizza un SimpleClientHttpRequestFactory basato su classi J2SE standard come java.net.HttpURLConnection.

mi è venuta in mente una soluzione basata su Apache HttpClient documenti e questi post: http://vincentdevillers.blogspot.pt/2013/02/configure-best-spring-resttemplate.html http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Fondamentalmente questo permette per un bean RestTemplate che si fida solo certificati firmati dalla CA principale nel truststore configurato .

@Configuration 
public class RestClientConfig { 

    // e.g. Add http.client.ssl.trust-store=classpath:ssl/truststore.jks to application.properties 
    @Value("${http.client.ssl.trust-store}") 
    private Resource trustStore; 

    @Value("${http.client.ssl.trust-store-password}") 
    private char[] trustStorePassword; 

    @Value("${http.client.maxPoolSize}") 
    private Integer maxPoolSize; 


    @Bean 
    public ClientHttpRequestFactory httpRequestFactory() { 
     return new HttpComponentsClientHttpRequestFactory(httpClient()); 
    } 

    @Bean 
    public HttpClient httpClient() { 

     // Trust own CA and all child certs 
     Registry<ConnectionSocketFactory> socketFactoryRegistry = null; 
     try { 
      SSLContext sslContext = SSLContexts 
        .custom() 
        .loadTrustMaterial(trustStore.getFile(), 
          trustStorePassword) 
        .build(); 

      // Since only our own certs are trusted, hostname verification is probably safe to bypass 
      SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, 
        new HostnameVerifier() { 

         @Override 
         public boolean verify(final String hostname, 
           final SSLSession session) { 
          return true; 
         } 
      }); 

      socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() 
        .register("http", PlainConnectionSocketFactory.getSocketFactory()) 
        .register("https", sslSocketFactory) 
        .build();   

     } catch (Exception e) { 
      //TODO: handle exceptions 
      e.printStackTrace(); 
     } 

     PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 
     connectionManager.setMaxTotal(maxPoolSize); 
     // This client is for internal connections so only one route is expected 
     connectionManager.setDefaultMaxPerRoute(maxPoolSize); 
     return HttpClientBuilder.create() 
       .setConnectionManager(connectionManager) 
       .disableCookieManagement() 
       .disableAuthCaching() 
       .build(); 
    } 

    @Bean 
    public RestTemplate restTemplate() { 
     RestTemplate restTemplate = new RestTemplate(); 
     restTemplate.setRequestFactory(httpRequestFactory()); 
     return restTemplate; 
    }  
} 

E quindi è possibile utilizzare questo client Resto personalizzato ogni volta che è necessario, ad esempio:

@Autowired 
private RestTemplate restTemplate; 

restTemplate.getForEntity(...) 

Questo presuppone il tentativo di connettersi a un riposo finale, ma è anche possibile utilizzare il sopra HttpClient fagioli per quello che vuoi

+0

Ho svalutato questo perché ho messo insieme una piccola porzione di codice per dimostrare e dimostrare che il 'server.ssl.trust-store' è per mutuo TLS (ha effetto se' server.ssl.client-auth' è impostato) e non per le connessioni in uscita. La risposta può essere accettata come risposta StackOverflow. Voglio anche sottolineare che la documentazione è abbastanza sufficiente: https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html –

-3

In un'infrastruttura Microservice (non va bene il problema, lo so;)) non si deve utilizzare:

server: 
    ssl: 
    trust-store: path-to-truststore... 
    trust-store-password: my-secret-password... 

Invece il loadbalancer nastro può essere configuered:

ribbon: 
    TrustStore: keystore.jks 
    TrustStorePassword : example 
    ReadTimeout: 60000 
    IsSecure: true 
    MaxAutoRetries: 1 

Qui https://github.com/rajaramkushwaha/https-zuul-proxy-spring-boot-app voi può trovare un campione funzionante. C'è stata anche una discussione github a riguardo, ma non l'ho più trovata.

+0

Downvoted. Anche in un'infrastruttura di microservizi, ci sono casi in cui è assolutamente necessario * configurare * il trust store. ad esempio, se il tuo servizio raggiunge un endpoint HTTPS downstream che è firmato dalla CA interna della tua organizzazione. – sworisbreathing

10

Nel caso in cui sia necessario effettuare una chiamata REST è possibile utilizzare il modo successivo.

Funzionerà per le chiamate in uscita tramite RestTemplate.

Dichiarare il bean RestTemplate come questo.

@Configuration 
public class SslConfiguration { 
    @Value("${http.client.ssl.trust-store}") 
    private Resource keyStore; 
    @Value("${http.client.ssl.trust-store-password}") 
    private String keyStorePassword; 

    @Bean 
    RestTemplate restTemplate() throws Exception { 
     SSLContext sslContext = new SSLContextBuilder() 
       .loadTrustMaterial(
         keyStore.getURL(), 
         keyStorePassword.toCharArray() 
       ).build(); 
     SSLConnectionSocketFactory socketFactory = 
       new SSLConnectionSocketFactory(sslContext); 
     HttpClient httpClient = HttpClients.custom() 
       .setSSLSocketFactory(socketFactory).build(); 
     HttpComponentsClientHttpRequestFactory factory = 
       new HttpComponentsClientHttpRequestFactory(httpClient); 
     return new RestTemplate(factory); 
    } 
} 

Dove http.client.ssl.trust-store e http.client.ssl.trust-store-password punto trustStore in JKS formato e la password per il truststore specificato.

Questo sostituirà il bean RestTemplate fornito con Spring Boot e farà in modo che utilizzi l'archivio sicuro di cui hai bisogno.

+0

"http.client.ssl.trust-store" indica il percorso del keystore? –

+0

Fondamentalmente è il percorso del truststore. Tuttavia potrebbe essere il caso di archiviare certificati attendibili nello stesso file in cui sono presenti certificati e chiavi private. Se questo è il caso, puoi usare il keystore lì. Puoi trovare maggiori dettagli qui https://stackoverflow.com/a/6341566/2065796 –

+0

'http.client.ssl.trust-store' e' http.client.ssl.trust-store-password' sono proprietà personalizzate, aren sono loro? –

2

Qui la mia versione estesa di Oleksandr Shpota's answer, incluse le importazioni. Il pacchetto org.apache.http.* può essere trovato in org.apache.httpcomponents:httpclient. Ho commentato le modifiche:

import org.apache.http.client.HttpClient; 
import org.apache.http.conn.ssl.NoopHostnameVerifier; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.conn.ssl.TrustSelfSignedStrategy; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.ssl.SSLContexts; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.core.io.Resource; 
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 
import org.springframework.web.client.RestTemplate; 

@Value("${http.client.ssl.key-store}") 
private Resource keyStore; 

@Value("${http.client.ssl.trust-store}") 
private Resource trustStore; 

// I use the same pw for both keystores: 
@Value("${http.client.ssl.trust-store-password}") 
private String keyStorePassword; 

// wasn't able to provide this as a @Bean...: 
private RestTemplate getRestTemplate() { 
    try { 
    SSLContext sslContext = SSLContexts.custom() 
     // keystore wasn't within the question's scope, yet it might be handy: 
     .loadKeyMaterial(
      keyStore.getFile(), 
      keyStorePassword.toCharArray(), 
      keyStorePassword.toCharArray()) 
     .loadTrustMaterial(
      trustStore.getURL(), 
      keyStorePassword.toCharArray(), 
      // use this for self-signed certificates only: 
      new TrustSelfSignedStrategy()) 
     .build(); 

    HttpClient httpClient = HttpClients.custom() 
     // use NoopHostnameVerifier with caution, see https://stackoverflow.com/a/22901289/3890673 
     .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier())) 
     .build(); 

    return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient)); 
    } catch (IOException | GeneralSecurityException e) { 
    throw new RuntimeException(e); 
    } 
} 
4

Ho avuto lo stesso problema con la Primavera di avvio, Primavera Cloud (microservices) ed un certificato SSL self-signed. Il keystore funzionava fuori dalla scatola dalle proprietà dell'applicazione e Truststore no.

Ho finito per mantenere sia il keystore che la configurazione trustore in application.properties e aggiungendo un bean di configurazione separato per la configurazione delle proprietà del truststore con il sistema.

@Configuration 
public class SSLConfig { 
@Autowired 
private Environment env; 

@PostConstruct 
private void configureSSL() { 
    //set to TLSv1.1 or TLSv1.2 
    System.setProperty("https.protocols", "TLSv1.1"); 

    //load the 'javax.net.ssl.trustStore' and 'javax.net.ssl.trustStorePassword' from application.properties 
    System.setProperty("javax.net.ssl.trustStore", env.getProperty("server.ssl.trust-store")); 
    System.setProperty("javax.net.ssl.trustStorePassword",env.getProperty("server.ssl.trust-store-password")); 
} 
1

proprietà java "javax.net.ssl.trustStore" e "javax.net.ssl.trustStorePassword" non corrispondono a "server.ssl.trust-store" e "server.ssl.trust-store -password "da Spring boot" application.properties "(" application.yml ")

quindi non è possibile impostare" javax.net.ssl.trustStore "e" javax.net.ssl.trustStorePassword "semplicemente impostando" server.ssl.trust-store "e" server.ssl.trust-store-password "in" application.properties "(" application.yml ")

un'alternativa dell'impostazione" javax.net.ssl.trustStore "e" javax.net.ssl.trustStorePassword "è di avvio Primavera Externalized Configuration

sotto sono i brani della mia realizzazione:

classe Parametri contiene le impostazioni esterni

@Component 
@ConfigurationProperties("params") 
public class Params{ 

    //default values, can be override by external settings 
    public static String trustStorePath = "config/client-truststore.jks"; 
    public static String trustStorePassword = "wso2carbon"; 
    public static String keyStorePath = "config/wso2carbon.jks"; 
    public static String keyStorePassword = "wso2carbon"; 
    public static String defaultType = "JKS"; 

    public void setTrustStorePath(String trustStorePath){ 
     Params.trustStorePath = trustStorePath; 
    } 

    public void settrustStorePassword(String trustStorePassword){ 
     Params.trustStorePassword=trustStorePassword; 
    } 

    public void setKeyStorePath(String keyStorePath){ 
     Params.keyStorePath = keyStorePath; 
    } 

    public void setkeyStorePassword(String keyStorePassword){ 
     Params.keyStorePassword = keyStorePassword; 
    } 

    public void setDefaultType(String defaultType){ 
     Params.defaultType = defaultType; 
    } 

classe KeyStoreUtil impegna le impostazioni di" javax. net.ssl.trustStore "e" javax.net.ssl. trustStorePassword"

public class KeyStoreUtil { 

    public static void setTrustStoreParams() { 
     File filePath = new File(Params.trustStorePath); 
     String tsp = filePath.getAbsolutePath(); 
     System.setProperty("javax.net.ssl.trustStore", tsp); 
     System.setProperty("javax.net.ssl.trustStorePassword", Params.trustStorePassword); 
     System.setProperty("javax.net.ssl.keyStoreType", Params.defaultType); 

    } 

    public static void setKeyStoreParams() { 
     File filePath = new File(Params.keyStorePath); 
     String ksp = filePath.getAbsolutePath(); 
     System.setProperty("Security.KeyStore.Location", ksp); 
     System.setProperty("Security.KeyStore.Password", Params.keyStorePassword); 

    }  
} 

si ottiene il setter eseguiti all'interno della funzione di avvio

@SpringBootApplication 
@ComponentScan("com.myapp.profiles") 
public class ProfilesApplication { 

    public static void main(String[] args) { 
     KeyStoreUtil.setKeyStoreParams(); 
     KeyStoreUtil.setTrustStoreParams(); 
     SpringApplication.run(ProfilesApplication.class, args); 
    } 
} 

l'application.yml

--- 
params: 
    trustStorePath: config/client-truststore.jks 
    trustStorePassword: wso2carbon 
    keyStorePath: config/wso2carbon.jks 
    keyStorePassword: wso2carbon 
    defaultType: JKS 
--- 

infine, all'interno dell'ambiente in esecuzione (server di distribuzione), si crea una cartella denominata "config" nella stessa cartella in cui è archiviato l'archivio jar.

all'interno della cartella "config", si memorizzano "application.yml", "client-truststore.jks" e "wso2carbon.jks". fatto!

0

fatto questa domanda a pagina Gitter Primavera-boot:

Problemi correlati