Enabling client certificate passthrough without validation - kubernetes

I'm trying to configure nginx-ingress for Kubernetes so that client certificate is passed on to backend service without validation.
Due to customer requests we are using client certificates for authentication but the certificates are not signed by the server and as such it's not really our job to validate the certificate, only to check that it is on the allowed certificates list.
Things work well on our test server where we use certificates signed by the servers CA certificate but after setting
nginx.ingress.kubernetes.io/auth-tls-verify-client: "off"
the client certificate is no longer forwarded in request header even though we still have
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
Does nginx-ingress even allow passing through client certificates without validation?
I expected that disabling auth-tls-verify-client would just stop nginx-ingress from validating the certificate signature and still pass it through, but instead it disappeared from the request.

May I suggest looking at this issue
When adding auth-tls-pass-certificate-to-upstream: true to an ingress resource, the client certificate passed to the ingress controller is not forwarded to the backend pod.
Apparently, the issues was
the issue to be more around standardization of passing client certificates in headers. I've found nginx is passing the client cert to the backend pod in the Ssl-client-certificate header.
In your case, I would suggest checking all the header values for the certificate, and see if it is there under a different name.
On top of this, remember to check that you **start the nginx ingress controller with flag enable-ssl-passthrough

Related

Self-signed certificates ok for kubernetes validating webhooks?

I'm trying to understand the security implications for using self-signed certificates for a Kubernetes validating webhook.
If I'm understanding correctly, the certificate is simply used to be able to serve the validating webhook server over https. When the Kubernetes api-server receives a request that matches the configuration for a validating webhook, it'll first check with the validating webhook server over https. If your validating webhook server lives on the Kubernetes cluster (is not external) then this traffic is all internal to a Kubernetes cluster. If this is the case is it problematic that the cert is self-signed?
If I'm understanding correctly, the certificate is simply used to be
able to serve the validating webhook server over https.
Basically yes.
If your validating webhook server lives on the Kubernetes cluster (is
not external) then this traffic is all internal to a Kubernetes
cluster. If this is the case is it problematic that the cert is
self-signed?
If the issuing process is handled properly and in secure manner, self-signed certs shouldn't be a problem at all. Compare with this example.

How do I use HTTPS between a GKE Ingress and the Service it forwards to?

On Google Kubernetes Engine (GKE) you can use the cloud.google.com/app-protocols annotation on a Service to specify what protocol is used on that port (HTTP or HTTPS) docs
When you create an External HTTP(S) Ingress, it will use this protocol between the Ingress and the Service.
How do I set things up so that the Service uses a certificate that is actually trusted by the Ingress?
Does it just trust any certificate signed by the Cluster Root CA? Manage tls in a cluster suggests you need to include the pod IP address in the CSR - does that mean generating the CSR and waiting for the signed certificate to be created should be part of my container startup process?
Turns out when the "GKE Ingress for HTTP(S) Load Balancing" uses HTTPS to connect to the service, it accepts any certificate valid (even a self-signed one), without further configuration.
Apparently it does not use TLS to protect against MITM attacks here (which I guess might be reasonable).

Allow access namespace only with certificate

I have the following scenario:
The user red make a http request to one of the three services in the namespace1. Somehow in the K8s, it should verify, if the user red has a valid certificate for namespace1 to call services or not. In this case, the user red owns the right certificate for the namespace1, so it allows to call any services within the namespace1. The same rule is also apply for user blue.
But when user red try to call services in the namespace2, then requests should be rejected, because it does not own the right certificat for namespace2.
The question is, it is possible to create namespace certificate in kubernetes. For example, when I have a certificate A, then I can only access namespace1 but not namespace2.
I think Kubernetes Services don’t offer such features. The authentication should be done in an ingress controller (e.g. nginx-ingress). You just deploy two different ones, one per namespace, with different certificate configuration.
Not exactly what you want but it's possible to do per domain.You can use an ingress controller such as ambassador with SNI support.You supply separate TLS certificates for different domains, instead of using a single TLS certificate for all domains.It is designed to be configured on a per-mapping basis, enabling application developers or service owners to individually manage how their service gets exposed over TLS.
Using SNI instead multiple ingress controller deployments is more scalable because multiple load balancers or IPs for those ingress controllers can be avoided.
The problem with SNI is client library and browser support is limited.

haproxy require client certificate for specific url?

I want to configure Haproxy so that it only requires client certificate when specific URL accessed? Ex:
www.test.com - it proceeds normally.
www.test.com/secure - haproxy requires the client certificate.
To understand why this isn't directly possible requires an understanding of how TLS (SSL) works. TLS encrypts the connection before the HTTP request is sent (over the now-encrypted connection). By the time the URL is known by HAProxy, the time for requiring a client certificate has already passed.
For practical reasons, an endpoint (HAProxy frontend or listen) needs to either require a certificate for connections, or not... however, using verify optional it might be possible to achieve what you want. Using verify optional means that the proxy will ask for a client cert upon connection, and if either the client offers no cert or if the cert is valid according to the ca-file, the client will be allowed to connect. Invalid certs will result in disconnection.
Then, the ssl_c_used fetch could be used to deny requests for that path for clients who didn't present the "optional" certificate, earlier.
http-request deny if { path_beg /secure } ! { ssl_c_used }
The viability of this solution depends on how gracefully browsers behave when asked for a certificate that they would not have -- and all connecting browsers will be asked for a certificate.
But there is no way of doing exactly what you are asking, either in HAProxy or on any other platform since, by design, the path is unknown until after TLS negotiation is already complete.

How can I overcome the x509 signed by unknown certificate authority error when using the default Kubernetes API Server virtual IP?

I have a Kubernetes cluster running in High Availability mode with 3 master nodes. When I try to run the DNS cluster add-on as-is, the kube2sky application errors with an x509 signed by unknown certificate authority message for the API Server service address (which in my case is 10.100.0.1). Reading through some of the GitHub issues, it looked like Tim Hockin had fixed this type of issue via using the default service account tokens available.
All 3 of my master nodes generate their own certificates for the secured API port, so is there something special I need to do configuration-wise on the API servers to get the CA certificate included in the default service account token?
It would be ideal to have the service IP of the API in the SAN field of all your server certificates.
If this is not possible in your setup, set the clusters{}.cluster.insecure-skip-tls-verify field to true in your kubeconfig file, or the pass the --insecure-skip-tls-verify flag to kubectl.
If you are trying to reach the API from within a pod you could use the secrets mounted via the Service Account. By default, if you use the default secret, the CA certificate and a signed token are mounted to /var/run/secrets/kubernetes.io/serviceaccount/ in every pod, and any client can use them from within the pod to communicate with the API. This would help you solving the unknown certificate authority error and provide you with an easy way to authenticate against your API servers at the same time.