Skip to content

Commit

Permalink
Merge pull request #1205 from cloudflare/watson/fix-delegation-support
Browse files Browse the repository at this point in the history
Support for DelegationUsage extension
  • Loading branch information
Watson Ladd committed Sep 15, 2021
2 parents 29ae05f + a8591c3 commit 503b4d7
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 15 deletions.
5 changes: 3 additions & 2 deletions cli/testdata/csr.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
"1.2.3.4.5": "abc"
}
}
]
}
],
"delegation_enabled": true
}
29 changes: 17 additions & 12 deletions csr/csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Name struct {
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
E string `json:"E,omitempty" yaml:"E,omitempty"`
E string `json:"E,omitempty" yaml:"E,omitempty"`
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
}
Expand Down Expand Up @@ -136,14 +136,15 @@ type CAConfig struct {
// A CertificateRequest encapsulates the API interface to the
// certificate request functionality.
type CertificateRequest struct {
CN string `json:"CN" yaml:"CN"`
Names []Name `json:"names" yaml:"names"`
Hosts []string `json:"hosts" yaml:"hosts"`
KeyRequest *KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
CN string `json:"CN" yaml:"CN"`
Names []Name `json:"names" yaml:"names"`
Hosts []string `json:"hosts" yaml:"hosts"`
KeyRequest *KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
DelegationEnabled bool `json:"delegation_enabled,omitempty" yaml:"delegation_enabled,omitempty"`
Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
}

// New returns a new, empty CertificateRequest with a
Expand Down Expand Up @@ -196,9 +197,9 @@ func (cr *CertificateRequest) Name() (pkix.Name, error) {
}
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
}
if n.E != "" {
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
}
if n.E != "" {
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
}
}
name.SerialNumber = cr.SerialNumber
return name, nil
Expand Down Expand Up @@ -430,6 +431,10 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
}
}

if req.DelegationEnabled {
tpl.ExtraExtensions = append(tpl.Extensions, helpers.DelegationExtension)
}

if req.Extensions != nil {
err = appendExtensionsToCSR(req.Extensions, &tpl)
if err != nil {
Expand Down
47 changes: 47 additions & 0 deletions csr/csr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -786,3 +786,50 @@ func TestExtractCertificateRequest(t *testing.T) {
t.Fatal("Bad Certificate Request!")
}
}

// TestDelegationCSR tests that we create requests with the DC extension
func TestDelegationCSR(t *testing.T) {
var cr = &CertificateRequest{
CN: "Test Common Name",
Names: []Name{
{
C: "US",
ST: "California",
L: "San Francisco",
O: "CloudFlare, Inc.",
OU: "Systems Engineering",
},
{
C: "GB",
ST: "London",
L: "London",
O: "CloudFlare, Inc",
OU: "Systems Engineering",
},
},
DelegationEnabled: true,
Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
KeyRequest: NewKeyRequest(),
}
csr, _, err := ParseRequest(cr)
if err != nil {
t.Fatal("could not generate csr")
}
unPem, _ := pem.Decode(csr)
if unPem == nil {
t.Fatal("Failed to decode pem")
}
res, err := x509.ParseCertificateRequest(unPem.Bytes)
if err != nil {
t.Fatalf("spat out nonsense as a csr: %v", err)
}
found := false
for _, ext := range res.Extensions {
if ext.Id.Equal(helpers.DelegationUsage) {
found = true
}
}
if !found {
t.Fatal("generated csr has no extension")
}
}
10 changes: 10 additions & 0 deletions helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ const OneYear = 8760 * time.Hour
// OneDay is a time.Duration representing a day's worth of seconds.
const OneDay = 24 * time.Hour

// DelegationUsage is the OID for the DelegationUseage extensions
var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44}

// DelegationExtension
var DelegationExtension = pkix.Extension{
Id: DelegationUsage,
Critical: false,
Value: []byte{0x05, 0x00}, // ASN.1 NULL
}

// InclusiveDate returns the time.Time representation of a date - 1
// nanosecond. This allows time.After to be used inclusively.
func InclusiveDate(year int, month time.Month, day int) time.Time {
Expand Down
5 changes: 4 additions & 1 deletion signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/info"
)

Expand All @@ -45,7 +46,7 @@ type Extension struct {
// Extensions provided in the signRequest are copied into the certificate, as
// long as they are in the ExtensionWhitelist for the signer's policy.
// Extensions requested in the CSR are ignored, except for those processed by
// ParseCertificateRequest (mainly subjectAltName).
// ParseCertificateRequest (mainly subjectAltName) and DelegationUsage.
type SignRequest struct {
Hosts []string `json:"hosts"`
Request string `json:"certificate_request"`
Expand Down Expand Up @@ -240,6 +241,8 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
template.IsCA = constraints.IsCA
template.MaxPathLen = constraints.MaxPathLen
template.MaxPathLenZero = template.MaxPathLen == 0
} else if val.Id.Equal(helpers.DelegationUsage) {
template.ExtraExtensions = append(template.ExtraExtensions, val)
} else {
// If the profile has 'copy_extensions' to true then lets add it
if p.CopyExtensions {
Expand Down

0 comments on commit 503b4d7

Please sign in to comment.