Skip to content

Commit 192bef1

Browse files
James Alsethkonstraint-bot
andauthored
Add support for setting the constraint enforcement action per policy (#71)
* Add @enforcement to Rego comment header block * generate updated cli docs Co-authored-by: konstraint-bot <konstraint-bot@dev.null>
1 parent a654ec1 commit 192bef1

File tree

8 files changed

+54
-6
lines changed

8 files changed

+54
-6
lines changed

docs/cli/konstraint.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ A tool to create and manage Gatekeeper CRDs from Rego
1717
* [konstraint create](konstraint_create.md) - Create Gatekeeper constraints from Rego policies
1818
* [konstraint doc](konstraint_doc.md) - Generate documentation from Rego policies
1919

20-
###### Auto generated by spf13/cobra on 26-Aug-2020
20+
###### Auto generated by spf13/cobra on 30-Sep-2020

docs/cli/konstraint_create.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Create constraints with the Gatekeeper enforcement action set to dryrun
2626
### Options
2727

2828
```
29-
-d, --dryrun Sets the enforcement action of the constraints to dryrun
29+
-d, --dryrun Sets the enforcement action of the constraints to dryrun, overriding the @enforcement tag
3030
-h, --help help for create
3131
-o, --output string Specify an output directory for the Gatekeeper resources
3232
```
@@ -35,4 +35,4 @@ Create constraints with the Gatekeeper enforcement action set to dryrun
3535

3636
* [konstraint](konstraint.md) - Konstraint
3737

38-
###### Auto generated by spf13/cobra on 26-Aug-2020
38+
###### Auto generated by spf13/cobra on 30-Sep-2020

docs/cli/konstraint_doc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ Set the URL where the policies are hosted at
3535

3636
* [konstraint](konstraint.md) - Konstraint
3737

38-
###### Auto generated by spf13/cobra on 26-Aug-2020
38+
###### Auto generated by spf13/cobra on 30-Sep-2020

docs/constraint_creation.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,15 @@ This comment block should:
4848
- Include a human readable description of what the policy does.
4949
- Set the matchers used when generating the Constraints.
5050

51+
It may also specify the enforcment action (either `deny` or `dryrun`) that Gatekeeper should take when a resource violates the constraint. If no enforcement action is specified, Konstraint defaults to using `deny` to align with Gatekeeper's default action. If the enforcement is set to `dryrun`, the policy will be skipped in the documentation generation.
52+
5153
```rego
5254
# @title Pods must not run with access to the host IPC
5355
#
5456
# Pods that are allowed to access the host IPC can read memory of
5557
# the other containers, breaking that security boundary.
5658
#
59+
# @enforcement deny
5760
# @kinds apps/DaemonSet apps/Deployment apps/StatefulSet core/Pod
5861
package pod_deny_host_ipc
5962

internal/commands/create.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Create constraints with the Gatekeeper enforcement action set to dryrun
4949
}
5050

5151
cmd.PersistentFlags().StringP("output", "o", "", "Specify an output directory for the Gatekeeper resources")
52-
cmd.PersistentFlags().BoolP("dryrun", "d", false, "Sets the enforcement action of the constraints to dryrun")
52+
cmd.PersistentFlags().BoolP("dryrun", "d", false, "Sets the enforcement action of the constraints to dryrun, overriding the @enforcement tag")
5353

5454
return &cmd
5555
}
@@ -140,8 +140,9 @@ func getConstraint(violation rego.Rego) (unstructured.Unstructured, error) {
140140
constraint.SetGroupVersionKind(gvk)
141141
constraint.SetName(violation.Name())
142142

143+
// the dryrun flag overrides any enforcement action specified in the rego header
143144
dryrun := viper.GetBool("dryrun")
144-
if dryrun {
145+
if dryrun || violation.Enforcement() == "dryrun" {
145146
if err := unstructured.SetNestedField(constraint.Object, "dryrun", "spec", "enforcementAction"); err != nil {
146147
return unstructured.Unstructured{}, fmt.Errorf("set constraint dryrun: %w", err)
147148
}

internal/commands/document.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ func getDocumentation(path string, outputDirectory string) (map[rego.Severity][]
101101
continue
102102
}
103103

104+
if policy.Enforcement() == "dryrun" {
105+
continue
106+
}
107+
104108
var url string
105109
if viper.GetString("url") != "" {
106110
url = viper.GetString("url") + "/" + policy.Path()

internal/rego/rego.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ func (r Rego) Title() string {
129129
return trimString(title)
130130
}
131131

132+
// Enforcement returns the enforcement action in the header comment
133+
// Defaults to deny if no enforcement action is specified
134+
func (r Rego) Enforcement() string {
135+
enforcement := "deny"
136+
for _, comment := range r.comments {
137+
if !strings.Contains(comment, "@enforcement") {
138+
continue
139+
}
140+
141+
enforcement = strings.SplitAfter(comment, "@enforcement")[1]
142+
break
143+
}
144+
145+
return trimString(enforcement)
146+
}
147+
132148
// Description returns the entire description
133149
// found in the header comment of the rego file.
134150
func (r Rego) Description() string {

internal/rego/rego_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,27 @@ third`
105105
t.Errorf("unexpected Source. expected %v, actual %v", expected, actual)
106106
}
107107
}
108+
109+
func TestEnforcement(t *testing.T) {
110+
comments := []string{
111+
"@title Test",
112+
"description",
113+
"@enforcement dryrun",
114+
"@kinds apps/Deployment",
115+
}
116+
rego := Rego{
117+
comments: comments,
118+
}
119+
120+
actual := rego.Enforcement()
121+
const expected = "dryrun"
122+
if actual != expected {
123+
t.Errorf("unexpected Enforcement. expected %v, actual %v", expected, actual)
124+
}
125+
126+
actualDefault := Rego{}.Enforcement()
127+
const expectedDefault = "deny"
128+
if actualDefault != expectedDefault {
129+
t.Errorf("unexpected Enforcement. expected %v, actual %v", expectedDefault, actualDefault)
130+
}
131+
}

0 commit comments

Comments
 (0)