Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warn enforcement action #1107

Merged
merged 11 commits into from
Mar 9, 2021
Merged

Conversation

sozercan
Copy link
Member

@sozercan sozercan commented Feb 1, 2021

Signed-off-by: Sertac Ozercan sozercan@gmail.com

What this PR does / why we need it:
Creates a new enforcement action called warn that provides a warning during admission (only difference compared to dryrun). Requires Kubernetes v1.19+ clusters. For non-v1.19+ clusters, it behaves identical to dryrun.

$ kubectl apply pause.yaml
Warning: [denied by prod-repo-is-openpolicyagent] container <pause> has an invalid image repo <mcr.microsoft.com/oss/kubernetes/pause:1.4.0>, allowed repos are ["only-this-repo"]
pod/pause created

Which issue(s) this PR fixes (optional, using fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when the PR gets merged):
Closes #701

Special notes for your reviewer:
This can also be merged into dryrun since functionality is very similar.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
@codecov-io
Copy link

codecov-io commented Feb 1, 2021

Codecov Report

Merging #1107 (27cd3cf) into master (321d8a8) will decrease coverage by 0.07%.
The diff coverage is 12.19%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1107      +/-   ##
==========================================
- Coverage   49.17%   49.10%   -0.08%     
==========================================
  Files          63       63              
  Lines        4390     4423      +33     
==========================================
+ Hits         2159     2172      +13     
- Misses       1970     1993      +23     
+ Partials      261      258       -3     
Flag Coverage Δ
unittests 49.10% <12.19%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
pkg/webhook/policy.go 28.62% <11.11%> (-2.82%) ⬇️
pkg/util/enforcement_action.go 25.00% <100.00%> (ø)
...onstrainttemplate/constrainttemplate_controller.go 58.89% <0.00%> (+3.23%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 321d8a8...27cd3cf. Read the comment docs.

pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
resDeny,
resWarn,
},
ExpectedMsgCount: 2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also test that the correct message is going to the correct response field, event type and log line.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
@ritazh
Copy link
Member

ritazh commented Feb 4, 2021

At highlevel, we should decide on what is the expected user experience for admission response for each enforcementAction should be.
Here is a proposal:

  • dryrun: no warning, no deny message
  • warning: warning message, no deny message
  • deny: deny message, no warning

Both deny and dryrun should behave the same as they do today.

WDYT?

@maxsmythe
Copy link
Contributor

SGTM

What about when there are multiple violations?

say: 1 deny, 1 dryrun, 1 warning

What gets returned?

@sozercan
Copy link
Member Author

sozercan commented Feb 4, 2021

I am thinking:

  • no message for dryrun
  • "would have denied by" warning for warn
  • "denied by" for deny as the actual admission response

which will end as deny.

@ritazh
Copy link
Member

ritazh commented Feb 4, 2021

What about when there are multiple violations?
say: 1 deny, 1 dryrun, 1 warning
What gets returned?

This would return: 1 warning and 1 deny

@maxsmythe
Copy link
Contributor

SGTM

@maxsmythe
Copy link
Contributor

What events and logs get written?

@sozercan
Copy link
Member Author

sozercan commented Feb 4, 2021

For log-denies, we don't differentiate between dryrun and deny today, so warn should be same.

For events, we can make a new reason called WarningAdmission (+1 here) or WarningViolation (we are calling FailedAdmission for deny events and DryrunViolation for dryrun events).

Thoughts?

However, if we create a new reason, we won't be able to fallback to dryrun reason for pre-1.19 cluster.

@maxsmythe
Copy link
Contributor

Per

