open-consul/agent/connect/x509_patch_test.go
R.B. Boyer c3d5a2a5ab
connect/ca: cease including the common name field in generated certs (#10424)
As part of this change, we ensure that the SAN extensions are marked as
critical when the subject is empty so that AWS PCA tolerates the loss of
common names well and continues to function as a Connect CA provider.

Parts of this currently hack around a bug in crypto/x509 and can be
removed after https://go-review.googlesource.com/c/go/+/329129 lands in
a Go release.

Note: the AWS PCA tests do not run automatically, but the following
passed locally for me:

    ENABLE_AWS_PCA_TESTS=1 go test ./agent/connect/ca -run TestAWS
2021-06-25 13:00:00 -05:00

127 lines
3.3 KiB
Go

package connect
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"math/big"
"testing"
)
var testPrivateKey_x509 *rsa.PrivateKey
func TestX509_EmptySubject(t *testing.T) {
// NOTE: this test is lifted straight out of the stdlib with no changes. to
// show that the cert-only workflow is fine.
template := x509.Certificate{
SerialNumber: big.NewInt(1),
DNSNames: []string{"example.com"},
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &testPrivateKey_x509.PublicKey, testPrivateKey_x509)
if err != nil {
t.Fatalf("failed to create certificate: %s", err)
}
cert, err := x509.ParseCertificate(derBytes)
if err != nil {
t.Fatalf("failed to parse certificate: %s", err)
}
for _, ext := range cert.Extensions {
if ext.Id.Equal(x509_oidExtensionSubjectAltName) {
if !ext.Critical {
t.Fatal("SAN extension is not critical")
}
return
}
}
t.Fatal("SAN extension is missing")
}
func TestX509_EmptySubjectInCSR(t *testing.T) {
// NOTE: the CSR-only workflow is flawed so we hack around it
for _, tc := range []struct {
name string
hack bool
expectCritical bool
}{
{name: "unmodified stdlib",
hack: false,
expectCritical: false,
},
{name: "hacked stdlib",
hack: true,
expectCritical: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
template := x509.CertificateRequest{
DNSNames: []string{"example.com"},
}
if tc.hack {
HackSANExtensionForCSR(&template)
}
derBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, testPrivateKey_x509)
if err != nil {
t.Fatalf("failed to create certificate request: %s", err)
}
csr, err := x509.ParseCertificateRequest(derBytes)
if err != nil {
t.Fatalf("failed to parse certificate request: %s", err)
}
for _, ext := range csr.Extensions {
if ext.Id.Equal(x509_oidExtensionSubjectAltName) {
if tc.expectCritical {
if !ext.Critical {
t.Fatal("SAN extension is not critical")
}
} else {
if ext.Critical {
t.Fatal("SAN extension is critical now; maybe we don't need the hack anymore with this version of Go?")
}
}
return
}
}
t.Fatal("SAN extension is missing")
})
}
}
func init() {
block, _ := pem.Decode([]byte(pemPrivateKey_x509))
var err error
testPrivateKey_x509, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
}
var pemPrivateKey_x509 = `
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCxoeCUW5KJxNPxMp+KmCxKLc1Zv9Ny+4CFqcUXVUYH69L3mQ7v
IWrJ9GBfcaA7BPQqUlWxWM+OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7
J7jgCQ4RK3F/PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB
AoGAYrf6Hbk+mT5AI33k2Jt1kcweodBP7UkExkPxeuQzRVe0KVJw0EkcFhywKpr1
V5eLMrILWcJnpyHE5slWwtFHBG6a5fLaNtsBBtcAIfqTQ0Vfj5c6SzVaJv0Z5rOd
7gQF6isy3t3w9IF3We9wXQKzT6q5ypPGdm6fciKQ8RnzREkCQQDZwppKATqQ41/R
vhSj90fFifrGE6aVKC1hgSpxGQa4oIdsYYHwMzyhBmWW9Xv/R+fPyr8ZwPxp2c12
33QwOLPLAkEA0NNUb+z4ebVVHyvSwF5jhfJxigim+s49KuzJ1+A2RaSApGyBZiwS
rWvWkB471POAKUYt5ykIWVZ83zcceQiNTwJBAMJUFQZX5GDqWFc/zwGoKkeR49Yi
MTXIvf7Wmv6E++eFcnT461FlGAUHRV+bQQXGsItR/opIG7mGogIkVXa3E1MCQARX
AAA7eoZ9AEHflUeuLn9QJI/r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo
6vdM4QGKTJoO+SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS/cy+mweCMwyJ1PFEc4FX6
wg/HcAJWY60xZTJDFN+Qfx8ZQvBEin6c2/h+zZi5IVY=
-----END RSA PRIVATE KEY-----
`