bitnami / charts

Bitnami Helm Charts
https://bitnami.com
Other
9.03k stars 9.22k forks source link

[bitnami/nginx] make ssl offloading with ingress more logic/intuitive #26334

Closed TiepiNL closed 5 months ago

TiepiNL commented 5 months ago

Name and Version

bitnami/nginx 17.1.0

What is the problem this feature will solve?

If the nginx template is used with a ClusterIP service and TLS enabled ingress, then the ingress takes care of the ssl handling and forwards http traffic to the service. However, by default this results in a "400 bad request" ("the plain http request was sent to https port").

I have been able to work around this issue by investigating the ingress template at https://github.com/bitnami/charts/blob/main/bitnami/nginx/templates/ingress.yaml#L33. Since containerPorts.https is set by default, the ingress will always create a backend rule for https. Once I manually set containerPorts.https to "", the ingress was configured for a http backend.

What is the feature you are proposing to solve the problem?

I would expect a more intuitive way to make ssl offloading work. For example, based on a "false" value for tls.enabled (https://github.com/bitnami/charts/blob/main/bitnami/nginx/README.md#nginx-deployment-parameters).

What alternatives have you considered?

I've tried to add the annotation nginx.ingress.kubernetes.io/ssl-redirect: "false" as described here: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#server-side-https-enforcement-through-redirect, but it didn't seem to help. Which makes sense, since the traffic was already http, the issue is that it's send the the https port.

I am quite new to K8s and Helm charts. Perhaps I overlook something?

jotamartos commented 5 months ago

Hi @TiepiNL,

If the nginx template is used with a ClusterIP service and TLS enabled ingress, then the ingress takes care of the ssl handling and forwards http traffic to the service. However, by default this results in a "400 bad request" ("the plain http request was sent to https port").

Could you please share the values you used to deploy the solution and the steps to reproduce the error?

Thanks

JuryA commented 5 months ago

I explained the reason in https://github.com/bitnami/charts/issues/25560#issuecomment-2153284852 why the current state is not correct.

TL;DR

The annotation nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" is used in NGINX Ingress to indicate that the communication between the Ingress controller and the backend service should use HTTPS. While this may seem like a good approach for ensuring secure communication between the Ingress and backend services, there are several reasons why it is often considered an anti-pattern:

Reasons It's Considered an Anti-Pattern

  1. Complexity in Certificate Management:

    • Multiple Certificates: Each backend service needs its own TLS certificate. This can lead to a complex setup and increased maintenance burden as certificates need to be managed, renewed, and distributed across multiple services.
    • Certificate Validity: Ensuring that all certificates are valid and have not expired adds another layer of operational complexity.
  2. Increased Configuration Overhead:

    • Service Configuration: Each service must be configured to support HTTPS, which involves setting up the TLS certificates correctly within each pod. This can be error-prone and requires additional configuration management.
    • Ingress Configuration: The Ingress resource must be explicitly configured to communicate with each service using HTTPS, which adds to the configuration overhead.
  3. Performance Overheads:

    • TLS Handshake: Each request to a backend service involves a TLS handshake, which can introduce latency and consume additional resources.
    • Resource Usage: Encrypting and decrypting traffic multiple times (once at the ingress and again at the backend) consumes more CPU resources, which could be better utilized elsewhere.
  4. Security Concerns:

    • Potential Misconfiguration: Misconfigurations can lead to scenarios where sensitive data might not be encrypted as intended. Ensuring end-to-end encryption without a proper service mesh can be challenging.
    • Attack Surface: The attack surface is increased as more components are responsible for handling encryption and decryption. This can potentially introduce vulnerabilities if not managed correctly.

Recommended Alternatives

  1. TLS Termination at the Ingress:

    • Centralized Management: TLS termination at the ingress centralizes the certificate management, reducing complexity and making it easier to maintain.
    • Resource Optimization: Offloading TLS termination to the ingress controller reduces the load on backend services, leading to better resource utilization.
  2. Service Mesh:

    • Automated Certificate Management: Service meshes like Istio or Linkerd automate the management of TLS certificates for intra-cluster communication, ensuring that traffic is encrypted without manual configuration.
    • Enhanced Security: Service meshes provide additional security features like mutual TLS (mTLS), traffic policies, and observability, which enhance the overall security posture of the cluster.

Conclusion

Using nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" can introduce significant complexity, increase the risk of misconfiguration, and lead to performance inefficiencies. For most scenarios, terminating TLS at the ingress and using a service mesh for end-to-end encryption within the cluster is a more scalable, secure, and manageable approach.