Skip to content

Commit

Permalink
Support all fields of the name constraints extension when generating …
Browse files Browse the repository at this point in the history
…CA certificates (#29245)

Support all fields of the name constraints extension when generating CA certs.

The PKI secrets engine only provided parameter permitted_dns_domains to create
the name constraints extension when generating CA certificates.

Add the following parameters to provide full support for the extension:

  * permitted_email_addresses
  * permitted_ip_ranges
  * permitted_uri_domains
  * excluded_dns_domains
  * excluded_email_addresses
  * excluded_ip_ranges
  * excluded_uri_domains

Specifying any combination of these parameters will trigger the creation of the
name constraints extension as per RFC 5280 section 4.2.1.10.
  • Loading branch information
victorr authored Dec 20, 2024
1 parent df73491 commit b9e949b
Show file tree
Hide file tree
Showing 10 changed files with 588 additions and 218 deletions.
56 changes: 56 additions & 0 deletions builtin/logical/pki/cert_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,19 @@ func generateCert(sc *storageContext,
if isCA {
data.Params.IsCA = isCA
data.Params.PermittedDNSDomains = input.apiData.Get("permitted_dns_domains").([]string)
data.Params.ExcludedDNSDomains = input.apiData.Get("excluded_dns_domains").([]string)
data.Params.PermittedIPRanges, err = convertIpRanges(input.apiData.Get("permitted_ip_ranges").([]string))
if err != nil {
return nil, nil, errutil.UserError{Err: fmt.Sprintf("invalid permitted_ip_ranges value: %s", err)}
}
data.Params.ExcludedIPRanges, err = convertIpRanges(input.apiData.Get("excluded_ip_ranges").([]string))
if err != nil {
return nil, nil, errutil.UserError{Err: fmt.Sprintf("invalid excluded_ip_ranges value: %s", err)}
}
data.Params.PermittedEmailAddresses = input.apiData.Get("permitted_email_addresses").([]string)
data.Params.ExcludedEmailAddresses = input.apiData.Get("excluded_email_addresses").([]string)
data.Params.PermittedURIDomains = input.apiData.Get("permitted_uri_domains").([]string)
data.Params.ExcludedURIDomains = input.apiData.Get("excluded_uri_domains").([]string)

if data.SigningBundle == nil {
// Generating a self-signed root certificate. Since we have no
Expand Down Expand Up @@ -399,6 +412,21 @@ func generateCert(sc *storageContext,
return parsedBundle, warnings, nil
}

// convertIpRanges parses each string in the input slice as an IP network. Input
// strings are expected to be in the CIDR notation of IP address and prefix length
// like "192.0.2.0/24" or "2001:db8::/32", as defined in RFC 4632 and RFC 4291.
func convertIpRanges(ipRanges []string) ([]*net.IPNet, error) {
var ret []*net.IPNet
for _, ipRange := range ipRanges {
_, ipnet, err := net.ParseCIDR(ipRange)
if err != nil {
return nil, fmt.Errorf("error parsing IP range %q: %w", ipRange, err)
}
ret = append(ret, ipnet)
}
return ret, nil
}

// N.B.: This is only meant to be used for generating intermediate CAs.
// It skips some sanity checks.
func generateIntermediateCSR(sc *storageContext, input *inputBundle, randomSource io.Reader) (*certutil.ParsedCSRBundle, []string, error) {
Expand Down Expand Up @@ -472,6 +500,34 @@ func (i SignCertInputFromDataFields) GetPermittedDomains() []string {
return i.data.Get("permitted_dns_domains").([]string)
}

func (i SignCertInputFromDataFields) GetExcludedDomains() []string {
return i.data.Get("excluded_dns_domains").([]string)
}

func (i SignCertInputFromDataFields) GetPermittedIpRanges() ([]*net.IPNet, error) {
return convertIpRanges(i.data.Get("permitted_ip_ranges").([]string))
}

func (i SignCertInputFromDataFields) GetExcludedIpRanges() ([]*net.IPNet, error) {
return convertIpRanges(i.data.Get("excluded_ip_ranges").([]string))
}

func (i SignCertInputFromDataFields) GetPermittedEmailAddresses() []string {
return i.data.Get("permitted_email_addresses").([]string)
}

func (i SignCertInputFromDataFields) GetExcludedEmailAddresses() []string {
return i.data.Get("excluded_email_addresses").([]string)
}

func (i SignCertInputFromDataFields) GetPermittedUriDomains() []string {
return i.data.Get("permitted_uri_domains").([]string)
}

func (i SignCertInputFromDataFields) GetExcludedUriDomains() []string {
return i.data.Get("excluded_uri_domains").([]string)
}

func (i SignCertInputFromDataFields) IgnoreCSRSignature() bool {
return false
}
Expand Down
Loading

0 comments on commit b9e949b

Please sign in to comment.