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 PodSecurityPolicy information to audit logs #58143

Conversation

CaoShuFeng
Copy link
Contributor

@CaoShuFeng CaoShuFeng commented Jan 11, 2018

Depends on: #58806
Fix #56209

Release note:

PodSecurityPolicy admission information is added to audit logs

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jan 11, 2018
@CaoShuFeng CaoShuFeng force-pushed the audit_annotation_another_version branch from 68fdf4c to 3c05701 Compare January 15, 2018 10:32
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jan 15, 2018
@CaoShuFeng
Copy link
Contributor Author

/assign @sttts @liggitt
What's your opinion about this version?

if err != nil {
return admission.NewForbidden(a, err)
}
if apiequality.Semantic.DeepEqual(pod, allowedPod) {
ae := a.GetAuditEvent()
audit.LogAnnotations(ae, "podsecuritypolicy/validate", pspName)
Copy link
Contributor

Choose a reason for hiding this comment

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

we need better keys here, maybe podsecuritypolicy.admission.k8s.io/policy

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 always use full names

allowed bool
errors []error
allowed bool
clusterRoleBinding string
Copy link
Contributor

Choose a reason for hiding this comment

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

would move these into its own struct. maybe struct reason

@@ -74,6 +82,21 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (aut

r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)
if ruleCheckingVisitor.allowed {
ae := requestAttributes.GetAuditEvent()
if ae != nil {
if ruleCheckingVisitor.clusterRoleBinding != "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

len(...) != 0 is our convention

@@ -32,9 +33,10 @@ type attributesRecord struct {
object runtime.Object
oldObject runtime.Object
userInfo user.Info
ae *audit.Event
Copy link
Contributor

Choose a reason for hiding this comment

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

auditEvent

// PSP will store admission information in Annotations, like name of the policy which admits
// the request.
// +optional
Annotations map[string]string
Copy link
Contributor

Choose a reason for hiding this comment

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

@tallclair @crassirostris @ericchiang @soltysh this is about the API. Are we happy with this representation?

Choose a reason for hiding this comment

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

I'm fine with this interface, but I remember someone was not happy with it

Copy link
Contributor

Choose a reason for hiding this comment

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

We have plugin names (those which are also used in the apiserver flags). We could make this more structured using them if we concentrate on admission. We could render the whole chain here in the event.

RBAC would then be another step, probably with an explicit authorization field.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not too happy with the name, but can't come up with a better one, so I guess I'll just have to live with it ;).
As for the structured, having map[string]string give us more freedom, if we decide to add additional information. Maybe we should name the field as AdditionalInfo or something like that? At the same time, I'm worried this might end up being a grab bag for all the things we want to have here. Hm....

Copy link
Contributor

Choose a reason for hiding this comment

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

I just spoke with @sttts and we agreed it would be nice to:

  1. be able to decide which admission and rbac plugins are logged, so that would require additional rule changes
  2. Authorization logging happens in authorizingVisitor which is perfect, but admission happens only in PSP, I'd imagine this should happen a level higher to be able to do what I said in 1.

@tallclair @crassirostris @ericchiang @CaoShuFeng opinions?

Copy link
Member

Choose a reason for hiding this comment

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

be able to decide which admission and rbac plugins are logged, so that would require additional rule changes

This feels like something that should be resolved with filters, if we ever get around to implementing them. We don't currently allow fine grained selection of what's logged, so I think the current approach is consistent.

Authorization logging happens in authorizingVisitor which is perfect,

Only for RBAC, it's an implementation detail.

but admission happens only in PSP, I'd imagine this should happen a level higher to be able to do what I said in 1.

I see this field as arbitrary metadata that plugins invoked in the serving path can add to. I think the authorization & admission interfaces should enable this on a case-by-case basis.

I'm happy with the current unstructured approach.

@@ -94,7 +94,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object
audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer)

userInfo, _ := request.UserFrom(ctx)
admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo)
admissionAttributes := admission.NewAttributesRecordWithAudit(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo, ae)
Copy link
Contributor

Choose a reason for hiding this comment

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

do we really need this new func name?

}

