Adds correct support for TLS Muthual autentication and depth verification
modified: controllers/nginx/configuration.md modified: controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl modified: core/pkg/ingress/annotations/authtls/main.go modified: core/pkg/ingress/controller/backend_ssl.go modified: core/pkg/ingress/controller/controller.go modified: core/pkg/ingress/controller/util_test.go modified: core/pkg/ingress/resolver/main.go modified: core/pkg/ingress/types.go modified: core/pkg/net/ssl/ssl.go modified: examples/PREREQUISITES.md new file: examples/auth/client-certs/nginx/README.md new file: examples/auth/client-certs/nginx/nginx-tls-auth.yaml
This commit is contained in:
parent
f5e005f84f
commit
a342c0bce3
12 changed files with 349 additions and 52 deletions
|
|
@ -36,6 +36,105 @@ $ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
|
|||
secret "tls-secret" created
|
||||
```
|
||||
|
||||
## CA Authentication
|
||||
You can act as your very own CA, or use an existing one. As an exercise / learning, we're going to generate our
|
||||
own CA, and also generate a client certificate.
|
||||
|
||||
These instructions are based in CoreOS OpenSSL [instructions](https://coreos.com/kubernetes/docs/latest/openssl.html)
|
||||
|
||||
### Generating a CA
|
||||
|
||||
First of all, you've to generate a CA. This is going to be the one who will sign your client certificates.
|
||||
In real production world, you may face CAs with intermediate certificates, as the following:
|
||||
|
||||
```console
|
||||
$ openssl s_client -connect www.google.com:443
|
||||
[...]
|
||||
---
|
||||
Certificate chain
|
||||
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
|
||||
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
|
||||
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
|
||||
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
|
||||
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
|
||||
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
|
||||
|
||||
```
|
||||
|
||||
To generate our CA Certificate, we've to run the following commands:
|
||||
|
||||
```console
|
||||
$ openssl genrsa -out ca.key 2048
|
||||
$ openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj "/CN=example-ca"
|
||||
```
|
||||
|
||||
This will generate two files: A private key (ca.key) and a public key (ca.crt). This CA is valid for 10000 days.
|
||||
The ca.crt can be used later in the step of creation of CA authentication secret.
|
||||
|
||||
### Generating the client certificate
|
||||
The following steps generates a client certificate signed by the CA generated above. This client can be
|
||||
used to authenticate in a tls-auth configured ingress.
|
||||
|
||||
First, we need to generate an 'openssl.cnf' file that will be used while signing the keys:
|
||||
|
||||
```
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
```
|
||||
|
||||
Then, a user generates his very own private key (that he needs to keep secret)
|
||||
and a CSR (Certificate Signing Request) that will be sent to the CA to sign and generate a certificate.
|
||||
|
||||
```console
|
||||
$ openssl genrsa -out client1.key 2048
|
||||
$ openssl req -new -key client1.key -out client1.csr -subj "/CN=client1" -config openssl.cnf
|
||||
```
|
||||
|
||||
As the CA receives the generated 'client1.csr' file, it signs it and generates a client.crt certificate:
|
||||
|
||||
```console
|
||||
$ openssl x509 -req -in client1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client1.crt -days 365 -extensions v3_req -extfile openssl.cnf
|
||||
```
|
||||
|
||||
Then, you'll have 3 files: the client.key (user's private key), client.crt (user's public key) and client.csr (disposable CSR).
|
||||
|
||||
|
||||
### Creating the CA Authentication secret
|
||||
If you're using the CA Authentication feature, you need to generate a secret containing
|
||||
all the authorized CAs. You must download them from your CA site in PEM format (like the following):
|
||||
|
||||
```
|
||||
-----BEGIN CERTIFICATE-----
|
||||
[....]
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
You can have as many certificates as you want. If they're in the binary DER format,
|
||||
you can convert them as the following:
|
||||
|
||||
```console
|
||||
$ openssl x509 -in certificate.der -inform der -out certificate.crt -outform pem
|
||||
```
|
||||
|
||||
Then, you've to concatenate them all in only one file, named 'ca.crt' as the following:
|
||||
|
||||
|
||||
```console
|
||||
$ cat certificate1.crt certificate2.crt certificate3.crt >> ca.crt
|
||||
```
|
||||
|
||||
The final step is to create a secret with the content of this file. This secret is going to be used in
|
||||
the TLS Auth directive:
|
||||
|
||||
```console
|
||||
$ kubectl create secret generic caingress --namespace=default --from-file=ca.crt
|
||||
```
|
||||
|
||||
## Test HTTP Service
|
||||
|
||||
All examples that require a test HTTP Service use the standard http-svc pod,
|
||||
|
|
|
|||
86
examples/auth/client-certs/nginx/README.md
Normal file
86
examples/auth/client-certs/nginx/README.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# TLS authentication
|
||||
|
||||
This example demonstrates how to enable the TLS Authentication through the nginx Ingress controller.
|
||||
|
||||
## Terminology
|
||||
|
||||
* CA: Certificate authority signing the client cert, in this example we will play the role of a CA.
|
||||
You can generate a CA cert as show in this doc.
|
||||
|
||||
* CA Certificate(s) - Certificate Authority public key. Client certs must chain back to this cert,
|
||||
meaning the Issuer field of some certificate in the chain leading up to the client cert must contain
|
||||
the name of this CA. For purposes of this example, this is a self signed certificate.
|
||||
|
||||
* CA chains: A chain of certificates where the parent has a Subject field matching the Issuer field of
|
||||
the child, except for the root, which has Issuer == Subject.
|
||||
|
||||
* Client Cert: Certificate used by the clients to authenticate themselves with the loadbalancer/backends.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need a valid CA File, composed of a group of valid enabled CAs. This MUST be in PEM Format.
|
||||
The instructions are described [here](../../../PREREQUISITES.md#ca-authentication)
|
||||
|
||||
Also your ingress must be configured as a HTTPs/TLS Ingress.
|
||||
|
||||
## Deployment
|
||||
|
||||
Certificate Authentication is achieved through 2 annotations on the Ingress, as shown in the [example](nginx-tls-auth.yaml).
|
||||
|
||||
|Name|Description|Values|
|
||||
| --- | --- | --- |
|
||||
|ingress.kubernetes.io/auth-tls-secret|Sets the secret that contains the authorized CA Chain|string|
|
||||
|ingress.kubernetes.io/auth-tls-verify-depth|The verification depth Certificate Authentication will make|number (default to 1)|
|
||||
|
||||
|
||||
The following command instructs the controller to enable TLS authentication using the secret from the ``ingress.kubernetes.io/auth-tls-secret``
|
||||
annotation on the Ingress. Clients must present this cert to the loadbalancer, or they will receive a HTTP 400 response
|
||||
|
||||
```console
|
||||
$ kubectl create -f nginx-tls-auth.yaml
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
You can confirm that the Ingress works.
|
||||
|
||||
```console
|
||||
$ kubectl describe ing nginx-test
|
||||
Name: nginx-test
|
||||
Namespace: default
|
||||
Address: 104.198.183.6
|
||||
Default backend: default-http-backend:80 (10.180.0.4:8080,10.240.0.2:8080)
|
||||
TLS:
|
||||
tls-secret terminates ingress.test.com
|
||||
Rules:
|
||||
Host Path Backends
|
||||
---- ---- --------
|
||||
*
|
||||
http-svc:80 (<none>)
|
||||
Annotations:
|
||||
auth-tls-secret: default/caingress
|
||||
auth-tls-verify-depth: 3
|
||||
|
||||
Events:
|
||||
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
|
||||
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||
7s 7s 1 {nginx-ingress-controller } Normal CREATE default/nginx-test
|
||||
7s 7s 1 {nginx-ingress-controller } Normal UPDATE default/nginx-test
|
||||
7s 7s 1 {nginx-ingress-controller } Normal CREATE ip: 104.198.183.6
|
||||
7s 7s 1 {nginx-ingress-controller } Warning MAPPING Ingress rule 'default/nginx-test' contains no path definition. Assuming /
|
||||
|
||||
|
||||
$ curl -k https://ingress.test.com
|
||||
HTTP/1.1 400 Bad Request
|
||||
Server: nginx/1.11.9
|
||||
|
||||
$ curl -I -k --key ~/user.key --cert ~/user.cer https://ingress.test.com
|
||||
HTTP/1.1 200 OK
|
||||
Server: nginx/1.11.9
|
||||
|
||||
```
|
||||
|
||||
You must use the full DNS name while testing, as NGINX relies on the Server Name (SNI) to select the correct Ingress to be used.
|
||||
|
||||
The curl version used here was ``curl 7.47.0``
|
||||
25
examples/auth/client-certs/nginx/nginx-tls-auth.yaml
Normal file
25
examples/auth/client-certs/nginx/nginx-tls-auth.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
# Create this with kubectl create secret generic caingress --from-file=ca.crt --namespace=default
|
||||
ingress.kubernetes.io/auth-tls-secret: "default/caingress"
|
||||
ingress.kubernetes.io/auth-tls-verify-depth: "3"
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
name: nginx-test
|
||||
namespace: default
|
||||
spec:
|
||||
rules:
|
||||
- host: ingress.test.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: http-svc:80
|
||||
servicePort: 80
|
||||
path: /
|
||||
tls:
|
||||
- hosts:
|
||||
- ingress.test.com
|
||||
# Create this cert as described in 'multi-tls' example
|
||||
secretName: cert
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue