Exposing HTTPS applications in OpenShift

En pleno 2019 securizar el tráfico de las aplicaciones con HTTPS debería ser prácticamente una obligación, tanto para accesos internos como externos. Por ello, en el presente artículo se pretende detallar las distintas posibilidades existentes en OpenShift para llevarlo a cabo así como las ventajas y desventajas de cada uno. ¡Comenzamos!

Caso de uso

Se dispone en OpenShift de un microservicio Java desarrollado con Spring Boot que se quiere securizar con HTTPS.

¿Que es HTTPS?

HTTPS es el acrónimo de Hypertext Transfer Protocol Secure o lo que es lo mismo, la versión segura de HTTP, el archiconocido protocolo de transferencia de datos.

La principal diferencia entre ambos es evidente: Con el protocolo HTTP los datos viajan en claro y son legibles o susceptibles de ser manipulados por todo aquel que los capture, mientras que con HTTPS van cifrados, por lo que de nada sirve interceptarlos (Siempre y cuando se implemente con un algoritmo seguro claro está).

Adicionalmenteaquellos dominios protegidos con HTTPS que cuenten con un certificado valido(no autofirmado ni expirado) garantizan que el usuario accede realmente a la páginaweb deseada.

OpenShift

En la plataforma de orquestación de contenedores de Red Hat se disponen las siguientes opciones para securizar el tráfico.

Secured Routes

Un route es un mecanismo de OpenShift para exponer un service en un hostname (por ejemplo, http://www.myapp.com) y hacerloaccesible a clientes externos a través de dicho dominio. Dicho de otra forma,en el caso de uso planteado permite exponer una URL pública para interactuarcon el microservicio en cuestión.

Un service en cambio es un balanceador de carga interno que redirige las peticiones entre las distintas réplicas de la aplicación. Al tratarse de un balanceador interno, no es accesible desde fuera de OpenShift y de ahí a la necesidad de los routes.

Dicho esto,OpenShift permite configurar los routes para funcionar con HTTPS. Basta conproporcionar un certificado y una clave pública. (En caso de no proporcionarninguno, se hará uso del certificado interno de la plataforma)

apiVersion: v1
kind: Route
metadata:
  name: myapp-route 
spec:
  host: www.myapp.com
  to:
    kind: Service
    name: myapp-service 
  tls:
    termination: edge            
    key: |-                      
      -----BEGIN PRIVATE KEY-----
      [...]
      -----END PRIVATE KEY-----
    certificate: |-              
      -----BEGIN CERTIFICATE-----
      [...]
      -----END CERTIFICATE-----
    caCertificate: |-            
      -----BEGIN CERTIFICATE-----
      [...]
      -----END CERTIFICATE-----

La principal ventaja de esta solución es que la seguridad se gestiona de forma centralizada a nivel de plataforma y es completamente transparente para las aplicaciones.

Por contra, la comunicación no es segura de punto a punto. Es decir, la conexión únicamente está cifrada desde el cliente hasta el route, mientras que el tramo entre el route y la aplicación funciona bajo HTTP. Dependiendo de los requisitos de seguridad puede no ser suficiente.

Adicionalmente comentar que los routes no son compatibles con two-way SSL authentication, requisito que imponen muchas de las nubles publicas hoy en día. 

Service Mesh (Istio)

Un service mesh es un software que normalmente se despliega junto a los microservicios y que se encarga de gestionar las comunicaciones hacia este. Trabaja a nivel de capa de red proporcionando funcionalidades tan necesarias como service discovery, load balancing, encryption, authentication/authorization, circuit breaker, monitoring o tracing entre otros, abstrayendo a los microservicios de ello.

Istio es el service mesh open source que ha irrumpido con fuerza en los meses y que está impulsado por Google. La versión 1.0 fue liberada el pasado 31 de Julio.

Para securizar el trafico HTTPS en Istio es necesario crear un objeto de tipo Gateway y proporcionar un certificado y una clave pública.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: myapp-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
      privateKey: /etc/istio/ingressgateway-certs/tls.key
    hosts:
    - "httpbin.myapp.com"

Al igual que con los routes de OpenShift, la principal ventaja de esta solución es que la seguridad se gestiona de forma centralizada a nivel de service mesh y es completamente transparente para las aplicaciones.

Por contra, la comunicación no es segura de punto a punto. Es decir, la conexión únicamente está cifrada desde el cliente hasta el pod en el que conviven el microservicio y el service mesh. La comunicación restante, a pesar de ser local, no está securizada y dependiendo de los requisitos de seguridad puede no ser suficiente.

App

La última alternativa es configurar la propia aplicación para funcionar bajo HTTPS, algo que en el caso de Spring es relativamente sencillo.

# SERVER
server:
  port:8443
  ssl:
    key-store: /deployments/config/security/tls-certificate.jks	
    key-store-password: changeit	
    keyStoreType: JKS	
    keyAlias: myapp	
    trust-store: /deployments/config/security/tls-certificate.jks	
    trust-store-password: changeit

El truststore no es posible definirlo a través de la configuración, por lo que una posibilidad es hacerlo vía código.

@Configuration
@ConditionalOnProperty(value = "server.ssl.trust-store", matchIfMissing = false)
@EnableConfigurationProperties(SSLProperties.class)
@AllArgsConstructor
public class SecurityConfig implements WebMvcConfigurer {

	/** The ssl properties. */
	private SSLProperties ssl;

	/** Trust Store Configuration Properties **/
	@PostConstruct
    public void setProperty() {
		System.setProperty("javax.net.ssl.trustStore", ssl.getTrustStore());
		System.setProperty("javax.net.ssl.trustStorePassword", ssl.getTrustStorePassword()); 
    }	
}

Adicionalmente es necesario definir un route de OpenShift configurado como passthrough para permitir accesos externos.

apiVersion: v1
kind: Route
metadata:
  name: myapp-route
spec:
  host: www.myapp.com
  to:
    kind: Service
    name: myapp-service 
  tls:
    termination: passthrough

La principal ventaja de esta solución es que la conexión esta securizada de punto a punto, inclusive el tramo relativo al pod.

Por contra, la gestión de esta recae sobre las propias aplicaciones, por lo que cada una es responsable de su implementación y mantenimiento.

Conclusiones

En conclusión, el caso de uso y los requisitos de seguridad determinan que soluciones se ajusta mejor a cada uno, pero para un humilde servidor el futuro se dibuja en forma de service mesh.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s