// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
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 + 4 CFqcUXVUYH69L3mQ7v
IWrJ9GBfcaA7BPQqUlWxWM + OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7
J7jgCQ4RK3F / PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB
AoGAYrf6Hbk + mT5AI33k2Jt1kcweodBP7UkExkPxeuQzRVe0KVJw0EkcFhywKpr1
V5eLMrILWcJnpyHE5slWwtFHBG6a5fLaNtsBBtcAIfqTQ0Vfj5c6SzVaJv0Z5rOd
7 gQF6isy3t3w9IF3We9wXQKzT6q5ypPGdm6fciKQ8RnzREkCQQDZwppKATqQ41 / R
vhSj90fFifrGE6aVKC1hgSpxGQa4oIdsYYHwMzyhBmWW9Xv / R + fPyr8ZwPxp2c12
33 QwOLPLAkEA0NNUb + z4ebVVHyvSwF5jhfJxigim + s49KuzJ1 + A2RaSApGyBZiwS
rWvWkB471POAKUYt5ykIWVZ83zcceQiNTwJBAMJUFQZX5GDqWFc / zwGoKkeR49Yi
MTXIvf7Wmv6E ++ eFcnT461FlGAUHRV + bQQXGsItR / opIG7mGogIkVXa3E1MCQARX
AAA7eoZ9AEHflUeuLn9QJI / r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo
6 vdM4QGKTJoO + SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS / cy + mweCMwyJ1PFEc4FX6
wg / HcAJWY60xZTJDFN + Qfx8ZQvBEin6c2 / h + zZi5IVY =
-- -- - END RSA PRIVATE KEY -- -- -
`