Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

https backends' certificates are not verified #4503

Closed
sebastianblunt opened this issue Aug 28, 2019 · 13 comments
Closed

https backends' certificates are not verified #4503

sebastianblunt opened this issue Aug 28, 2019 · 13 comments

Comments

@sebastianblunt
Copy link

sebastianblunt commented Aug 28, 2019

Is this a request for help? (If yes, you should use our troubleshooting guide and community support channels, see https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/.):

What keywords did you search in NGINX Ingress controller issues before filing this one? (If you have found any duplicates, you should instead reply there.):

  • secure-verify-ca-secret

(found #2680 which is closed)


Is this a BUG REPORT or FEATURE REQUEST? (choose one):
BUG REPORT

NGINX Ingress controller version: Tested on 0.24.1 and 0.26.1

Kubernetes version (use kubectl version):

Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-20T04:49:16Z", GoVersion:"go1.12.6", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", GitCommit:"5e53fd6bc17c0dec8434817e69b04a25d8ae0ff0", GitTreeState:"clean", BuildDate:"2019-06-06T01:36:19Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}

Environment:

  • Cloud provider or hardware configuration:
  • OS (e.g. from /etc/os-release):
  • Kernel (e.g. uname -a): Darwin SebsMacbook.local 18.7.0 Darwin Kernel Version 18.7.0: Thu Jun 20 18:42:21 PDT 2019; root:xnu-4903.270.47~4/RELEASE_X86_64 x86_64
  • Install tools: docker-for-desktop
  • Others:

What happened:

I am unable to get nginx-ingress-controller to reject a backend certificate. Specifying one certificate in the nginx.ingress.kubernetes.io/secure-verify-ca-secret annotation for an ingress, and having the corresponding backend serve up a completely different (and self-signed) certificate does not lead to any error.

If setting the annotation to a non-existent secret, you get the following logs:

nginx-ingress-controller-6ff7d577b6-f6wxn nginx-ingress-controller W0828 23:37:47.095620       7 backend_ssl.go:48] Error obtaining X.509 certificate: no object matching key "default/does-not-exist" in local store
nginx-ingress-controller-6ff7d577b6-m4r2c nginx-ingress-controller [28/Aug/2019:23:37:47 +0000]TCP200000.000
nginx-ingress-controller-6ff7d577b6-tb2qt nginx-ingress-controller W0828 23:37:47.095405       7 backend_ssl.go:48] Error obtaining X.509 certificate: no object matching key "default/does-not-exist" in local store

If the secret does exist, I see:

nginx-ingress-controller-6ff7d577b6-f6wxn nginx-ingress-controller-6ff7d577b6-tb2qt nginx-ingress-controller I0828 23:37:01.867776       7 backend_ssl.go:68] Adding Secret "default/backend-test" to the local store
nginx-ingress-controller-6ff7d577b6-f6wxn nginx-ingress-controller I0828 23:37:01.868308       7 event.go:209] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"test-ingress", UID:"5202edcd-c9ec-11e9-b08a-025000000001", APIVersion:"extensions/v1beta1", ResourceVersion:"51689", FieldPath:""}): type: 'Normal' reason: 'UPDATE' Ingress default/test-ingress
nginx-ingress-controller I0828 23:37:01.868384       7 event.go:209] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"test-ingress", UID:"5202edcd-c9ec-11e9-b08a-025000000001", APIVersion:"extensions/v1beta1", ResourceVersion:"51689", FieldPath:""}): type: 'Normal' reason: 'UPDATE' Ingress default/test-ingress
nginx-ingress-controller-6ff7d577b6-m4r2c nginx-ingress-controller I0828 23:37:01.867704       7 backend_ssl.go:68] Adding Secret "default/backend-test" to the local store
nginx-ingress-controller-6ff7d577b6-m4r2c nginx-ingress-controller I0828 23:37:01.867991       7 event.go:209] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"test-ingress", UID:"5202edcd-c9ec-11e9-b08a-025000000001", APIVersion:"extensions/v1beta1", ResourceVersion:"51689", FieldPath:""}): type: 'Normal' reason: 'UPDATE' Ingress default/test-ingress
nginx-ingress-controller-6ff7d577b6-tb2qt nginx-ingress-controller I0828 23:37:01.871129       7 backend_ssl.go:68] Adding Secret "default/backend-test" to the local store
nginx-ingress-controller-6ff7d577b6-m4r2c nginx-ingress-controller [28/Aug/2019:23:37:01 +0000]TCP200000.000
nginx-ingress-controller-6ff7d577b6-f6wxn nginx-ingress-controller [28/Aug/2019:23:37:01 +0000]TCP200000.000
nginx-ingress-controller-6ff7d577b6-tb2qt nginx-ingress-controller [28/Aug/2019:23:37:01 +0000]TCP200000.000

