Merge pull request #5552 from sathyanarays/isCaFix
Fixing CA flag in basic constraints extension
This commit is contained in:
commit
4ffd6213e7
@ -64,6 +64,12 @@ const (
|
||||
// This feature gate will disable auto-generated CertificateRequest name
|
||||
// Github Issue: https://github.com/cert-manager/cert-manager/issues/4956
|
||||
StableCertificateRequestName featuregate.Feature = "StableCertificateRequestName"
|
||||
|
||||
// Alpha: v1.11
|
||||
// UseCertificateRequestBasicConstraints will add Basic Constraints section in the Extension Request of the Certificate Signing Request
|
||||
// This feature will add BasicConstraints section with CA field defaulting to false; CA field will be set true if the Certificate resource spec has isCA as true
|
||||
// Github Issue: https://github.com/cert-manager/cert-manager/issues/5539
|
||||
UseCertificateRequestBasicConstraints featuregate.Feature = "UseCertificateRequestBasicConstraints"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -81,4 +87,5 @@ var defaultCertManagerFeatureGates = map[featuregate.Feature]featuregate.Feature
|
||||
ServerSideApply: {Default: false, PreRelease: featuregate.Alpha},
|
||||
LiteralCertificateSubject: {Default: false, PreRelease: featuregate.Alpha},
|
||||
StableCertificateRequestName: {Default: false, PreRelease: featuregate.Alpha},
|
||||
UseCertificateRequestBasicConstraints: {Default: false, PreRelease: featuregate.Alpha},
|
||||
}
|
||||
|
||||
@ -216,6 +216,14 @@ func GenerateCSR(crt *v1.Certificate) (*x509.CertificateRequest, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(feature.UseCertificateRequestBasicConstraints) {
|
||||
extension, err := buildBasicConstraintsExtensionsForCertificate(crt.Spec.IsCA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extraExtensions = append(extraExtensions, extension)
|
||||
}
|
||||
|
||||
if isLiteralCertificateSubjectEnabled() && len(crt.Spec.LiteralSubject) > 0 {
|
||||
rawSubject, err := ParseSubjectStringToRawDerBytes(crt.Spec.LiteralSubject)
|
||||
if err != nil {
|
||||
@ -298,6 +306,27 @@ func buildKeyUsagesExtensionsForCertificate(crt *v1.Certificate) ([]pkix.Extensi
|
||||
return extraExtensions, nil
|
||||
}
|
||||
|
||||
func buildBasicConstraintsExtensionsForCertificate(isCA bool) (pkix.Extension, error) {
|
||||
|
||||
basicConstraints := pkix.Extension{
|
||||
Id: OIDExtensionBasicConstraints,
|
||||
}
|
||||
|
||||
constraint := struct {
|
||||
IsCA bool
|
||||
}{
|
||||
IsCA: isCA,
|
||||
}
|
||||
|
||||
var err error
|
||||
basicConstraints.Value, err = asn1.Marshal(constraint)
|
||||
if err != nil {
|
||||
return pkix.Extension{}, err
|
||||
}
|
||||
|
||||
return basicConstraints, nil
|
||||
}
|
||||
|
||||
// GenerateTemplate will create a x509.Certificate for the given Certificate resource.
|
||||
// This should create a Certificate template that is equivalent to the CertificateRequest
|
||||
// generated by GenerateCSR.
|
||||
|
||||
@ -416,6 +416,30 @@ func TestGenerateCSR(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
basicConstraintsGenerator := func(isCA bool) ([]byte, error) {
|
||||
return asn1.Marshal(struct {
|
||||
IsCA bool
|
||||
}{
|
||||
IsCA: isCA,
|
||||
})
|
||||
}
|
||||
|
||||
basicConstraintsWithCA, err := basicConstraintsGenerator(true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
basicConstraintsWithoutCA, err := basicConstraintsGenerator(false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 0xa0 = DigitalSignature, Encipherment and KeyCertSign usage
|
||||
asn1KeyUsageWithCa, err := asn1.Marshal(asn1.BitString{Bytes: []byte{0xa4}, BitLength: asn1BitLength([]byte{0xa4})})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
exampleLiteralSubject := "CN=actual-cn, OU=FooLong, OU=Bar, O=example.org"
|
||||
rawExampleLiteralSubject, err := ParseSubjectStringToRawDerBytes(exampleLiteralSubject)
|
||||
if err != nil {
|
||||
@ -434,6 +458,7 @@ func TestGenerateCSR(t *testing.T) {
|
||||
want *x509.CertificateRequest
|
||||
wantErr bool
|
||||
literalCertificateSubjectFeatureEnabled bool
|
||||
basicConstraintsFeatureEnabled bool
|
||||
}{
|
||||
{
|
||||
name: "Generate CSR from certificate with only DNS",
|
||||
@ -457,6 +482,64 @@ func TestGenerateCSR(t *testing.T) {
|
||||
ExtraExtensions: defaultExtraExtensions,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Generate CSR from certificate with isCA set",
|
||||
crt: &cmapi.Certificate{Spec: cmapi.CertificateSpec{CommonName: "example.org", IsCA: true}},
|
||||
want: &x509.CertificateRequest{
|
||||
Version: 0,
|
||||
SignatureAlgorithm: x509.SHA256WithRSA,
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
Subject: pkix.Name{CommonName: "example.org"},
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: OIDExtensionKeyUsage,
|
||||
Value: asn1KeyUsageWithCa,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Generate CSR from certificate with isCA not set and with UseCertificateRequestBasicConstraints flag enabled",
|
||||
crt: &cmapi.Certificate{Spec: cmapi.CertificateSpec{CommonName: "example.org"}},
|
||||
want: &x509.CertificateRequest{
|
||||
Version: 0,
|
||||
SignatureAlgorithm: x509.SHA256WithRSA,
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
Subject: pkix.Name{CommonName: "example.org"},
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: OIDExtensionKeyUsage,
|
||||
Value: asn1KeyUsage,
|
||||
},
|
||||
{
|
||||
Id: OIDExtensionBasicConstraints,
|
||||
Value: basicConstraintsWithoutCA,
|
||||
},
|
||||
},
|
||||
},
|
||||
basicConstraintsFeatureEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "Generate CSR from certificate with isCA set and with UseCertificateRequestBasicConstraints flag enabled",
|
||||
crt: &cmapi.Certificate{Spec: cmapi.CertificateSpec{CommonName: "example.org", IsCA: true}},
|
||||
want: &x509.CertificateRequest{
|
||||
Version: 0,
|
||||
SignatureAlgorithm: x509.SHA256WithRSA,
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
Subject: pkix.Name{CommonName: "example.org"},
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: OIDExtensionKeyUsage,
|
||||
Value: asn1KeyUsageWithCa,
|
||||
},
|
||||
{
|
||||
Id: OIDExtensionBasicConstraints,
|
||||
Value: basicConstraintsWithCA,
|
||||
},
|
||||
},
|
||||
},
|
||||
basicConstraintsFeatureEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "Generate CSR from certificate with extended key usages",
|
||||
crt: &cmapi.Certificate{Spec: cmapi.CertificateSpec{CommonName: "example.org", Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageIPsecEndSystem}}},
|
||||
@ -518,6 +601,7 @@ func TestGenerateCSR(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate, feature.LiteralCertificateSubject, tt.literalCertificateSubjectFeatureEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate, feature.UseCertificateRequestBasicConstraints, tt.basicConstraintsFeatureEnabled)()
|
||||
got, err := GenerateCSR(tt.crt)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GenerateCSR() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
var (
|
||||
OIDExtensionKeyUsage = []int{2, 5, 29, 15}
|
||||
OIDExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
|
||||
OIDExtensionBasicConstraints = []int{2, 5, 29, 19}
|
||||
)
|
||||
|
||||
// RFC 5280, 4.2.1.12 Extended Key Usage
|
||||
|
||||
Loading…
Reference in New Issue
Block a user