if r.EnforcementAction == "deny" || r.EnforcementAction == "dryrun" {
if *logDenies {
log.WithValues(
logging.Process, "admission",
logging.EventType, "violation",
logging.ConstraintName, r.Constraint.GetName(),
logging.ConstraintGroup, r.Constraint.GroupVersionKind().Group,
logging.ConstraintAPIVersion, r.Constraint.GroupVersionKind().Version,
logging.ConstraintKind, r.Constraint.GetKind(),
logging.ConstraintAction, r.EnforcementAction,

--log-denies reports the enforcement action on the constraint, we should continue with that. IMO we can also drop the

if r.EnforcementAction == "deny" || r.EnforcementAction == "dryrun" {

line, and just report any violation we see as we see it.

Per

logging.ConstraintAction: r.EnforcementAction,

events are currently emitted with the enforcement action as-written written as an annotation. IMO that works as-is.

WRT event reasons...

I don't think we are coupled to the K8s admission webhook here, so there is no risk in adding a new reason for a new violation type. Users who don't use warning will not see any new behavior. Users who do will see the appropriate event reason in their cluster regardless of K8s version.

Another question is... what purpose do we want Event reason to serve? Is it a proxy for the enforcement action, which is how it's currently written? Is it more about categorizing the events between "those that cause rejections and those that dont", and users have the ability to dig deeper by looking at the event annotations?

If the later, we should change the text for reason. We have wriggle room to do so b/c events are still alpha.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
@sozercan
Copy link
Member Author

sozercan commented Mar 1, 2021

@maxsmythe @ritazh updated this per the discussion above. let me know what you think

  • added would have denied by text to warning
  • multiple violations with different enforcement actions will return both warning and deny. In case of deny, resource will get denied.
  • created a new event type called WarningAdmission

Copy link
Contributor

@maxsmythe maxsmythe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking close! A couple of nits and a question about word choice for "warning" events.

pkg/webhook/policy.go Outdated Show resolved Hide resolved
pkg/webhook/policy.go Outdated Show resolved Hide resolved
eventMsg = "Dryrun violation"
reason = "DryrunViolation"
case string(util.Warn):
eventMsg = "Admission webhook \"validation.gatekeeper.sh\" would have denied the request"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"would have denied the request" seems more appropriate for dryrun, where we are presumably dry-running against a future deny. The request "would have been rejected" if this had not been a dry run.

"raised a warning for this request" maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated eventMsg. should we change warning message to include raised a warning for this request too?

so it's either
Warning: [would have denied by cm-must-have-gk] you must provide labels: {"gatekeeper"}

or

Warning: [cm-must-have-gk raised a warning for this request] you must provide labels: {"gatekeeper"}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just:

Warning: [cm-must-have-gk] you must provide labels: {"gatekeeper"}

?

It sounds like kubectl is responsible for providing the context about what is a warning vs. not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see we're adding "denied by" by default.

We could use [warning from cm-must-have-gk] .....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: in the beginning is automatically added, so that'll be

Warning: [warning from cm-must-have-gk] you must provide labels: {"gatekeeper"}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove both denied by ... and would have denied by ...?

for 1 warning, 1 deny:

Warning: [cm-must-have-gk] you must provide labels: {"gatekeeper"}
Error from server ([deny-all-deny] DATA: {}): error when creating "test/bats/tests/bad/bad_cm.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [deny-all-deny] DATA: {}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that approach, personally.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this change existing behavior/expectation though? especially if users have been parsing that string

@ritazh wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would change existing behavior. I suppose whether that matters depends on whether we view the string format as part of our API. I'd consider these intended to be human-readable, and therefore not part of the API.

HTTP status codes and the API as defined by K8s should be what machines rely on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@maxsmythe
Copy link
Contributor

Also, it looks like hte unit tests are failing?

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
pkg/webhook/policy.go Outdated Show resolved Hide resolved
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
@sozercan sozercan requested a review from maxsmythe March 8, 2021 21:18
Copy link
Contributor

@maxsmythe maxsmythe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@sozercan sozercan merged commit 426949f into open-policy-agent:master Mar 9, 2021
@sozercan sozercan deleted the warn-ea branch March 9, 2021 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create another enforcementAction called warn
5 participants