2022-03-08 12:26:07 +00:00
|
|
|
package policy
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2022-05-06 11:12:13 +00:00
|
|
|
"go.step.sm/linkedca"
|
|
|
|
|
2022-03-08 12:26:07 +00:00
|
|
|
"github.com/smallstep/certificates/policy"
|
|
|
|
)
|
|
|
|
|
|
|
|
// X509Policy is an alias for policy.X509NamePolicyEngine
|
|
|
|
type X509Policy policy.X509NamePolicyEngine
|
|
|
|
|
|
|
|
// UserPolicy is an alias for policy.SSHNamePolicyEngine
|
|
|
|
type UserPolicy policy.SSHNamePolicyEngine
|
|
|
|
|
|
|
|
// HostPolicy is an alias for policy.SSHNamePolicyEngine
|
|
|
|
type HostPolicy policy.SSHNamePolicyEngine
|
|
|
|
|
|
|
|
// NewX509PolicyEngine creates a new x509 name policy engine
|
|
|
|
func NewX509PolicyEngine(policyOptions X509PolicyOptionsInterface) (X509Policy, error) {
|
|
|
|
// return early if no policy engine options to configure
|
|
|
|
if policyOptions == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
options := []policy.NamePolicyOption{}
|
|
|
|
|
|
|
|
allowed := policyOptions.GetAllowedNameOptions()
|
|
|
|
if allowed != nil && allowed.HasNames() {
|
|
|
|
options = append(options,
|
2022-04-28 12:49:23 +00:00
|
|
|
policy.WithPermittedCommonNames(allowed.CommonNames...),
|
2022-04-21 10:14:03 +00:00
|
|
|
policy.WithPermittedDNSDomains(allowed.DNSDomains...),
|
|
|
|
policy.WithPermittedIPsOrCIDRs(allowed.IPRanges...),
|
|
|
|
policy.WithPermittedEmailAddresses(allowed.EmailAddresses...),
|
|
|
|
policy.WithPermittedURIDomains(allowed.URIDomains...),
|
2022-03-08 12:26:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
denied := policyOptions.GetDeniedNameOptions()
|
|
|
|
if denied != nil && denied.HasNames() {
|
|
|
|
options = append(options,
|
2022-04-28 12:49:23 +00:00
|
|
|
policy.WithExcludedCommonNames(denied.CommonNames...),
|
2022-04-21 10:14:03 +00:00
|
|
|
policy.WithExcludedDNSDomains(denied.DNSDomains...),
|
|
|
|
policy.WithExcludedIPsOrCIDRs(denied.IPRanges...),
|
|
|
|
policy.WithExcludedEmailAddresses(denied.EmailAddresses...),
|
|
|
|
policy.WithExcludedURIDomains(denied.URIDomains...),
|
2022-03-08 12:26:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure no policy engine is returned when no name options were provided
|
|
|
|
if len(options) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:12:13 +00:00
|
|
|
// check if configuration specifies that wildcard names are allowed
|
2022-04-29 13:08:19 +00:00
|
|
|
if policyOptions.AreWildcardNamesAllowed() {
|
2022-04-19 08:24:52 +00:00
|
|
|
options = append(options, policy.WithAllowLiteralWildcardNames())
|
|
|
|
}
|
2022-03-08 12:26:07 +00:00
|
|
|
|
2022-05-06 11:12:13 +00:00
|
|
|
// enable subject common name verification by default
|
|
|
|
options = append(options, policy.WithSubjectCommonNameVerification())
|
|
|
|
|
2022-03-08 12:26:07 +00:00
|
|
|
return policy.New(options...)
|
|
|
|
}
|
|
|
|
|
|
|
|
type sshPolicyEngineType string
|
|
|
|
|
|
|
|
const (
|
|
|
|
UserPolicyEngineType sshPolicyEngineType = "user"
|
|
|
|
HostPolicyEngineType sshPolicyEngineType = "host"
|
|
|
|
)
|
|
|
|
|
|
|
|
// newSSHUserPolicyEngine creates a new SSH user certificate policy engine
|
|
|
|
func NewSSHUserPolicyEngine(policyOptions SSHPolicyOptionsInterface) (UserPolicy, error) {
|
|
|
|
policyEngine, err := newSSHPolicyEngine(policyOptions, UserPolicyEngineType)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return policyEngine, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// newSSHHostPolicyEngine create a new SSH host certificate policy engine
|
|
|
|
func NewSSHHostPolicyEngine(policyOptions SSHPolicyOptionsInterface) (HostPolicy, error) {
|
|
|
|
policyEngine, err := newSSHPolicyEngine(policyOptions, HostPolicyEngineType)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return policyEngine, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// newSSHPolicyEngine creates a new SSH name policy engine
|
|
|
|
func newSSHPolicyEngine(policyOptions SSHPolicyOptionsInterface, typ sshPolicyEngineType) (policy.SSHNamePolicyEngine, error) {
|
|
|
|
// return early if no policy engine options to configure
|
|
|
|
if policyOptions == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
allowed *SSHNameOptions
|
|
|
|
denied *SSHNameOptions
|
|
|
|
)
|
|
|
|
|
|
|
|
switch typ {
|
|
|
|
case UserPolicyEngineType:
|
|
|
|
allowed = policyOptions.GetAllowedUserNameOptions()
|
|
|
|
denied = policyOptions.GetDeniedUserNameOptions()
|
|
|
|
case HostPolicyEngineType:
|
|
|
|
allowed = policyOptions.GetAllowedHostNameOptions()
|
|
|
|
denied = policyOptions.GetDeniedHostNameOptions()
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown SSH policy engine type %s provided", typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
options := []policy.NamePolicyOption{}
|
|
|
|
|
|
|
|
if allowed != nil && allowed.HasNames() {
|
|
|
|
options = append(options,
|
2022-04-21 10:14:03 +00:00
|
|
|
policy.WithPermittedDNSDomains(allowed.DNSDomains...),
|
|
|
|
policy.WithPermittedIPsOrCIDRs(allowed.IPRanges...),
|
|
|
|
policy.WithPermittedEmailAddresses(allowed.EmailAddresses...),
|
|
|
|
policy.WithPermittedPrincipals(allowed.Principals...),
|
2022-03-08 12:26:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if denied != nil && denied.HasNames() {
|
|
|
|
options = append(options,
|
2022-04-21 10:14:03 +00:00
|
|
|
policy.WithExcludedDNSDomains(denied.DNSDomains...),
|
|
|
|
policy.WithExcludedIPsOrCIDRs(denied.IPRanges...),
|
|
|
|
policy.WithExcludedEmailAddresses(denied.EmailAddresses...),
|
|
|
|
policy.WithExcludedPrincipals(denied.Principals...),
|
2022-03-08 12:26:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure no policy engine is returned when no name options were provided
|
|
|
|
if len(options) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return policy.New(options...)
|
|
|
|
}
|
2022-05-06 11:12:13 +00:00
|
|
|
|
2022-05-06 11:23:09 +00:00
|
|
|
func LinkedToCertificates(p *linkedca.Policy) *Options {
|
2022-05-06 11:12:13 +00:00
|
|
|
// return early
|
|
|
|
if p == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// return early if x509 nor SSH is set
|
|
|
|
if p.GetX509() == nil && p.GetSsh() == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
opts := &Options{}
|
|
|
|
|
|
|
|
// fill x509 policy configuration
|
|
|
|
if x509 := p.GetX509(); x509 != nil {
|
|
|
|
opts.X509 = &X509PolicyOptions{}
|
|
|
|
if allow := x509.GetAllow(); allow != nil {
|
|
|
|
opts.X509.AllowedNames = &X509NameOptions{}
|
|
|
|
if allow.Dns != nil {
|
|
|
|
opts.X509.AllowedNames.DNSDomains = allow.Dns
|
|
|
|
}
|
|
|
|
if allow.Ips != nil {
|
|
|
|
opts.X509.AllowedNames.IPRanges = allow.Ips
|
|
|
|
}
|
|
|
|
if allow.Emails != nil {
|
|
|
|
opts.X509.AllowedNames.EmailAddresses = allow.Emails
|
|
|
|
}
|
|
|
|
if allow.Uris != nil {
|
|
|
|
opts.X509.AllowedNames.URIDomains = allow.Uris
|
|
|
|
}
|
|
|
|
if allow.CommonNames != nil {
|
|
|
|
opts.X509.AllowedNames.CommonNames = allow.CommonNames
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if deny := x509.GetDeny(); deny != nil {
|
|
|
|
opts.X509.DeniedNames = &X509NameOptions{}
|
|
|
|
if deny.Dns != nil {
|
|
|
|
opts.X509.DeniedNames.DNSDomains = deny.Dns
|
|
|
|
}
|
|
|
|
if deny.Ips != nil {
|
|
|
|
opts.X509.DeniedNames.IPRanges = deny.Ips
|
|
|
|
}
|
|
|
|
if deny.Emails != nil {
|
|
|
|
opts.X509.DeniedNames.EmailAddresses = deny.Emails
|
|
|
|
}
|
|
|
|
if deny.Uris != nil {
|
|
|
|
opts.X509.DeniedNames.URIDomains = deny.Uris
|
|
|
|
}
|
|
|
|
if deny.CommonNames != nil {
|
|
|
|
opts.X509.DeniedNames.CommonNames = deny.CommonNames
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
opts.X509.AllowWildcardNames = x509.GetAllowWildcardNames()
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill ssh policy configuration
|
|
|
|
if ssh := p.GetSsh(); ssh != nil {
|
|
|
|
opts.SSH = &SSHPolicyOptions{}
|
|
|
|
if host := ssh.GetHost(); host != nil {
|
|
|
|
opts.SSH.Host = &SSHHostCertificateOptions{}
|
|
|
|
if allow := host.GetAllow(); allow != nil {
|
|
|
|
opts.SSH.Host.AllowedNames = &SSHNameOptions{}
|
|
|
|
if allow.Dns != nil {
|
|
|
|
opts.SSH.Host.AllowedNames.DNSDomains = allow.Dns
|
|
|
|
}
|
|
|
|
if allow.Ips != nil {
|
|
|
|
opts.SSH.Host.AllowedNames.IPRanges = allow.Ips
|
|
|
|
}
|
|
|
|
if allow.Principals != nil {
|
|
|
|
opts.SSH.Host.AllowedNames.Principals = allow.Principals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if deny := host.GetDeny(); deny != nil {
|
|
|
|
opts.SSH.Host.DeniedNames = &SSHNameOptions{}
|
|
|
|
if deny.Dns != nil {
|
|
|
|
opts.SSH.Host.DeniedNames.DNSDomains = deny.Dns
|
|
|
|
}
|
|
|
|
if deny.Ips != nil {
|
|
|
|
opts.SSH.Host.DeniedNames.IPRanges = deny.Ips
|
|
|
|
}
|
|
|
|
if deny.Principals != nil {
|
|
|
|
opts.SSH.Host.DeniedNames.Principals = deny.Principals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if user := ssh.GetUser(); user != nil {
|
|
|
|
opts.SSH.User = &SSHUserCertificateOptions{}
|
|
|
|
if allow := user.GetAllow(); allow != nil {
|
|
|
|
opts.SSH.User.AllowedNames = &SSHNameOptions{}
|
|
|
|
if allow.Emails != nil {
|
|
|
|
opts.SSH.User.AllowedNames.EmailAddresses = allow.Emails
|
|
|
|
}
|
|
|
|
if allow.Principals != nil {
|
|
|
|
opts.SSH.User.AllowedNames.Principals = allow.Principals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if deny := user.GetDeny(); deny != nil {
|
|
|
|
opts.SSH.User.DeniedNames = &SSHNameOptions{}
|
|
|
|
if deny.Emails != nil {
|
|
|
|
opts.SSH.User.DeniedNames.EmailAddresses = deny.Emails
|
|
|
|
}
|
|
|
|
if deny.Principals != nil {
|
|
|
|
opts.SSH.User.DeniedNames.Principals = deny.Principals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return opts
|
|
|
|
}
|