c3d5a2a5ab
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
127 lines
3.3 KiB
Go
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-----
|
|
`
|