mirror of https://github.com/status-im/consul.git
[NET-6593] agent: check for minimum RSA key size (#20112)
* agent: check for minimum RSA key size * add changelog * agent: add test for RSA generated key sizes * use constants in generating priv key func * update key size error message
This commit is contained in:
parent
670b140d87
commit
7724bb88d5
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:security
|
||||||
|
Update RSA key generation to use a key size of at least 2048 bits.
|
||||||
|
```
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -107,6 +108,45 @@ func TestAutoEncrypt_generateCSR(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAutoEncrypt_generateCSR_RSA(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
keySize int
|
||||||
|
expectedKeySize int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "DefaultKeySize",
|
||||||
|
keySize: 0,
|
||||||
|
expectedKeySize: 4096,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KeySize2048",
|
||||||
|
keySize: 2048,
|
||||||
|
expectedKeySize: 2048,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tcase := range testCases {
|
||||||
|
t.Run(tcase.name, func(t *testing.T) {
|
||||||
|
ac := AutoConfig{config: &config.RuntimeConfig{
|
||||||
|
ConnectCAConfig: map[string]interface{}{
|
||||||
|
"PrivateKeyType": "rsa",
|
||||||
|
"PrivateKeyBits": tcase.keySize,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Generate a private RSA key.
|
||||||
|
_, key, err := ac.generateCSR()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Parse the private key and check it's length.
|
||||||
|
pemBlock, _ := pem.Decode([]byte(key))
|
||||||
|
priv, _ := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
|
||||||
|
require.Equal(t, tcase.expectedKeySize, priv.N.BitLen())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAutoEncrypt_hosts(t *testing.T) {
|
func TestAutoEncrypt_hosts(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
serverProvider ServerProvider
|
serverProvider ServerProvider
|
||||||
|
|
|
@ -241,7 +241,12 @@ func (ac *AutoConfig) generateCSR() (csr string, key string, err error) {
|
||||||
conf.PrivateKeyType = connect.DefaultPrivateKeyType
|
conf.PrivateKeyType = connect.DefaultPrivateKeyType
|
||||||
}
|
}
|
||||||
if conf.PrivateKeyBits == 0 {
|
if conf.PrivateKeyBits == 0 {
|
||||||
conf.PrivateKeyBits = connect.DefaultPrivateKeyBits
|
// If using an RSA key, a key size of at least 2048 bits is recommended; 4096 bits is better.
|
||||||
|
if conf.PrivateKeyType == connect.PrivateKeyTypeRSA {
|
||||||
|
conf.PrivateKeyBits = connect.DefaultPrivateKeyBitsRSA
|
||||||
|
} else {
|
||||||
|
conf.PrivateKeyBits = connect.DefaultPrivateKeyBits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new private key
|
// Create a new private key
|
||||||
|
|
|
@ -21,6 +21,11 @@ const (
|
||||||
DefaultPrivateKeyType = "ec"
|
DefaultPrivateKeyType = "ec"
|
||||||
DefaultPrivateKeyBits = 256
|
DefaultPrivateKeyBits = 256
|
||||||
DefaultIntermediateCertTTL = 24 * 365 * time.Hour
|
DefaultIntermediateCertTTL = 24 * 365 * time.Hour
|
||||||
|
|
||||||
|
// RSA specific settings.
|
||||||
|
PrivateKeyTypeRSA = "rsa"
|
||||||
|
MinPrivateKeyBitsRSA = 2048
|
||||||
|
DefaultPrivateKeyBitsRSA = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
func pemEncode(value []byte, blockType string) (string, error) {
|
func pemEncode(value []byte, blockType string) (string, error) {
|
||||||
|
@ -35,6 +40,11 @@ func pemEncode(value []byte, blockType string) (string, error) {
|
||||||
func generateRSAKey(keyBits int) (crypto.Signer, string, error) {
|
func generateRSAKey(keyBits int) (crypto.Signer, string, error) {
|
||||||
var pk *rsa.PrivateKey
|
var pk *rsa.PrivateKey
|
||||||
|
|
||||||
|
// Check for a secure key length.
|
||||||
|
if keyBits < MinPrivateKeyBitsRSA {
|
||||||
|
return nil, "", fmt.Errorf("error generating RSA private key: invalid key size %d, must be at least %d bits", keyBits, MinPrivateKeyBitsRSA)
|
||||||
|
}
|
||||||
|
|
||||||
pk, err := rsa.GenerateKey(rand.Reader, keyBits)
|
pk, err := rsa.GenerateKey(rand.Reader, keyBits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", fmt.Errorf("error generating RSA private key: %s", err)
|
return nil, "", fmt.Errorf("error generating RSA private key: %s", err)
|
||||||
|
@ -87,9 +97,9 @@ func generateECDSAKey(keyBits int) (crypto.Signer, string, error) {
|
||||||
// GeneratePrivateKey generates a new Private key
|
// GeneratePrivateKey generates a new Private key
|
||||||
func GeneratePrivateKeyWithConfig(keyType string, keyBits int) (crypto.Signer, string, error) {
|
func GeneratePrivateKeyWithConfig(keyType string, keyBits int) (crypto.Signer, string, error) {
|
||||||
switch strings.ToLower(keyType) {
|
switch strings.ToLower(keyType) {
|
||||||
case "rsa":
|
case PrivateKeyTypeRSA:
|
||||||
return generateRSAKey(keyBits)
|
return generateRSAKey(keyBits)
|
||||||
case "ec":
|
case DefaultPrivateKeyType:
|
||||||
return generateECDSAKey(keyBits)
|
return generateECDSAKey(keyBits)
|
||||||
default:
|
default:
|
||||||
return nil, "", fmt.Errorf("unknown private key type requested: %s", keyType)
|
return nil, "", fmt.Errorf("unknown private key type requested: %s", keyType)
|
||||||
|
|
Loading…
Reference in New Issue