Add e2e Tests for AuthTLS

Adds E2E tests for the following annotations:

- auth-tls-secret
- auth-tls-verify-depth
- auth-tls-verify-client
- auth-tls-error-page
- auth-tls-pass-certificate-to-upstream
This commit is contained in:
Fernando Diaz 2018-10-05 22:35:56 -05:00
parent 85424d4af3
commit b503c6bdeb
4 changed files with 395 additions and 12 deletions

View file

@ -263,6 +263,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b
glog.Infof("nginx.conf:\n%v", o)
}
// passes the nginx config to the passed function
if matcher(strings.Join(strings.Fields(o), " ")) {
match = true
}

View file

@ -51,21 +51,24 @@ func CreateIngressTLSSecret(client kubernetes.Interface, hosts []string, secretN
return nil, fmt.Errorf("require a non-empty host for client hello")
}
var k, c bytes.Buffer
var serverKey, serverCert bytes.Buffer
var data map[string][]byte
host := strings.Join(hosts, ",")
if err := generateRSACert(host, true, &k, &c); err != nil {
if err := generateRSACert(host, true, &serverKey, &serverCert); err != nil {
return nil, err
}
cert, key := c.Bytes(), k.Bytes()
data = map[string][]byte{
v1.TLSCertKey: serverCert.Bytes(),
v1.TLSPrivateKeyKey: serverKey.Bytes(),
}
newSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
},
Data: map[string][]byte{
v1.TLSCertKey: cert,
v1.TLSPrivateKeyKey: key,
},
Data: data,
}
var apierr error
@ -81,7 +84,59 @@ func CreateIngressTLSSecret(client kubernetes.Interface, hosts []string, secretN
}
serverName := hosts[0]
return tlsConfig(serverName, cert)
return tlsConfig(serverName, serverCert.Bytes())
}
// CreateIngressMASecret creates or updates a Secret containing a Mutual Auth
// certificate-chain for the given Ingress and returns a TLS configuration suitable
// for HTTP clients to use against that particular Ingress.
func CreateIngressMASecret(client kubernetes.Interface, host string, secretName, namespace string) (*tls.Config, error) {
if len(host) == 0 {
return nil, fmt.Errorf("requires a non-empty host")
}
var caCert, serverKey, serverCert, clientKey, clientCert bytes.Buffer
var data map[string][]byte
if err := generateRSAMutualAuthCerts(host, &caCert, &serverKey, &serverCert, &clientKey, &clientCert); err != nil {
return nil, err
}
data = map[string][]byte{
v1.TLSCertKey: serverCert.Bytes(),
v1.TLSPrivateKeyKey: serverKey.Bytes(),
"ca.crt": caCert.Bytes(),
}
newSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
},
Data: data,
}
var apierr error
curSecret, err := client.CoreV1().Secrets(namespace).Get(secretName, metav1.GetOptions{})
if err == nil && curSecret != nil {
curSecret.Data = newSecret.Data
_, apierr = client.CoreV1().Secrets(namespace).Update(curSecret)
} else {
_, apierr = client.CoreV1().Secrets(namespace).Create(newSecret)
}
if apierr != nil {
return nil, apierr
}
clientPair, err := tls.X509KeyPair(clientCert.Bytes(), clientKey.Bytes())
if err != nil {
return nil, err
}
return &tls.Config{
ServerName: host,
Certificates: []tls.Certificate{clientPair},
InsecureSkipVerify: true,
}, nil
}
// WaitForTLS waits until the TLS handshake with a given server completes successfully.
@ -141,8 +196,125 @@ func generateRSACert(host string, isCA bool, keyOut, certOut io.Writer) error {
return fmt.Errorf("failed creating cert: %v", err)
}
if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
return fmt.Errorf("failed creating keay: %v", err)
return fmt.Errorf("failed creating key: %v", err)
}
return nil
}
// generateRSAMutualAuthCerts generates a complete basic self-signed certificate-chain (ca, server, client) using a
// key-length of rsaBits, valid for validFor time.
func generateRSAMutualAuthCerts(host string, caCertOut, serverKeyOut, serverCertOut, clientKeyOut, clientCertOut io.Writer) error {
notBefore := time.Now()
notAfter := notBefore.Add(validFor)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate serial number: %s", err)
}
// Generate the CA key and CA cert
caKey, err := rsa.GenerateKey(rand.Reader, rsaBits)
if err != nil {
return fmt.Errorf("failed to generate key: %v", err)
}
caTemplate := x509.Certificate{
Subject: pkix.Name{
CommonName: host + "-ca",
Organization: []string{"Acme Co"},
},
SerialNumber: serialNumber,
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
caTemplate.IsCA = true
caTemplate.KeyUsage |= x509.KeyUsageCertSign
caBytes, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, &caKey.PublicKey, caKey)
if err != nil {
return fmt.Errorf("failed to create certificate: %s", err)
}
if err := pem.Encode(caCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil {
return fmt.Errorf("failed creating cert: %v", err)
}
// Generate the Server Key and CSR for the server
serverKey, err := rsa.GenerateKey(rand.Reader, rsaBits)
if err != nil {
return fmt.Errorf("failed to generate key: %v", err)
}
// Create the server cert and sign with the csr
serialNumber, err = rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate serial number: %s", err)
}
serverTemplate := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: host,
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
}
serverBytes, err := x509.CreateCertificate(rand.Reader, &serverTemplate, &caTemplate, &serverKey.PublicKey, caKey)
if err != nil {
return fmt.Errorf("failed to create certificate: %s", err)
}
if err := pem.Encode(serverCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: serverBytes}); err != nil {
return fmt.Errorf("failed creating cert: %v", err)
}
if err := pem.Encode(serverKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(serverKey)}); err != nil {
return fmt.Errorf("failed creating key: %v", err)
}
// Create the client key and certificate
clientKey, err := rsa.GenerateKey(rand.Reader, rsaBits)
if err != nil {
return fmt.Errorf("failed to generate key: %v", err)
}
serialNumber, err = rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate serial number: %s", err)
}
clientTemplate := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: host + "-client",
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
}
clientBytes, err := x509.CreateCertificate(rand.Reader, &clientTemplate, &caTemplate, &clientKey.PublicKey, caKey)
if err != nil {
return fmt.Errorf("failed to create certificate: %s", err)
}
if err := pem.Encode(clientCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: clientBytes}); err != nil {
return fmt.Errorf("failed creating cert: %v", err)
}
if err := pem.Encode(clientKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(clientKey)}); err != nil {
return fmt.Errorf("failed creating key: %v", err)
}
return nil
}