Запустите SpringBoot на heroku с SSL

#spring-boot #ssl #heroku

#весенняя загрузка #ssl #heroku

Вопрос:

Пытаюсь запустить SpringBoot на Heroku с самозаверяющим сертификатом и включенным SSL. Вот мое приложение.yaml:

 server:
  ssl:
    key-store-type: PKCS12
    key-store: classpath:server-dev.p12
    key-store-password: changeit
    key-password: changeit
    key-alias: server-dev
    trust-store: classpath:root_CA-truststore.jks
    trust-store-password: changeit
    trust-store-type: JKS
    client-auth: need
    enabled: true

  # forward-headers-strategy: tried native / framework, didn't help
  use-forward-headers: true
  

Вот мой SecurityConfig

 @EnableWebSecurity
@Component
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final X509PrincipalExtractorWithCertificateValidation x509PrincipalExtractorWithCertificateValidation;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .requiresChannel()
                .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                .requiresSecure()

                .and()
                .authorizeRequests()
                .antMatchers("/private/api/v1/security/test")
                .authenticated()
                .and()
                .x509()
                .x509PrincipalExtractor(x509PrincipalExtractorWithCertificateValidation)
                .userDetailsService(userDetailsService())
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.NEVER)

                .and()
                .authorizeRequests()
                .antMatchers("/**").permitAll()

                .and()
                .csrf()
                .disable();
    }
}
  

что бы я ни делал, все запросы получают 400

Вот журнал curl:

 curl -kvI https://my-server.herokuapp.com/swagger-ui.html#/ 
*   Trying 34.246.118.170...
* TCP_NODELAY set
* Connected to my-server.herokuapp.com (XXX.XXX.XXX.XXX) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=Heroku, Inc.; CN=*.herokuapp.com
*  start date: Jun 15 00:00:00 2020 GMT
*  expire date: Jul  7 12:00:00 2021 GMT
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
*  SSL certificate verify ok.
> HEAD /swagger-ui.html HTTP/1.1
> Host: my-server.herokuapp.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 400 
HTTP/1.1 400 
< Server: Cowboy
Server: Cowboy
< Date: Tue, 18 Aug 2020 23:13:58 GMT
Date: Tue, 18 Aug 2020 23:13:58 GMT
< Connection: keep-alive
Connection: keep-alive
< Content-Type: text/plain;charset=UTF-8
Content-Type: text/plain;charset=UTF-8
< Via: 1.1 vegur
Via: 1.1 vegur

< 
* Connection #0 to host my-server.herokuapp.com left intact

  

Что я делаю не так?

UPD Я включил отладку для встроенного в SpringBoot tomcat

 2020-08-19T00:21:58.085035 00:00 app[web.1]: 00:21:58.084  [https-jsse-nio-30633-Acceptor] DEBUG o.a.tomcat.util.threads.LimitLatch - Counting up[https-jsse-nio-30633-Acceptor] latch=1
2020-08-19T00:21:58.085334 00:00 app[web.1]: 00:21:58.085  [https-jsse-nio-30633-exec-9] DEBUG o.a.tomcat.util.net.NioEndpoint - Error during SSL handshake
2020-08-19T00:21:58.085336 00:00 app[web.1]: java.io.IOException: Found an plain text HTTP request on what should be an encrypted TLS connection
2020-08-19T00:21:58.085337 00:00 app[web.1]: at org.apache.tomcat.util.net.SecureNioChannel.processSNI(SecureNioChannel.java:322)
2
  

Heroku по какой-то причине отправляет HTTP-трафик….

Ответ №1:

У меня была точно такая же проблема, как и у вас. Я также хотел настроить MTLS с помощью Spring Boot.

К сожалению, MTLS не поддерживается Heroku, поскольку соединения от маршрутизатора к серверным динамическим системам являются чистыми HTTP-запросами. Это немного трагично, но, похоже, вам нужно найти другое решение.

Смотрите здесь официальный ответ из раздела справки Heroku:

https://help.heroku.com/3NTWIMNK/does-heroku-support-client-side-ssl-connections-a-k-a-two-way-authentication