in lib/validator/policy_builder.go [222:300]
func ValidatePolicy(policy *pb.Policy, defs map[string]*pb.VisaType, sources map[string]*pb.TrustedSource, args map[string]string) (string, error) {
usedArgs := make(map[string]bool)
valArgs := args
if valArgs == nil {
// To allow variable substitution to be attempted, set up variables to substitute based on definitions (regex match not required).
valArgs = make(map[string]string)
for v := range policy.VariableDefinitions {
valArgs[v] = "a"
}
}
for i, any := range policy.AnyOf {
for j, clause := range any.AllOf {
if err := validateVisaType(clause.Type, defs); err != nil {
return httputils.StatusPath("anyOf", strconv.Itoa(i), "allOf", strconv.Itoa(j), "type"), err
}
if _, err := expandSources(clause.Type, clause.Source, sources); err != nil {
return httputils.StatusPath("anyOf", strconv.Itoa(i), "allOf", strconv.Itoa(j), "source"), err
}
if _, err := expandValues(clause.Value, valArgs); err != nil {
return httputils.StatusPath("anyOf", strconv.Itoa(i), "allOf", strconv.Itoa(j), "value"), err
}
valArgs, err := strutil.ExtractVariables(clause.Value)
if err != nil {
return httputils.StatusPath("anyOf", strconv.Itoa(i), "allOf", strconv.Itoa(j), "value"), err
}
for arg := range valArgs {
usedArgs[arg] = true
}
if _, err := expandBy(clause.By); err != nil {
return httputils.StatusPath("anyOf", strconv.Itoa(i), "allOf", strconv.Itoa(j), "by"), err
}
}
}
for name, v := range policy.VariableDefinitions {
if len(v.Regexp) == 0 {
return httputils.StatusPath("variableDefinitions", name, "regexp"), fmt.Errorf("regular expression not specified")
}
re, err := regexp.Compile(v.Regexp)
if err != nil {
return httputils.StatusPath("variableDefinitions", name, "regexp"), fmt.Errorf("invalid regular expression: %v", err)
}
if args != nil {
arg, ok := args[name]
if !ok {
return httputils.StatusPath("variableDefinitions", name), fmt.Errorf("variable not provided")
}
if !re.Match([]byte(arg)) {
return httputils.StatusPath("variableDefinitions", name), fmt.Errorf("variable value %q invalid format", arg)
}
}
if v.Ui == nil || v.Ui["description"] == "" {
return httputils.StatusPath("variableDefinitions", name, "ui", "description"), fmt.Errorf("description not provided")
}
}
prefix := "variableDefinitions"
if args != nil {
prefix = "vars"
}
for arg := range usedArgs {
if len(policy.VariableDefinitions) == 0 {
return httputils.StatusPath(prefix, arg), fmt.Errorf("policy does not use variables")
}
if _, ok := policy.VariableDefinitions[arg]; !ok {
return httputils.StatusPath(prefix, arg), fmt.Errorf("undefined variable")
}
if args != nil {
if _, ok := args[arg]; !ok {
return httputils.StatusPath(prefix, arg), fmt.Errorf("undefined variable")
}
}
}
for arg := range args {
if _, ok := usedArgs[arg]; !ok {
return httputils.StatusPath(prefix, arg), fmt.Errorf("unused variable")
}
}
return "", nil
}