forked from TrueCloudLab/certificates
Add configuration option for specifying the minimum public key length
Instead of using the defaultPublicKeyValidator a new validator called publicKeyMinimumLengthValidator has been implemented that uses a configurable minimum length for public keys in CSRs. It's also an option to alter the defaultPublicKeyValidator to also take a parameter, but that would touch quite some lines of code. This might be a viable option after merging SCEP support.
This commit is contained in:
parent
4168449935
commit
2beea1aa89
2 changed files with 47 additions and 4 deletions
|
@ -2,6 +2,7 @@ package provisioner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -17,6 +18,8 @@ type SCEP struct {
|
||||||
ForceCN bool `json:"forceCN,omitempty"`
|
ForceCN bool `json:"forceCN,omitempty"`
|
||||||
ChallengePassword string `json:"challenge,omitempty"`
|
ChallengePassword string `json:"challenge,omitempty"`
|
||||||
Capabilities []string `json:"capabilities,omitempty"`
|
Capabilities []string `json:"capabilities,omitempty"`
|
||||||
|
// MinimumPublicKeyLength is the minimum length for public keys in CSRs
|
||||||
|
MinimumPublicKeyLength int `json:"minimumPublicKeyLength,omitempty"`
|
||||||
Options *Options `json:"options,omitempty"`
|
Options *Options `json:"options,omitempty"`
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
claimer *Claimer
|
claimer *Claimer
|
||||||
|
@ -79,6 +82,15 @@ func (s *SCEP) Init(config Config) (err error) {
|
||||||
s.secretChallengePassword = s.ChallengePassword
|
s.secretChallengePassword = s.ChallengePassword
|
||||||
s.ChallengePassword = "*** redacted ***"
|
s.ChallengePassword = "*** redacted ***"
|
||||||
|
|
||||||
|
// Default to 2048 bits minimum public key length (for CSRs) if not set
|
||||||
|
if s.MinimumPublicKeyLength == 0 {
|
||||||
|
s.MinimumPublicKeyLength = 2048
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.MinimumPublicKeyLength%8 != 0 {
|
||||||
|
return fmt.Errorf("only minimum public keys exactly divisible by 8 are supported; %d is not exactly divisibly by 8", s.MinimumPublicKeyLength)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: add other, SCEP specific, options?
|
// TODO: add other, SCEP specific, options?
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -94,7 +106,7 @@ func (s *SCEP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e
|
||||||
newForceCNOption(s.ForceCN),
|
newForceCNOption(s.ForceCN),
|
||||||
profileDefaultDuration(s.claimer.DefaultTLSCertDuration()),
|
profileDefaultDuration(s.claimer.DefaultTLSCertDuration()),
|
||||||
// validators
|
// validators
|
||||||
defaultPublicKeyValidator{},
|
newPublicKeyMinimumLengthValidator(s.MinimumPublicKeyLength),
|
||||||
newValidityValidator(s.claimer.MinTLSCertDuration(), s.claimer.MaxTLSCertDuration()),
|
newValidityValidator(s.claimer.MinTLSCertDuration(), s.claimer.MaxTLSCertDuration()),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -117,6 +118,36 @@ func (v defaultPublicKeyValidator) Valid(req *x509.CertificateRequest) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// publicKeyMinimumLengthValidator validates the length (in bits) of the public key
|
||||||
|
// of a certificate request is at least a certain length
|
||||||
|
type publicKeyMinimumLengthValidator struct {
|
||||||
|
length int
|
||||||
|
}
|
||||||
|
|
||||||
|
// newPublicKeyMinimumLengthValidator creates a new publicKeyMinimumLengthValidator
|
||||||
|
// with the given length as its minimum value
|
||||||
|
// TODO: change the defaultPublicKeyValidator to have a configurable length instead?
|
||||||
|
func newPublicKeyMinimumLengthValidator(length int) publicKeyMinimumLengthValidator {
|
||||||
|
return publicKeyMinimumLengthValidator{
|
||||||
|
length: length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid checks that certificate request common name matches the one configured.
|
||||||
|
func (v publicKeyMinimumLengthValidator) Valid(req *x509.CertificateRequest) error {
|
||||||
|
switch k := req.PublicKey.(type) {
|
||||||
|
case *rsa.PublicKey:
|
||||||
|
minimumLengthInBytes := v.length / 8
|
||||||
|
if k.Size() < minimumLengthInBytes {
|
||||||
|
return fmt.Errorf("rsa key in CSR must be at least %d bits (%d bytes)", v.length, minimumLengthInBytes)
|
||||||
|
}
|
||||||
|
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.
|
// commonNameValidator validates the common name of a certificate request.
|
||||||
type commonNameValidator string
|
type commonNameValidator string
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue