Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions policy/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,10 @@ func NewMatch() *Match {
// Match declares a condition (defaults to true) as well as an output or a rule.
// Either the output or the rule field may be set, but not both.
type Match struct {
condition ValueString
output *ValueString
rule *Rule
condition ValueString
output *ValueString
explanation *ValueString
rule *Rule
}

// Condition returns the condition CEL expression.
Expand All @@ -227,6 +228,19 @@ func (m *Match) Output() ValueString {
return ValueString{}
}

// HasExplanation indicates whether the explanation field is set of the match.
func (m *Match) HasExplanation() bool {
return m.explanation != nil
}

// Explanation returns the explanation expression, or empty expression if output is not set.
func (m *Match) Explanation() ValueString {
if m.HasExplanation() {
return *m.explanation
}
return ValueString{}
}

// HasRule indicates whether the rule field is set on a match.
func (m *Match) HasRule() bool {
return m.rule != nil
Expand All @@ -247,6 +261,11 @@ func (m *Match) SetOutput(o ValueString) {
m.output = &o
}

// SetExplanation sets the explanation expression for the match.
func (m *Match) SetExplanation(e ValueString) {
m.explanation = &e
}

// SetRule sets the rule for the match.
func (m *Match) SetRule(r *Rule) {
m.rule = r
Expand Down Expand Up @@ -633,10 +652,18 @@ func (p *parserImpl) ParseMatch(ctx ParserContext, policy *Policy, node *yaml.No
p.ReportErrorAtID(keyID, "only the rule or the output may be set")
}
m.SetOutput(ctx.NewString(val))
case "explanation":
if m.HasRule() {
p.ReportErrorAtID(keyID, "explanation can only be set on output match cases, not nested rules")
}
m.SetExplanation(ctx.NewString(val))
case "rule":
if m.HasOutput() {
p.ReportErrorAtID(keyID, "only the rule or the output may be set")
}
if m.HasExplanation() {
p.ReportErrorAtID(keyID, "explanation can only be set on output match cases, not nested rules")
}
m.SetRule(p.ParseRule(ctx, policy, val))
default:
p.visitor.MatchTag(ctx, keyID, fieldName, val, policy, m)
Expand Down
26 changes: 26 additions & 0 deletions policy/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ rule:
output: "world"`,
err: `ERROR: <input>:8:7: only the rule or the output may be set
| output: "world"
| ......^`,
},
{
txt: `
rule:
match:
- condition: "true"
explanation: "hi"
rule:
match:
- output: "hello"`,
err: `ERROR: <input>:6:7: explanation can only be set on output match cases, not nested rules
| rule:
| ......^`,
},
{
txt: `
rule:
match:
- condition: "true"
rule:
match:
- output: "hello"
explanation: "hi"`,
err: `ERROR: <input>:8:7: explanation can only be set on output match cases, not nested rules
| explanation: "hi"
| ......^`,
},
}
Expand Down
1 change: 1 addition & 0 deletions policy/testdata/nested_rule/policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ rule:
resource.origin in variables.banned_regions &&
!(resource.origin in variables.permitted_regions)
output: "{'banned': true}"
explanation: "'resource is in the banned region ' + resource.origin"
- condition: resource.origin in variables.permitted_regions
output: "{'banned': false}"
- output: "{'banned': true}"