Skip to content

Commit

Permalink
Validate server cert against ca cert for registry mirror
Browse files Browse the repository at this point in the history
  • Loading branch information
vivek-koppuru committed Jun 15, 2022
1 parent dc30f16 commit 491bd4e
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 37 deletions.
19 changes: 9 additions & 10 deletions pkg/crypto/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
type DefaultTlsValidator struct{}

type TlsValidator interface {
ValidateCert(host, port, cert string) error
ValidateCert(host, port, caCertContent string) error
HasSelfSignedCert(host, port string) (bool, error)
}

Expand All @@ -37,9 +37,9 @@ func (tv *DefaultTlsValidator) HasSelfSignedCert(host, port string) (bool, error
}

// ValidateCert parses the cert, ensures that the cert format is valid and verifies that the cert is valid for the url
func (tv *DefaultTlsValidator) ValidateCert(host, port, cert string) error {
func (tv *DefaultTlsValidator) ValidateCert(host, port, caCertContent string) error {
// Validates that the cert format is valid
block, _ := pem.Decode([]byte(cert))
block, _ := pem.Decode([]byte(caCertContent))
if block == nil {
return fmt.Errorf("failed to parse certificate PEM")
}
Expand All @@ -50,15 +50,14 @@ func (tv *DefaultTlsValidator) ValidateCert(host, port, cert string) error {

roots := x509.NewCertPool()
roots.AddCert(providedCert)
opts := x509.VerifyOptions{
DNSName: host,
Roots: roots,
conf := &tls.Config{
InsecureSkipVerify: false,
RootCAs: roots,
}

// Verifies that the cert is valid
_, err = providedCert.Verify(opts)
// Verifies that the cert is valid by making a connection to the endpoint
_, err = tls.Dial("tcp", net.JoinHostPort(host, port), conf)
if err != nil {
return fmt.Errorf("failed to verify certificate: %v", err)
return fmt.Errorf("verifying connection to host: %v", err)
}
return nil
}
162 changes: 141 additions & 21 deletions pkg/crypto/validator_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,97 @@
package crypto_test

import (
"crypto/tls"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/aws/eks-anywhere/pkg/constants"
"github.com/aws/eks-anywhere/pkg/crypto"
)

const (
endpoint = "unit-test.local"
invalid_endpoint = "invalid-endpoint.local"
port = constants.DefaultHttpsPort
endpoint = "127.0.0.1"
invalidEndpoint = "invalid-endpoint.local"
port = constants.DefaultHttpsPort
/*
This certificate was generated using the following commands and is valid only for `unit-test.local`
This certificate was generated using the following commands and is valid only for `127.0.0.1`
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr
openssl x509 -req -extfile <(printf "subjectAltName=DNS:unit-test.local") -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
openssl x509 -req -extfile <(printf "subjectAltName=IP:127.0.0.1") -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
*/
cert = `
caCert = `
-----BEGIN CERTIFICATE-----
MIICrjCCAZYCCQD6stMfKEVAGTANBgkqhkiG9w0BAQsFADAZMQswCQYDVQQGEwJV
UzEKMAgGA1UEAwwBKjAeFw0yMjA2MTUwNzE4MDRaFw0zMjA2MTIwNzE4MDRaMBkx
CzAJBgNVBAYTAlVTMQowCAYDVQQDDAEqMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAv25FFUfMGKdF9wRb3GBBmE0F0ifMz8nUb52nEX0+BGFg+x6Q8gRD
xTCvCwZoMOo2uRZpaz6KtGQywFuuQ5h8VrYB3WcuDPcpg1OJueWrITRY0NHUBMjh
JbvvqZGs8I/DfKoQOyxcXoeIMfbSW2IHnMeHzTfE9lkGiZatQVqlRQAOkshFIed6
YZ2p3hgxrzkPmTTiDNoQQotluTN0FcNgUwiKYGINVlmH4LaDobranBaMLztulWsK
0tQiDw2e7aaAZmxqaUN6QRMzwc1g2mvj+PXNf/V3/WGymsXUShy9zCx4PiMDuINW
fA/EhAdkZk0MrpYbfk221gSfxxvnd1xFLwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQCwRcvdYlSPYypWh7B1gCvqoq4XNk8YiRPs8X4JLly41uXlgQLfDw9oJUnR0h8c
TNObdEZEdsneinC8Gwg9hscooB2R5iYyqDjST0NAS7jPDDx9x42iRY6naUW7zuVZ
2IC/9ss4BZYlS0zztUOBDax9YOJxV3dwROwnfFqGiiiYqWuDfhlfUaHj6q+NAX9/
xISi7YOoym7wHgMlMIEwGKfMLPOgvZBnU8vMqVqhbxMjAx42VdWyyV8AOcIZxasq
jXcaCczmsh5VMZHNocnTmivmY3KwmUXgC+/4w7E/fRGPblh+2CKxBO6Wlz+ZyN1n
CNgC8QQ1opc4yanhaAZgn/Yd
-----END CERTIFICATE-----
`
serverKey = `
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDZzMrH+mOavXSn
XHV9lMywwmZARE0TLpuyUTBDuYwVHG13Yx5X7br3uwEtyp2tTUBMHRh+2uVf/7lm
fQfy0AoE5O2qa4EvuOc4zS8eHr1gW4rFC++EzA2FrTMLGczIwKzPPa4VAMteQyCj
LYmfdrOSLSM0Fn7TPFJ1c3DBjj1pY/DdIs/GPItPnL7B2m+gNSQ9E5lRJ/DmP1j8
2+hnScbB5GiLqdZBASd7T+Dwp7gUqZInMKdW6JJjbUY9xNXcHrCS7GINuXHbo5CK
z9Z19nl7+v0fzQbcVP6fH2jWAo7vfFd9IR+Tz/7zJ76UescRS1ONEu6071KfTA7j
fW1dhgqLAgMBAAECggEAdbH0NsK5Boqwuiv9laJORoqWpM4D9ISwQFkdQsvGxjW5
ddWLNSrTaUGV7n/aWycuwrLKZOq3Hvxa3OZd4DnJ4EExqXE0u2wpDwnaF2W3IpX1
VGwRv+pguEcTGUGU5zsvZ0JGizUFsOeHgIaAIzsK6MgZiPFLEa08Rhne6cmKqCMI
tueV7Rqwbbd6+pvnvHFqSrA9KHaJax9+GY0rDr3KlzuJkjK0Wy1D13j/1fkDzalN
opsxF3rShEuTHAVEiwjS+nzD5g6KZ3q2WDTRSKVAbh50rBOEPE9ERwY0vlEQRgKP
4YX/UH1DLDRiDguM2Fr4nhIiTlL98nF6EVLnD7dugQKBgQD+8ZWrvgRlvcqVJmB8
BloKWsoyJp3BgBO77ys0j1fgmQe+TPLpsnVetGmjIK75EQmv/30/lFoLXIM9sfcY
4WgOsnndXFS8gKLfvG8+yMVoSwxNIR/2dNnqZuohqp5LCMlamb7Xvb2rkeSMOx4P
Q0OkTgd0YSl2l7VUwCmBs0VBSwKBgQDas89DAkBVN6q0NRd3iqrjcAN5kKchFO3W
IyDVwrrqhodnx7c7GncPULacMjOs1FPDrhiBoE7x5pDO4v30uVQKrKRZbmN4EHJC
lAUVGKBJFG5RFGzqWrCWf4Hdzynlv5na2SYtGfcmEV5F5ja9ZoDxsOdnjvy6yh0p
E44mtB3TwQKBgGVxASn2EM/e5eXVAF05Ncia+Ytc/DaLXM7RyrI+Oyw+F+uruJgu
jy8gwEvNbHHkSqOCGHcc83tD02DQGE8JGZuHfqAK5hifYq99zhIAVzQ5cGqcPJiX
REJVsuG0fwnCNERdmqdDc136TiNSPpK6JAcTmTnAk3wBv4A6egmGqI7jAoGAG4Vb
BIyo+dBKe+jebh2WCY7T8R1B2sjecP70p9GcYdzR9z5LkXVwHA5FHHy4wfvqGoqy
7MT2ijxAZrhryrrzl3BIMjTQ8Y/oQPaNeS0jJm8avrs6RXdqF1YuSnJCTHYC72Y6
Bpzo2/J9kYA5zTWz7jYbuI1mwj6i0sNyNO6ffkECgYBJ3xZ/h5zDsrbxPDiTsXCs
3liEvmzCibkoCexflz/sN524E1d3F5jj+gsTvcXTvYTaSKLkjRgvtGT9deSCJt76
wKprVZnZJeY+y21aOW1+HM22zfrGJ1GLt1Qjx33GLDzxPJDL9gsHzyRM0S2wLa8u
z9TAYr37qFPTWOJJtmRitg==
-----END PRIVATE KEY-----
`
serverCert = `
-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIJAJA97n2wo1wBMA0GCSqGSIb3DQEBBQUAMBkxCzAJBgNV
BAYTAlVTMQowCAYDVQQDDAEqMB4XDTIyMDYxNTA3MTkwOVoXDTIzMDYxNTA3MTkw
OVowGTELMAkGA1UEBhMCVVMxCjAIBgNVBAMMASowggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDZzMrH+mOavXSnXHV9lMywwmZARE0TLpuyUTBDuYwVHG13
Yx5X7br3uwEtyp2tTUBMHRh+2uVf/7lmfQfy0AoE5O2qa4EvuOc4zS8eHr1gW4rF
C++EzA2FrTMLGczIwKzPPa4VAMteQyCjLYmfdrOSLSM0Fn7TPFJ1c3DBjj1pY/Dd
Is/GPItPnL7B2m+gNSQ9E5lRJ/DmP1j82+hnScbB5GiLqdZBASd7T+Dwp7gUqZIn
MKdW6JJjbUY9xNXcHrCS7GINuXHbo5CKz9Z19nl7+v0fzQbcVP6fH2jWAo7vfFd9
IR+Tz/7zJ76UescRS1ONEu6071KfTA7jfW1dhgqLAgMBAAGjEzARMA8GA1UdEQQI
MAaHBH8AAAEwDQYJKoZIhvcNAQEFBQADggEBAJTUv9eqrYJnF9ugKpC6QjsxQzJm
6A9Xwc13ORcno+NlYip1t0ITgW2ZebUboqvScy2B+IHM9HyQGkmVu8bXFJQ1clxy
HHA7Xp3xM+zB1KnvQ0ZPbaHnquOl39nULOCTxqSWCN8fqCuA/X3y9UiYL6P1cYRz
GFuoSgMoU+CrhkMQbF8c4dvl1Wr52Re9SYoX0o74N45pXhOMjeqUq2Mauapq7pFE
+21Y+KHEXojBWEufU8F6ihmWDMqu2vbbfODT63qp+6+VAiQOvMrBvsjW7Iq86VLE
8jddCYLRLwQjqaSn6APSSEocuzzP2J6CeGA4mxXHZz5gD22pugKbKLjHxwQ=
-----END CERTIFICATE-----
`
incorrectCert = `
-----BEGIN CERTIFICATE-----
MIID/jCCAuagAwIBAgIUO/ncrEaWxLUqZ8IioBVCRl1P2R4wDQYJKoZIhvcNAQEL
BQAwgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH
Expand All @@ -44,30 +117,77 @@ zwaAnAW1ZiriAbeFx+xOaO1fETVSm+5Poyl97r5Mmu97+3IpoWHFPO2z4Os9vn3q
XsKvL2lz2uQY+ZbrfvrL20p2
-----END CERTIFICATE-----
`
invalid_cert = `
invalidCert = `
-----BEGIN CERTIFICATE-----
invalidCert
-----END CERTIFICATE-----
`
)

func TestValidateCertValidCert(t *testing.T) {
tv := crypto.NewTlsValidator()
if err := tv.ValidateCert(endpoint, port, cert); err != nil {
t.Fatalf("Failed to validate cert: %v", err)
func TestValidateCert(t *testing.T) {
svr, err := runTestServer()
if err != nil {
t.Fatalf("starting test server: %v", err)
}
}

func TestValidateCertInvalidEndpoint(t *testing.T) {
tv := crypto.NewTlsValidator()
if err := tv.ValidateCert(invalid_endpoint, port, cert); err == nil {
t.Fatalf("Certificate validation passed for invalid endpoint")
defer svr.Close()
serverPort := strings.Split(svr.URL, ":")[2]
tests := []struct {
testName string
endpoint string
port string
caCert string
wantError bool
}{
{
testName: "valid cert",
endpoint: endpoint,
port: serverPort,
caCert: caCert,
wantError: false,
},
{
testName: "invalid endpoint",
endpoint: invalidEndpoint,
port: serverPort,
caCert: caCert,
wantError: true,
},
{
testName: "incorrect cert",
endpoint: endpoint,
port: serverPort,
caCert: incorrectCert,
wantError: true,
},
{
testName: "invalid cert format",
endpoint: endpoint,
port: serverPort,
caCert: invalidCert,
wantError: true,
},
}
for _, tc := range tests {
t.Run(tc.testName, func(t *testing.T) {
tv := crypto.NewTlsValidator()
err := tv.ValidateCert(tc.endpoint, tc.port, tc.caCert)
if (err != nil) != tc.wantError {
t.Fatalf("ValidateCert() error = %v, wantError %v", err, tc.wantError)
}
})
}
}

func TestValidateCertInvalidCert(t *testing.T) {
tv := crypto.NewTlsValidator()
if err := tv.ValidateCert(endpoint, port, invalid_cert); err == nil {
t.Fatalf("Certificate validation passed for invalid cert")
func runTestServer() (*httptest.Server, error) {
mux := http.NewServeMux()
svr := httptest.NewUnstartedServer(mux)
certificate, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
if err != nil {
return nil, fmt.Errorf("creating key pair: %v", err)
}
svr.TLS = &tls.Config{
Certificates: []tls.Certificate{certificate},
}
svr.StartTLS()
return svr, nil
}
2 changes: 1 addition & 1 deletion pkg/validations/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func ValidateCertForRegistryMirror(clusterSpec *cluster.Spec, tlsValidator TlsVa
}

if certContent != "" {
err := tlsValidator.ValidateCert(host, port, certContent)
err = tlsValidator.ValidateCert(host, port, certContent)
if err != nil {
return fmt.Errorf("invalid registry certificate: %v", err)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/validations/mocks/tls.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/validations/tls.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package validations

type TlsValidator interface {
ValidateCert(host, port, cert string) error
ValidateCert(host, port, caCertContent string) error
HasSelfSignedCert(host, port string) (bool, error)
}

0 comments on commit 491bd4e

Please sign in to comment.