consul/agent/connect/generate_test.go

145 lines
4.0 KiB
Go

package connect
import (
"fmt"
"testing"
"time"
"crypto/x509"
"encoding/pem"
"github.com/hashicorp/consul/agent/structs"
"github.com/stretchr/testify/require"
)
type KeyConfig struct {
keyType string
keyBits int
}
var goodParams = []KeyConfig{
{keyType: "rsa", keyBits: 2048},
{keyType: "rsa", keyBits: 4096},
{keyType: "ec", keyBits: 224},
{keyType: "ec", keyBits: 256},
{keyType: "ec", keyBits: 384},
{keyType: "ec", keyBits: 521},
}
var badParams = []KeyConfig{
{keyType: "rsa", keyBits: 0},
{keyType: "rsa", keyBits: 1024},
{keyType: "rsa", keyBits: 24601},
{keyType: "ec", keyBits: 0},
{keyType: "ec", keyBits: 512},
{keyType: "ec", keyBits: 321},
{keyType: "ecdsa", keyBits: 256}, // test for "ecdsa" instead of "ec"
{keyType: "aes", keyBits: 128},
}
func makeConfig(kc KeyConfig) structs.CommonCAProviderConfig {
return structs.CommonCAProviderConfig{
LeafCertTTL: 3 * 24 * time.Hour,
IntermediateCertTTL: 365 * 24 * time.Hour,
PrivateKeyType: kc.keyType,
PrivateKeyBits: kc.keyBits,
}
}
func testGenerateRSAKey(t *testing.T, bits int) {
r := require.New(t)
_, rsaBlock, err := GeneratePrivateKeyWithConfig("rsa", bits)
r.NoError(err)
r.Contains(rsaBlock, "RSA PRIVATE KEY")
rsaBytes, _ := pem.Decode([]byte(rsaBlock))
r.NotNil(rsaBytes)
rsaKey, err := x509.ParsePKCS1PrivateKey(rsaBytes.Bytes)
r.NoError(err)
r.NoError(rsaKey.Validate())
r.Equal(bits/8, rsaKey.Size()) // note: returned size is in bytes. 2048/8==256
}
func testGenerateECDSAKey(t *testing.T, bits int) {
r := require.New(t)
_, pemBlock, err := GeneratePrivateKeyWithConfig("ec", bits)
r.NoError(err)
r.Contains(pemBlock, "EC PRIVATE KEY")
block, _ := pem.Decode([]byte(pemBlock))
r.NotNil(block)
pk, err := x509.ParseECPrivateKey(block.Bytes)
r.NoError(err)
r.Equal(bits, pk.Curve.Params().BitSize)
}
// Tests to make sure we are able to generate every type of private key supported by the x509 lib.
func TestGenerateKeys(t *testing.T) {
t.Parallel()
for _, params := range goodParams {
t.Run(fmt.Sprintf("TestGenerateKeys-%s-%d", params.keyType, params.keyBits),
func(t *testing.T) {
switch params.keyType {
case "rsa":
testGenerateRSAKey(t, params.keyBits)
case "ec":
testGenerateECDSAKey(t, params.keyBits)
default:
t.Fatalf("unknown key type: %s", params.keyType)
}
})
}
}
// Tests a variety of valid private key configs to make sure they're accepted.
func TestValidateGoodConfigs(t *testing.T) {
t.Parallel()
for _, params := range goodParams {
config := makeConfig(params)
t.Run(fmt.Sprintf("TestValidateGoodConfigs-%s-%d", params.keyType, params.keyBits),
func(t *testing.T) {
require.New(t).NoError(config.Validate(), "unexpected error: type=%s bits=%d",
params.keyType, params.keyBits)
})
}
}
// Tests a variety of invalid private key configs to make sure they're caught.
func TestValidateBadConfigs(t *testing.T) {
t.Parallel()
for _, params := range badParams {
config := makeConfig(params)
t.Run(fmt.Sprintf("TestValidateBadConfigs-%s-%d", params.keyType, params.keyBits), func(t *testing.T) {
require.New(t).Error(config.Validate(), "expected error: type=%s bits=%d",
params.keyType, params.keyBits)
})
}
}
// Tests the ability of a CA to sign a CSR using a different key type. This is
// allowed by TLS 1.2 and should succeed in all combinations.
func TestSignatureMismatches(t *testing.T) {
t.Parallel()
r := require.New(t)
for _, p1 := range goodParams {
for _, p2 := range goodParams {
if p1 == p2 {
continue
}
t.Run(fmt.Sprintf("TestMismatches-%s%d-%s%d", p1.keyType, p1.keyBits, p2.keyType, p2.keyBits), func(t *testing.T) {
ca := TestCAWithKeyType(t, nil, p1.keyType, p1.keyBits)
r.Equal(p1.keyType, ca.PrivateKeyType)
r.Equal(p1.keyBits, ca.PrivateKeyBits)
certPEM, keyPEM, err := testLeaf(t, "foobar.service.consul", "default", ca, p2.keyType, p2.keyBits)
r.NoError(err)
_, err = ParseCert(certPEM)
r.NoError(err)
_, err = ParseSigner(keyPEM)
r.NoError(err)
})
}
}
}