forked from TrueCloudLab/certificates
513 lines
13 KiB
Go
Executable file
513 lines
13 KiB
Go
Executable file
package x509policy
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type NamePolicyOption func(e *NamePolicyEngine) error
|
|
|
|
// TODO: wrap (more) errors; and prove a set of known (exported) errors
|
|
|
|
func WithEnableSubjectCommonNameVerification() NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
e.verifySubjectCommonName = true
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedDNSDomains(domains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range domains {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse permitted domain constraint %q", domain)
|
|
}
|
|
}
|
|
e.permittedDNSDomains = domains
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedDNSDomains(domains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range domains {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse permitted domain constraint %q", domain)
|
|
}
|
|
}
|
|
e.permittedDNSDomains = append(e.permittedDNSDomains, domains...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedDNSDomains(domains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range domains {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse excluded domain constraint %q", domain)
|
|
}
|
|
}
|
|
e.excludedDNSDomains = domains
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedDNSDomains(domains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range domains {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse excluded domain constraint %q", domain)
|
|
}
|
|
}
|
|
e.excludedDNSDomains = append(e.excludedDNSDomains, domains...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedDNSDomain(domain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse permitted domain constraint %q", domain)
|
|
}
|
|
e.permittedDNSDomains = []string{domain}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedDNSDomain(domain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse permitted domain constraint %q", domain)
|
|
}
|
|
e.permittedDNSDomains = append(e.permittedDNSDomains, domain)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedDNSDomain(domain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse excluded domain constraint %q", domain)
|
|
}
|
|
e.excludedDNSDomains = []string{domain}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedDNSDomain(domain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateDNSDomainConstraint(domain); err != nil {
|
|
return errors.Errorf("cannot parse excluded domain constraint %q", domain)
|
|
}
|
|
e.excludedDNSDomains = append(e.excludedDNSDomains, domain)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedIPRanges(ipRanges []*net.IPNet) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
e.permittedIPRanges = ipRanges
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedIPRanges(ipRanges []*net.IPNet) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
e.permittedIPRanges = append(e.permittedIPRanges, ipRanges...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedCIDRs(cidrs []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
networks := []*net.IPNet{}
|
|
for _, cidr := range cidrs {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse permitted CIDR constraint %q", cidr)
|
|
}
|
|
networks = append(networks, nw)
|
|
}
|
|
e.permittedIPRanges = networks
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedCIDRs(cidrs []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
networks := []*net.IPNet{}
|
|
for _, cidr := range cidrs {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse permitted CIDR constraint %q", cidr)
|
|
}
|
|
networks = append(networks, nw)
|
|
}
|
|
e.permittedIPRanges = append(e.permittedIPRanges, networks...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedCIDRs(cidrs []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
networks := []*net.IPNet{}
|
|
for _, cidr := range cidrs {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse excluded CIDR constraint %q", cidr)
|
|
}
|
|
networks = append(networks, nw)
|
|
}
|
|
e.excludedIPRanges = networks
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedCIDRs(cidrs []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
networks := []*net.IPNet{}
|
|
for _, cidr := range cidrs {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse excluded CIDR constraint %q", cidr)
|
|
}
|
|
networks = append(networks, nw)
|
|
}
|
|
e.excludedIPRanges = append(e.excludedIPRanges, networks...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedCIDR(cidr string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse permitted CIDR constraint %q", cidr)
|
|
}
|
|
e.permittedIPRanges = []*net.IPNet{nw}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedCIDR(cidr string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse permitted CIDR constraint %q", cidr)
|
|
}
|
|
e.permittedIPRanges = append(e.permittedIPRanges, nw)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedIP(ip net.IP) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
var mask net.IPMask
|
|
if !isIPv4(ip) {
|
|
mask = net.CIDRMask(128, 128)
|
|
} else {
|
|
mask = net.CIDRMask(32, 32)
|
|
}
|
|
nw := &net.IPNet{
|
|
IP: ip,
|
|
Mask: mask,
|
|
}
|
|
e.permittedIPRanges = []*net.IPNet{nw}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedIP(ip net.IP) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
var mask net.IPMask
|
|
if !isIPv4(ip) {
|
|
mask = net.CIDRMask(128, 128)
|
|
} else {
|
|
mask = net.CIDRMask(32, 32)
|
|
}
|
|
nw := &net.IPNet{
|
|
IP: ip,
|
|
Mask: mask,
|
|
}
|
|
e.permittedIPRanges = append(e.permittedIPRanges, nw)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedIPRanges(ipRanges []*net.IPNet) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
e.excludedIPRanges = ipRanges
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedIPRanges(ipRanges []*net.IPNet) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
e.excludedIPRanges = append(e.excludedIPRanges, ipRanges...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedCIDR(cidr string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse excluded CIDR constraint %q", cidr)
|
|
}
|
|
e.excludedIPRanges = []*net.IPNet{nw}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedCIDR(cidr string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
_, nw, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return errors.Errorf("cannot parse excluded CIDR constraint %q", cidr)
|
|
}
|
|
e.excludedIPRanges = append(e.excludedIPRanges, nw)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedIP(ip net.IP) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
var mask net.IPMask
|
|
if !isIPv4(ip) {
|
|
mask = net.CIDRMask(128, 128)
|
|
} else {
|
|
mask = net.CIDRMask(32, 32)
|
|
}
|
|
nw := &net.IPNet{
|
|
IP: ip,
|
|
Mask: mask,
|
|
}
|
|
e.excludedIPRanges = []*net.IPNet{nw}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedIP(ip net.IP) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
var mask net.IPMask
|
|
if !isIPv4(ip) {
|
|
mask = net.CIDRMask(128, 128)
|
|
} else {
|
|
mask = net.CIDRMask(32, 32)
|
|
}
|
|
nw := &net.IPNet{
|
|
IP: ip,
|
|
Mask: mask,
|
|
}
|
|
e.excludedIPRanges = append(e.excludedIPRanges, nw)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedEmailAddresses(emailAddresses []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, email := range emailAddresses {
|
|
if err := validateEmailConstraint(email); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.permittedEmailAddresses = emailAddresses
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedEmailAddresses(emailAddresses []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, email := range emailAddresses {
|
|
if err := validateEmailConstraint(email); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.permittedEmailAddresses = append(e.permittedEmailAddresses, emailAddresses...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedEmailAddresses(emailAddresses []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, email := range emailAddresses {
|
|
if err := validateEmailConstraint(email); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.excludedEmailAddresses = emailAddresses
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedEmailAddresses(emailAddresses []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, email := range emailAddresses {
|
|
if err := validateEmailConstraint(email); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.excludedEmailAddresses = append(e.excludedEmailAddresses, emailAddresses...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedEmailAddress(emailAddress string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateEmailConstraint(emailAddress); err != nil {
|
|
return err
|
|
}
|
|
e.permittedEmailAddresses = []string{emailAddress}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedEmailAddress(emailAddress string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateEmailConstraint(emailAddress); err != nil {
|
|
return err
|
|
}
|
|
e.permittedEmailAddresses = append(e.permittedEmailAddresses, emailAddress)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedEmailAddress(emailAddress string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateEmailConstraint(emailAddress); err != nil {
|
|
return err
|
|
}
|
|
e.excludedEmailAddresses = []string{emailAddress}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedEmailAddress(emailAddress string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateEmailConstraint(emailAddress); err != nil {
|
|
return err
|
|
}
|
|
e.excludedEmailAddresses = append(e.excludedEmailAddresses, emailAddress)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedURIDomains(uriDomains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range uriDomains {
|
|
if err := validateURIDomainConstraint(domain); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.permittedURIDomains = uriDomains
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedURIDomains(uriDomains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range uriDomains {
|
|
if err := validateURIDomainConstraint(domain); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.permittedURIDomains = append(e.permittedURIDomains, uriDomains...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithPermittedURIDomain(uriDomain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateURIDomainConstraint(uriDomain); err != nil {
|
|
return err
|
|
}
|
|
e.permittedURIDomains = []string{uriDomain}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddPermittedURIDomain(uriDomain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateURIDomainConstraint(uriDomain); err != nil {
|
|
return err
|
|
}
|
|
e.permittedURIDomains = append(e.permittedURIDomains, uriDomain)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedURIDomains(uriDomains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range uriDomains {
|
|
if err := validateURIDomainConstraint(domain); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.excludedURIDomains = uriDomains
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedURIDomains(uriDomains []string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
for _, domain := range uriDomains {
|
|
if err := validateURIDomainConstraint(domain); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
e.excludedURIDomains = append(e.excludedURIDomains, uriDomains...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func WithExcludedURIDomain(uriDomain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateURIDomainConstraint(uriDomain); err != nil {
|
|
return err
|
|
}
|
|
e.excludedURIDomains = []string{uriDomain}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func AddExcludedURIDomain(uriDomain string) NamePolicyOption {
|
|
return func(e *NamePolicyEngine) error {
|
|
if err := validateURIDomainConstraint(uriDomain); err != nil {
|
|
return err
|
|
}
|
|
e.excludedURIDomains = append(e.excludedURIDomains, uriDomain)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func validateDNSDomainConstraint(domain string) error {
|
|
if _, ok := domainToReverseLabels(domain); !ok {
|
|
return errors.Errorf("cannot parse permitted domain constraint %q", domain)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateEmailConstraint(constraint string) error {
|
|
if strings.Contains(constraint, "@") {
|
|
_, ok := parseRFC2821Mailbox(constraint)
|
|
if !ok {
|
|
return fmt.Errorf("cannot parse email constraint %q", constraint)
|
|
}
|
|
}
|
|
_, ok := domainToReverseLabels(constraint)
|
|
if !ok {
|
|
return fmt.Errorf("cannot parse email domain constraint %q", constraint)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateURIDomainConstraint(constraint string) error {
|
|
_, ok := domainToReverseLabels(constraint)
|
|
if !ok {
|
|
return fmt.Errorf("cannot parse URI domain constraint %q", constraint)
|
|
}
|
|
return nil
|
|
}
|