What you expected to happen:

Backend certificates that do not exactly match the certificate specified in secure-verify-ca-secret to be rejected.

How to reproduce it (as minimally and precisely as possible):

Apply the following:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
  labels:
    app: test-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deployment
  template:
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
      - name: main
        image: nicolaka/netshoot
        command: ["bash", "-c"]
        args:
        - "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key -out cert -subj /CN=test-deployment && while true; do openssl s_server -key key -cert cert -accept 443 -www; done"
        ports:
        - containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  selector:
    app: test-deployment
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/secure-verify-ca-secret: "backend-test"
spec:
  rules:
  - http:
      paths:
      - path: /test
        backend:
          serviceName: test-service
          servicePort: 443

and run

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key -out cert -subj /CN=invalid
kubectl create secret tls backend-test --key key --cert cert

Anything else we need to know:

The now-deleted documentation for secure-verify-ca-secret said

Note that if an invalid or non-existent secret is given,
the ingress controller will ignore the `secure-backends` annotation.

Currently there is no documentation for secure-verify-ca-secret except that the annotation exists.

Even if it is possible to get it to reject certificates, I would still expect the behavior of secure-verify-ca-secret to be fail by default (if the secret is somehow misconfigured or missing), or at the very least give an error in that case.

@sebastianblunt sebastianblunt changed the title Certificate mismatch with secure-verify-ca-secret does not lead to any errors https backend's certificates are not verified Sep 2, 2019
@sebastianblunt sebastianblunt changed the title https backend's certificates are not verified https backends' certificates are not verified Sep 2, 2019
@aledbf
Copy link
Member

aledbf commented Oct 1, 2019

@sebastianblunt please update to 0.26.1 and make sure you enable the setting proxy-ssl-verify

nginx.ingress.kubernetes.io/proxy-ssl-verify: Enables or disables verification of the proxied HTTPS server certificate. (default: off)

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-certificate-authentication

This was added in 0.26.0 - #4327

@sebastianblunt
Copy link
Author

Thanks, I hadn't seen those new annotations.

Setting proxy-ssl-verify: "on" on its own has no effect (no logs at all, even when I misunderstood and put the name of a secret instead of on). If I also set proxy-ssl-secret to a secret containing a ca.crt field, then it will correctly reject the backend certificate and give me a 502 response. However if I do not also include tls.key and tls.crt, I get

nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller -------------------------------------------------------------------------------
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller Error: exit status 1
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller 2019/10/01 00:51:49 [emerg] 1886#1886: SSL_CTX_use_PrivateKey_file("/etc/ingress-controller/ssl/ca-default-backend-test.pem") failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: ANY PRIVATE KEY error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/ingress-controller/ssl/ca-default-backend-test.pem") failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: ANY PRIVATE KEY error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller nginx: configuration file /tmp/nginx-cfg097909986 test failed
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller -------------------------------------------------------------------------------
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller W1001 00:51:49.391143       6 queue.go:130] requeuing default/backend-test, err
nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller -------------------------------------------------------------------------------

For this use case, I don't need mutual authentication, however I can put dummy values into tls.key and tls.crt and just have my backend service ignore the client certs for now.

I presume the secure-verify-ca-secret annotation is no longer used for anything then?

@aledbf
Copy link
Member

aledbf commented Oct 1, 2019

SSL: error:0909006C:PEM routines:get_name:no start line:Expecting

That means there is an issue with the format of the certificate.

Please check two things:

  • get the temporal nginx.conf file (like /tmp/nginx-cfg097909986) using kubectl exec -it <ingress controller pod> cat /tmp/nginx-cfg097909986
  • get the certificate stored in /etc/ingress-controller/ssl/ca-default-backend-test.pem and check is valid using the openssl command.

