Upgrade k8s package verison (#5358)

* upgrade k8s package version

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

* Script upgrade and code formatting.

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-11-15 14:56:38 +08:00
committed by GitHub
parent 5f91c1663a
commit 44167aa47a
3106 changed files with 321340 additions and 172080 deletions

View File

@@ -1,9 +1,8 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- sig-auth-audit-approvers
- sig-auth-audit-approvers
reviewers:
- sig-auth-audit-reviewers
- sig-auth-audit-reviewers
labels:
- sig/auth
- sig/auth

View File

@@ -18,8 +18,11 @@ package audit
import (
"context"
"sync"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/klog/v2"
)
// The key type is unexported to prevent collisions
@@ -27,7 +30,15 @@ type key int
const (
// auditAnnotationsKey is the context key for the audit annotations.
// TODO: consolidate all audit info under the AuditContext, rather than storing 3 separate keys.
auditAnnotationsKey key = iota
// auditKey is the context key for storing the audit event that is being
// captured and the evaluated policy that applies to the given request.
auditKey
// auditAnnotationsMutexKey is the context key for the audit annotations mutex.
auditAnnotationsMutexKey
)
// annotations = *[]annotation instead of a map to preserve order of insertions
@@ -45,6 +56,7 @@ func WithAuditAnnotations(parent context.Context) context.Context {
if _, ok := parent.Value(auditAnnotationsKey).(*[]annotation); ok {
return parent
}
parent = withAuditAnnotationsMutex(parent)
var annotations []annotation // avoid allocations until we actually need it
return genericapirequest.WithValue(parent, auditAnnotationsKey, &annotations)
@@ -58,27 +70,156 @@ func WithAuditAnnotations(parent context.Context) context.Context {
// Handlers that are unaware of their position in the overall request flow should
// prefer AddAuditAnnotation over LogAnnotation to avoid dropping annotations.
func AddAuditAnnotation(ctx context.Context, key, value string) {
// use the audit event directly if we have it
if ae := genericapirequest.AuditEventFrom(ctx); ae != nil {
LogAnnotation(ae, key, value)
mutex, ok := auditAnnotationsMutex(ctx)
if !ok {
// auditing is not enabled
return
}
annotations, ok := ctx.Value(auditAnnotationsKey).(*[]annotation)
if !ok {
return // adding audit annotation is not supported at this call site
mutex.Lock()
defer mutex.Unlock()
ae := AuditEventFrom(ctx)
var ctxAnnotations *[]annotation
if ae == nil {
ctxAnnotations, _ = ctx.Value(auditAnnotationsKey).(*[]annotation)
}
*annotations = append(*annotations, annotation{key: key, value: value})
addAuditAnnotationLocked(ae, ctxAnnotations, key, value)
}
// AddAuditAnnotations is a bulk version of AddAuditAnnotation. Refer to AddAuditAnnotation for
// restrictions on when this can be called.
// keysAndValues are the key-value pairs to add, and must have an even number of items.
func AddAuditAnnotations(ctx context.Context, keysAndValues ...string) {
mutex, ok := auditAnnotationsMutex(ctx)
if !ok {
// auditing is not enabled
return
}
mutex.Lock()
defer mutex.Unlock()
ae := AuditEventFrom(ctx)
var ctxAnnotations *[]annotation
if ae == nil {
ctxAnnotations, _ = ctx.Value(auditAnnotationsKey).(*[]annotation)
}
if len(keysAndValues)%2 != 0 {
klog.Errorf("Dropping mismatched audit annotation %q", keysAndValues[len(keysAndValues)-1])
}
for i := 0; i < len(keysAndValues); i += 2 {
addAuditAnnotationLocked(ae, ctxAnnotations, keysAndValues[i], keysAndValues[i+1])
}
}
// AddAuditAnnotationsMap is a bulk version of AddAuditAnnotation. Refer to AddAuditAnnotation for
// restrictions on when this can be called.
func AddAuditAnnotationsMap(ctx context.Context, annotations map[string]string) {
mutex, ok := auditAnnotationsMutex(ctx)
if !ok {
// auditing is not enabled
return
}
mutex.Lock()
defer mutex.Unlock()
ae := AuditEventFrom(ctx)
var ctxAnnotations *[]annotation
if ae == nil {
ctxAnnotations, _ = ctx.Value(auditAnnotationsKey).(*[]annotation)
}
for k, v := range annotations {
addAuditAnnotationLocked(ae, ctxAnnotations, k, v)
}
}
// addAuditAnnotationLocked is the shared code for recording an audit annotation. This method should
// only be called while the auditAnnotationsMutex is locked.
func addAuditAnnotationLocked(ae *auditinternal.Event, annotations *[]annotation, key, value string) {
if ae != nil {
logAnnotation(ae, key, value)
} else if annotations != nil {
*annotations = append(*annotations, annotation{key: key, value: value})
}
}
// This is private to prevent reads/write to the slice from outside of this package.
// The audit event should be directly read to get access to the annotations.
func auditAnnotationsFrom(ctx context.Context) []annotation {
annotations, ok := ctx.Value(auditAnnotationsKey).(*[]annotation)
func addAuditAnnotationsFrom(ctx context.Context, ev *auditinternal.Event) {
mutex, ok := auditAnnotationsMutex(ctx)
if !ok {
return nil // adding audit annotation is not supported at this call site
// auditing is not enabled
return
}
return *annotations
mutex.Lock()
defer mutex.Unlock()
annotations, ok := ctx.Value(auditAnnotationsKey).(*[]annotation)
if !ok {
return // no annotations to copy
}
for _, kv := range *annotations {
logAnnotation(ev, kv.key, kv.value)
}
}
// LogAnnotation fills in the Annotations according to the key value pair.
func logAnnotation(ae *auditinternal.Event, key, value string) {
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
return
}
if ae.Annotations == nil {
ae.Annotations = make(map[string]string)
}
if v, ok := ae.Annotations[key]; ok && v != value {
klog.Warningf("Failed to set annotations[%q] to %q for audit:%q, it has already been set to %q", key, value, ae.AuditID, ae.Annotations[key])
return
}
ae.Annotations[key] = value
}
// WithAuditContext returns a new context that stores the pair of the audit
// configuration object that applies to the given request and
// the audit event that is going to be written to the API audit log.
func WithAuditContext(parent context.Context, ev *AuditContext) context.Context {
parent = withAuditAnnotationsMutex(parent)
return genericapirequest.WithValue(parent, auditKey, ev)
}
// AuditEventFrom returns the audit event struct on the ctx
func AuditEventFrom(ctx context.Context) *auditinternal.Event {
if o := AuditContextFrom(ctx); o != nil {
return o.Event
}
return nil
}
// AuditContextFrom returns the pair of the audit configuration object
// that applies to the given request and the audit event that is going to
// be written to the API audit log.
func AuditContextFrom(ctx context.Context) *AuditContext {
ev, _ := ctx.Value(auditKey).(*AuditContext)
return ev
}
// WithAuditAnnotationMutex adds a mutex for guarding context.AddAuditAnnotation.
func withAuditAnnotationsMutex(parent context.Context) context.Context {
if _, ok := parent.Value(auditAnnotationsMutexKey).(*sync.Mutex); ok {
return parent
}
var mutex sync.Mutex
return genericapirequest.WithValue(parent, auditAnnotationsMutexKey, &mutex)
}
// AuditAnnotationsMutex returns the audit annotations mutex from the context.
func auditAnnotationsMutex(ctx context.Context) (*sync.Mutex, bool) {
mutex, ok := ctx.Value(auditAnnotationsMutexKey).(*sync.Mutex)
return mutex, ok
}

65
vendor/k8s.io/apiserver/pkg/audit/evaluator.go generated vendored Normal file
View File

@@ -0,0 +1,65 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package audit
import (
"k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
// AuditContext is a pair of the audit configuration object that applies to
// a given request and the audit Event object that is being captured.
// It's a convenient placeholder to store both these objects in the request context.
type AuditContext struct {
// RequestAuditConfig is the audit configuration that applies to the request
RequestAuditConfig RequestAuditConfig
// Event is the audit Event object that is being captured to be written in
// the API audit log. It is set to nil when the request is not being audited.
Event *audit.Event
}
// RequestAuditConfig is the evaluated audit configuration that is applicable to
// a given request. PolicyRuleEvaluator evaluates the audit policy against the
// authorizer attributes and returns a RequestAuditConfig that applies to the request.
type RequestAuditConfig struct {
// OmitStages is the stages that need to be omitted from being audited.
OmitStages []audit.Stage
// OmitManagedFields indicates whether to omit the managed fields of the request
// and response bodies from being written to the API audit log.
OmitManagedFields bool
}
// RequestAuditConfigWithLevel includes Level at which the request is being audited.
// PolicyRuleEvaluator evaluates the audit configuration for a request
// against the authorizer attributes and returns an RequestAuditConfigWithLevel
// that applies to the request.
type RequestAuditConfigWithLevel struct {
RequestAuditConfig
// Level at which the request is being audited at
Level audit.Level
}
// PolicyRuleEvaluator exposes methods for evaluating the policy rules.
type PolicyRuleEvaluator interface {
// EvaluatePolicyRule evaluates the audit policy of the apiserver against
// the given authorizer attributes and returns the audit configuration that
// is applicable to the given equest.
EvaluatePolicyRule(authorizer.Attributes) RequestAuditConfigWithLevel
}

View File

@@ -60,8 +60,8 @@ func EventString(ev *auditinternal.Event) string {
ip = ev.SourceIPs[0]
}
return fmt.Sprintf("%s AUDIT: id=%q stage=%q ip=%q method=%q user=%q groups=%q as=%q asgroups=%q namespace=%q uri=%q response=\"%s\"",
ev.RequestReceivedTimestamp.Format(time.RFC3339Nano), ev.AuditID, ev.Stage, ip, ev.Verb, username, groups, asuser, asgroups, namespace, ev.RequestURI, response)
return fmt.Sprintf("%s AUDIT: id=%q stage=%q ip=%q method=%q user=%q groups=%q as=%q asgroups=%q user-agent=%q namespace=%q uri=%q response=\"%s\"",
ev.RequestReceivedTimestamp.Format(time.RFC3339Nano), ev.AuditID, ev.Stage, ip, ev.Verb, username, groups, asuser, asgroups, ev.UserAgent, namespace, ev.RequestURI, response)
}
func auditStringSlice(inList []string) string {

View File

@@ -32,7 +32,7 @@ const (
/*
* By default, all the following metrics are defined as falling under
* ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1209-metrics-stability/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes)
* ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1209-metrics-stability/kubernetes-control-plane-metrics-stability.md#stability-classes)
*
* Promoting the stability level of the metric is a responsibility of the component owner, since it
* involves explicitly acknowledging support for the metric across multiple releases, in accordance with

View File

@@ -20,6 +20,7 @@ import (
"strings"
"k8s.io/apiserver/pkg/apis/audit"
auditinternal "k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
@@ -28,18 +29,12 @@ const (
DefaultAuditLevel = audit.LevelNone
)
// Checker exposes methods for checking the policy rules.
type Checker interface {
// Check the audit level for a request with the given authorizer attributes.
LevelAndStages(authorizer.Attributes) (audit.Level, []audit.Stage)
}
// NewChecker creates a new policy checker.
func NewChecker(policy *audit.Policy) Checker {
// NewPolicyRuleEvaluator creates a new policy rule evaluator.
func NewPolicyRuleEvaluator(policy *audit.Policy) auditinternal.PolicyRuleEvaluator {
for i, rule := range policy.Rules {
policy.Rules[i].OmitStages = unionStages(policy.OmitStages, rule.OmitStages)
}
return &policyChecker{*policy}
return &policyRuleEvaluator{*policy}
}
func unionStages(stageLists ...[]audit.Stage) []audit.Stage {
@@ -56,22 +51,48 @@ func unionStages(stageLists ...[]audit.Stage) []audit.Stage {
return result
}
// FakeChecker creates a checker that returns a constant level for all requests (for testing).
func FakeChecker(level audit.Level, stage []audit.Stage) Checker {
return &fakeChecker{level, stage}
// NewFakePolicyRuleEvaluator creates a fake policy rule evaluator that returns
// a constant level for all requests (for testing).
func NewFakePolicyRuleEvaluator(level audit.Level, stage []audit.Stage) auditinternal.PolicyRuleEvaluator {
return &fakePolicyRuleEvaluator{level, stage}
}
type policyChecker struct {
type policyRuleEvaluator struct {
audit.Policy
}
func (p *policyChecker) LevelAndStages(attrs authorizer.Attributes) (audit.Level, []audit.Stage) {
func (p *policyRuleEvaluator) EvaluatePolicyRule(attrs authorizer.Attributes) auditinternal.RequestAuditConfigWithLevel {
for _, rule := range p.Rules {
if ruleMatches(&rule, attrs) {
return rule.Level, rule.OmitStages
return auditinternal.RequestAuditConfigWithLevel{
Level: rule.Level,
RequestAuditConfig: auditinternal.RequestAuditConfig{
OmitStages: rule.OmitStages,
OmitManagedFields: isOmitManagedFields(&rule, p.OmitManagedFields),
},
}
}
}
return DefaultAuditLevel, p.OmitStages
return auditinternal.RequestAuditConfigWithLevel{
Level: DefaultAuditLevel,
RequestAuditConfig: auditinternal.RequestAuditConfig{
OmitStages: p.OmitStages,
OmitManagedFields: p.OmitManagedFields,
},
}
}
// isOmitManagedFields returns whether to omit managed fields from the request
// and response bodies from being written to the API audit log.
// If a user specifies OmitManagedFields inside a policy rule, that overrides
// the global policy default in Policy.OmitManagedFields.
func isOmitManagedFields(policyRule *audit.PolicyRule, policyDefault bool) bool {
if policyRule.OmitManagedFields == nil {
return policyDefault
}
return *policyRule.OmitManagedFields
}
// Check whether the rule matches the request attrs.
@@ -209,11 +230,16 @@ func hasString(slice []string, value string) bool {
return false
}
type fakeChecker struct {
type fakePolicyRuleEvaluator struct {
level audit.Level
stage []audit.Stage
}
func (f *fakeChecker) LevelAndStages(_ authorizer.Attributes) (audit.Level, []audit.Stage) {
return f.level, f.stage
func (f *fakePolicyRuleEvaluator) EvaluatePolicyRule(_ authorizer.Attributes) auditinternal.RequestAuditConfigWithLevel {
return auditinternal.RequestAuditConfigWithLevel{
Level: f.level,
RequestAuditConfig: auditinternal.RequestAuditConfig{
OmitStages: f.stage,
},
}
}

View File

@@ -1,53 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package policy
import (
"fmt"
"k8s.io/apiserver/pkg/apis/audit"
)
// EnforcePolicy drops any part of the event that doesn't conform to a policy level
// or omitStages and sets the event level accordingly
func EnforcePolicy(event *audit.Event, level audit.Level, omitStages []audit.Stage) (*audit.Event, error) {
for _, stage := range omitStages {
if event.Stage == stage {
return nil, nil
}
}
return enforceLevel(event, level)
}
func enforceLevel(event *audit.Event, level audit.Level) (*audit.Event, error) {
switch level {
case audit.LevelMetadata:
event.Level = audit.LevelMetadata
event.ResponseObject = nil
event.RequestObject = nil
case audit.LevelRequest:
event.Level = audit.LevelRequest
event.ResponseObject = nil
case audit.LevelRequestResponse:
event.Level = audit.LevelRequestResponse
case audit.LevelNone:
return nil, nil
default:
return nil, fmt.Errorf("level unknown: %s", level)
}
return event, nil
}

View File

@@ -23,8 +23,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1"
"k8s.io/apiserver/pkg/apis/audit/validation"
"k8s.io/apiserver/pkg/audit"
@@ -33,8 +31,6 @@ import (
var (
apiGroupVersions = []schema.GroupVersion{
auditv1beta1.SchemeGroupVersion,
auditv1alpha1.SchemeGroupVersion,
auditv1.SchemeGroupVersion,
}
apiGroupVersionSet = map[schema.GroupVersion]bool{}
@@ -78,10 +74,6 @@ func LoadPolicyFromBytes(policyDef []byte) (*auditinternal.Policy, error) {
return nil, fmt.Errorf("unknown group version field %v in policy", gvk)
}
if gv != auditv1.SchemeGroupVersion {
klog.Warningf("%q is deprecated and will be removed in a future release, use %q instead", gv, auditv1.SchemeGroupVersion)
}
if err := validation.ValidatePolicy(policy); err != nil {
return nil, err.ToAggregate()
}

View File

@@ -24,10 +24,10 @@ import (
// AllStages returns all possible stages
func AllStages() sets.String {
return sets.NewString(
audit.StageRequestReceived,
audit.StageResponseStarted,
audit.StageResponseComplete,
audit.StagePanic,
string(audit.StageRequestReceived),
string(audit.StageResponseStarted),
string(audit.StageResponseComplete),
string(audit.StagePanic),
)
}

View File

@@ -18,14 +18,12 @@ package audit
import (
"bytes"
"context"
"fmt"
"net/http"
"reflect"
"time"
"github.com/google/uuid"
"k8s.io/klog/v2"
authnv1 "k8s.io/api/authentication/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -36,6 +34,10 @@ import (
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/klog/v2"
"github.com/google/uuid"
)
const (
@@ -52,14 +54,11 @@ func NewEventFromRequest(req *http.Request, requestReceivedTimestamp time.Time,
Level: level,
}
// prefer the id from the headers. If not available, create a new one.
// TODO(audit): do we want to forbid the header for non-front-proxy users?
ids := req.Header.Get(auditinternal.HeaderAuditID)
if ids != "" {
ev.AuditID = types.UID(ids)
} else {
ev.AuditID = types.UID(uuid.New().String())
auditID, found := request.AuditIDFrom(req.Context())
if !found {
auditID = types.UID(uuid.New().String())
}
ev.AuditID = auditID
ips := utilnet.SourceIPs(req)
ev.SourceIPs = make([]string, len(ips))
@@ -88,9 +87,7 @@ func NewEventFromRequest(req *http.Request, requestReceivedTimestamp time.Time,
}
}
for _, kv := range auditAnnotationsFrom(req.Context()) {
LogAnnotation(ev, kv.key, kv.value)
}
addAuditAnnotationsFrom(req.Context(), ev)
return ev, nil
}
@@ -113,7 +110,8 @@ func LogImpersonatedUser(ae *auditinternal.Event, user user.Info) {
// LogRequestObject fills in the request object into an audit event. The passed runtime.Object
// will be converted to the given gv.
func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.GroupVersionResource, subresource string, s runtime.NegotiatedSerializer) {
func LogRequestObject(ctx context.Context, obj runtime.Object, objGV schema.GroupVersion, gvr schema.GroupVersionResource, subresource string, s runtime.NegotiatedSerializer) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
return
}
@@ -153,9 +151,19 @@ func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.Gr
return
}
if shouldOmitManagedFields(ctx) {
copy, ok, err := copyWithoutManagedFields(obj)
if err != nil {
klog.Warningf("error while dropping managed fields from the request for %q error: %v", reflect.TypeOf(obj).Name(), err)
}
if ok {
obj = copy
}
}
// TODO(audit): hook into the serializer to avoid double conversion
var err error
ae.RequestObject, err = encodeObject(obj, gvr.GroupVersion(), s)
ae.RequestObject, err = encodeObject(obj, objGV, s)
if err != nil {
// TODO(audit): add error slice to audit event struct
klog.Warningf("Auditing failed of %v request: %v", reflect.TypeOf(obj).Name(), err)
@@ -164,7 +172,8 @@ func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.Gr
}
// LogRequestPatch fills in the given patch as the request object into an audit event.
func LogRequestPatch(ae *auditinternal.Event, patch []byte) {
func LogRequestPatch(ctx context.Context, patch []byte) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelRequest) {
return
}
@@ -177,22 +186,36 @@ func LogRequestPatch(ae *auditinternal.Event, patch []byte) {
// LogResponseObject fills in the response object into an audit event. The passed runtime.Object
// will be converted to the given gv.
func LogResponseObject(ae *auditinternal.Event, obj runtime.Object, gv schema.GroupVersion, s runtime.NegotiatedSerializer) {
func LogResponseObject(ctx context.Context, obj runtime.Object, gv schema.GroupVersion, s runtime.NegotiatedSerializer) {
ae := AuditEventFrom(ctx)
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
return
}
if status, ok := obj.(*metav1.Status); ok {
// selectively copy the bounded fields.
ae.ResponseStatus = &metav1.Status{
Status: status.Status,
Reason: status.Reason,
Code: status.Code,
Status: status.Status,
Message: status.Message,
Reason: status.Reason,
Details: status.Details,
Code: status.Code,
}
}
if ae.Level.Less(auditinternal.LevelRequestResponse) {
return
}
if shouldOmitManagedFields(ctx) {
copy, ok, err := copyWithoutManagedFields(obj)
if err != nil {
klog.Warningf("error while dropping managed fields from the response for %q error: %v", reflect.TypeOf(obj).Name(), err)
}
if ok {
obj = copy
}
}
// TODO(audit): hook into the serializer to avoid double conversion
var err error
ae.ResponseObject, err = encodeObject(obj, gv, s)
@@ -216,25 +239,10 @@ func encodeObject(obj runtime.Object, gv schema.GroupVersion, serializer runtime
return &runtime.Unknown{
Raw: buf.Bytes(),
ContentType: runtime.ContentTypeJSON,
ContentType: mediaType,
}, nil
}
// LogAnnotation fills in the Annotations according to the key value pair.
func LogAnnotation(ae *auditinternal.Event, key, value string) {
if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
return
}
if ae.Annotations == nil {
ae.Annotations = make(map[string]string)
}
if v, ok := ae.Annotations[key]; ok && v != value {
klog.Warningf("Failed to set annotations[%q] to %q for audit:%q, it has already been set to %q", key, value, ae.AuditID, ae.Annotations[key])
return
}
ae.Annotations[key] = value
}
// truncate User-Agent if too long, otherwise return it directly.
func maybeTruncateUserAgent(req *http.Request) string {
ua := req.UserAgent()
@@ -244,3 +252,72 @@ func maybeTruncateUserAgent(req *http.Request) string {
return ua
}
// copyWithoutManagedFields will make a deep copy of the specified object and
// will discard the managed fields from the copy.
// The specified object is expected to be a meta.Object or a "list".
// The specified object obj is treated as readonly and hence not mutated.
// On return, an error is set if the function runs into any error while
// removing the managed fields, the boolean value is true if the copy has
// been made successfully, otherwise false.
func copyWithoutManagedFields(obj runtime.Object) (runtime.Object, bool, error) {
isAccessor := true
if _, err := meta.Accessor(obj); err != nil {
isAccessor = false
}
isList := meta.IsListType(obj)
_, isTable := obj.(*metav1.Table)
if !isAccessor && !isList && !isTable {
return nil, false, nil
}
// TODO a deep copy isn't really needed here, figure out how we can reliably
// use shallow copy here to omit the manageFields.
copy := obj.DeepCopyObject()
if isAccessor {
if err := removeManagedFields(copy); err != nil {
return nil, false, err
}
}
if isList {
if err := meta.EachListItem(copy, removeManagedFields); err != nil {
return nil, false, err
}
}
if isTable {
table := copy.(*metav1.Table)
for i := range table.Rows {
rowObj := table.Rows[i].Object
if err := removeManagedFields(rowObj.Object); err != nil {
return nil, false, err
}
}
}
return copy, true, nil
}
func removeManagedFields(obj runtime.Object) error {
if obj == nil {
return nil
}
accessor, err := meta.Accessor(obj)
if err != nil {
return err
}
accessor.SetManagedFields(nil)
return nil
}
func shouldOmitManagedFields(ctx context.Context) bool {
if auditContext := AuditContextFrom(ctx); auditContext != nil {
return auditContext.RequestAuditConfig.OmitManagedFields
}
// If we can't decide, return false to maintain current behavior which is
// to retain the manage fields in the audit.
return false
}

View File

@@ -25,8 +25,6 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/apis/audit/v1"
"k8s.io/apiserver/pkg/apis/audit/v1alpha1"
"k8s.io/apiserver/pkg/apis/audit/v1beta1"
)
var Scheme = runtime.NewScheme()
@@ -35,8 +33,6 @@ var Codecs = serializer.NewCodecFactory(Scheme)
func init() {
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(v1.AddToScheme(Scheme))
utilruntime.Must(v1alpha1.AddToScheme(Scheme))
utilruntime.Must(v1beta1.AddToScheme(Scheme))
utilruntime.Must(auditinternal.AddToScheme(Scheme))
utilruntime.Must(Scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion))
utilruntime.Must(Scheme.SetVersionPriority(v1.SchemeGroupVersion))
}

View File

@@ -48,6 +48,7 @@ func (u union) ProcessEvents(events ...*auditinternal.Event) bool {
func (u union) Run(stopCh <-chan struct{}) error {
var funcs []func() error
for _, backend := range u.backends {
backend := backend
funcs = append(funcs, func() error {
return backend.Run(stopCh)
})