forked from TrueCloudLab/certificates
Enforce >= 2048 bit rsa keys at the provisioner layer
* Fixes #94 * In the future this should be configurable by provisioner
This commit is contained in:
parent
0939f0d053
commit
2b41faa9cf
22 changed files with 250 additions and 39 deletions
|
@ -24,6 +24,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/assert"
|
||||
"github.com/smallstep/certificates/authority"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/logging"
|
||||
|
@ -150,7 +152,7 @@ func parseCertificate(data string) *x509.Certificate {
|
|||
}
|
||||
|
||||
func parseCertificateRequest(data string) *x509.CertificateRequest {
|
||||
block, _ := pem.Decode([]byte(csrPEM))
|
||||
block, _ := pem.Decode([]byte(data))
|
||||
if block == nil {
|
||||
panic("failed to parse certificate request PEM")
|
||||
}
|
||||
|
@ -387,11 +389,11 @@ func TestSignRequest_Validate(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
err error
|
||||
}{
|
||||
{"missing csr", fields{CertificateRequest{}, "foobarzar", time.Time{}, time.Time{}}, true},
|
||||
{"invalid csr", fields{CertificateRequest{bad}, "foobarzar", time.Time{}, time.Time{}}, true},
|
||||
{"missing ott", fields{CertificateRequest{csr}, "", time.Time{}, time.Time{}}, true},
|
||||
{"missing csr", fields{CertificateRequest{}, "foobarzar", time.Time{}, time.Time{}}, errors.New("missing csr")},
|
||||
{"invalid csr", fields{CertificateRequest{bad}, "foobarzar", time.Time{}, time.Time{}}, errors.New("invalid csr")},
|
||||
{"missing ott", fields{CertificateRequest{csr}, "", time.Time{}, time.Time{}}, errors.New("missing ott")},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -401,8 +403,12 @@ func TestSignRequest_Validate(t *testing.T) {
|
|||
NotAfter: NewTimeDuration(tt.fields.NotAfter),
|
||||
NotBefore: NewTimeDuration(tt.fields.NotBefore),
|
||||
}
|
||||
if err := s.Validate(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("SignRequest.Validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
if err := s.Validate(); err != nil {
|
||||
if assert.NotNil(t, tt.err) {
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
}
|
||||
} else {
|
||||
assert.Nil(t, tt.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -446,7 +446,7 @@ func TestAuthority_AuthorizeSign(t *testing.T) {
|
|||
}
|
||||
} else {
|
||||
if assert.Nil(t, tc.err) {
|
||||
assert.Len(t, 7, got)
|
||||
assert.Len(t, 8, got)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -538,7 +538,7 @@ func TestAuthority_Authorize(t *testing.T) {
|
|||
}
|
||||
} else {
|
||||
if assert.Nil(t, tc.err) {
|
||||
assert.Len(t, 7, got)
|
||||
assert.Len(t, 8, got)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -287,6 +287,7 @@ func (p *AWS) AuthorizeSign(token string) ([]SignOption, error) {
|
|||
}
|
||||
|
||||
return append(so,
|
||||
defaultPublicKeyValidator{},
|
||||
commonNameValidator(payload.Claims.Subject),
|
||||
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID),
|
||||
|
|
|
@ -326,11 +326,11 @@ func TestAWS_AuthorizeSign(t *testing.T) {
|
|||
wantLen int
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", p1, args{t1}, 4, false},
|
||||
{"ok", p2, args{t2}, 6, false},
|
||||
{"ok", p2, args{t2Hostname}, 6, false},
|
||||
{"ok", p2, args{t2PrivateIP}, 6, false},
|
||||
{"ok", p1, args{t4}, 4, false},
|
||||
{"ok", p1, args{t1}, 5, false},
|
||||
{"ok", p2, args{t2}, 7, false},
|
||||
{"ok", p2, args{t2Hostname}, 7, false},
|
||||
{"ok", p2, args{t2PrivateIP}, 7, false},
|
||||
{"ok", p1, args{t4}, 5, false},
|
||||
{"fail account", p3, args{t3}, 0, true},
|
||||
{"fail token", p1, args{"token"}, 0, true},
|
||||
{"fail subject", p1, args{failSubject}, 0, true},
|
||||
|
|
|
@ -275,6 +275,7 @@ func (p *Azure) AuthorizeSign(token string) ([]SignOption, error) {
|
|||
}
|
||||
|
||||
return append(so,
|
||||
defaultPublicKeyValidator{},
|
||||
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeAzure, p.Name, p.TenantID),
|
||||
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
|
||||
|
|
|
@ -281,9 +281,9 @@ func TestAzure_AuthorizeSign(t *testing.T) {
|
|||
wantLen int
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", p1, args{t1}, 3, false},
|
||||
{"ok", p2, args{t2}, 5, false},
|
||||
{"ok", p1, args{t11}, 3, false},
|
||||
{"ok", p1, args{t1}, 4, false},
|
||||
{"ok", p2, args{t2}, 6, false},
|
||||
{"ok", p1, args{t11}, 4, false},
|
||||
{"fail tenant", p3, args{t3}, 0, true},
|
||||
{"fail resource group", p4, args{t4}, 0, true},
|
||||
{"fail token", p1, args{"token"}, 0, true},
|
||||
|
|
|
@ -228,6 +228,7 @@ func (p *GCP) AuthorizeSign(token string) ([]SignOption, error) {
|
|||
}
|
||||
|
||||
return append(so,
|
||||
defaultPublicKeyValidator{},
|
||||
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeGCP, p.Name, claims.Subject, "InstanceID", ce.InstanceID, "InstanceName", ce.InstanceName),
|
||||
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
|
||||
|
|
|
@ -311,9 +311,9 @@ func TestGCP_AuthorizeSign(t *testing.T) {
|
|||
wantLen int
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", p1, args{t1}, 3, false},
|
||||
{"ok", p2, args{t2}, 5, false},
|
||||
{"ok", p3, args{t3}, 3, false},
|
||||
{"ok", p1, args{t1}, 4, false},
|
||||
{"ok", p2, args{t2}, 6, false},
|
||||
{"ok", p3, args{t3}, 4, false},
|
||||
{"fail token", p1, args{"token"}, 0, true},
|
||||
{"fail key", p1, args{failKey}, 0, true},
|
||||
{"fail iss", p1, args{failIss}, 0, true},
|
||||
|
|
|
@ -143,6 +143,7 @@ func (p *JWK) AuthorizeSign(token string) ([]SignOption, error) {
|
|||
|
||||
dnsNames, ips, emails := x509util.SplitSANs(claims.SANs)
|
||||
return []SignOption{
|
||||
defaultPublicKeyValidator{},
|
||||
commonNameValidator(claims.Subject),
|
||||
dnsNamesValidator(dnsNames),
|
||||
ipAddressesValidator(ips),
|
||||
|
|
|
@ -265,14 +265,14 @@ func TestJWK_AuthorizeSign(t *testing.T) {
|
|||
}
|
||||
} else {
|
||||
if assert.NotNil(t, got) {
|
||||
assert.Len(t, 7, got)
|
||||
assert.Len(t, 8, got)
|
||||
|
||||
_cnv := got[0]
|
||||
_cnv := got[1]
|
||||
cnv, ok := _cnv.(commonNameValidator)
|
||||
assert.True(t, ok)
|
||||
assert.Equals(t, string(cnv), "subject")
|
||||
|
||||
_dnv := got[1]
|
||||
_dnv := got[2]
|
||||
dnv, ok := _dnv.(dnsNamesValidator)
|
||||
assert.True(t, ok)
|
||||
if tt.name == "ok-sans" {
|
||||
|
|
|
@ -264,21 +264,19 @@ func (o *OIDC) AuthorizeSign(token string) ([]SignOption, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
so := []SignOption{
|
||||
defaultPublicKeyValidator{},
|
||||
profileDefaultDuration(o.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID),
|
||||
newValidityValidator(o.claimer.MinTLSCertDuration(), o.claimer.MaxTLSCertDuration()),
|
||||
}
|
||||
// Admins should be able to authorize any SAN
|
||||
if o.IsAdmin(claims.Email) {
|
||||
return []SignOption{
|
||||
profileDefaultDuration(o.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID),
|
||||
newValidityValidator(o.claimer.MinTLSCertDuration(), o.claimer.MaxTLSCertDuration()),
|
||||
}, nil
|
||||
return so, nil
|
||||
}
|
||||
|
||||
return []SignOption{
|
||||
emailOnlyIdentity(claims.Email),
|
||||
profileDefaultDuration(o.claimer.DefaultTLSCertDuration()),
|
||||
newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID),
|
||||
newValidityValidator(o.claimer.MinTLSCertDuration(), o.claimer.MaxTLSCertDuration()),
|
||||
}, nil
|
||||
return append(so, emailOnlyIdentity(claims.Email)), nil
|
||||
}
|
||||
|
||||
// AuthorizeRenewal returns an error if the renewal is disabled.
|
||||
|
|
|
@ -286,9 +286,9 @@ func TestOIDC_AuthorizeSign(t *testing.T) {
|
|||
} else {
|
||||
assert.NotNil(t, got)
|
||||
if tt.name == "admin" {
|
||||
assert.Len(t, 3, got)
|
||||
} else {
|
||||
assert.Len(t, 4, got)
|
||||
} else {
|
||||
assert.Len(t, 5, got)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package provisioner
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
|
@ -10,6 +12,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/cli/crypto/x509util"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// Options contains the options that can be passed to the Sign method.
|
||||
|
@ -78,7 +81,7 @@ func (e emailOnlyIdentity) Valid(req *x509.CertificateRequest) error {
|
|||
case len(req.EmailAddresses) == 0:
|
||||
return errors.New("certificate request does not contain any email address")
|
||||
case len(req.EmailAddresses) > 1:
|
||||
return errors.New("certificate request does not contain too many email addresses")
|
||||
return errors.New("certificate request contains too many email addresses")
|
||||
case req.EmailAddresses[0] == "":
|
||||
return errors.New("certificate request cannot contain an empty email address")
|
||||
case req.EmailAddresses[0] != string(e):
|
||||
|
@ -88,6 +91,23 @@ func (e emailOnlyIdentity) Valid(req *x509.CertificateRequest) error {
|
|||
}
|
||||
}
|
||||
|
||||
// defaultPublicKeyValidator validates the public key of a certificate request.
|
||||
type defaultPublicKeyValidator struct{}
|
||||
|
||||
// Valid checks that certificate request common name matches the one configured.
|
||||
func (v defaultPublicKeyValidator) Valid(req *x509.CertificateRequest) error {
|
||||
switch k := req.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
if k.Size() < 256 {
|
||||
return errors.New("rsa key in CSR must be at least 2048 bits (256 bytes)")
|
||||
}
|
||||
case *ecdsa.PublicKey, ed25519.PublicKey:
|
||||
default:
|
||||
return errors.Errorf("unrecognized public key of type '%T' in CSR", k)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// commonNameValidator validates the common name of a certificate request.
|
||||
type commonNameValidator string
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@ import (
|
|||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/assert"
|
||||
"github.com/smallstep/cli/crypto/pemutil"
|
||||
"github.com/smallstep/cli/crypto/x509util"
|
||||
stepx509 "github.com/smallstep/cli/pkg/x509"
|
||||
)
|
||||
|
||||
func Test_emailOnlyIdentity_Valid(t *testing.T) {
|
||||
|
@ -41,6 +47,72 @@ func Test_emailOnlyIdentity_Valid(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_defaultPublicKeyValidator_Valid(t *testing.T) {
|
||||
_shortRSA, err := pemutil.Read("./testdata/short-rsa.csr")
|
||||
assert.FatalError(t, err)
|
||||
shortRSA, ok := _shortRSA.(*x509.CertificateRequest)
|
||||
assert.Fatal(t, ok)
|
||||
|
||||
_rsa, err := pemutil.Read("./testdata/rsa.csr")
|
||||
assert.FatalError(t, err)
|
||||
rsaCSR, ok := _rsa.(*x509.CertificateRequest)
|
||||
assert.Fatal(t, ok)
|
||||
|
||||
_ecdsa, err := pemutil.Read("./testdata/ecdsa.csr")
|
||||
assert.FatalError(t, err)
|
||||
ecdsaCSR, ok := _ecdsa.(*x509.CertificateRequest)
|
||||
assert.Fatal(t, ok)
|
||||
|
||||
_ed25519, err := pemutil.Read("./testdata/ed25519.csr", pemutil.WithStepCrypto())
|
||||
assert.FatalError(t, err)
|
||||
ed25519CSR, ok := _ed25519.(*stepx509.CertificateRequest)
|
||||
assert.Fatal(t, ok)
|
||||
|
||||
v := defaultPublicKeyValidator{}
|
||||
tests := []struct {
|
||||
name string
|
||||
csr *x509.CertificateRequest
|
||||
err error
|
||||
}{
|
||||
{
|
||||
"fail/unrecognized-key-type",
|
||||
&x509.CertificateRequest{PublicKey: "foo"},
|
||||
errors.New("unrecognized public key of type 'string' in CSR"),
|
||||
},
|
||||
{
|
||||
"fail/rsa/too-short",
|
||||
shortRSA,
|
||||
errors.New("rsa key in CSR must be at least 2048 bits (256 bytes)"),
|
||||
},
|
||||
{
|
||||
"ok/rsa",
|
||||
rsaCSR,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ok/ecdsa",
|
||||
ecdsaCSR,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ok/ed25519",
|
||||
x509util.ToX509CertificateRequest(ed25519CSR),
|
||||
nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := v.Valid(tt.csr); err != nil {
|
||||
if assert.NotNil(t, tt.err) {
|
||||
assert.HasPrefix(t, err.Error(), tt.err.Error())
|
||||
}
|
||||
} else {
|
||||
assert.Nil(t, tt.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_commonNameValidator_Valid(t *testing.T) {
|
||||
type args struct {
|
||||
req *x509.CertificateRequest
|
||||
|
|
7
authority/provisioner/testdata/ecdsa.csr
vendored
Normal file
7
authority/provisioner/testdata/ecdsa.csr
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIHqMIGRAgEAMA4xDDAKBgNVBAMTA2ZvbzBZMBMGByqGSM49AgEGCCqGSM49AwEH
|
||||
A0IABKdDjTb7XIYCWC4QUq1xn5hgf3J4WpfWbd3C5frKrA4/VdQ+XfpHQIxDoHqh
|
||||
jcWke0SEETc9i6HDDtWv8bXSETegITAfBgkqhkiG9w0BCQ4xEjAQMA4GA1UdEQQH
|
||||
MAWCA2ZvbzAKBggqhkjOPQQDAgNIADBFAiEA1pFLT8p/YogG0o6NEEmdxzwbOzJA
|
||||
A+C+DvoT91c1OcQCIGUjP3s+k6Xwdf/VukUZXTfG1lobmkZhO3vYxAjPkwA7
|
||||
-----END CERTIFICATE REQUEST-----
|
8
authority/provisioner/testdata/ecdsa.key
vendored
Normal file
8
authority/provisioner/testdata/ecdsa.key
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,54abd40e525b255542ee6161ec438721
|
||||
|
||||
fJvmEc5n0IG4t4FKF+ekKhpog4ods2nZjBR5KLkGH5oSGAOEADSXIRBK76Jnm/nz
|
||||
Kv8ZwGqxNnoJUQyeTMlyg5OnOUAQPyNBPvoItOlD2DP32WJXgQ+NSHB2h9pcBGYG
|
||||
yLWrCtzl9/P9REWskanPO4RujP27Ht62omcMO7SxxNI=
|
||||
-----END EC PRIVATE KEY-----
|
6
authority/provisioner/testdata/ed25519.csr
vendored
Normal file
6
authority/provisioner/testdata/ed25519.csr
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIGuMGICAQAwDjEMMAoGA1UEAxMDZm9vMCowBQYDK2VwAyEA3yF/Igqb5UTp6XOq
|
||||
yj+cZL9nIfjDKrUT0fMzDAHtIqqgITAfBgkqhkiG9w0BCQ4xEjAQMA4GA1UdEQQH
|
||||
MAWCA2ZvbzAFBgMrZXADQQAIAx7N6ezi4NL8n0oJU8v3AmVSi0XvTuIHXUtcLGoU
|
||||
OZtlO3zjWI+DgcT/ADeEKn+T8OazDxcCbTBbHiM2hIsA
|
||||
-----END CERTIFICATE REQUEST-----
|
6
authority/provisioner/testdata/ed25519.key
vendored
Normal file
6
authority/provisioner/testdata/ed25519.key
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIGkMGAGCSqGSIb3DQEFDTBTMDIGCSqGSIb3DQEFDDAlBBDJ0vCXdpPyUiLlbge5
|
||||
1g0jAgMBhqAwDAYIKoZIhvcNAgkAADAdBglghkgBZQMEASoEENtOknzU2eS2mlxl
|
||||
73Yo/IoEQEyJS2EEx3+oYaKlFIB90e1Zkmi8da7d3r2iUlfc7faRAiKChcEvtEas
|
||||
vYF2l9LEZ9DXv1Rm1uyNuSpXuddHScE=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
16
authority/provisioner/testdata/rsa.csr
vendored
Normal file
16
authority/provisioner/testdata/rsa.csr
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICdDCCAVwCAQAwDjEMMAoGA1UEAxMDZm9vMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEA86h3t/KJylE0/aPxvF9JqPaOwSsGexuDWqDVJSOWBJi/ZqUA
|
||||
Ea2Gy05ZIJkQ5GOy0bUs2JCNCVXVkfPrUkX6IvIlXpTjutjMDYyYGdgQjzpKPnOA
|
||||
v3mO2a7mLMzJunws7pvrUPP7z5KDCKSAPf6VAcu/na8rGDWn1TUYR8hINK1rLQQf
|
||||
OcyNWrr7yLkR84jSsrw/Qgc8NS//F4ccca1NfZecPEtxgcHjKdDQZ3SYRAfb6Dc0
|
||||
jRuvoByAd3q9okOOr70gpMXgpoFVArDynaHMPK9xJ1w2p3s2/NhOYgY9f9rtcWTo
|
||||
afoAcHK1jy5iQCogFUKt1bUCz5IsaYkRt+D+HQIDAQABoCEwHwYJKoZIhvcNAQkO
|
||||
MRIwEDAOBgNVHREEBzAFggNmb28wDQYJKoZIhvcNAQELBQADggEBAOsv1UKwEbcY
|
||||
8Fj2Pl55BjkqQG4PqSQdWJZfK0ol/GRty5XFaTgOUZyTeXOag84OGw0qM0E7kkUa
|
||||
O5QwDOpnmIgg01Ywr4QM166l1iED+eOUscXJMonBAsS3JNYF1JxcDyKzIl/dt9+w
|
||||
JXQ64uquuD57amOs8++ROfKW988HzXm0OnoHj8LZ1Mq2yUmxvnnfVnmMpZWo43sA
|
||||
8NQs4v9dT5wLByFvBjcaWiGVZwZiwT4Q/Msskv9L0o1On0fgCJ6PjLYdblTwMHDZ
|
||||
syH+X8SsUqeEmyvtiRc1XUeFbxS2hnPXJCXeyfljqwsBNGaVhBXcsV2Lg7IaloBF
|
||||
/RyWqQZ44eE=
|
||||
-----END CERTIFICATE REQUEST-----
|
30
authority/provisioner/testdata/rsa.key
vendored
Normal file
30
authority/provisioner/testdata/rsa.key
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,e77ed7e2d2572b5a246a1c4b994190bb
|
||||
|
||||
29o7UA/L7OF7inTPKkwBrtd8CJdXVQs9R3oJPitmFk8SZbrLHEiEhF1C0uB3xK3s
|
||||
GWQ9O7bjERM3uAvQkd7MSkUUBpyPXS9GFacd85e85d1Ubl6miTAwkFrQnT9yn6n/
|
||||
Fak5JtkmdB6ObfVTioOwT1jdtGTifKg1bIhYISgwqCWhgV2fUFk6HQAAIMXTTRc+
|
||||
ZK1WbunT7LimYrnN3gQ4ylm/4C8nQl3JCGpvWZaRoH91q1LLD6IwWmX0D09F37dU
|
||||
X3KoKv/GvuDlV3H1dUBwxhU+GI5/lItPp9OcdLZnnr67Gs+X+do3MFT1h675TM4N
|
||||
c9QEIJB6RYatLBKHCS7j8W7EbuJAFZ+MCCapP92ERmVVVsWPY+V7CDVQxM2v4X/w
|
||||
7C7JYx8b4xuQbdvu9KVU5irsXg8hBx7kDb/mtWjT4+8+sseLKA4oOmI6XwVMdbow
|
||||
MciGilAIaNtWwQHe0EK9E9tiQfc9OyzxdrfplRckAAehHuPGU7+iMCsigCLT3aiV
|
||||
CDHmnLdTXKIvGe8faTQoJphrb9F8bobGo5D4ZqX5f6gKuPIJsfd/r0GD8VNSF/Q7
|
||||
SJQMhkVyaixFB0gQbmea7sTyScdW+Qne7nLpam3ISgo+G4CAH8W88wLnuHMLmvoC
|
||||
ZE3HvArSeQZ0WPHgB86AfoNRIxd6Emgb+dFyA6wPJC29nZkB8PFSrAHp0zp7KilF
|
||||
fe9K2dVAUBZFhQthQIYAjJmYLCukLhxUALiqdSmQZrt6DSE33K8s5ed2KJu/60G6
|
||||
lZwIzQHPXesRhwmwbkfPB8CyWM+L6osdWv8QyMdM8Wb+66zkhKWBNbm+ccMfP6Zf
|
||||
1ynF/a/DRX8bf81w+nvLsCGTdxVuEVEpuzS1NclKTmYQu58Ol0RgQe2JSxL89n+A
|
||||
JAHUu9g9LcTg2jNPjxeA/vusSXMZRrPqrUCYhHhcgR4mE13uyyFI/9frk0gPpKXp
|
||||
/FislMydWov2JRp1ixzypMBqlFR/zF6j6m3P1g7gchwScWzrZQHD58xdRin4Udiv
|
||||
OR4huswh5v2i/0KozBoUAwbvPGERnMlTaGoBMPJ5Xe/jkBJw3uC3Dhi74uyUCjqU
|
||||
hMQW4RJKmuiZVfAIX0RdgeUWXPs+8pf2pXrpIiVHCAHDrxXNMC7X6/9EcBN15B88
|
||||
W5/KIRngDeB2oVYrn1GfO7iLu1Rd8VFXyaVItOXq7WrL2pwm8ANhWcFDdnXf6jHW
|
||||
BcKss1j8rZxOchksf+ZPXhn3QkdooD9iVONky1zLIsV5GPwMe8+yXwXznzJSbHH7
|
||||
dOfhK93fZqUwx4gFULwCuWIwLTfNmQ3VzdKioGt39RFDVQb+pbR7p9jv899VjsVO
|
||||
TBBpRa00fvbK1H2CMVHnwwIf82M4XypSNGR/tSD3AImZPb5RfZnznoXXCMEfYVsd
|
||||
8/Ry4GHusA+zxCjCxHFtXVkb9sklewJtnUmN5mUzo/81szuigLB5IADR21IOyVBq
|
||||
A4kz96Ta885Z5owhonfZp1HD53pDEbxCuuIy+fgYfjfDSAj3L/QT3ZKrdcIdYQap
|
||||
PhrNRW3j38koAatTLd3+E9KqBO5BiY+T5h+Q3XesWnaXInfu5WKiiEm5hHiejA0C
|
||||
-----END RSA PRIVATE KEY-----
|
10
authority/provisioner/testdata/short-rsa.csr
vendored
Normal file
10
authority/provisioner/testdata/short-rsa.csr
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBdDCB2wIBADAOMQwwCgYDVQQDEwNmb28wgaIwDQYJKoZIhvcNAQEBBQADgZAA
|
||||
MIGMAoGEAK8dks7oV6kcIFEaWna7CDGYPAE8IL7rNi+ruQ1dIYz+JtxT7OPjbCn/
|
||||
t5iqni96+35iS/8CvMtEuquOMTMSWOWwlurrbTbLqCazuz/g233o8udxSxhny3cY
|
||||
wHogp4cXCX6cFll6DeUnoCEuTTSIu8IBHbK48VfNw4V4gGz6cp/H93HrAgMBAAGg
|
||||
ITAfBgkqhkiG9w0BCQ4xEjAQMA4GA1UdEQQHMAWCA2ZvbzANBgkqhkiG9w0BAQsF
|
||||
AAOBhABCZsYM+Kgje68Z9Fjl2+cBwtQHvZDarh+cz6W1SchinZ1T0aNQvSj/otOe
|
||||
ttnEF4Rq8zqzr4fbv+AF451Mx36AkfgZr9XWGzxidrH+fBCNWXWNR+ymhrL6UFTG
|
||||
2FbarLt9jN2aJLAYQPwtSeGTAZ74tLOPRPnTP6aMfFNg4XCR0uveHA==
|
||||
-----END CERTIFICATE REQUEST-----
|
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
@ -203,6 +204,33 @@ func TestSign(t *testing.T) {
|
|||
},
|
||||
}
|
||||
},
|
||||
"fail rsa key too short": func(t *testing.T) *signTest {
|
||||
shortRSAKeyPEM := `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBdDCB2wIBADAOMQwwCgYDVQQDEwNmb28wgaIwDQYJKoZIhvcNAQEBBQADgZAA
|
||||
MIGMAoGEAK8dks7oV6kcIFEaWna7CDGYPAE8IL7rNi+ruQ1dIYz+JtxT7OPjbCn/
|
||||
t5iqni96+35iS/8CvMtEuquOMTMSWOWwlurrbTbLqCazuz/g233o8udxSxhny3cY
|
||||
wHogp4cXCX6cFll6DeUnoCEuTTSIu8IBHbK48VfNw4V4gGz6cp/H93HrAgMBAAGg
|
||||
ITAfBgkqhkiG9w0BCQ4xEjAQMA4GA1UdEQQHMAWCA2ZvbzANBgkqhkiG9w0BAQsF
|
||||
AAOBhABCZsYM+Kgje68Z9Fjl2+cBwtQHvZDarh+cz6W1SchinZ1T0aNQvSj/otOe
|
||||
ttnEF4Rq8zqzr4fbv+AF451Mx36AkfgZr9XWGzxidrH+fBCNWXWNR+ymhrL6UFTG
|
||||
2FbarLt9jN2aJLAYQPwtSeGTAZ74tLOPRPnTP6aMfFNg4XCR0uveHA==
|
||||
-----END CERTIFICATE REQUEST-----`
|
||||
block, _ := pem.Decode([]byte(shortRSAKeyPEM))
|
||||
assert.FatalError(t, err)
|
||||
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||||
assert.FatalError(t, err)
|
||||
|
||||
return &signTest{
|
||||
auth: a,
|
||||
csr: csr,
|
||||
extraOpts: extraOpts,
|
||||
signOpts: signOpts,
|
||||
err: &apiError{errors.New("sign: rsa key in CSR must be at least 2048 bits (256 bytes)"),
|
||||
http.StatusUnauthorized,
|
||||
context{"csr": csr, "signOptions": signOpts},
|
||||
},
|
||||
}
|
||||
},
|
||||
"fail store cert in db": func(t *testing.T) *signTest {
|
||||
csr := getCSR(t, priv)
|
||||
_a := testAuthority(t)
|
||||
|
|
Loading…
Reference in a new issue