@ramosbugs
Copy link

@aledbf the error message @sebastianblunt included makes it pretty clear that the controller is looking for a private key in that file, not an x509 certificate. Is there no way for the ingress controller to verify the backend cert without also enabling client auth?

Also, if the secure-verify-ca-secret annotation is no longer supported and it's now silently ignored, then that's a breaking change that introduced a security vulnerability to all existing Kubernetes deployments that rely on that annotation to prevent MITM attacks in their backends. Rather than silently ignore the option, I think it's fairly critical for the ingress controller to hard fail if that config option is used on a newer version where it's unsupported.

@ramosbugs
Copy link

@sebastianblunt
Copy link
Author

If proxy-ssl-verify is set to "on" I also think it would be best to have it hard fail if it can't find the proxy-ssl-secret, instead of silently accepting an unverified certificate.

@ramosbugs
Copy link

Related: #3484
Possible root cause: #3203

@aledbf
Copy link
Member

aledbf commented Oct 1, 2019

  1. create ssl certificates
# from https://kubernetes.github.io/ingress-nginx/examples/PREREQUISITES/
openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Fake CA'

openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=valid'
openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key
kubectl create secret generic ca-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt
  1. create deployment and ingress
echo "
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
  labels:
    app: test-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deployment
  template:
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
      - name: main
        image: nicolaka/netshoot
        command: ['bash', '-c']
        args:
        - 'while true; do openssl s_server -key key -cert /data/tls.crt -key /data/tls.key -accept 443 -www; done'
        ports:
        - containerPort: 443
        volumeMounts:
          - mountPath: /data
            name: tls-secret
            readOnly: true
      volumes:
        - name: tls-secret
          secret:
            secretName: tls-secret
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  selector:
    app: test-deployment
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/configuration-snippet: |
      # this is required because the CN of the generated certificate.
      # or nginx sends the content of $proxy_host https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_name
      proxy_ssl_name valid;
    nginx.ingress.kubernetes.io/proxy-ssl-secret: default/ca-secret
    nginx.ingress.kubernetes.io/proxy-ssl-verify: 'on'
    #nginx.ingress.kubernetes.io/proxy-ssl-protocols: TLSv1.1
spec:
  rules:
  - host: test-deployment
    http:
      paths:
      - path: /valid
        backend:
          serviceName: test-service
          servicePort: 443
      - path: /invalid
        backend:
          serviceName: test-invalid-service
          servicePort: 443
" | kubectl apply -f -

Get ingress controller pod name:

export POD=$(kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -o jsonpath="{.items[0].metadata.name}")

Run a test:

kubectl exec -n ingress-nginx $POD -- curl localhost/valid -H 'Host: test-deployment'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<HTML><BODY BGCOLOR="#ffffff">
<pre>

