Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kubernetes HTTP to HTTPS Redirect on AWS with ELB terminating SSL

I'm trying to set up a simple HTTP to HTTPS redirect for traffic going to a Kubernetes cluster. The SSL termination is happening on the ELB. When I try to use the nginx.ingress.kubernetes.io/ssl-redirect = true it results in an infinite redirect which led me to setting up a config map to handle this (nginx-ingress: Too many redirects when force-ssl is enabled).

Now there seems to be no redirection happening at all.

My ingress service is defined as:

apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:...:certificate/...
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
  labels:
    k8s-addon: ingress-nginx.addons.k8s.io
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Cluster
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: http
  - name: http
    port: 80
    protocol: TCP
    targetPort: http
  selector:
    app: ingress-nginx
  type: LoadBalancer

My config map is defined as:

apiVersion: v1
kind: ConfigMap
data:
  client-body-buffer-size: 32M
  hsts: "true"
  proxy-body-size: 1G
  proxy-buffering: "off"
  proxy-read-timeout: "600"
  proxy-send-timeout: "600"
  server-tokens: "false"
  ssl-redirect: "false"
  upstream-keepalive-connections: "50"
  use-proxy-protocol: "true"
  http-snippet: |
    server {
      listen 8080 proxy_protocol;
      server_tokens off;
      return 307 https://$host$request_uri;
    }
metadata:
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: ingress-nginx
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: tcp-services
  namespace: ingress-nginx
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: udp-services
  namespace: ingress-nginx

And, the ingress is defined as:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gateway-ingress
  annotations:
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/cors-allow-headers: Authorization, origin, accept
    nginx.ingress.kubernetes.io/cors-allow-methods: GET, OPTIONS
    nginx.ingress.kubernetes.io/cors-allow-origin: gateway.example.com.com/monitor
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: gateway.example.com
    http:
      paths:
      - backend:
          serviceName: gateway
          servicePort: 8080
        path: /
  tls:
  - hosts:
    - gateway.example.com
like image 737
BHarman Avatar asked Aug 16 '18 17:08

BHarman


People also ask

What is SSL termination in Kubernetes?

Terminating at an external load balancer A common strategy for TLS/SSL termination and Kubernetes is to use an external load balancer such as an AWS Elastic Load Balancer or Google Cloud Load Balancer. This approach offloads the computation and management of TLS/SSL to another system.

How do I redirect http traffic to HTTPS on my classic load balancer in ELB?

Classic Load Balancers can't redirect HTTP traffic to HTTPS by default. Instead, configure your rewrite rules for the web servers instances behind the Classic Load Balancer. You must configure your rewrite rules to use the X-Forwarded-Proto header and redirect only HTTP clients.

How do I redirect http to HTTPS in Alb?

Select a load balancer, and then choose HTTP Listener. Under Rules, choose View/edit rules. Choose Edit Rule to modify the existing default rule to redirect all HTTP requests to HTTPS.


1 Answers

The issue was the target port I was using on the load balancer not matching the port the redirection server was listening on:

ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: http

This was just sending everything to port 80. It should have been this:

ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080

That way it matches up with the ConfigMap's:

data:
  ...
  http-snippet: |
    server {
      listen 8080 proxy_protocol;
      server_tokens off;
      return 307 https://$host$request_uri;
    }
like image 200
BHarman Avatar answered Oct 12 '22 12:10

BHarman