2019-04-24 21:52:08 +00:00
|
|
|
package schema
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// ACLRule represent one ACL rule "weak" coerces a single value into string slice.
|
2019-04-24 21:52:08 +00:00
|
|
|
type ACLRule struct {
|
2020-04-16 00:18:11 +00:00
|
|
|
Domains []string `mapstructure:"domain,weak"`
|
2020-01-21 20:56:44 +00:00
|
|
|
Policy string `mapstructure:"policy"`
|
2020-04-16 00:18:11 +00:00
|
|
|
Subjects []string `mapstructure:"subject,weak"`
|
2020-01-21 20:56:44 +00:00
|
|
|
Networks []string `mapstructure:"networks"`
|
|
|
|
Resources []string `mapstructure:"resources"`
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// IsPolicyValid check if policy is valid.
|
2019-04-24 21:52:08 +00:00
|
|
|
func IsPolicyValid(policy string) bool {
|
2020-05-02 16:20:40 +00:00
|
|
|
return policy == denyPolicy || policy == "one_factor" || policy == "two_factor" || policy == "bypass"
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// IsSubjectValid check if a subject is valid.
|
2019-04-24 21:52:08 +00:00
|
|
|
func IsSubjectValid(subject string) bool {
|
|
|
|
return subject == "" || strings.HasPrefix(subject, "user:") || strings.HasPrefix(subject, "group:")
|
|
|
|
}
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// IsNetworkValid check if a network is valid.
|
2019-04-24 21:52:08 +00:00
|
|
|
func IsNetworkValid(network string) bool {
|
|
|
|
_, _, err := net.ParseCIDR(network)
|
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// Validate validate an ACL Rule.
|
2019-04-24 21:52:08 +00:00
|
|
|
func (r *ACLRule) Validate(validator *StructValidator) {
|
2020-04-16 00:18:11 +00:00
|
|
|
if len(r.Domains) == 0 {
|
2019-04-24 21:52:08 +00:00
|
|
|
validator.Push(fmt.Errorf("Domain must be provided"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if !IsPolicyValid(r.Policy) {
|
|
|
|
validator.Push(fmt.Errorf("A policy must either be 'deny', 'two_factor', 'one_factor' or 'bypass'"))
|
|
|
|
}
|
|
|
|
|
2020-04-16 00:18:11 +00:00
|
|
|
for i, subject := range r.Subjects {
|
|
|
|
if !IsSubjectValid(subject) {
|
|
|
|
validator.Push(fmt.Errorf("Subject %d must start with 'user:' or 'group:'", i))
|
|
|
|
}
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, network := range r.Networks {
|
|
|
|
if !IsNetworkValid(network) {
|
|
|
|
validator.Push(fmt.Errorf("Network %d must be a valid CIDR", i))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AccessControlConfiguration represents the configuration related to ACLs.
|
|
|
|
type AccessControlConfiguration struct {
|
2020-01-21 20:56:44 +00:00
|
|
|
DefaultPolicy string `mapstructure:"default_policy"`
|
|
|
|
Rules []ACLRule `mapstructure:"rules"`
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 21:03:38 +00:00
|
|
|
// Validate validate the access control configuration.
|
2019-04-24 21:52:08 +00:00
|
|
|
func (acc *AccessControlConfiguration) Validate(validator *StructValidator) {
|
|
|
|
if acc.DefaultPolicy == "" {
|
2020-05-02 16:20:40 +00:00
|
|
|
acc.DefaultPolicy = denyPolicy
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !IsPolicyValid(acc.DefaultPolicy) {
|
|
|
|
validator.Push(fmt.Errorf("'default_policy' must either be 'deny', 'two_factor', 'one_factor' or 'bypass'"))
|
|
|
|
}
|
|
|
|
}
|