s_server -key key -cert /data/tls.crt -key /data/tls.key -accept 443 -www 
Secure Renegotiation IS supported
Ciphers supported in s_server binary
TLSv1.3    :TLS_AES_256_GCM_SHA384    TLSv1.3    :TLS_CHACHA20_POLY1305_SHA256 
TLSv1.3    :TLS_AES_128_GCM_SHA256    TLSv1.2    :ECDHE-ECDSA-AES256-GCM-SHA384 
TLSv1.2    :ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2    :DHE-RSA-AES256-GCM-SHA384 
TLSv1.2    :ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2    :ECDHE-RSA-CHACHA20-POLY1305 
TLSv1.2    :DHE-RSA-CHACHA20-POLY1305 TLSv1.2    :ECDHE-ECDSA-AES128-GCM-SHA256 
TLSv1.2    :ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2    :DHE-RSA-AES128-GCM-SHA256 
TLSv1.2    :ECDHE-ECDSA-AES256-SHA384 TLSv1.2    :ECDHE-RSA-AES256-SHA384   
TLSv1.2    :DHE-RSA-AES256-SHA256     TLSv1.2    :ECDHE-ECDSA-AES128-SHA256 
TLSv1.2    :ECDHE-RSA-AES128-SHA256   TLSv1.2    :DHE-RSA-AES128-SHA256     
TLSv1.0    :ECDHE-ECDSA-AES256-SHA    TLSv1.0    :ECDHE-RSA-AES256-SHA      
SSLv3      :DHE-RSA-AES256-SHA        TLSv1.0    :ECDHE-ECDSA-AES128-SHA    
TLSv1.0    :ECDHE-RSA-AES128-SHA      SSLv3      :DHE-RSA-AES128-SHA        
TLSv1.2    :RSA-PSK-AES256-GCM-SHA384 TLSv1.2    :DHE-PSK-AES256-GCM-SHA384 
TLSv1.2    :RSA-PSK-CHACHA20-POLY1305 TLSv1.2    :DHE-PSK-CHACHA20-POLY1305 
TLSv1.2    :ECDHE-PSK-CHACHA20-POLY1305 TLSv1.2    :AES256-GCM-SHA384         
TLSv1.2    :PSK-AES256-GCM-SHA384     TLSv1.2    :PSK-CHACHA20-POLY1305     
TLSv1.2    :RSA-PSK-AES128-GCM-SHA256 TLSv1.2    :DHE-PSK-AES128-GCM-SHA256 
TLSv1.2    :AES128-GCM-SHA256         TLSv1.2    :PSK-AES128-GCM-SHA256     
TLSv1.2    :AES256-SHA256             TLSv1.2    :AES128-SHA256             
TLSv1.0    :ECDHE-PSK-AES256-CBC-SHA384 TLSv1.0    :ECDHE-PSK-AES256-CBC-SHA  
SSLv3      :SRP-RSA-AES-256-CBC-SHA   SSLv3      :SRP-AES-256-CBC-SHA       
TLSv1.0    :RSA-PSK-AES256-CBC-SHA384 TLSv1.0    :DHE-PSK-AES256-CBC-SHA384 
SSLv3      :RSA-PSK-AES256-CBC-SHA    SSLv3      :DHE-PSK-AES256-CBC-SHA    
SSLv3      :AES256-SHA                TLSv1.0    :PSK-AES256-CBC-SHA384     
SSLv3      :PSK-AES256-CBC-SHA        TLSv1.0    :ECDHE-PSK-AES128-CBC-SHA256 
TLSv1.0    :ECDHE-PSK-AES128-CBC-SHA  SSLv3      :SRP-RSA-AES-128-CBC-SHA   
SSLv3      :SRP-AES-128-CBC-SHA       TLSv1.0    :RSA-PSK-AES128-CBC-SHA256 
TLSv1.0    :DHE-PSK-AES128-CBC-SHA256 SSLv3      :RSA-PSK-AES128-CBC-SHA    
SSLv3      :DHE-PSK-AES128-CBC-SHA    SSLv3      :AES128-SHA                
TLSv1.0    :PSK-AES128-CBC-SHA256     SSLv3      :PSK-AES128-CBC-SHA        
---
Ciphers common between both SSL end points:
ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 
ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305 
ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 
ECDHE-ECDSA-AES256-SHA384  ECDHE-RSA-AES256-SHA384    DHE-RSA-AES256-SHA256     
ECDHE-ECDSA-AES128-SHA256  ECDHE-RSA-AES128-SHA256    DHE-RSA-AES128-SHA256     
ECDHE-ECDSA-AES256-SHA     ECDHE-RSA-AES256-SHA       DHE-RSA-AES256-SHA        
ECDHE-ECDSA-AES128-SHA     ECDHE-RSA-AES128-SHA       DHE-RSA-AES128-SHA        
AES256-GCM-SHA384          AES128-GCM-SHA256          AES256-SHA256             
AES128-SHA256              AES256-SHA                 AES128-SHA
Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Supported Elliptic Groups: X25519:P-256:X448:P-521:P-384
Shared Elliptic groups: X25519:P-256:X448:P-521:P-384
---
No server certificate CA names sent
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 
    Session-ID-ctx: 01000000
    Master-Key: 24E0267B752D3515353D3A7A1B3E73110A07EBE083BC506E31A724CBC988299BE2B772898F662A11058F74F1A7DBB3C4
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1569897752
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: yes
---
   0 items in the session cache
   0 client connects (SSL_connect())
   0 client renegotiates (SSL_connect())
   0 client connects that finished
   1 server accepts (SSL_accept())
   0 server renegotiates (SSL_accept())
   1 server accepts that finished
   0 session cache hits
   0 session cache misses
   0 session cache timeouts
   0 callback cache hits
   0 cache full overflows (128 allowed)