func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, userInfo user.Info) Attributes {
func NewAttributesRecordWithAudit(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, userInfo user.Info, ae *audit.Event) Attributes {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would keep the old func name and make that argument mandatory (possibly nil)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK.
I will modify all NewAttributesRecord functions.

$ LANG=C grep "NewAttributesRecord" * -r  | grep "\.go"  | wc -l
262

:)

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

For easier review, please do that in another commit.

99% of those calls are in tests btw. Was surprised that the number is that high.

@sttts
Copy link
Contributor

sttts commented Jan 16, 2018

What's your opinion about this version?

Much better. It's what I expected 👍

@CaoShuFeng
Copy link
Contributor Author

Much better. It's what I expected 👍

Thanks. I will address all your comments and add some unit tests.

@@ -42,7 +42,7 @@ type AuthorizationRuleResolver interface {

// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, and each error encountered resolving those rules.
// If visitor() returns false, visiting is short-circuited.
VisitRulesFor(user user.Info, namespace string, visitor func(rule *rbac.PolicyRule, err error) bool)
VisitRulesFor(user user.Info, namespace string, visitor func(rule *rbac.PolicyRule, clusterRolebinding, clusterRole, roleBinding, role string, err error) bool)
Copy link
Member

Choose a reason for hiding this comment

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

prefer (*rbac.RoleRef, *rbac.PolicyRule, ...), since we have the reference already?

Copy link
Member

@liggitt liggitt Jan 17, 2018

Choose a reason for hiding this comment

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

hmm, I guess you need the binding name/namespace as well

@@ -61,6 +62,9 @@ type Attributes interface {

// GetPath returns the path of the request
GetPath() string

// GetAuditEvent returns the audit event of the request
GetAuditEvent() *audit.Event
Copy link
Member

@liggitt liggitt Jan 16, 2018

Choose a reason for hiding this comment

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

this interface is supposed to be fully serializable so it can be delegated via a subject access review. an audit.Event pointer breaks that, and implies getting a writeable object out of the attributes, which reverses the information flow of this interface

Copy link
Contributor

Choose a reason for hiding this comment

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

Which means that we have to expose the audit annotations (or any other data structure we choose) for authz/n in a different way here. Also a delgated authorizer should fill in values.

Copy link
Member

@liggitt liggitt Jan 19, 2018

Choose a reason for hiding this comment

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

authz already has the ability to return a reason along with the authorization decision. can we use that from the outside, rather than plumbing audit into all the authorizers? that would work with remote authorization as well without any changes to the authz APIs

Copy link
Contributor

Choose a reason for hiding this comment

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

@tallclair @crassirostris can you comment whether the reason is enough?

Copy link
Member

@liggitt liggitt Jan 19, 2018

Choose a reason for hiding this comment

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

I would expect the following behavior:

  • when authorization failed, the reason would contain aggregated reasons from all authorizers that provided failure reasons
  • when authorization succeeded, the reason would contain the reason from the succeeding authorizer if it provided one

Copy link
Member

Choose a reason for hiding this comment

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

the authorizer reason is currently plumbed all the way up to https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go#L49 which seems like a much easier place to get a handle to the audit event

Copy link
Member

@liggitt liggitt Jan 19, 2018

Choose a reason for hiding this comment

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

PR that makes RBAC return a detailed reason for what it allows that includes the subject, binding, and role: #58531

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -74,6 +82,21 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (aut

r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)
if ruleCheckingVisitor.allowed {
ae := requestAttributes.GetAuditEvent()
Copy link
Member

Choose a reason for hiding this comment

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

getting an object out of requestAttributes in order to write back to it is a fundamental change in the way the authorizer attributes are used, and breaks remote delegation cases for that interface

Copy link
Contributor

Choose a reason for hiding this comment

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

See above. We need an explicit data structure here. Not a huge event with unclear ownership.

@CaoShuFeng CaoShuFeng force-pushed the audit_annotation_another_version branch from 3c05701 to c77617a Compare January 19, 2018 09:14
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jan 19, 2018
@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 19, 2018
@tallclair
Copy link
Member

/status approved-for-milestone

@k8s-github-robot
Copy link

[MILESTONENOTIFIER] Milestone Pull Request: Up-to-date for process

@CaoShuFeng @justinsb @liggitt @sttts @tallclair

Pull Request Labels
  • sig/auth: Pull Request will be escalated to these SIGs if needed.
  • priority/important-soon: Escalate to the pull request owners and SIG owner; move out of milestone after several unsuccessful escalation attempts.
  • kind/feature: New functionality.
Help

@CaoShuFeng CaoShuFeng force-pushed the audit_annotation_another_version branch from edeaa55 to e71fa21 Compare June 4, 2018 02:15
record.annotations = make(map[string]string)
}
if v, ok := record.annotations[key]; ok && v != value {
return fmt.Errorf("admission annotations are not allowd to be overwritten, key:%q, old value: %q, new value:%q", key, record.annotations[key], value)
Copy link
Contributor

Choose a reason for hiding this comment

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

this switched to an error from a warning? Am fine with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.
According to @tallclair 's suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

"podsecuritypolicy.admission.k8s.io/validate-policy": "privileged",
"podsecuritypolicy.admission.k8s.io/admit-policy": "privileged",
},
"unexpected final annotations")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: odd formatting. usually we put the ) on the next line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

// AnnotationsGetter allows users to get annotations from Attributes. An alternate Attribute should implement
// this interface.
type AnnotationsGetter interface {
GetAnnotations() map[string]string
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see this used. Premature abstraction? Would drop it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This interface is used according to @liggitt 's suggestion.

d7474b8#r29220311

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's used in WithAudit decorator to check the attribute interface.
Would be useful for alternate Attributes.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, sounds reasonable.

@CaoShuFeng CaoShuFeng force-pushed the audit_annotation_another_version branch from e71fa21 to 2414228 Compare June 4, 2018 11:23
WithAudit admission decorator log annotations to audit events set by
the decorated admission controller
@sttts
Copy link
Contributor

sttts commented Jun 4, 2018

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 4, 2018
@sttts
Copy link
Contributor

sttts commented Jun 4, 2018

@tallclair @liggitt approved?

@liggitt
Copy link
Member

liggitt commented Jun 4, 2018

/approve

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: CaoShuFeng, liggitt, sttts

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 4, 2018
@fejta-bot
Copy link

/retest
This bot automatically retries jobs that failed/flaked on approved PRs (send feedback to fejta).

Review the full test history for this PR.

Silence the bot with an /lgtm cancel comment for consistent failures.

@jberkus
Copy link

jberkus commented Jun 4, 2018

/retest pull-kubernetes-e2e-kops-aws

@liggitt
Copy link
Member

liggitt commented Jun 4, 2018

/retest

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 61610, 64591, 58143, 63929). If you want to cherry-pick this change to another branch, please follow the instructions here.

@k8s-github-robot k8s-github-robot merged commit 08c15a6 into kubernetes:master Jun 4, 2018
k8s-github-robot pushed a commit that referenced this pull request Aug 22, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: #58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```
k8s-publishing-bot added a commit to kubernetes/api that referenced this pull request Aug 23, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
k8s-publishing-bot added a commit to kubernetes/apiserver that referenced this pull request Aug 23, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
sttts pushed a commit to sttts/api that referenced this pull request Sep 5, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
sttts pushed a commit to sttts/apiserver that referenced this pull request Sep 5, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
k8s-publishing-bot added a commit to kubernetes/api that referenced this pull request Sep 6, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
k8s-publishing-bot added a commit to kubernetes/apiserver that referenced this pull request Sep 6, 2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: kubernetes/kubernetes#58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```

Kubernetes-commit: 4e76bb487e50996468bea6638f8ade45911953de
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/audit cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/auth Categorizes an issue or PR as relevant to SIG Auth. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet