Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport of Ensure RSA keys are at least 2048 bits in length into release/1.16.x #17935

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions agent/structs/config_entry_inline_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import (
"errors"
"fmt"

"github.com/hashicorp/consul/acl"
"github.com/miekg/dns"

"github.com/hashicorp/consul/acl"
)

// InlineCertificateConfigEntry manages the configuration for an inline certificate
Expand Down Expand Up @@ -42,8 +43,13 @@ func (e *InlineCertificateConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta {
}
func (e *InlineCertificateConfigEntry) GetRaftIndex() *RaftIndex { return &e.RaftIndex }

// Envoy will silently reject any keys that are less than 2048 bytes long
// https://github.com/envoyproxy/envoy/blob/main/source/extensions/transport_sockets/tls/context_impl.cc#L238
const MinKeyLength = 2048

func (e *InlineCertificateConfigEntry) Validate() error {
if err := validateConfigEntryMeta(e.Meta); err != nil {
err := validateConfigEntryMeta(e.Meta)
if err != nil {
return err
}

Expand All @@ -52,13 +58,25 @@ func (e *InlineCertificateConfigEntry) Validate() error {
return errors.New("failed to parse private key PEM")
}

if privateKeyBlock.Type == "RSA PRIVATE KEY" {
key, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if err != nil {
return err
}

// ensure private key is of the correct length
if key.N.BitLen() < MinKeyLength {
return errors.New("key length must be at least 2048 bits")
}
}

certificateBlock, _ := pem.Decode([]byte(e.Certificate))
if certificateBlock == nil {
return errors.New("failed to parse certificate PEM")
}

// make sure we have a valid x509 certificate
_, err := x509.ParseCertificate(certificateBlock.Bytes)
_, err = x509.ParseCertificate(certificateBlock.Bytes)
if err != nil {
return fmt.Errorf("failed to parse certificate: %w", err)
}
Expand Down
24 changes: 24 additions & 0 deletions agent/structs/config_entry_inline_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ NtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO
qwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww
AAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r
-----END CERTIFICATE-----`
tooShortPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCtmK1VjmXJ7vm4CZkkOSjc+kjGNMlyce5rXxwlDRz9LcGGc3Tg
kwUJesyBpDtxLLVHXQIPr5mWYbX/W/ezQ9sntxrATbDek8pBgoOlARebwkD2ivVW
BWfVhlryVihWlXApKiJ2n3i0m+OVtdrceC9Bv2hEMhYVOwzxtb3O0YFkbwIDAQAB
AoGAIxgnipFUEKPIRiVimUkY8ruCdNd9Fi7kNT6wEOl6v9A9PHIg4bm3Hfh+WYMb
JUEVkMzDuuoUEavFQE+WXt5L8oE1lEBmN2++FQsvllN+MRBTRg2sfw4mUWDI6S4r
h8+XNTzTIg2sUd2J3o2qNmQoOheYb+iuYDj76IFoEdwwZ0kCQQDYKKs5HAbnrLj1
UrOp8TyHdFf0YNw5tGdbNTbffq4rlBD6SW70+Sj624i2UqdnYwRiWzdXv3zN08aI
Vfoh2cGlAkEAzZe5B6BhiX/PcIYutMtuT3K+mysFNlowrutXWoQOpR7gGAkgEt6e
oCDgx1QJRjsp6NFQxKc6l034Hzs17gqJgwJAcu9U873aUg9+HTuHOoKB28haCCAE
mU46cr3d2oKCW7uUN3EaZXmid5iJneBfENMOfrnfuHGiC9NiShXlNWCS3QJAO5Ne
w83+1ahaxUGs4SkeExmuECrcPM7P0rBRxOIFmGWlDHIAgFdQYhiE6l34vghA8b1O
CV5oRRYL84jl7M/S3wJBALDfL5YXcc8P6scLJJ1biqhLYppvGN5CUwbsJsluvHCW
XCTVIbPOaS42A0xUfpoiTcdbNSFRvdCzPR5nsGy8Y7g=
-----END RSA PRIVATE KEY-----`
)

func TestInlineCertificate(t *testing.T) {
Expand All @@ -140,6 +155,15 @@ func TestInlineCertificate(t *testing.T) {
},
validateErr: "failed to parse certificate PEM",
},
"invalid private key length": {
entry: &InlineCertificateConfigEntry{
Kind: InlineCertificate,
Name: "cert-two",
PrivateKey: tooShortPrivateKey,
Certificate: "foo",
},
validateErr: "key length must be at least 2048 bits",
},
"mismatched certificate": {
entry: &InlineCertificateConfigEntry{
Kind: InlineCertificate,
Expand Down