---
no client certificate available
</pre></BODY></HTML>

100  4932    0  4932    0     0   535k      0 --:--:-- --:--:-- --:--:--  535k
  1. Create a different deployment to verify nginx is checking the certificate
echo "
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment2
  labels:
    app: test-deployment2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deployment2
  template:
    metadata:
      labels:
        app: test-deployment2
    spec:
      containers:
      - name: main
        image: nicolaka/netshoot
        command: ['bash', '-c']
        args:
        - 'openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key -out cert -subj /CN=test-deployment && while true; do openssl s_server -key key -cert cert -accept 443 -www; done'
        ports:
        - containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
  name: test-invalid-service
spec:
  selector:
    app: test-deployment2
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443
" | kubectl apply -f -

4. check the certificate verification fails

```console 
kubectl exec -n ingress-nginx $POD -- curl localhost/invalid -H 'Host: test-deployment'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
10<html>0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty/1.15.8.2</center>
</body>
</html>
0   163  100   163    0     0  10866      0 --:--:-- --:--:-- --:--:-- 11642

From the ingress controller logs:

2019/10/01 02:43:03 [error] 199#199: *405 upstream SSL certificate verify error: (18:self signed certificate) while SSL handshaking to upstream, client: 127.0.0.1, server: test-deployment, request: "GET /invalid HTTP/1.1", upstream: "https://172.17.0.10:443/invalid", host: "test-deployment"
2019/10/01 02:43:03 [error] 199#199: *405 upstream SSL certificate verify error: (18:self signed certificate) while SSL handshaking to upstream, client: 127.0.0.1, server: test-deployment, request: "GET /invalid HTTP/1.1", upstream: "https://172.17.0.10:443/invalid", host: "test-deployment"
2019/10/01 02:43:03 [error] 199#199: *405 upstream SSL certificate verify error: (18:self signed certificate) while SSL handshaking to upstream, client: 127.0.0.1, server: test-deployment, request: "GET /invalid HTTP/1.1", upstream: "https://172.17.0.10:443/invalid", host: "test-deployment"
127.0.0.1 - - [01/Oct/2019:02:43:03 +0000] "GET /invalid HTTP/1.1" 502 163 "-" "curl/7.64.0" 86 0.005 [default-test-invalid-service-443] [] 172.17.0.10:443, 172.17.0.10:443, 172.17.0.10:443 0, 0, 0 0.003, 0.001, 0.001 502, 502, 502 9a9d92f1b5c6de5185d0178335e44b79

@aledbf
Copy link
Member

aledbf commented Oct 1, 2019

@aledbf
Copy link
Member

aledbf commented Oct 1, 2019

Is there no way for the ingress controller to verify the backend cert without also enabling client auth?

nginx-ingress-controller-7f79b7f689-dsp29 nginx-ingress-controller nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/ingress-controller/ssl/ca-default-backend-test.pem") failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: ANY PRIVATE KEY error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)

Right now the cert and key are not optional https://github.com/kubernetes/ingress-nginx/blob/master/rootfs/etc/nginx/template/nginx.tmpl#L820

@ramosbugs
Copy link

Hi @aledbf,

Thanks for confirming the expected behavior. I think the biggest issue here is that the old option, secure-verify-ca-secret, silently stopped providing the security guarantees that users previously relied upon. Consequently, there may well be Kubernetes deployments in production whose owners believe they are protected against MITM attacks, but who in fact are not. In the future, I strongly caution against removing security features in a way that will fail silently, and instead to fail hard if someone is relying upon a security feature that is no longer supported.

Additionally, I think a security advisory is in order here to alert users that this configuration option is now silently ignored, along with a patch release that will switch the behavior to failing hard.

@janosi
Copy link
Contributor

janosi commented Oct 18, 2019

#4688 is to fix the one-way authentication issue when only the ca.crt is in the secret referred by the annotation proxy-ssl-secret.

@aledbf
Copy link
Member

aledbf commented Dec 10, 2019

Closing. Fixed in #4689

@aledbf aledbf closed this as completed Dec 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants