vendor dependencies

This commit is contained in:
Sergiusz Urbaniak 2019-04-24 11:06:03 +02:00
parent 604208ef4f
commit 72abf135d6
1156 changed files with 78178 additions and 105799 deletions

View file

@ -34,6 +34,7 @@ type attributesRecord struct {
resource schema.GroupVersionResource
subresource string
operation Operation
dryRun bool
object runtime.Object
oldObject runtime.Object
userInfo user.Info
@ -44,7 +45,7 @@ type attributesRecord struct {
annotationsLock sync.RWMutex
}
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 NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, dryRun bool, userInfo user.Info) Attributes {
return &attributesRecord{
kind: kind,
namespace: namespace,
@ -52,6 +53,7 @@ func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind s
resource: resource,
subresource: subresource,
operation: operation,
dryRun: dryRun,
object: object,
oldObject: oldObject,
userInfo: userInfo,
@ -82,6 +84,10 @@ func (record *attributesRecord) GetOperation() Operation {
return record.operation
}
func (record *attributesRecord) IsDryRun() bool {
return record.dryRun
}
func (record *attributesRecord) GetObject() runtime.Object {
return record.object
}

View file

@ -44,7 +44,7 @@ func WithAudit(i Interface, ae *auditinternal.Event) Interface {
return &auditHandler{i, ae}
}
func (handler auditHandler) Admit(a Attributes) error {
func (handler auditHandler) Admit(a Attributes, o ObjectInterfaces) error {
if !handler.Interface.Handles(a.GetOperation()) {
return nil
}
@ -53,13 +53,13 @@ func (handler auditHandler) Admit(a Attributes) error {
}
var err error
if mutator, ok := handler.Interface.(MutationInterface); ok {
err = mutator.Admit(a)
err = mutator.Admit(a, o)
handler.logAnnotations(a)
}
return err
}
func (handler auditHandler) Validate(a Attributes) error {
func (handler auditHandler) Validate(a Attributes, o ObjectInterfaces) error {
if !handler.Interface.Handles(a.GetOperation()) {
return nil
}
@ -68,7 +68,7 @@ func (handler auditHandler) Validate(a Attributes) error {
}
var err error
if validator, ok := handler.Interface.(ValidationInterface); ok {
err = validator.Validate(a)
err = validator.Validate(a, o)
handler.logAnnotations(a)
}
return err

View file

@ -26,13 +26,13 @@ func NewChainHandler(handlers ...Interface) chainAdmissionHandler {
}
// Admit performs an admission control check using a chain of handlers, and returns immediately on first error
func (admissionHandler chainAdmissionHandler) Admit(a Attributes) error {
func (admissionHandler chainAdmissionHandler) Admit(a Attributes, o ObjectInterfaces) error {
for _, handler := range admissionHandler {
if !handler.Handles(a.GetOperation()) {
continue
}
if mutator, ok := handler.(MutationInterface); ok {
err := mutator.Admit(a)
err := mutator.Admit(a, o)
if err != nil {
return err
}
@ -42,13 +42,13 @@ func (admissionHandler chainAdmissionHandler) Admit(a Attributes) error {
}
// Validate performs an admission control check using a chain of handlers, and returns immediately on first error
func (admissionHandler chainAdmissionHandler) Validate(a Attributes) error {
func (admissionHandler chainAdmissionHandler) Validate(a Attributes, o ObjectInterfaces) error {
for _, handler := range admissionHandler {
if !handler.Handles(a.GetOperation()) {
continue
}
if validator, ok := handler.(ValidationInterface); ok {
err := validator.Validate(a)
err := validator.Validate(a, o)
if err != nil {
return err
}

View file

@ -25,8 +25,8 @@ import (
"path"
"path/filepath"
"github.com/ghodss/yaml"
"github.com/golang/glog"
"k8s.io/klog"
"sigs.k8s.io/yaml"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
@ -87,7 +87,6 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string, con
}
return configProvider{
config: decodedConfig,
scheme: configScheme,
}, nil
}
// we got an error where the decode wasn't related to a missing type
@ -127,13 +126,11 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string, con
}
return configProvider{
config: internalConfig,
scheme: configScheme,
}, nil
}
type configProvider struct {
config *apiserver.AdmissionConfiguration
scheme *runtime.Scheme
}
// GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration.
@ -146,7 +143,7 @@ func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfi
if pluginCfg.Path != "" {
content, err := ioutil.ReadFile(pluginCfg.Path)
if err != nil {
glog.Fatalf("Couldn't open admission plugin configuration %s: %#v", pluginCfg.Path, err)
klog.Fatalf("Couldn't open admission plugin configuration %s: %#v", pluginCfg.Path, err)
return nil, err
}
return bytes.NewBuffer(content), nil

View file

@ -1,88 +0,0 @@
/*
Copyright 2017 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 configuration
import (
"fmt"
"reflect"
"sort"
"github.com/golang/glog"
"k8s.io/api/admissionregistration/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
type InitializerConfigurationLister interface {
List(opts metav1.ListOptions) (*v1alpha1.InitializerConfigurationList, error)
}
type InitializerConfigurationManager struct {
*poller
}
func NewInitializerConfigurationManager(c InitializerConfigurationLister) *InitializerConfigurationManager {
getFn := func() (runtime.Object, error) {
list, err := c.List(metav1.ListOptions{})
if err != nil {
if errors.IsNotFound(err) || errors.IsForbidden(err) {
glog.V(5).Infof("Initializers are disabled due to an error: %v", err)
return nil, ErrDisabled
}
return nil, err
}
return mergeInitializerConfigurations(list), nil
}
return &InitializerConfigurationManager{
newPoller(getFn),
}
}
// Initializers returns the merged InitializerConfiguration.
func (im *InitializerConfigurationManager) Initializers() (*v1alpha1.InitializerConfiguration, error) {
configuration, err := im.poller.configuration()
if err != nil {
return nil, err
}
initializerConfiguration, ok := configuration.(*v1alpha1.InitializerConfiguration)
if !ok {
return nil, fmt.Errorf("expected type %v, got type %v", reflect.TypeOf(initializerConfiguration), reflect.TypeOf(configuration))
}
return initializerConfiguration, nil
}
func (im *InitializerConfigurationManager) Run(stopCh <-chan struct{}) {
im.poller.Run(stopCh)
}
func mergeInitializerConfigurations(initializerConfigurationList *v1alpha1.InitializerConfigurationList) *v1alpha1.InitializerConfiguration {
configurations := initializerConfigurationList.Items
sort.SliceStable(configurations, InitializerConfigurationSorter(configurations).ByName)
var ret v1alpha1.InitializerConfiguration
for _, c := range configurations {
ret.Initializers = append(ret.Initializers, c.Initializers...)
}
return &ret
}
type InitializerConfigurationSorter []v1alpha1.InitializerConfiguration
func (a InitializerConfigurationSorter) ByName(i, j int) bool {
return a[i].Name < a[j].Name
}

View file

@ -17,7 +17,6 @@ limitations under the License.
package initializer
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/client-go/informers"
@ -28,7 +27,6 @@ type pluginInitializer struct {
externalClient kubernetes.Interface
externalInformers informers.SharedInformerFactory
authorizer authorizer.Authorizer
scheme *runtime.Scheme
}
// New creates an instance of admission plugins initializer.
@ -37,13 +35,11 @@ func New(
extClientset kubernetes.Interface,
extInformers informers.SharedInformerFactory,
authz authorizer.Authorizer,
scheme *runtime.Scheme,
) pluginInitializer {
return pluginInitializer{
externalClient: extClientset,
externalInformers: extInformers,
authorizer: authz,
scheme: scheme,
}
}
@ -61,10 +57,6 @@ func (i pluginInitializer) Initialize(plugin admission.Interface) {
if wants, ok := plugin.(WantsAuthorizer); ok {
wants.SetAuthorizer(i.authorizer)
}
if wants, ok := plugin.(WantsScheme); ok {
wants.SetScheme(i.scheme)
}
}
var _ admission.PluginInitializer = pluginInitializer{}

View file

@ -17,7 +17,6 @@ limitations under the License.
package initializer
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/client-go/informers"
@ -41,9 +40,3 @@ type WantsAuthorizer interface {
SetAuthorizer(authorizer.Authorizer)
admission.InitializationValidator
}
// WantsScheme defines a function that accepts runtime.Scheme for admission plugins that need it.
type WantsScheme interface {
SetScheme(*runtime.Scheme)
admission.InitializationValidator
}

View file

@ -41,6 +41,11 @@ type Attributes interface {
GetSubresource() string
// GetOperation is the operation being performed
GetOperation() Operation
// IsDryRun indicates that modifications will definitely not be persisted for this request. This is to prevent
// admission controllers with side effects and a method of reconciliation from being overwhelmed.
// However, a value of false for this does not mean that the modification will be persisted, because it
// could still be rejected by a subsequent validation step.
IsDryRun() bool
// GetObject is the object from the incoming request prior to default values being applied
GetObject() runtime.Object
// GetOldObject is the existing object. Only populated for UPDATE requests.
@ -57,6 +62,20 @@ type Attributes interface {
AddAnnotation(key, value string) error
}
// ObjectInterfaces is an interface used by AdmissionController to get object interfaces
// such as Converter or Defaulter. These interfaces are normally coming from Request Scope
// to handle special cases like CRDs.
type ObjectInterfaces interface {
// GetObjectCreater is the ObjectCreator appropriate for the requested object.
GetObjectCreater() runtime.ObjectCreater
// GetObjectTyper is the ObjectTyper appropriate for the requested object.
GetObjectTyper() runtime.ObjectTyper
// GetObjectDefaulter is the ObjectDefaulter appropriate for the requested object.
GetObjectDefaulter() runtime.ObjectDefaulter
// GetObjectConvertor is the ObjectConvertor appropriate for the requested object.
GetObjectConvertor() runtime.ObjectConvertor
}
// privateAnnotationsGetter is a private interface which allows users to get annotations from Attributes.
type privateAnnotationsGetter interface {
getAnnotations() map[string]string
@ -79,7 +98,7 @@ type MutationInterface interface {
Interface
// Admit makes an admission decision based on the request attributes
Admit(a Attributes) (err error)
Admit(a Attributes, o ObjectInterfaces) (err error)
}
// ValidationInterface is an abstract, pluggable interface for Admission Control decisions.
@ -87,7 +106,7 @@ type ValidationInterface interface {
Interface
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate
Validate(a Attributes) (err error)
Validate(a Attributes, o ObjectInterfaces) (err error)
}
// Operation is the type of resource operation being checked for admission control

View file

@ -75,27 +75,27 @@ type pluginHandlerWithMetrics struct {
}
// Admit performs a mutating admission control check and emit metrics.
func (p pluginHandlerWithMetrics) Admit(a admission.Attributes) error {
func (p pluginHandlerWithMetrics) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
mutatingHandler, ok := p.Interface.(admission.MutationInterface)
if !ok {
return nil
}
start := time.Now()
err := mutatingHandler.Admit(a)
err := mutatingHandler.Admit(a, o)
p.observer(time.Since(start), err != nil, a, stepAdmit, p.extraLabels...)
return err
}
// Validate performs a non-mutating admission control check and emits metrics.
func (p pluginHandlerWithMetrics) Validate(a admission.Attributes) error {
func (p pluginHandlerWithMetrics) Validate(a admission.Attributes, o admission.ObjectInterfaces) error {
validatingHandler, ok := p.Interface.(admission.ValidationInterface)
if !ok {
return nil
}
start := time.Now()
err := validatingHandler.Validate(a)
err := validatingHandler.Validate(a, o)
p.observer(time.Since(start), err != nil, a, stepValidate, p.extraLabels...)
return err
}
@ -112,17 +112,17 @@ func newAdmissionMetrics() *AdmissionMetrics {
// Admission metrics for a step of the admission flow. The entire admission flow is broken down into a series of steps
// Each step is identified by a distinct type label value.
step := newMetricSet("step",
[]string{"type", "operation", "group", "version", "resource", "subresource", "rejected"},
[]string{"type", "operation", "rejected"},
"Admission sub-step %s, broken out for each operation and API resource and step type (validate or admit).", true)
// Built-in admission controller metrics. Each admission controller is identified by name.
controller := newMetricSet("controller",
[]string{"name", "type", "operation", "group", "version", "resource", "subresource", "rejected"},
[]string{"name", "type", "operation", "rejected"},
"Admission controller %s, identified by name and broken out for each operation and API resource and type (validate or admit).", false)
// Admission webhook metrics. Each webhook is identified by name.
webhook := newMetricSet("webhook",
[]string{"name", "type", "operation", "group", "version", "resource", "subresource", "rejected"},
[]string{"name", "type", "operation", "rejected"},
"Admission webhook %s, identified by name and broken out for each operation and API resource and type (validate or admit).", false)
step.mustRegister()
@ -139,36 +139,45 @@ func (m *AdmissionMetrics) reset() {
// ObserveAdmissionStep records admission related metrics for a admission step, identified by step type.
func (m *AdmissionMetrics) ObserveAdmissionStep(elapsed time.Duration, rejected bool, attr admission.Attributes, stepType string, extraLabels ...string) {
gvr := attr.GetResource()
m.step.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), gvr.Group, gvr.Version, gvr.Resource, attr.GetSubresource(), strconv.FormatBool(rejected))...)
m.step.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), strconv.FormatBool(rejected))...)
}
// ObserveAdmissionController records admission related metrics for a built-in admission controller, identified by it's plugin handler name.
func (m *AdmissionMetrics) ObserveAdmissionController(elapsed time.Duration, rejected bool, attr admission.Attributes, stepType string, extraLabels ...string) {
gvr := attr.GetResource()
m.controller.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), gvr.Group, gvr.Version, gvr.Resource, attr.GetSubresource(), strconv.FormatBool(rejected))...)
m.controller.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), strconv.FormatBool(rejected))...)
}
// ObserveWebhook records admission related metrics for a admission webhook.
func (m *AdmissionMetrics) ObserveWebhook(elapsed time.Duration, rejected bool, attr admission.Attributes, stepType string, extraLabels ...string) {
gvr := attr.GetResource()
m.webhook.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), gvr.Group, gvr.Version, gvr.Resource, attr.GetSubresource(), strconv.FormatBool(rejected))...)
m.webhook.observe(elapsed, append(extraLabels, stepType, string(attr.GetOperation()), strconv.FormatBool(rejected))...)
}
type metricSet struct {
latencies *prometheus.HistogramVec
latenciesSummary *prometheus.SummaryVec
latencies *prometheus.HistogramVec
deprecatedLatencies *prometheus.HistogramVec
latenciesSummary *prometheus.SummaryVec
deprecatedLatenciesSummary *prometheus.SummaryVec
}
func newMetricSet(name string, labels []string, helpTemplate string, hasSummary bool) *metricSet {
var summary *prometheus.SummaryVec
var summary, deprecatedSummary *prometheus.SummaryVec
if hasSummary {
summary = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: fmt.Sprintf("%s_admission_latencies_seconds_summary", name),
Help: fmt.Sprintf(helpTemplate, "latency summary"),
Name: fmt.Sprintf("%s_admission_duration_seconds_summary", name),
Help: fmt.Sprintf(helpTemplate, "latency summary in seconds"),
MaxAge: latencySummaryMaxAge,
},
labels,
)
deprecatedSummary = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: fmt.Sprintf("%s_admission_latencies_milliseconds_summary", name),
Help: fmt.Sprintf("(Deprecated) "+helpTemplate, "latency summary in milliseconds"),
MaxAge: latencySummaryMaxAge,
},
labels,
@ -180,38 +189,62 @@ func newMetricSet(name string, labels []string, helpTemplate string, hasSummary
prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: fmt.Sprintf("%s_admission_latencies_seconds", name),
Help: fmt.Sprintf(helpTemplate, "latency histogram"),
Name: fmt.Sprintf("%s_admission_duration_seconds", name),
Help: fmt.Sprintf(helpTemplate, "latency histogram in seconds"),
Buckets: latencyBuckets,
},
labels,
),
deprecatedLatencies: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: fmt.Sprintf("%s_admission_latencies_milliseconds", name),
Help: fmt.Sprintf("(Deprecated) "+helpTemplate, "latency histogram in milliseconds"),
Buckets: latencyBuckets,
},
labels,
),
latenciesSummary: summary,
latenciesSummary: summary,
deprecatedLatenciesSummary: deprecatedSummary,
}
}
// MustRegister registers all the prometheus metrics in the metricSet.
func (m *metricSet) mustRegister() {
prometheus.MustRegister(m.latencies)
prometheus.MustRegister(m.deprecatedLatencies)
if m.latenciesSummary != nil {
prometheus.MustRegister(m.latenciesSummary)
}
if m.deprecatedLatenciesSummary != nil {
prometheus.MustRegister(m.deprecatedLatenciesSummary)
}
}
// Reset resets all the prometheus metrics in the metricSet.
func (m *metricSet) reset() {
m.latencies.Reset()
m.deprecatedLatencies.Reset()
if m.latenciesSummary != nil {
m.latenciesSummary.Reset()
}
if m.deprecatedLatenciesSummary != nil {
m.deprecatedLatenciesSummary.Reset()
}
}
// Observe records an observed admission event to all metrics in the metricSet.
func (m *metricSet) observe(elapsed time.Duration, labels ...string) {
elapsedSeconds := elapsed.Seconds()
elapsedMicroseconds := float64(elapsed / time.Microsecond)
m.latencies.WithLabelValues(labels...).Observe(elapsedMicroseconds)
m.latencies.WithLabelValues(labels...).Observe(elapsedSeconds)
m.deprecatedLatencies.WithLabelValues(labels...).Observe(elapsedMicroseconds)
if m.latenciesSummary != nil {
m.latenciesSummary.WithLabelValues(labels...).Observe(elapsedMicroseconds)
m.latenciesSummary.WithLabelValues(labels...).Observe(elapsedSeconds)
}
if m.deprecatedLatenciesSummary != nil {
m.deprecatedLatenciesSummary.WithLabelValues(labels...).Observe(elapsedMicroseconds)
}
}

View file

@ -1,368 +0,0 @@
/*
Copyright 2017 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 initialization
import (
"fmt"
"io"
"strings"
"github.com/golang/glog"
"k8s.io/api/admissionregistration/v1alpha1"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/validation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/configuration"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes"
)
const (
// Name of admission plug-in
PluginName = "Initializers"
)
// Register registers a plugin
func Register(plugins *admission.Plugins) {
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
return NewInitializer(), nil
})
}
type initializerOptions struct {
Initializers []string
}
type InitializationConfig interface {
Run(stopCh <-chan struct{})
Initializers() (*v1alpha1.InitializerConfiguration, error)
}
type initializer struct {
config InitializationConfig
authorizer authorizer.Authorizer
}
// NewInitializer creates a new initializer plugin which assigns newly created resources initializers
// based on configuration loaded from the admission API group.
// FUTURE: this may be moved to the storage layer of the apiserver, but for now this is an alpha feature
// that can be disabled.
func NewInitializer() admission.Interface {
return &initializer{}
}
// ValidateInitialization implements the InitializationValidator interface.
func (i *initializer) ValidateInitialization() error {
if i.config == nil {
return fmt.Errorf("the Initializer admission plugin requires a Kubernetes client to be provided")
}
if i.authorizer == nil {
return fmt.Errorf("the Initializer admission plugin requires an authorizer to be provided")
}
if !utilfeature.DefaultFeatureGate.Enabled(features.Initializers) {
if err := utilfeature.DefaultFeatureGate.Set(string(features.Initializers) + "=true"); err != nil {
glog.Errorf("error enabling Initializers feature as part of admission plugin setup: %v", err)
} else {
glog.Infof("enabled Initializers feature as part of admission plugin setup")
}
}
i.config.Run(wait.NeverStop)
return nil
}
// SetExternalKubeClientSet implements the WantsExternalKubeClientSet interface.
func (i *initializer) SetExternalKubeClientSet(client clientset.Interface) {
i.config = configuration.NewInitializerConfigurationManager(client.AdmissionregistrationV1alpha1().InitializerConfigurations())
}
// SetAuthorizer implements the WantsAuthorizer interface.
func (i *initializer) SetAuthorizer(a authorizer.Authorizer) {
i.authorizer = a
}
var initializerFieldPath = field.NewPath("metadata", "initializers")
// readConfig holds requests instead of failing them if the server is not yet initialized
// or is unresponsive. It formats the returned error for client use if necessary.
func (i *initializer) readConfig(a admission.Attributes) (*v1alpha1.InitializerConfiguration, error) {
// read initializers from config
config, err := i.config.Initializers()
if err == nil {
return config, nil
}
// if initializer configuration is disabled, fail open
if err == configuration.ErrDisabled {
return &v1alpha1.InitializerConfiguration{}, nil
}
e := errors.NewServerTimeout(a.GetResource().GroupResource(), "create", 1)
if err == configuration.ErrNotReady {
e.ErrStatus.Message = fmt.Sprintf("Waiting for initialization configuration to load: %v", err)
e.ErrStatus.Reason = "LoadingConfiguration"
e.ErrStatus.Details.Causes = append(e.ErrStatus.Details.Causes, metav1.StatusCause{
Type: "InitializerConfigurationPending",
Message: "The server is waiting for the initializer configuration to be loaded.",
})
} else {
e.ErrStatus.Message = fmt.Sprintf("Unable to refresh the initializer configuration: %v", err)
e.ErrStatus.Reason = "LoadingConfiguration"
e.ErrStatus.Details.Causes = append(e.ErrStatus.Details.Causes, metav1.StatusCause{
Type: "InitializerConfigurationFailure",
Message: "An error has occurred while refreshing the initializer configuration, no resources can be created until a refresh succeeds.",
})
}
return nil, e
}
// Admit checks for create requests to add initializers, or update request to enforce invariants.
// The admission controller fails open if the object doesn't have ObjectMeta (can't be initialized).
// A client with sufficient permission ("initialize" verb on resource) can specify its own initializers
// or an empty initializers struct (which bypasses initialization). Only clients with the initialize verb
// can update objects that have not completed initialization. Sub resources can still be modified on
// resources that are undergoing initialization.
// TODO: once this logic is ready for beta, move it into the REST storage layer.
func (i *initializer) Admit(a admission.Attributes) (err error) {
switch a.GetOperation() {
case admission.Create, admission.Update:
default:
return nil
}
// TODO: should sub-resource action should be denied until the object is initialized?
if len(a.GetSubresource()) > 0 {
return nil
}
switch a.GetOperation() {
case admission.Create:
accessor, err := meta.Accessor(a.GetObject())
if err != nil {
// objects without meta accessor cannot be checked for initialization, and it is possible to make calls
// via our API that don't have ObjectMeta
return nil
}
existing := accessor.GetInitializers()
if existing != nil {
glog.V(5).Infof("Admin bypassing initialization for %s", a.GetResource())
// it must be possible for some users to bypass initialization - for now, check the initialize operation
if err := i.canInitialize(a, "create with initializers denied"); err != nil {
return err
}
// allow administrators to bypass initialization by setting an empty initializers struct
if len(existing.Pending) == 0 && existing.Result == nil {
accessor.SetInitializers(nil)
return nil
}
} else {
glog.V(5).Infof("Checking initialization for %s", a.GetResource())
config, err := i.readConfig(a)
if err != nil {
return err
}
// Mirror pods are exempt from initialization because they are created and initialized
// on the Kubelet before they appear in the API.
// TODO: once this moves to REST storage layer, this becomes a pod specific concern
if a.GetKind().GroupKind() == v1.SchemeGroupVersion.WithKind("Pod").GroupKind() {
accessor, err := meta.Accessor(a.GetObject())
if err != nil {
return err
}
annotations := accessor.GetAnnotations()
if _, isMirror := annotations[v1.MirrorPodAnnotationKey]; isMirror {
return nil
}
}
names := findInitializers(config, a.GetResource())
if len(names) == 0 {
glog.V(5).Infof("No initializers needed")
return nil
}
glog.V(5).Infof("Found initializers for %s: %v", a.GetResource(), names)
accessor.SetInitializers(newInitializers(names))
}
case admission.Update:
accessor, err := meta.Accessor(a.GetObject())
if err != nil {
// objects without meta accessor cannot be checked for initialization, and it is possible to make calls
// via our API that don't have ObjectMeta
return nil
}
updated := accessor.GetInitializers()
// controllers deployed with an empty initializers.pending have their initializers set to nil
// but should be able to update without changing their manifest
if updated != nil && len(updated.Pending) == 0 && updated.Result == nil {
accessor.SetInitializers(nil)
updated = nil
}
existingAccessor, err := meta.Accessor(a.GetOldObject())
if err != nil {
// if the old object does not have an accessor, but the new one does, error out
return fmt.Errorf("initialized resources must be able to set initializers (%T): %v", a.GetOldObject(), err)
}
existing := existingAccessor.GetInitializers()
// updates on initialized resources are allowed
if updated == nil && existing == nil {
return nil
}
glog.V(5).Infof("Modifying uninitialized resource %s", a.GetResource())
// because we are called before validation, we need to ensure the update transition is valid.
if errs := validation.ValidateInitializersUpdate(updated, existing, initializerFieldPath); len(errs) > 0 {
return errors.NewInvalid(a.GetKind().GroupKind(), a.GetName(), errs)
}
// caller must have the ability to mutate un-initialized resources
if err := i.canInitialize(a, "update to uninitialized resource denied"); err != nil {
return err
}
// TODO: restrict initialization list changes to specific clients?
}
return nil
}
func (i *initializer) canInitialize(a admission.Attributes, message string) error {
// caller must have the ability to mutate un-initialized resources
decision, reason, err := i.authorizer.Authorize(authorizer.AttributesRecord{
Name: a.GetName(),
ResourceRequest: true,
User: a.GetUserInfo(),
Verb: "initialize",
Namespace: a.GetNamespace(),
APIGroup: a.GetResource().Group,
APIVersion: a.GetResource().Version,
Resource: a.GetResource().Resource,
})
if err != nil {
return err
}
if decision != authorizer.DecisionAllow {
return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("%s: %s", message, reason))
}
return nil
}
// Handles returns true if this admission controller can handle the given operation
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
func (i *initializer) Handles(op admission.Operation) bool {
return op == admission.Create || op == admission.Update
}
// newInitializers populates an Initializers struct.
func newInitializers(names []string) *metav1.Initializers {
if len(names) == 0 {
return nil
}
var init []metav1.Initializer
for _, name := range names {
init = append(init, metav1.Initializer{Name: name})
}
return &metav1.Initializers{
Pending: init,
}
}
// findInitializers returns the list of initializer names that apply to a config. It returns an empty list
// if no initializers apply.
func findInitializers(initializers *v1alpha1.InitializerConfiguration, gvr schema.GroupVersionResource) []string {
var names []string
for _, init := range initializers.Initializers {
if !matchRule(init.Rules, gvr) {
continue
}
names = append(names, init.Name)
}
return names
}
// matchRule returns true if any rule matches the provided group version resource.
func matchRule(rules []v1alpha1.Rule, gvr schema.GroupVersionResource) bool {
for _, rule := range rules {
if !hasGroup(rule.APIGroups, gvr.Group) {
return false
}
if !hasVersion(rule.APIVersions, gvr.Version) {
return false
}
if !hasResource(rule.Resources, gvr.Resource) {
return false
}
}
return len(rules) > 0
}
func hasGroup(groups []string, group string) bool {
if groups[0] == "*" {
return true
}
for _, g := range groups {
if g == group {
return true
}
}
return false
}
func hasVersion(versions []string, version string) bool {
if versions[0] == "*" {
return true
}
for _, v := range versions {
if v == version {
return true
}
}
return false
}
func hasResource(resources []string, resource string) bool {
if resources[0] == "*" || resources[0] == "*/*" {
return true
}
for _, r := range resources {
if strings.Contains(r, "/") {
continue
}
if r == resource {
return true
}
}
return false
}

View file

@ -21,7 +21,7 @@ import (
"io"
"time"
"github.com/golang/glog"
"k8s.io/klog"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
@ -38,7 +38,7 @@ import (
)
const (
// Name of admission plug-in
// PluginName indicates the name of admission plug-in
PluginName = "NamespaceLifecycle"
// how long a namespace stays in the force live lookup cache before expiration.
forceLiveLookupTTL = 30 * time.Second
@ -72,7 +72,8 @@ type Lifecycle struct {
var _ = initializer.WantsExternalKubeInformerFactory(&Lifecycle{})
var _ = initializer.WantsExternalKubeClientSet(&Lifecycle{})
func (l *Lifecycle) Admit(a admission.Attributes) error {
// Admit makes an admission decision based on the request attributes
func (l *Lifecycle) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
// prevent deletion of immortal namespaces
if a.GetOperation() == admission.Delete && a.GetKind().GroupKind() == v1.SchemeGroupVersion.WithKind("Namespace").GroupKind() && l.immortalNamespaces.Has(a.GetName()) {
return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
@ -138,7 +139,7 @@ func (l *Lifecycle) Admit(a admission.Attributes) error {
exists = true
}
if exists {
glog.V(4).Infof("found %s in cache after waiting", a.GetNamespace())
klog.V(4).Infof("found %s in cache after waiting", a.GetNamespace())
}
}
@ -159,7 +160,7 @@ func (l *Lifecycle) Admit(a admission.Attributes) error {
case err != nil:
return errors.NewInternalError(err)
}
glog.V(4).Infof("found %s via storage lookup", a.GetNamespace())
klog.V(4).Infof("found %s via storage lookup", a.GetNamespace())
}
// ensure that we're not trying to create objects in terminating namespaces

View file

@ -17,7 +17,7 @@ limitations under the License.
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
// +k8s:defaulter-gen=TypeMeta
// +groupName=apiserver.config.k8s.io
// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=apiserver.config.k8s.io
package v1alpha1

View file

@ -32,11 +32,18 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission,
Convert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission,
)
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*WebhookAdmission)(nil), (*webhookadmission.WebhookAdmission)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission(a.(*WebhookAdmission), b.(*webhookadmission.WebhookAdmission), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*webhookadmission.WebhookAdmission)(nil), (*WebhookAdmission)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission(a.(*webhookadmission.WebhookAdmission), b.(*WebhookAdmission), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission(in *WebhookAdmission, out *webhookadmission.WebhookAdmission, s conversion.Scope) error {

View file

@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
@ -35,8 +36,8 @@ var (
)
func init() {
webhookadmission.AddToScheme(scheme)
v1alpha1.AddToScheme(scheme)
utilruntime.Must(webhookadmission.AddToScheme(scheme))
utilruntime.Must(v1alpha1.AddToScheme(scheme))
}
// LoadConfig extract the KubeConfigFile from configFile

View file

@ -45,3 +45,9 @@ func ToStatusErr(webhookName string, result *metav1.Status) *apierrors.StatusErr
ErrStatus: *result,
}
}
// NewDryRunUnsupportedErr returns a StatusError with information about the webhook plugin
func NewDryRunUnsupportedErr(webhookName string) *apierrors.StatusError {
reason := fmt.Sprintf("admission webhook %q does not support dry run", webhookName)
return apierrors.NewBadRequest(reason)
}

View file

@ -17,39 +17,27 @@ limitations under the License.
package generic
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
)
// convertor converts objects to the desired version.
type convertor struct {
Scheme *runtime.Scheme
}
// ConvertToGVK converts object to the desired gvk.
func (c *convertor) ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind) (runtime.Object, error) {
func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o admission.ObjectInterfaces) (runtime.Object, error) {
// Unlike other resources, custom resources do not have internal version, so
// if obj is a custom resource, it should not need conversion.
if obj.GetObjectKind().GroupVersionKind() == gvk {
return obj, nil
}
out, err := c.Scheme.New(gvk)
out, err := o.GetObjectCreater().New(gvk)
if err != nil {
return nil, err
}
err = c.Scheme.Convert(obj, out, nil)
err = o.GetObjectConvertor().Convert(obj, out, nil)
if err != nil {
return nil, err
}
// Explicitly set the GVK
out.GetObjectKind().SetGroupVersionKind(gvk)
return out, nil
}
// Validate checks if the conversion has a scheme.
func (c *convertor) Validate() error {
if c.Scheme == nil {
return fmt.Errorf("the convertor requires a scheme")
}
return nil
}

View file

@ -41,5 +41,5 @@ type VersionedAttributes struct {
// Dispatcher dispatches webhook call to a list of webhooks with admission attributes as argument.
type Dispatcher interface {
// Dispatch a request to the webhooks using the given webhooks. A non-nil error means the request is rejected.
Dispatch(ctx context.Context, a *VersionedAttributes, hooks []*v1beta1.Webhook) error
Dispatch(ctx context.Context, a *VersionedAttributes, o admission.ObjectInterfaces, hooks []*v1beta1.Webhook) error
}

View file

@ -21,14 +21,15 @@ import (
"fmt"
"io"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/rules"
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
)
@ -40,8 +41,7 @@ type Webhook struct {
sourceFactory sourceFactory
hookSource Source
clientManager *config.ClientManager
convertor *convertor
clientManager *webhook.ClientManager
namespaceMatcher *namespace.Matcher
dispatcher Dispatcher
}
@ -52,7 +52,7 @@ var (
)
type sourceFactory func(f informers.SharedInformerFactory) Source
type dispatcherFactory func(cm *config.ClientManager) Dispatcher
type dispatcherFactory func(cm *webhook.ClientManager) Dispatcher
// NewWebhook creates a new generic admission webhook.
func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory sourceFactory, dispatcherFactory dispatcherFactory) (*Webhook, error) {
@ -61,23 +61,22 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
return nil, err
}
cm, err := config.NewClientManager()
cm, err := webhook.NewClientManager(admissionv1beta1.SchemeGroupVersion, admissionv1beta1.AddToScheme)
if err != nil {
return nil, err
}
authInfoResolver, err := config.NewDefaultAuthenticationInfoResolver(kubeconfigFile)
authInfoResolver, err := webhook.NewDefaultAuthenticationInfoResolver(kubeconfigFile)
if err != nil {
return nil, err
}
// Set defaults which may be overridden later.
cm.SetAuthenticationInfoResolver(authInfoResolver)
cm.SetServiceResolver(config.NewDefaultServiceResolver())
cm.SetServiceResolver(webhook.NewDefaultServiceResolver())
return &Webhook{
Handler: handler,
sourceFactory: sourceFactory,
clientManager: &cm,
convertor: &convertor{},
namespaceMatcher: &namespace.Matcher{},
dispatcher: dispatcherFactory(&cm),
}, nil
@ -86,23 +85,16 @@ func NewWebhook(handler *admission.Handler, configFile io.Reader, sourceFactory
// SetAuthenticationInfoResolverWrapper sets the
// AuthenticationInfoResolverWrapper.
// TODO find a better way wire this, but keep this pull small for now.
func (a *Webhook) SetAuthenticationInfoResolverWrapper(wrapper config.AuthenticationInfoResolverWrapper) {
func (a *Webhook) SetAuthenticationInfoResolverWrapper(wrapper webhook.AuthenticationInfoResolverWrapper) {
a.clientManager.SetAuthenticationInfoResolverWrapper(wrapper)
}
// SetServiceResolver sets a service resolver for the webhook admission plugin.
// Passing a nil resolver does not have an effect, instead a default one will be used.
func (a *Webhook) SetServiceResolver(sr config.ServiceResolver) {
func (a *Webhook) SetServiceResolver(sr webhook.ServiceResolver) {
a.clientManager.SetServiceResolver(sr)
}
// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
func (a *Webhook) SetScheme(scheme *runtime.Scheme) {
if scheme != nil {
a.convertor.Scheme = scheme
}
}
// SetExternalKubeClientSet implements the WantsExternalKubeInformerFactory interface.
// It sets external ClientSet for admission plugins that need it
func (a *Webhook) SetExternalKubeClientSet(client clientset.Interface) {
@ -130,9 +122,6 @@ func (a *Webhook) ValidateInitialization() error {
if err := a.clientManager.Validate(); err != nil {
return fmt.Errorf("clientManager is not properly setup: %v", err)
}
if err := a.convertor.Validate(); err != nil {
return fmt.Errorf("convertor is not properly setup: %v", err)
}
return nil
}
@ -154,7 +143,7 @@ func (a *Webhook) ShouldCallHook(h *v1beta1.Webhook, attr admission.Attributes)
}
// Dispatch is called by the downstream Validate or Admit methods.
func (a *Webhook) Dispatch(attr admission.Attributes) error {
func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfaces) error {
if rules.IsWebhookConfigurationResource(attr) {
return nil
}
@ -162,6 +151,7 @@ func (a *Webhook) Dispatch(attr admission.Attributes) error {
return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request"))
}
hooks := a.hookSource.Webhooks()
// TODO: Figure out if adding one second timeout make sense here.
ctx := context.TODO()
var relevantHooks []*v1beta1.Webhook
@ -185,18 +175,18 @@ func (a *Webhook) Dispatch(attr admission.Attributes) error {
Attributes: attr,
}
if oldObj := attr.GetOldObject(); oldObj != nil {
out, err := a.convertor.ConvertToGVK(oldObj, attr.GetKind())
out, err := ConvertToGVK(oldObj, attr.GetKind(), o)
if err != nil {
return apierrors.NewInternalError(err)
}
versionedAttr.VersionedOldObject = out
}
if obj := attr.GetObject(); obj != nil {
out, err := a.convertor.ConvertToGVK(obj, attr.GetKind())
out, err := ConvertToGVK(obj, attr.GetKind(), o)
if err != nil {
return apierrors.NewInternalError(err)
}
versionedAttr.VersionedObject = out
}
return a.dispatcher.Dispatch(ctx, &versionedAttr, relevantHooks)
return a.dispatcher.Dispatch(ctx, &versionedAttr, o, relevantHooks)
}

View file

@ -24,77 +24,106 @@ import (
"time"
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
"k8s.io/klog"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/util/webhook"
)
type mutatingDispatcher struct {
cm *config.ClientManager
cm *webhook.ClientManager
plugin *Plugin
}
func newMutatingDispatcher(p *Plugin) func(cm *config.ClientManager) generic.Dispatcher {
return func(cm *config.ClientManager) generic.Dispatcher {
func newMutatingDispatcher(p *Plugin) func(cm *webhook.ClientManager) generic.Dispatcher {
return func(cm *webhook.ClientManager) generic.Dispatcher {
return &mutatingDispatcher{cm, p}
}
}
var _ generic.Dispatcher = &mutatingDispatcher{}
func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error {
func (a *mutatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error {
for _, hook := range relevantHooks {
t := time.Now()
err := a.callAttrMutatingHook(ctx, hook, attr)
err := a.callAttrMutatingHook(ctx, hook, attr, o)
admissionmetrics.Metrics.ObserveWebhook(time.Since(t), err != nil, attr.Attributes, "admit", hook.Name)
if err == nil {
continue
}
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok {
if callErr, ok := err.(*webhook.ErrCallingWebhook); ok {
if ignoreClientCallFailures {
glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
utilruntime.HandleError(callErr)
continue
}
glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err)
klog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err)
}
return apierrors.NewInternalError(err)
}
// convert attr.VersionedObject to the internal version in the underlying admission.Attributes
if attr.VersionedObject != nil {
return a.plugin.scheme.Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil)
return o.GetObjectConvertor().Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil)
}
return nil
}
// note that callAttrMutatingHook updates attr
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes, o admission.ObjectInterfaces) error {
if attr.IsDryRun() {
if h.SideEffects == nil {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
}
if !(*h.SideEffects == v1beta1.SideEffectClassNone || *h.SideEffects == v1beta1.SideEffectClassNoneOnDryRun) {
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
}
}
// Currently dispatcher only supports `v1beta1` AdmissionReview
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
if !util.HasAdmissionReviewVersion(v1beta1.SchemeGroupVersion.Version, h) {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("webhook does not accept v1beta1 AdmissionReview")}
}
// Make the webhook request
request := request.CreateAdmissionReview(attr)
client, err := a.cm.HookClient(h)
client, err := a.cm.HookClient(util.HookClientConfigForWebhook(h))
if err != nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
}
response := &admissionv1beta1.AdmissionReview{}
if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
r := client.Post().Context(ctx).Body(&request)
if h.TimeoutSeconds != nil {
r = r.Timeout(time.Duration(*h.TimeoutSeconds) * time.Second)
}
if err := r.Do().Into(response); err != nil {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
}
if response.Response == nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
}
for k, v := range response.Response.AuditAnnotations {
key := h.Name + "/" + k
if err := attr.AddAnnotation(key, v); err != nil {
klog.Warningf("Failed to set admission audit annotation %s to %s for mutating webhook %s: %v", key, v, h.Name, err)
}
}
if !response.Response.Allowed {
@ -118,7 +147,8 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
return apierrors.NewInternalError(fmt.Errorf("admission webhook %q attempted to modify the object, which is not supported for this operation", h.Name))
}
objJS, err := runtime.Encode(a.plugin.jsonSerializer, attr.VersionedObject)
jsonSerializer := json.NewSerializer(json.DefaultMetaFactory, o.GetObjectCreater(), o.GetObjectTyper(), false)
objJS, err := runtime.Encode(jsonSerializer, attr.VersionedObject)
if err != nil {
return apierrors.NewInternalError(err)
}
@ -133,17 +163,17 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
// They are represented as Unstructured.
newVersionedObject = &unstructured.Unstructured{}
} else {
newVersionedObject, err = a.plugin.scheme.New(attr.GetKind())
newVersionedObject, err = o.GetObjectCreater().New(attr.GetKind())
if err != nil {
return apierrors.NewInternalError(err)
}
}
// TODO: if we have multiple mutating webhooks, we can remember the json
// instead of encoding and decoding for each one.
if _, _, err := a.plugin.jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil {
if _, _, err := jsonSerializer.Decode(patchedJS, nil, newVersionedObject); err != nil {
return apierrors.NewInternalError(err)
}
attr.VersionedObject = newVersionedObject
a.plugin.scheme.Default(attr.VersionedObject)
o.GetObjectDefaulter().Default(attr.VersionedObject)
return nil
}

View file

@ -17,18 +17,15 @@ limitations under the License.
package mutating
import (
"fmt"
"io"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/configuration"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
)
const (
// Name of admission plug-in
// PluginName indicates the name of admission plug-in
PluginName = "MutatingAdmissionWebhook"
)
@ -47,9 +44,6 @@ func Register(plugins *admission.Plugins) {
// Plugin is an implementation of admission.Interface.
type Plugin struct {
*generic.Webhook
scheme *runtime.Scheme
jsonSerializer *json.Serializer
}
var _ admission.MutationInterface = &Plugin{}
@ -67,30 +61,15 @@ func NewMutatingWebhook(configFile io.Reader) (*Plugin, error) {
return p, nil
}
// SetScheme sets a serializer(NegotiatedSerializer) which is derived from the scheme
func (a *Plugin) SetScheme(scheme *runtime.Scheme) {
a.Webhook.SetScheme(scheme)
if scheme != nil {
a.scheme = scheme
a.jsonSerializer = json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false)
}
}
// ValidateInitialization implements the InitializationValidator interface.
func (a *Plugin) ValidateInitialization() error {
if err := a.Webhook.ValidateInitialization(); err != nil {
return err
}
if a.scheme == nil {
return fmt.Errorf("scheme is not properly setup")
}
if a.jsonSerializer == nil {
return fmt.Errorf("jsonSerializer is not properly setup")
}
return nil
}
// Admit makes an admission decision based on the request attributes.
func (a *Plugin) Admit(attr admission.Attributes) error {
return a.Webhook.Dispatch(attr)
func (a *Plugin) Admit(attr admission.Attributes, o admission.ObjectInterfaces) error {
return a.Webhook.Dispatch(attr, o)
}

View file

@ -36,6 +36,7 @@ func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.A
UID: aUserInfo.GetUID(),
Username: aUserInfo.GetName(),
}
dryRun := attr.IsDryRun()
// Convert the extra information in the user object
for key, val := range aUserInfo.GetExtra() {
@ -66,6 +67,7 @@ func CreateAdmissionReview(attr *generic.VersionedAttributes) admissionv1beta1.A
OldObject: runtime.RawExtension{
Object: attr.VersionedOldObject,
},
DryRun: &dryRun,
},
}
}

View file

@ -20,6 +20,8 @@ import (
"strings"
"k8s.io/api/admissionregistration/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
)
@ -31,7 +33,8 @@ type Matcher struct {
// Matches returns if the Attr matches the Rule.
func (r *Matcher) Matches() bool {
return r.operation() &&
return r.scope() &&
r.operation() &&
r.group() &&
r.version() &&
r.resource()
@ -50,6 +53,25 @@ func exactOrWildcard(items []string, requested string) bool {
return false
}
var namespaceResource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}
func (r *Matcher) scope() bool {
if r.Rule.Scope == nil || *r.Rule.Scope == v1beta1.AllScopes {
return true
}
// attr.GetNamespace() is set to the name of the namespace for requests of the namespace object itself.
switch *r.Rule.Scope {
case v1beta1.NamespacedScope:
// first make sure that we are not requesting a namespace object (namespace objects are cluster-scoped)
return r.Attr.GetResource() != namespaceResource && r.Attr.GetNamespace() != metav1.NamespaceNone
case v1beta1.ClusterScope:
// also return true if the request is for a namespace object (namespace objects are cluster-scoped)
return r.Attr.GetResource() == namespaceResource || r.Attr.GetNamespace() == metav1.NamespaceNone
default:
return false
}
}
func (r *Matcher) group() bool {
return exactOrWildcard(r.Rule.APIGroups, r.Attr.GetResource().Group)
}

View file

@ -0,0 +1,52 @@
/*
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 util
import (
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apiserver/pkg/util/webhook"
)
// HookClientConfigForWebhook construct a webhook.ClientConfig using a v1beta1.Webhook API object.
// webhook.ClientConfig is used to create a HookClient and the purpose of the config struct is to
// share that with other packages that need to create a HookClient.
func HookClientConfigForWebhook(w *v1beta1.Webhook) webhook.ClientConfig {
ret := webhook.ClientConfig{Name: w.Name, CABundle: w.ClientConfig.CABundle}
if w.ClientConfig.URL != nil {
ret.URL = *w.ClientConfig.URL
}
if w.ClientConfig.Service != nil {
ret.Service = &webhook.ClientConfigService{
Name: w.ClientConfig.Service.Name,
Namespace: w.ClientConfig.Service.Namespace,
}
if w.ClientConfig.Service.Path != nil {
ret.Service.Path = *w.ClientConfig.Service.Path
}
}
return ret
}
// HasAdmissionReviewVersion check whether a version is accepted by a given webhook.
func HasAdmissionReviewVersion(a string, w *v1beta1.Webhook) bool {
for _, b := range w.AdmissionReviewVersions {
if b == a {
return true
}
}
return false
}

View file

@ -22,30 +22,32 @@ import (
"sync"
"time"
"github.com/golang/glog"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/klog"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
"k8s.io/apiserver/pkg/admission/plugin/webhook/util"
"k8s.io/apiserver/pkg/util/webhook"
)
type validatingDispatcher struct {
cm *config.ClientManager
cm *webhook.ClientManager
}
func newValidatingDispatcher(cm *config.ClientManager) generic.Dispatcher {
func newValidatingDispatcher(cm *webhook.ClientManager) generic.Dispatcher {
return &validatingDispatcher{cm}
}
var _ generic.Dispatcher = &validatingDispatcher{}
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, relevantHooks []*v1beta1.Webhook) error {
func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.VersionedAttributes, o admission.ObjectInterfaces, relevantHooks []*v1beta1.Webhook) error {
wg := sync.WaitGroup{}
errCh := make(chan error, len(relevantHooks))
wg.Add(len(relevantHooks))
@ -61,19 +63,19 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.Versi
}
ignoreClientCallFailures := hook.FailurePolicy != nil && *hook.FailurePolicy == v1beta1.Ignore
if callErr, ok := err.(*webhookerrors.ErrCallingWebhook); ok {
if callErr, ok := err.(*webhook.ErrCallingWebhook); ok {
if ignoreClientCallFailures {
glog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
klog.Warningf("Failed calling webhook, failing open %v: %v", hook.Name, callErr)
utilruntime.HandleError(callErr)
return
}
glog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err)
klog.Warningf("Failed calling webhook, failing closed %v: %v", hook.Name, err)
errCh <- apierrors.NewInternalError(err)
return
}
glog.Warningf("rejected by webhook %q: %#v", hook.Name, err)
klog.Warningf("rejected by webhook %q: %#v", hook.Name, err)
errCh <- err
}(relevantHooks[i])
}
@ -97,19 +99,44 @@ func (d *validatingDispatcher) Dispatch(ctx context.Context, attr *generic.Versi
}
func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Webhook, attr *generic.VersionedAttributes) error {
if attr.IsDryRun() {
if h.SideEffects == nil {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook SideEffects is nil")}
}
if !(*h.SideEffects == v1beta1.SideEffectClassNone || *h.SideEffects == v1beta1.SideEffectClassNoneOnDryRun) {
return webhookerrors.NewDryRunUnsupportedErr(h.Name)
}
}
// Currently dispatcher only supports `v1beta1` AdmissionReview
// TODO: Make the dispatcher capable of sending multiple AdmissionReview versions
if !util.HasAdmissionReviewVersion(v1beta1.SchemeGroupVersion.Version, h) {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("webhook does not accept v1beta1 AdmissionReviewRequest")}
}
// Make the webhook request
request := request.CreateAdmissionReview(attr)
client, err := d.cm.HookClient(h)
client, err := d.cm.HookClient(util.HookClientConfigForWebhook(h))
if err != nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
}
response := &admissionv1beta1.AdmissionReview{}
if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
r := client.Post().Context(ctx).Body(&request)
if h.TimeoutSeconds != nil {
r = r.Timeout(time.Duration(*h.TimeoutSeconds) * time.Second)
}
if err := r.Do().Into(response); err != nil {
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: err}
}
if response.Response == nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
return &webhook.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
}
for k, v := range response.Response.AuditAnnotations {
key := h.Name + "/" + k
if err := attr.AddAnnotation(key, v); err != nil {
klog.Warningf("Failed to set admission audit annotation %s to %s for validating webhook %s: %v", key, v, h.Name, err)
}
}
if response.Response.Allowed {
return nil

View file

@ -25,7 +25,7 @@ import (
)
const (
// Name of admission plug-in
// PluginName indicates the name of admission plug-in
PluginName = "ValidatingAdmissionWebhook"
)
@ -59,6 +59,6 @@ func NewValidatingAdmissionWebhook(configFile io.Reader) (*Plugin, error) {
}
// Validate makes an admission decision based on the request attributes.
func (a *Plugin) Validate(attr admission.Attributes) error {
return a.Webhook.Dispatch(attr)
func (a *Plugin) Validate(attr admission.Attributes, o admission.ObjectInterfaces) error {
return a.Webhook.Dispatch(attr, o)
}

View file

@ -26,7 +26,7 @@ import (
"strings"
"sync"
"github.com/golang/glog"
"k8s.io/klog"
)
// Factory is a function that returns an Interface for admission decisions.
@ -75,13 +75,13 @@ func (ps *Plugins) Register(name string, plugin Factory) {
if ps.registry != nil {
_, found := ps.registry[name]
if found {
glog.Fatalf("Admission plugin %q was registered twice", name)
klog.Fatalf("Admission plugin %q was registered twice", name)
}
} else {
ps.registry = map[string]Factory{}
}
glog.V(1).Infof("Registered admission plugin %q", name)
klog.V(1).Infof("Registered admission plugin %q", name)
ps.registry[name] = plugin
}
@ -155,10 +155,10 @@ func (ps *Plugins) NewFromPlugins(pluginNames []string, configProvider ConfigPro
}
}
if len(mutationPlugins) != 0 {
glog.Infof("Loaded %d mutating admission controller(s) successfully in the following order: %s.", len(mutationPlugins), strings.Join(mutationPlugins, ","))
klog.Infof("Loaded %d mutating admission controller(s) successfully in the following order: %s.", len(mutationPlugins), strings.Join(mutationPlugins, ","))
}
if len(validationPlugins) != 0 {
glog.Infof("Loaded %d validating admission controller(s) successfully in the following order: %s.", len(validationPlugins), strings.Join(validationPlugins, ","))
klog.Infof("Loaded %d validating admission controller(s) successfully in the following order: %s.", len(validationPlugins), strings.Join(validationPlugins, ","))
}
return chainAdmissionHandler(handlers), nil
}
@ -166,7 +166,7 @@ func (ps *Plugins) NewFromPlugins(pluginNames []string, configProvider ConfigPro
// InitPlugin creates an instance of the named interface.
func (ps *Plugins) InitPlugin(name string, config io.Reader, pluginInitializer PluginInitializer) (Interface, error) {
if name == "" {
glog.Info("No admission plugin specified.")
klog.Info("No admission plugin specified.")
return nil, nil
}

28
vendor/k8s.io/apiserver/pkg/admission/util.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
/*
Copyright 2019 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 admission
import "k8s.io/apimachinery/pkg/runtime"
type SchemeBasedObjectInterfaces struct {
Scheme *runtime.Scheme
}
func (r *SchemeBasedObjectInterfaces) GetObjectCreater() runtime.ObjectCreater { return r.Scheme }
func (r *SchemeBasedObjectInterfaces) GetObjectTyper() runtime.ObjectTyper { return r.Scheme }
func (r *SchemeBasedObjectInterfaces) GetObjectDefaulter() runtime.ObjectDefaulter { return r.Scheme }
func (r *SchemeBasedObjectInterfaces) GetObjectConvertor() runtime.ObjectConvertor { return r.Scheme }

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
// +k8s:deepcopy-gen=package
// +groupName=apiserver.k8s.io
// Package apiserver is the internal version of the API.
// +groupName=apiserver.k8s.io
package apiserver // import "k8s.io/apiserver/pkg/apis/apiserver"

View file

@ -17,7 +17,7 @@ limitations under the License.
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/apis/apiserver
// +k8s:defaulter-gen=TypeMeta
// +groupName=apiserver.k8s.io
// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=apiserver.k8s.io
package v1alpha1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"

View file

@ -34,13 +34,28 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration,
Convert_apiserver_AdmissionConfiguration_To_v1alpha1_AdmissionConfiguration,
Convert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginConfiguration,
Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration,
)
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*AdmissionConfiguration)(nil), (*apiserver.AdmissionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(a.(*AdmissionConfiguration), b.(*apiserver.AdmissionConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AdmissionConfiguration)(nil), (*AdmissionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AdmissionConfiguration_To_v1alpha1_AdmissionConfiguration(a.(*apiserver.AdmissionConfiguration), b.(*AdmissionConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AdmissionPluginConfiguration)(nil), (*apiserver.AdmissionPluginConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_AdmissionPluginConfiguration_To_apiserver_AdmissionPluginConfiguration(a.(*AdmissionPluginConfiguration), b.(*apiserver.AdmissionPluginConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AdmissionPluginConfiguration)(nil), (*AdmissionPluginConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration(a.(*apiserver.AdmissionPluginConfiguration), b.(*AdmissionPluginConfiguration), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(in *AdmissionConfiguration, out *apiserver.AdmissionConfiguration, s conversion.Scope) error {

View file

@ -61,12 +61,8 @@ func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfigu
*out = *in
if in.Configuration != nil {
in, out := &in.Configuration, &out.Configuration
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
return
}

View file

@ -61,12 +61,8 @@ func (in *AdmissionPluginConfiguration) DeepCopyInto(out *AdmissionPluginConfigu
*out = *in
if in.Configuration != nil {
in, out := &in.Configuration, &out.Configuration
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
return
}

9
vendor/k8s.io/apiserver/pkg/apis/audit/OWNERS generated vendored Normal file
View file

@ -0,0 +1,9 @@
# See the OWNERS docs at https://go.k8s.io/owners
# approval on api packages bubbles to api-approvers
reviewers:
- sig-auth-audit-approvers
- sig-auth-audit-reviewers
labels:
- sig/auth

View file

@ -16,4 +16,5 @@ limitations under the License.
// +k8s:deepcopy-gen=package
// +groupName=audit.k8s.io
package audit // import "k8s.io/apiserver/pkg/apis/audit"

View file

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"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"
)
@ -29,7 +30,8 @@ import (
// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
utilruntime.Must(audit.AddToScheme(scheme))
utilruntime.Must(v1.AddToScheme(scheme))
utilruntime.Must(v1beta1.AddToScheme(scheme))
utilruntime.Must(v1alpha1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion))
utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion))
}

View file

@ -99,6 +99,10 @@ type Event struct {
// Source IPs, from where the request originated and intermediate proxies.
// +optional
SourceIPs []string
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
UserAgent string
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
@ -128,9 +132,10 @@ type Event struct {
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Keys should uniquely identify the informing component to avoid name
// collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values should be short. Annotations
// are included in the Metadata level.
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
Annotations map[string]string
}

View file

@ -14,28 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package flag
// +k8s:deepcopy-gen=package
// +k8s:protobuf-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/apis/audit
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
import (
goflag "flag"
"github.com/spf13/pflag"
)
// +groupName=audit.k8s.io
// NoOp implements goflag.Value and plfag.Value,
// but has a noop Set implementation
type NoOp struct{}
var _ goflag.Value = NoOp{}
var _ pflag.Value = NoOp{}
func (NoOp) String() string {
return ""
}
func (NoOp) Set(val string) error {
return nil
}
func (NoOp) Type() string {
return "NoOp"
}
package v1 // import "k8s.io/apiserver/pkg/apis/audit/v1"

2835
vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.pb.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,249 @@
/*
Copyright 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.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.apiserver.pkg.apis.audit.v1;
import "k8s.io/api/authentication/v1/generated.proto";
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1";
// Event captures all the information that can be included in an API audit log.
message Event {
// AuditLevel at which event was generated
optional string level = 1;
// Unique audit ID, generated for each request.
optional string auditID = 2;
// Stage of the request handling when this event instance was generated.
optional string stage = 3;
// RequestURI is the request URI as sent by the client to a server.
optional string requestURI = 4;
// Verb is the kubernetes verb associated with the request.
// For non-resource requests, this is the lower-cased HTTP method.
optional string verb = 5;
// Authenticated user information.
optional k8s.io.api.authentication.v1.UserInfo user = 6;
// Impersonated user information.
// +optional
optional k8s.io.api.authentication.v1.UserInfo impersonatedUser = 7;
// Source IPs, from where the request originated and intermediate proxies.
// +optional
repeated string sourceIPs = 8;
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
optional string userAgent = 16;
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
optional ObjectReference objectRef = 9;
// The response status, populated even when the ResponseObject is not a Status type.
// For successful responses, this will only include the Code and StatusSuccess.
// For non-status type error responses, this will be auto-populated with the error Message.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.Status responseStatus = 10;
// API object from the request, in JSON format. The RequestObject is recorded as-is in the request
// (possibly re-encoded as JSON), prior to version conversion, defaulting, admission or
// merging. It is an external versioned object type, and may not be a valid object on its own.
// Omitted for non-resource requests. Only logged at Request Level and higher.
// +optional
optional k8s.io.apimachinery.pkg.runtime.Unknown requestObject = 11;
// API object returned in the response, in JSON. The ResponseObject is recorded after conversion
// to the external type, and serialized as JSON. Omitted for non-resource requests. Only logged
// at Response Level.
// +optional
optional k8s.io.apimachinery.pkg.runtime.Unknown responseObject = 12;
// Time the request reached the apiserver.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime requestReceivedTimestamp = 13;
// Time the request reached current audit stage.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime stageTimestamp = 14;
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
map<string, string> annotations = 15;
}
// EventList is a list of audit Events.
message EventList {
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
repeated Event items = 2;
}
// GroupResources represents resource kinds in an API group.
message GroupResources {
// Group is the name of the API group that contains the resources.
// The empty string represents the core API group.
// +optional
optional string group = 1;
// Resources is a list of resources this rule applies to.
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
// An empty list implies all resources and subresources in this API groups apply.
// +optional
repeated string resources = 2;
// ResourceNames is a list of resource instance names that the policy matches.
// Using this field requires Resources to be specified.
// An empty list implies that every instance of the resource is matched.
// +optional
repeated string resourceNames = 3;
}
// ObjectReference contains enough information to let you inspect or modify the referred object.
message ObjectReference {
// +optional
optional string resource = 1;
// +optional
optional string namespace = 2;
// +optional
optional string name = 3;
// +optional
optional string uid = 4;
// APIGroup is the name of the API group that contains the referred object.
// The empty string represents the core API group.
// +optional
optional string apiGroup = 5;
// APIVersion is the version of the API group that contains the referred object.
// +optional
optional string apiVersion = 6;
// +optional
optional string resourceVersion = 7;
// +optional
optional string subresource = 8;
}
// Policy defines the configuration of audit logging, and the rules for how different request
// categories are logged.
message Policy {
// ObjectMeta is included for interoperability with API infrastructure.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Rules specify the audit Level a request should be recorded at.
// A request may match multiple rules, in which case the FIRST matching rule is used.
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered.
repeated PolicyRule rules = 2;
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
repeated string omitStages = 3;
}
// PolicyList is a list of audit Policies.
message PolicyList {
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
repeated Policy items = 2;
}
// PolicyRule maps requests based off metadata to an audit Level.
// Requests must match the rules of every field (an intersection of rules).
message PolicyRule {
// The Level that requests matching this rule are recorded at.
optional string level = 1;
// The users (by authenticated user name) this rule applies to.
// An empty list implies every user.
// +optional
repeated string users = 2;
// The user groups this rule applies to. A user is considered matching
// if it is a member of any of the UserGroups.
// An empty list implies every user group.
// +optional
repeated string userGroups = 3;
// The verbs that match this rule.
// An empty list implies every verb.
// +optional
repeated string verbs = 4;
// Resources that this rule matches. An empty list implies all kinds in all API groups.
// +optional
repeated GroupResources resources = 5;
// Namespaces that this rule matches.
// The empty string "" matches non-namespaced resources.
// An empty list implies every namespace.
// +optional
repeated string namespaces = 6;
// NonResourceURLs is a set of URL paths that should be audited.
// *s are allowed, but only as the full, final step in the path.
// Examples:
// "/metrics" - Log requests for apiserver metrics
// "/healthz*" - Log all health checks
// +optional
repeated string nonResourceURLs = 7;
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply.
// +optional
repeated string omitStages = 8;
}

58
vendor/k8s.io/apiserver/pkg/apis/audit/v1/register.go generated vendored Normal file
View file

@ -0,0 +1,58 @@
/*
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 v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package
const GroupName = "audit.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Event{},
&EventList{},
&Policy{},
&PolicyList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

280
vendor/k8s.io/apiserver/pkg/apis/audit/v1/types.go generated vendored Normal file
View file

@ -0,0 +1,280 @@
/*
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 v1
import (
authnv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
)
// Header keys used by the audit system.
const (
// Header to hold the audit ID as the request is propagated through the serving hierarchy. The
// Audit-ID header should be set by the first server to receive the request (e.g. the federation
// server or kube-aggregator).
HeaderAuditID = "Audit-ID"
)
// Level defines the amount of information logged during auditing
type Level string
// Valid audit levels
const (
// LevelNone disables auditing
LevelNone Level = "None"
// LevelMetadata provides the basic level of auditing.
LevelMetadata Level = "Metadata"
// LevelRequest provides Metadata level of auditing, and additionally
// logs the request object (does not apply for non-resource requests).
LevelRequest Level = "Request"
// LevelRequestResponse provides Request level of auditing, and additionally
// logs the response object (does not apply for non-resource requests).
LevelRequestResponse Level = "RequestResponse"
)
// Stage defines the stages in request handling that audit events may be generated.
type Stage string
// Valid audit stages.
const (
// The stage for events generated as soon as the audit handler receives the request, and before it
// is delegated down the handler chain.
StageRequestReceived = "RequestReceived"
// The stage for events generated once the response headers are sent, but before the response body
// is sent. This stage is only generated for long-running requests (e.g. watch).
StageResponseStarted = "ResponseStarted"
// The stage for events generated once the response body has been completed, and no more bytes
// will be sent.
StageResponseComplete = "ResponseComplete"
// The stage for events generated when a panic occurred.
StagePanic = "Panic"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Event captures all the information that can be included in an API audit log.
type Event struct {
metav1.TypeMeta `json:",inline"`
// AuditLevel at which event was generated
Level Level `json:"level" protobuf:"bytes,1,opt,name=level,casttype=Level"`
// Unique audit ID, generated for each request.
AuditID types.UID `json:"auditID" protobuf:"bytes,2,opt,name=auditID,casttype=k8s.io/apimachinery/pkg/types.UID"`
// Stage of the request handling when this event instance was generated.
Stage Stage `json:"stage" protobuf:"bytes,3,opt,name=stage,casttype=Stage"`
// RequestURI is the request URI as sent by the client to a server.
RequestURI string `json:"requestURI" protobuf:"bytes,4,opt,name=requestURI"`
// Verb is the kubernetes verb associated with the request.
// For non-resource requests, this is the lower-cased HTTP method.
Verb string `json:"verb" protobuf:"bytes,5,opt,name=verb"`
// Authenticated user information.
User authnv1.UserInfo `json:"user" protobuf:"bytes,6,opt,name=user"`
// Impersonated user information.
// +optional
ImpersonatedUser *authnv1.UserInfo `json:"impersonatedUser,omitempty" protobuf:"bytes,7,opt,name=impersonatedUser"`
// Source IPs, from where the request originated and intermediate proxies.
// +optional
SourceIPs []string `json:"sourceIPs,omitempty" protobuf:"bytes,8,rep,name=sourceIPs"`
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
UserAgent string `json:"userAgent,omitempty" protobuf:"bytes,16,opt,name=userAgent"`
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
ObjectRef *ObjectReference `json:"objectRef,omitempty" protobuf:"bytes,9,opt,name=objectRef"`
// The response status, populated even when the ResponseObject is not a Status type.
// For successful responses, this will only include the Code and StatusSuccess.
// For non-status type error responses, this will be auto-populated with the error Message.
// +optional
ResponseStatus *metav1.Status `json:"responseStatus,omitempty" protobuf:"bytes,10,opt,name=responseStatus"`
// API object from the request, in JSON format. The RequestObject is recorded as-is in the request
// (possibly re-encoded as JSON), prior to version conversion, defaulting, admission or
// merging. It is an external versioned object type, and may not be a valid object on its own.
// Omitted for non-resource requests. Only logged at Request Level and higher.
// +optional
RequestObject *runtime.Unknown `json:"requestObject,omitempty" protobuf:"bytes,11,opt,name=requestObject"`
// API object returned in the response, in JSON. The ResponseObject is recorded after conversion
// to the external type, and serialized as JSON. Omitted for non-resource requests. Only logged
// at Response Level.
// +optional
ResponseObject *runtime.Unknown `json:"responseObject,omitempty" protobuf:"bytes,12,opt,name=responseObject"`
// Time the request reached the apiserver.
// +optional
RequestReceivedTimestamp metav1.MicroTime `json:"requestReceivedTimestamp" protobuf:"bytes,13,opt,name=requestReceivedTimestamp"`
// Time the request reached current audit stage.
// +optional
StageTimestamp metav1.MicroTime `json:"stageTimestamp" protobuf:"bytes,14,opt,name=stageTimestamp"`
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,15,rep,name=annotations"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// EventList is a list of audit Events.
type EventList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []Event `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Policy defines the configuration of audit logging, and the rules for how different request
// categories are logged.
type Policy struct {
metav1.TypeMeta `json:",inline"`
// ObjectMeta is included for interoperability with API infrastructure.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Rules specify the audit Level a request should be recorded at.
// A request may match multiple rules, in which case the FIRST matching rule is used.
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered.
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,3,rep,name=omitStages"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// PolicyList is a list of audit Policies.
type PolicyList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []Policy `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// PolicyRule maps requests based off metadata to an audit Level.
// Requests must match the rules of every field (an intersection of rules).
type PolicyRule struct {
// The Level that requests matching this rule are recorded at.
Level Level `json:"level" protobuf:"bytes,1,opt,name=level,casttype=Level"`
// The users (by authenticated user name) this rule applies to.
// An empty list implies every user.
// +optional
Users []string `json:"users,omitempty" protobuf:"bytes,2,rep,name=users"`
// The user groups this rule applies to. A user is considered matching
// if it is a member of any of the UserGroups.
// An empty list implies every user group.
// +optional
UserGroups []string `json:"userGroups,omitempty" protobuf:"bytes,3,rep,name=userGroups"`
// The verbs that match this rule.
// An empty list implies every verb.
// +optional
Verbs []string `json:"verbs,omitempty" protobuf:"bytes,4,rep,name=verbs"`
// Rules can apply to API resources (such as "pods" or "secrets"),
// non-resource URL paths (such as "/api"), or neither, but not both.
// If neither is specified, the rule is treated as a default for all URLs.
// Resources that this rule matches. An empty list implies all kinds in all API groups.
// +optional
Resources []GroupResources `json:"resources,omitempty" protobuf:"bytes,5,rep,name=resources"`
// Namespaces that this rule matches.
// The empty string "" matches non-namespaced resources.
// An empty list implies every namespace.
// +optional
Namespaces []string `json:"namespaces,omitempty" protobuf:"bytes,6,rep,name=namespaces"`
// NonResourceURLs is a set of URL paths that should be audited.
// *s are allowed, but only as the full, final step in the path.
// Examples:
// "/metrics" - Log requests for apiserver metrics
// "/healthz*" - Log all health checks
// +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"`
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"`
}
// GroupResources represents resource kinds in an API group.
type GroupResources struct {
// Group is the name of the API group that contains the resources.
// The empty string represents the core API group.
// +optional
Group string `json:"group,omitempty" protobuf:"bytes,1,opt,name=group"`
// Resources is a list of resources this rule applies to.
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
// An empty list implies all resources and subresources in this API groups apply.
// +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,2,rep,name=resources"`
// ResourceNames is a list of resource instance names that the policy matches.
// Using this field requires Resources to be specified.
// An empty list implies that every instance of the resource is matched.
// +optional
ResourceNames []string `json:"resourceNames,omitempty" protobuf:"bytes,3,rep,name=resourceNames"`
}
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
// +optional
Resource string `json:"resource,omitempty" protobuf:"bytes,1,opt,name=resource"`
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,2,opt,name=namespace"`
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,3,opt,name=name"`
// +optional
UID types.UID `json:"uid,omitempty" protobuf:"bytes,4,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
// APIGroup is the name of the API group that contains the referred object.
// The empty string represents the core API group.
// +optional
APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,5,opt,name=apiGroup"`
// APIVersion is the version of the API group that contains the referred object.
// +optional
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,6,opt,name=apiVersion"`
// +optional
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,7,opt,name=resourceVersion"`
// +optional
Subresource string `json:"subresource,omitempty" protobuf:"bytes,8,opt,name=subresource"`
}

View file

@ -0,0 +1,328 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1
import (
unsafe "unsafe"
authenticationv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
types "k8s.io/apimachinery/pkg/types"
audit "k8s.io/apiserver/pkg/apis/audit"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*Event)(nil), (*audit.Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Event_To_audit_Event(a.(*Event), b.(*audit.Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Event)(nil), (*Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Event_To_v1_Event(a.(*audit.Event), b.(*Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*EventList)(nil), (*audit.EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_EventList_To_audit_EventList(a.(*EventList), b.(*audit.EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.EventList)(nil), (*EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_EventList_To_v1_EventList(a.(*audit.EventList), b.(*EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*GroupResources)(nil), (*audit.GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_GroupResources_To_audit_GroupResources(a.(*GroupResources), b.(*audit.GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.GroupResources)(nil), (*GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_GroupResources_To_v1_GroupResources(a.(*audit.GroupResources), b.(*GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ObjectReference)(nil), (*audit.ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ObjectReference_To_audit_ObjectReference(a.(*ObjectReference), b.(*audit.ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.ObjectReference)(nil), (*ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_ObjectReference_To_v1_ObjectReference(a.(*audit.ObjectReference), b.(*ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Policy)(nil), (*audit.Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Policy_To_audit_Policy(a.(*Policy), b.(*audit.Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Policy_To_v1_Policy(a.(*audit.Policy), b.(*Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyList)(nil), (*audit.PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_PolicyList_To_audit_PolicyList(a.(*PolicyList), b.(*audit.PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyList)(nil), (*PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyList_To_v1_PolicyList(a.(*audit.PolicyList), b.(*PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyRule)(nil), (*audit.PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_PolicyRule_To_audit_PolicyRule(a.(*PolicyRule), b.(*audit.PolicyRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyRule)(nil), (*PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyRule_To_v1_PolicyRule(a.(*audit.PolicyRule), b.(*PolicyRule), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1_Event_To_audit_Event(in *Event, out *audit.Event, s conversion.Scope) error {
out.Level = audit.Level(in.Level)
out.AuditID = types.UID(in.AuditID)
out.Stage = audit.Stage(in.Stage)
out.RequestURI = in.RequestURI
out.Verb = in.Verb
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.User, &out.User, 0); err != nil {
return err
}
out.ImpersonatedUser = (*audit.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
out.ObjectRef = (*audit.ObjectReference)(unsafe.Pointer(in.ObjectRef))
out.ResponseStatus = (*metav1.Status)(unsafe.Pointer(in.ResponseStatus))
out.RequestObject = (*runtime.Unknown)(unsafe.Pointer(in.RequestObject))
out.ResponseObject = (*runtime.Unknown)(unsafe.Pointer(in.ResponseObject))
out.RequestReceivedTimestamp = in.RequestReceivedTimestamp
out.StageTimestamp = in.StageTimestamp
out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations))
return nil
}
// Convert_v1_Event_To_audit_Event is an autogenerated conversion function.
func Convert_v1_Event_To_audit_Event(in *Event, out *audit.Event, s conversion.Scope) error {
return autoConvert_v1_Event_To_audit_Event(in, out, s)
}
func autoConvert_audit_Event_To_v1_Event(in *audit.Event, out *Event, s conversion.Scope) error {
out.Level = Level(in.Level)
out.AuditID = types.UID(in.AuditID)
out.Stage = Stage(in.Stage)
out.RequestURI = in.RequestURI
out.Verb = in.Verb
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.User, &out.User, 0); err != nil {
return err
}
out.ImpersonatedUser = (*authenticationv1.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
out.ObjectRef = (*ObjectReference)(unsafe.Pointer(in.ObjectRef))
out.ResponseStatus = (*metav1.Status)(unsafe.Pointer(in.ResponseStatus))
out.RequestObject = (*runtime.Unknown)(unsafe.Pointer(in.RequestObject))
out.ResponseObject = (*runtime.Unknown)(unsafe.Pointer(in.ResponseObject))
out.RequestReceivedTimestamp = in.RequestReceivedTimestamp
out.StageTimestamp = in.StageTimestamp
out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations))
return nil
}
// Convert_audit_Event_To_v1_Event is an autogenerated conversion function.
func Convert_audit_Event_To_v1_Event(in *audit.Event, out *Event, s conversion.Scope) error {
return autoConvert_audit_Event_To_v1_Event(in, out, s)
}
func autoConvert_v1_EventList_To_audit_EventList(in *EventList, out *audit.EventList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]audit.Event)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_v1_EventList_To_audit_EventList is an autogenerated conversion function.
func Convert_v1_EventList_To_audit_EventList(in *EventList, out *audit.EventList, s conversion.Scope) error {
return autoConvert_v1_EventList_To_audit_EventList(in, out, s)
}
func autoConvert_audit_EventList_To_v1_EventList(in *audit.EventList, out *EventList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]Event)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_audit_EventList_To_v1_EventList is an autogenerated conversion function.
func Convert_audit_EventList_To_v1_EventList(in *audit.EventList, out *EventList, s conversion.Scope) error {
return autoConvert_audit_EventList_To_v1_EventList(in, out, s)
}
func autoConvert_v1_GroupResources_To_audit_GroupResources(in *GroupResources, out *audit.GroupResources, s conversion.Scope) error {
out.Group = in.Group
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
out.ResourceNames = *(*[]string)(unsafe.Pointer(&in.ResourceNames))
return nil
}
// Convert_v1_GroupResources_To_audit_GroupResources is an autogenerated conversion function.
func Convert_v1_GroupResources_To_audit_GroupResources(in *GroupResources, out *audit.GroupResources, s conversion.Scope) error {
return autoConvert_v1_GroupResources_To_audit_GroupResources(in, out, s)
}
func autoConvert_audit_GroupResources_To_v1_GroupResources(in *audit.GroupResources, out *GroupResources, s conversion.Scope) error {
out.Group = in.Group
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
out.ResourceNames = *(*[]string)(unsafe.Pointer(&in.ResourceNames))
return nil
}
// Convert_audit_GroupResources_To_v1_GroupResources is an autogenerated conversion function.
func Convert_audit_GroupResources_To_v1_GroupResources(in *audit.GroupResources, out *GroupResources, s conversion.Scope) error {
return autoConvert_audit_GroupResources_To_v1_GroupResources(in, out, s)
}
func autoConvert_v1_ObjectReference_To_audit_ObjectReference(in *ObjectReference, out *audit.ObjectReference, s conversion.Scope) error {
out.Resource = in.Resource
out.Namespace = in.Namespace
out.Name = in.Name
out.UID = types.UID(in.UID)
out.APIGroup = in.APIGroup
out.APIVersion = in.APIVersion
out.ResourceVersion = in.ResourceVersion
out.Subresource = in.Subresource
return nil
}
// Convert_v1_ObjectReference_To_audit_ObjectReference is an autogenerated conversion function.
func Convert_v1_ObjectReference_To_audit_ObjectReference(in *ObjectReference, out *audit.ObjectReference, s conversion.Scope) error {
return autoConvert_v1_ObjectReference_To_audit_ObjectReference(in, out, s)
}
func autoConvert_audit_ObjectReference_To_v1_ObjectReference(in *audit.ObjectReference, out *ObjectReference, s conversion.Scope) error {
out.Resource = in.Resource
out.Namespace = in.Namespace
out.Name = in.Name
out.UID = types.UID(in.UID)
out.APIGroup = in.APIGroup
out.APIVersion = in.APIVersion
out.ResourceVersion = in.ResourceVersion
out.Subresource = in.Subresource
return nil
}
// Convert_audit_ObjectReference_To_v1_ObjectReference is an autogenerated conversion function.
func Convert_audit_ObjectReference_To_v1_ObjectReference(in *audit.ObjectReference, out *ObjectReference, s conversion.Scope) error {
return autoConvert_audit_ObjectReference_To_v1_ObjectReference(in, out, s)
}
func autoConvert_v1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]audit.PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]audit.Stage)(unsafe.Pointer(&in.OmitStages))
return nil
}
// Convert_v1_Policy_To_audit_Policy is an autogenerated conversion function.
func Convert_v1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error {
return autoConvert_v1_Policy_To_audit_Policy(in, out, s)
}
func autoConvert_audit_Policy_To_v1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]Stage)(unsafe.Pointer(&in.OmitStages))
return nil
}
// Convert_audit_Policy_To_v1_Policy is an autogenerated conversion function.
func Convert_audit_Policy_To_v1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error {
return autoConvert_audit_Policy_To_v1_Policy(in, out, s)
}
func autoConvert_v1_PolicyList_To_audit_PolicyList(in *PolicyList, out *audit.PolicyList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]audit.Policy)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_v1_PolicyList_To_audit_PolicyList is an autogenerated conversion function.
func Convert_v1_PolicyList_To_audit_PolicyList(in *PolicyList, out *audit.PolicyList, s conversion.Scope) error {
return autoConvert_v1_PolicyList_To_audit_PolicyList(in, out, s)
}
func autoConvert_audit_PolicyList_To_v1_PolicyList(in *audit.PolicyList, out *PolicyList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]Policy)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_audit_PolicyList_To_v1_PolicyList is an autogenerated conversion function.
func Convert_audit_PolicyList_To_v1_PolicyList(in *audit.PolicyList, out *PolicyList, s conversion.Scope) error {
return autoConvert_audit_PolicyList_To_v1_PolicyList(in, out, s)
}
func autoConvert_v1_PolicyRule_To_audit_PolicyRule(in *PolicyRule, out *audit.PolicyRule, s conversion.Scope) error {
out.Level = audit.Level(in.Level)
out.Users = *(*[]string)(unsafe.Pointer(&in.Users))
out.UserGroups = *(*[]string)(unsafe.Pointer(&in.UserGroups))
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
out.Resources = *(*[]audit.GroupResources)(unsafe.Pointer(&in.Resources))
out.Namespaces = *(*[]string)(unsafe.Pointer(&in.Namespaces))
out.NonResourceURLs = *(*[]string)(unsafe.Pointer(&in.NonResourceURLs))
out.OmitStages = *(*[]audit.Stage)(unsafe.Pointer(&in.OmitStages))
return nil
}
// Convert_v1_PolicyRule_To_audit_PolicyRule is an autogenerated conversion function.
func Convert_v1_PolicyRule_To_audit_PolicyRule(in *PolicyRule, out *audit.PolicyRule, s conversion.Scope) error {
return autoConvert_v1_PolicyRule_To_audit_PolicyRule(in, out, s)
}
func autoConvert_audit_PolicyRule_To_v1_PolicyRule(in *audit.PolicyRule, out *PolicyRule, s conversion.Scope) error {
out.Level = Level(in.Level)
out.Users = *(*[]string)(unsafe.Pointer(&in.Users))
out.UserGroups = *(*[]string)(unsafe.Pointer(&in.UserGroups))
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
out.Resources = *(*[]GroupResources)(unsafe.Pointer(&in.Resources))
out.Namespaces = *(*[]string)(unsafe.Pointer(&in.Namespaces))
out.NonResourceURLs = *(*[]string)(unsafe.Pointer(&in.NonResourceURLs))
out.OmitStages = *(*[]Stage)(unsafe.Pointer(&in.OmitStages))
return nil
}
// Convert_audit_PolicyRule_To_v1_PolicyRule is an autogenerated conversion function.
func Convert_audit_PolicyRule_To_v1_PolicyRule(in *audit.PolicyRule, out *PolicyRule, s conversion.Scope) error {
return autoConvert_audit_PolicyRule_To_v1_PolicyRule(in, out, s)
}

View file

@ -0,0 +1,291 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1
import (
authenticationv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Event) DeepCopyInto(out *Event) {
*out = *in
out.TypeMeta = in.TypeMeta
in.User.DeepCopyInto(&out.User)
if in.ImpersonatedUser != nil {
in, out := &in.ImpersonatedUser, &out.ImpersonatedUser
*out = new(authenticationv1.UserInfo)
(*in).DeepCopyInto(*out)
}
if in.SourceIPs != nil {
in, out := &in.SourceIPs, &out.SourceIPs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
*out = new(ObjectReference)
**out = **in
}
if in.ResponseStatus != nil {
in, out := &in.ResponseStatus, &out.ResponseStatus
*out = new(metav1.Status)
(*in).DeepCopyInto(*out)
}
if in.RequestObject != nil {
in, out := &in.RequestObject, &out.RequestObject
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
if in.ResponseObject != nil {
in, out := &in.ResponseObject, &out.ResponseObject
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
in.RequestReceivedTimestamp.DeepCopyInto(&out.RequestReceivedTimestamp)
in.StageTimestamp.DeepCopyInto(&out.StageTimestamp)
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Event.
func (in *Event) DeepCopy() *Event {
if in == nil {
return nil
}
out := new(Event)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Event) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EventList) DeepCopyInto(out *EventList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Event, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventList.
func (in *EventList) DeepCopy() *EventList {
if in == nil {
return nil
}
out := new(EventList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *EventList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GroupResources) DeepCopyInto(out *GroupResources) {
*out = *in
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ResourceNames != nil {
in, out := &in.ResourceNames, &out.ResourceNames
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupResources.
func (in *GroupResources) DeepCopy() *GroupResources {
if in == nil {
return nil
}
out := new(GroupResources)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectReference) DeepCopyInto(out *ObjectReference) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference.
func (in *ObjectReference) DeepCopy() *ObjectReference {
if in == nil {
return nil
}
out := new(ObjectReference)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Policy) DeepCopyInto(out *Policy) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]PolicyRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.OmitStages != nil {
in, out := &in.OmitStages, &out.OmitStages
*out = make([]Stage, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy.
func (in *Policy) DeepCopy() *Policy {
if in == nil {
return nil
}
out := new(Policy)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Policy) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyList) DeepCopyInto(out *PolicyList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Policy, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyList.
func (in *PolicyList) DeepCopy() *PolicyList {
if in == nil {
return nil
}
out := new(PolicyList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PolicyList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyRule) DeepCopyInto(out *PolicyRule) {
*out = *in
if in.Users != nil {
in, out := &in.Users, &out.Users
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.UserGroups != nil {
in, out := &in.UserGroups, &out.UserGroups
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Verbs != nil {
in, out := &in.Verbs, &out.Verbs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = make([]GroupResources, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Namespaces != nil {
in, out := &in.Namespaces, &out.Namespaces
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NonResourceURLs != nil {
in, out := &in.NonResourceURLs, &out.NonResourceURLs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.OmitStages != nil {
in, out := &in.OmitStages, &out.OmitStages
*out = make([]Stage, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyRule.
func (in *PolicyRule) DeepCopy() *PolicyRule {
if in == nil {
return nil
}
out := new(PolicyRule)
in.DeepCopyInto(out)
return out
}

View file

@ -0,0 +1,32 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
return nil
}

View file

@ -15,9 +15,11 @@ limitations under the License.
*/
// +k8s:deepcopy-gen=package
// +k8s:protobuf-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/apis/audit
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +groupName=audit.k8s.io
package v1alpha1 // import "k8s.io/apiserver/pkg/apis/audit/v1alpha1"

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1/generated.proto
// DO NOT EDIT!
/*
Package v1alpha1 is a generated protocol buffer package.
@ -266,6 +265,12 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) {
i += copy(dAtA[i:], v)
}
}
dAtA[i] = 0x92
i++
dAtA[i] = 0x1
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.UserAgent)))
i += copy(dAtA[i:], m.UserAgent)
return i, nil
}
@ -620,24 +625,6 @@ func (m *PolicyRule) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
@ -704,6 +691,8 @@ func (m *Event) Size() (n int) {
n += mapEntrySize + 2 + sovGenerated(uint64(mapEntrySize))
}
}
l = len(m.UserAgent)
n += 2 + l + sovGenerated(uint64(l))
return n
}
@ -890,6 +879,7 @@ func (this *Event) String() string {
`RequestReceivedTimestamp:` + strings.Replace(strings.Replace(this.RequestReceivedTimestamp.String(), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1), `&`, ``, 1) + `,`,
`StageTimestamp:` + strings.Replace(strings.Replace(this.StageTimestamp.String(), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1), `&`, ``, 1) + `,`,
`Annotations:` + mapStringForAnnotations + `,`,
`UserAgent:` + fmt.Sprintf("%v", this.UserAgent) + `,`,
`}`,
}, "")
return s
@ -1525,51 +1515,14 @@ func (m *Event) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.Annotations == nil {
m.Annotations = make(map[string]string)
}
if iNdEx < postIndex {
var valuekey uint64
var mapkey string
var mapvalue string
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
@ -1579,41 +1532,109 @@ func (m *Event) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if iNdEx >= l {
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
return io.ErrUnexpectedEOF
}
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
} else {
iNdEx = entryPreIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthGenerated
}
m.Annotations[mapkey] = mapvalue
iNdEx = postIndex
case 18:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field UserAgent", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
m.Annotations[mapkey] = mapvalue
} else {
var mapvalue string
m.Annotations[mapkey] = mapvalue
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.UserAgent = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
@ -2782,83 +2803,84 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 1242 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6f, 0x1b, 0x45,
// 1263 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
0x14, 0xcf, 0xd6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x99, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x84,
0x2c, 0x08, 0xbb, 0x49, 0x14, 0x68, 0x40, 0x02, 0x11, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x98, 0xc4,
0x95, 0xf8, 0x38, 0xb0, 0xb6, 0x5f, 0xec, 0xc5, 0xf6, 0xee, 0xb2, 0x33, 0xeb, 0x2a, 0x37, 0x0e,
0x5c, 0x91, 0xb8, 0xf3, 0xc7, 0x54, 0xdc, 0x72, 0xec, 0xb1, 0x27, 0x8b, 0x98, 0xff, 0x22, 0x87,
0x0a, 0xcd, 0xc7, 0xee, 0xac, 0x9d, 0x5a, 0x38, 0x1c, 0x7a, 0xdb, 0x79, 0xef, 0xf7, 0x7e, 0xef,
0xcd, 0xdb, 0xf7, 0x31, 0xe8, 0xdb, 0xc1, 0x01, 0xb5, 0x5c, 0xdf, 0x1e, 0x44, 0x6d, 0x08, 0x3d,
0x60, 0x40, 0xed, 0x31, 0x78, 0x5d, 0x3f, 0xb4, 0x95, 0xc2, 0x09, 0x5c, 0x0a, 0xe1, 0x18, 0x42,
0x3b, 0x18, 0xf4, 0xc4, 0xc9, 0x76, 0xa2, 0xae, 0xcb, 0xec, 0xf1, 0xae, 0x33, 0x0c, 0xfa, 0xce,
0xae, 0xdd, 0x03, 0x0f, 0x42, 0x87, 0x41, 0xd7, 0x0a, 0x42, 0x9f, 0xf9, 0xb8, 0x2e, 0x2d, 0xad,
0xc4, 0xd2, 0x0a, 0x06, 0x3d, 0x71, 0xb2, 0x84, 0xa5, 0x15, 0x5b, 0x6e, 0x7d, 0xd4, 0x73, 0x59,
0x3f, 0x6a, 0x5b, 0x1d, 0x7f, 0x64, 0xf7, 0xfc, 0x9e, 0x6f, 0x0b, 0x82, 0x76, 0x74, 0x2e, 0x4e,
0xe2, 0x20, 0xbe, 0x24, 0xf1, 0xd6, 0xb6, 0x0e, 0xc9, 0x76, 0x22, 0xd6, 0x07, 0x8f, 0xb9, 0x1d,
0x87, 0xb9, 0xbe, 0x67, 0x8f, 0x6f, 0x84, 0xb1, 0xb5, 0xaf, 0xd1, 0x23, 0xa7, 0xd3, 0x77, 0x3d,
0x08, 0x2f, 0xf4, 0x1d, 0x46, 0xc0, 0x9c, 0x37, 0x59, 0xd9, 0x8b, 0xac, 0xc2, 0xc8, 0x63, 0xee,
0x08, 0x6e, 0x18, 0x7c, 0xf2, 0x5f, 0x06, 0xb4, 0xd3, 0x87, 0x91, 0x33, 0x6f, 0x57, 0x7b, 0x5d,
0x40, 0xd9, 0x27, 0x63, 0xf0, 0x18, 0xfe, 0x09, 0xe5, 0x78, 0x34, 0x5d, 0x87, 0x39, 0xa6, 0x51,
0x35, 0xea, 0x85, 0xbd, 0x1d, 0x4b, 0xa7, 0x30, 0x21, 0xd5, 0x59, 0xe4, 0x68, 0x6b, 0xbc, 0x6b,
0x7d, 0xd3, 0xfe, 0x19, 0x3a, 0xec, 0x29, 0x30, 0xa7, 0x81, 0x2f, 0x27, 0x95, 0x95, 0xe9, 0xa4,
0x82, 0xb4, 0x8c, 0x24, 0xac, 0x78, 0x1b, 0x65, 0x87, 0x30, 0x86, 0xa1, 0x79, 0xa7, 0x6a, 0xd4,
0xf3, 0x8d, 0x77, 0x14, 0x38, 0x7b, 0xc4, 0x85, 0xd7, 0xf1, 0x07, 0x91, 0x20, 0xfc, 0x03, 0xca,
0xf3, 0xc0, 0x29, 0x73, 0x46, 0x81, 0x99, 0x11, 0x01, 0x7d, 0xb0, 0x5c, 0x40, 0x67, 0xee, 0x08,
0x1a, 0x9b, 0x8a, 0x3d, 0x7f, 0x16, 0x93, 0x10, 0xcd, 0x87, 0x8f, 0xd1, 0x9a, 0x28, 0x82, 0xe6,
0x63, 0x73, 0x55, 0x04, 0xb3, 0xaf, 0xe0, 0x6b, 0x87, 0x52, 0x7c, 0x3d, 0xa9, 0xbc, 0xbb, 0x28,
0xa5, 0xec, 0x22, 0x00, 0x6a, 0xb5, 0x9a, 0x8f, 0x49, 0x4c, 0xc2, 0xaf, 0x46, 0x99, 0xd3, 0x03,
0x33, 0x3b, 0x7b, 0xb5, 0x53, 0x2e, 0xbc, 0x8e, 0x3f, 0x88, 0x04, 0xe1, 0x3d, 0x84, 0x42, 0xf8,
0x25, 0x02, 0xca, 0x5a, 0xa4, 0x69, 0xde, 0x15, 0x26, 0x49, 0xea, 0x48, 0xa2, 0x21, 0x29, 0x14,
0xae, 0xa2, 0xd5, 0x31, 0x84, 0x6d, 0x73, 0x4d, 0xa0, 0xef, 0x29, 0xf4, 0xea, 0x33, 0x08, 0xdb,
0x44, 0x68, 0xf0, 0xd7, 0x68, 0x35, 0xa2, 0x10, 0x9a, 0x39, 0x91, 0xab, 0xf7, 0x53, 0xb9, 0xb2,
0x66, 0xcb, 0x94, 0xe7, 0xa8, 0x45, 0x21, 0x6c, 0x7a, 0xe7, 0xbe, 0x66, 0xe2, 0x12, 0x22, 0x18,
0x70, 0x1f, 0x95, 0xdc, 0x51, 0x00, 0x21, 0xf5, 0x3d, 0x5e, 0x2a, 0x5c, 0x63, 0xe6, 0x6f, 0xc5,
0xfa, 0x60, 0x3a, 0xa9, 0x94, 0x9a, 0x73, 0x1c, 0xe4, 0x06, 0x2b, 0xfe, 0x10, 0xe5, 0xa9, 0x1f,
0x85, 0x1d, 0x68, 0x9e, 0x50, 0x13, 0x55, 0x33, 0xf5, 0x7c, 0x63, 0x9d, 0xff, 0xb4, 0xd3, 0x58,
0x48, 0xb4, 0x1e, 0x9f, 0xa3, 0xbc, 0x2f, 0xea, 0x8a, 0xc0, 0xb9, 0x59, 0x10, 0xf1, 0x7c, 0x6a,
0x2d, 0xdb, 0xe5, 0xaa, 0x4c, 0x09, 0x9c, 0x43, 0x08, 0x5e, 0x07, 0xa4, 0x9f, 0x44, 0x48, 0x34,
0x35, 0xee, 0xa3, 0x62, 0x08, 0x34, 0xf0, 0x3d, 0x0a, 0xa7, 0xcc, 0x61, 0x11, 0x35, 0xef, 0x09,
0x67, 0xdb, 0xcb, 0x95, 0x9f, 0xb4, 0x69, 0xe0, 0xe9, 0xa4, 0x52, 0x24, 0x33, 0x3c, 0x64, 0x8e,
0x17, 0x3b, 0x68, 0x5d, 0xfd, 0x62, 0x19, 0x88, 0xb9, 0x2e, 0x1c, 0xd5, 0x17, 0x3a, 0x52, 0xdd,
0x6c, 0xb5, 0xbc, 0x81, 0xe7, 0x3f, 0xf7, 0x1a, 0x9b, 0xd3, 0x49, 0x65, 0x9d, 0xa4, 0x29, 0xc8,
0x2c, 0x23, 0xee, 0xea, 0xcb, 0x28, 0x1f, 0xc5, 0x5b, 0xfa, 0x98, 0xb9, 0x88, 0x72, 0x32, 0xc7,
0x89, 0x7f, 0x37, 0x90, 0xa9, 0xfc, 0x12, 0xe8, 0x80, 0x3b, 0x86, 0x6e, 0xd2, 0x77, 0xe6, 0x86,
0x70, 0x68, 0x2f, 0x97, 0xbd, 0xa7, 0x6e, 0x27, 0xf4, 0x45, 0x07, 0x57, 0x55, 0x65, 0x9a, 0x64,
0x01, 0x31, 0x59, 0xe8, 0x12, 0xfb, 0xa8, 0x28, 0x5a, 0x4d, 0x07, 0x51, 0xfa, 0x7f, 0x41, 0xc4,
0x9d, 0x5c, 0x3c, 0x9d, 0xa1, 0x23, 0x73, 0xf4, 0xf8, 0x39, 0x2a, 0x38, 0x9e, 0xe7, 0x33, 0xd1,
0x0a, 0xd4, 0xdc, 0xac, 0x66, 0xea, 0x85, 0xbd, 0x2f, 0x97, 0xaf, 0x4e, 0x31, 0x83, 0xad, 0x43,
0x4d, 0xf1, 0xc4, 0x63, 0xe1, 0x45, 0xe3, 0xbe, 0x72, 0x5f, 0x48, 0x69, 0x48, 0xda, 0xd3, 0xd6,
0x17, 0xa8, 0x34, 0x6f, 0x85, 0x4b, 0x28, 0x33, 0x80, 0x0b, 0x31, 0xc5, 0xf3, 0x84, 0x7f, 0xe2,
0x07, 0x28, 0x3b, 0x76, 0x86, 0x11, 0xc8, 0xd1, 0x4b, 0xe4, 0xe1, 0xb3, 0x3b, 0x07, 0x46, 0xed,
0x85, 0x81, 0xf2, 0xc2, 0xf9, 0x91, 0x4b, 0x19, 0xfe, 0xf1, 0xc6, 0x12, 0xb0, 0x96, 0xcb, 0x18,
0xb7, 0x16, 0x2b, 0xa0, 0xa4, 0x22, 0xce, 0xc5, 0x92, 0xd4, 0x02, 0x38, 0x43, 0x59, 0x97, 0xc1,
0x88, 0x9a, 0x77, 0x44, 0x7a, 0xec, 0x5b, 0xa6, 0xa7, 0xb1, 0x1e, 0x8f, 0xd5, 0x26, 0x67, 0x21,
0x92, 0xac, 0xf6, 0xa7, 0x81, 0x8a, 0x5f, 0x85, 0x7e, 0x14, 0x10, 0x90, 0xb3, 0x82, 0xe2, 0xf7,
0x50, 0xb6, 0xc7, 0x25, 0x32, 0x05, 0xda, 0x4e, 0xc2, 0xa4, 0x8e, 0xcf, 0x9e, 0x30, 0xb6, 0x10,
0x11, 0xa9, 0xd9, 0x93, 0xd0, 0x10, 0xad, 0xc7, 0x8f, 0x78, 0xa7, 0xca, 0xc3, 0xb1, 0x33, 0x02,
0x6a, 0x66, 0x84, 0x81, 0xea, 0xbf, 0x94, 0x82, 0xcc, 0xe2, 0x6a, 0xbf, 0x65, 0xd0, 0xc6, 0xdc,
0xe8, 0xc1, 0xdb, 0x28, 0x17, 0x83, 0x54, 0x84, 0x49, 0xd6, 0x62, 0x2e, 0x92, 0x20, 0xb0, 0x8d,
0xf2, 0x1e, 0xa7, 0x0a, 0x9c, 0x8e, 0xfa, 0x7f, 0x7a, 0xb9, 0x1d, 0xc7, 0x0a, 0xa2, 0x31, 0x7c,
0x55, 0xf0, 0x83, 0x58, 0x9a, 0xa9, 0x55, 0xc1, 0xb1, 0x44, 0x68, 0x70, 0x03, 0x65, 0x22, 0xb7,
0xab, 0x56, 0xdf, 0x8e, 0x02, 0x64, 0x5a, 0xcb, 0xae, 0x3d, 0x6e, 0xcc, 0x97, 0x98, 0x13, 0xb8,
0xcf, 0x20, 0xa4, 0xae, 0xef, 0xa9, 0xbd, 0x97, 0x2c, 0xb1, 0xc3, 0x93, 0xa6, 0xd2, 0x90, 0x14,
0x0a, 0x1f, 0xa2, 0x8d, 0xf8, 0x5a, 0xb1, 0xa1, 0xdc, 0x7e, 0x0f, 0x95, 0xe1, 0x06, 0x99, 0x55,
0x93, 0x79, 0x3c, 0xfe, 0x18, 0x15, 0x68, 0xd4, 0x4e, 0xd2, 0x27, 0xd7, 0x61, 0xd2, 0x26, 0xa7,
0x5a, 0x45, 0xd2, 0xb8, 0xda, 0x6b, 0x03, 0xdd, 0x3d, 0xf1, 0x87, 0x6e, 0xe7, 0xe2, 0x2d, 0x3c,
0x74, 0xbe, 0x43, 0xd9, 0x30, 0x1a, 0x42, 0x5c, 0xe7, 0xfb, 0xcb, 0xd7, 0xb9, 0x0c, 0x91, 0x44,
0x43, 0xd0, 0x45, 0xcb, 0x4f, 0x94, 0x48, 0x46, 0xfc, 0x08, 0x21, 0x7f, 0xe4, 0x32, 0x31, 0x8d,
0xe2, 0x22, 0x7c, 0x28, 0x02, 0x49, 0xa4, 0xfa, 0xb9, 0x91, 0x82, 0xd6, 0xfe, 0x32, 0x10, 0x92,
0xec, 0x6f, 0xa1, 0xd1, 0x5b, 0xb3, 0x8d, 0xbe, 0x73, 0xdb, 0x04, 0x2c, 0xe8, 0xf4, 0x17, 0x99,
0xf8, 0x0e, 0x3c, 0x27, 0xfa, 0x3d, 0x69, 0x2c, 0xf3, 0x9e, 0xac, 0xa0, 0x2c, 0x7f, 0xdc, 0xc4,
0xad, 0x9e, 0xe7, 0x48, 0xfe, 0x06, 0xa1, 0x44, 0xca, 0xb1, 0x85, 0x10, 0xff, 0x10, 0x33, 0x22,
0x4e, 0x6d, 0x91, 0xa7, 0xb6, 0x95, 0x48, 0x49, 0x0a, 0xc1, 0x09, 0xf9, 0xbb, 0x8b, 0x9a, 0xab,
0x9a, 0x90, 0x3f, 0xc7, 0x28, 0x91, 0x72, 0xec, 0xa6, 0x07, 0x4c, 0x56, 0x64, 0xe2, 0x60, 0xf9,
0x4c, 0xcc, 0x8e, 0x34, 0xdd, 0xf2, 0x6f, 0x1c, 0x4f, 0x16, 0x42, 0x49, 0xff, 0x53, 0xf3, 0xae,
0x8e, 0x3d, 0x19, 0x10, 0x94, 0xa4, 0x10, 0xf8, 0x73, 0xb4, 0xe1, 0xf9, 0x5e, 0x4c, 0xd5, 0x22,
0x47, 0xd4, 0x5c, 0x13, 0x46, 0xf7, 0x79, 0x13, 0x1e, 0xcf, 0xaa, 0xc8, 0x3c, 0x76, 0xae, 0x0a,
0x73, 0x4b, 0x57, 0x61, 0xc3, 0xba, 0xbc, 0x2a, 0xaf, 0xbc, 0xbc, 0x2a, 0xaf, 0xbc, 0xba, 0x2a,
0xaf, 0xfc, 0x3a, 0x2d, 0x1b, 0x97, 0xd3, 0xb2, 0xf1, 0x72, 0x5a, 0x36, 0x5e, 0x4d, 0xcb, 0xc6,
0xdf, 0xd3, 0xb2, 0xf1, 0xc7, 0x3f, 0xe5, 0x95, 0xef, 0x73, 0x71, 0x12, 0xfe, 0x0d, 0x00, 0x00,
0xff, 0xff, 0x17, 0x35, 0x5f, 0x9f, 0x18, 0x0e, 0x00, 0x00,
0x2c, 0x08, 0xbb, 0x49, 0x14, 0x68, 0x40, 0x02, 0x11, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x78, 0x89,
0x2b, 0xf1, 0xe7, 0xc0, 0xda, 0x7e, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xce, 0xac, 0xab, 0xdc, 0x38,
0x70, 0x45, 0xe2, 0xce, 0x87, 0xe0, 0x23, 0x54, 0xdc, 0x72, 0xec, 0xb1, 0x27, 0x8b, 0x98, 0x6f,
0x91, 0x03, 0x42, 0x33, 0xfb, 0x67, 0xd6, 0x4e, 0x2d, 0x1c, 0x0e, 0xbd, 0xed, 0xbc, 0xf7, 0x7b,
0xbf, 0xf7, 0xe6, 0xed, 0xfb, 0x33, 0xe4, 0xeb, 0xc1, 0x01, 0x33, 0x6c, 0xd7, 0x1c, 0x04, 0x6d,
0xf4, 0x1d, 0xe4, 0xc8, 0xcc, 0x31, 0x3a, 0x5d, 0xd7, 0x37, 0x23, 0x85, 0xe5, 0xd9, 0x0c, 0xfd,
0x31, 0xfa, 0xa6, 0x37, 0xe8, 0xc9, 0x93, 0x69, 0x05, 0x5d, 0x9b, 0x9b, 0xe3, 0x5d, 0x6b, 0xe8,
0xf5, 0xad, 0x5d, 0xb3, 0x87, 0x0e, 0xfa, 0x16, 0xc7, 0xae, 0xe1, 0xf9, 0x2e, 0x77, 0x69, 0x3d,
0xb4, 0x34, 0x12, 0x4b, 0xc3, 0x1b, 0xf4, 0xe4, 0xc9, 0x90, 0x96, 0x46, 0x6c, 0xb9, 0xf5, 0x41,
0xcf, 0xe6, 0xfd, 0xa0, 0x6d, 0x74, 0xdc, 0x91, 0xd9, 0x73, 0x7b, 0xae, 0x29, 0x09, 0xda, 0xc1,
0xb9, 0x3c, 0xc9, 0x83, 0xfc, 0x0a, 0x89, 0xb7, 0xb6, 0x55, 0x48, 0xa6, 0x15, 0xf0, 0x3e, 0x3a,
0xdc, 0xee, 0x58, 0xdc, 0x76, 0x1d, 0x73, 0x7c, 0x23, 0x8c, 0xad, 0x7d, 0x85, 0x1e, 0x59, 0x9d,
0xbe, 0xed, 0xa0, 0x7f, 0xa1, 0xee, 0x30, 0x42, 0x6e, 0xbd, 0xce, 0xca, 0x5c, 0x64, 0xe5, 0x07,
0x0e, 0xb7, 0x47, 0x78, 0xc3, 0xe0, 0xa3, 0xff, 0x32, 0x60, 0x9d, 0x3e, 0x8e, 0xac, 0x79, 0xbb,
0xda, 0x1f, 0xf7, 0x48, 0xf6, 0xc9, 0x18, 0x1d, 0x4e, 0x7f, 0x20, 0x39, 0x11, 0x4d, 0xd7, 0xe2,
0x96, 0xae, 0x55, 0xb5, 0x7a, 0x61, 0x6f, 0xc7, 0x50, 0x29, 0x4c, 0x48, 0x55, 0x16, 0x05, 0xda,
0x18, 0xef, 0x1a, 0x5f, 0xb5, 0x7f, 0xc4, 0x0e, 0x7f, 0x8a, 0xdc, 0x6a, 0xd0, 0xcb, 0x49, 0x65,
0x65, 0x3a, 0xa9, 0x10, 0x25, 0x83, 0x84, 0x95, 0x6e, 0x93, 0xec, 0x10, 0xc7, 0x38, 0xd4, 0xef,
0x54, 0xb5, 0x7a, 0xbe, 0xf1, 0x56, 0x04, 0xce, 0x1e, 0x09, 0xe1, 0x75, 0xfc, 0x01, 0x21, 0x88,
0x7e, 0x47, 0xf2, 0x22, 0x70, 0xc6, 0xad, 0x91, 0xa7, 0x67, 0x64, 0x40, 0xef, 0x2d, 0x17, 0xd0,
0x99, 0x3d, 0xc2, 0xc6, 0x66, 0xc4, 0x9e, 0x3f, 0x8b, 0x49, 0x40, 0xf1, 0xd1, 0x63, 0xb2, 0x26,
0x8b, 0xa0, 0xf9, 0x58, 0x5f, 0x95, 0xc1, 0xec, 0x47, 0xf0, 0xb5, 0xc3, 0x50, 0x7c, 0x3d, 0xa9,
0xbc, 0xbd, 0x28, 0xa5, 0xfc, 0xc2, 0x43, 0x66, 0xb4, 0x9a, 0x8f, 0x21, 0x26, 0x11, 0x57, 0x63,
0xdc, 0xea, 0xa1, 0x9e, 0x9d, 0xbd, 0xda, 0xa9, 0x10, 0x5e, 0xc7, 0x1f, 0x10, 0x82, 0xe8, 0x1e,
0x21, 0x3e, 0xfe, 0x14, 0x20, 0xe3, 0x2d, 0x68, 0xea, 0x77, 0xa5, 0x49, 0x92, 0x3a, 0x48, 0x34,
0x90, 0x42, 0xd1, 0x2a, 0x59, 0x1d, 0xa3, 0xdf, 0xd6, 0xd7, 0x24, 0xfa, 0x5e, 0x84, 0x5e, 0x7d,
0x86, 0x7e, 0x1b, 0xa4, 0x86, 0x7e, 0x49, 0x56, 0x03, 0x86, 0xbe, 0x9e, 0x93, 0xb9, 0x7a, 0x37,
0x95, 0x2b, 0x63, 0xb6, 0x4c, 0x45, 0x8e, 0x5a, 0x0c, 0xfd, 0xa6, 0x73, 0xee, 0x2a, 0x26, 0x21,
0x01, 0xc9, 0x40, 0xfb, 0xa4, 0x64, 0x8f, 0x3c, 0xf4, 0x99, 0xeb, 0x88, 0x52, 0x11, 0x1a, 0x3d,
0x7f, 0x2b, 0xd6, 0x07, 0xd3, 0x49, 0xa5, 0xd4, 0x9c, 0xe3, 0x80, 0x1b, 0xac, 0xf4, 0x7d, 0x92,
0x67, 0x6e, 0xe0, 0x77, 0xb0, 0x79, 0xc2, 0x74, 0x52, 0xcd, 0xd4, 0xf3, 0x8d, 0x75, 0xf1, 0xd3,
0x4e, 0x63, 0x21, 0x28, 0x3d, 0x3d, 0x27, 0x79, 0x57, 0xd6, 0x15, 0xe0, 0xb9, 0x5e, 0x90, 0xf1,
0x7c, 0x6c, 0x2c, 0xdb, 0xe5, 0x51, 0x99, 0x02, 0x9e, 0xa3, 0x8f, 0x4e, 0x07, 0x43, 0x3f, 0x89,
0x10, 0x14, 0x35, 0xed, 0x93, 0xa2, 0x8f, 0xcc, 0x73, 0x1d, 0x86, 0xa7, 0xdc, 0xe2, 0x01, 0xd3,
0xef, 0x49, 0x67, 0xdb, 0xcb, 0x95, 0x5f, 0x68, 0xd3, 0xa0, 0xd3, 0x49, 0xa5, 0x08, 0x33, 0x3c,
0x30, 0xc7, 0x4b, 0x2d, 0xb2, 0x1e, 0xfd, 0xe2, 0x30, 0x10, 0x7d, 0x5d, 0x3a, 0xaa, 0x2f, 0x74,
0x14, 0x75, 0xb3, 0xd1, 0x72, 0x06, 0x8e, 0xfb, 0xdc, 0x69, 0x6c, 0x4e, 0x27, 0x95, 0x75, 0x48,
0x53, 0xc0, 0x2c, 0x23, 0xed, 0xaa, 0xcb, 0x44, 0x3e, 0x8a, 0xb7, 0xf4, 0x31, 0x73, 0x91, 0xc8,
0xc9, 0x1c, 0x27, 0xfd, 0x55, 0x23, 0x7a, 0xe4, 0x17, 0xb0, 0x83, 0xf6, 0x18, 0xbb, 0x49, 0xdf,
0xe9, 0x1b, 0xd2, 0xa1, 0xb9, 0x5c, 0xf6, 0x9e, 0xda, 0x1d, 0xdf, 0x95, 0x1d, 0x5c, 0x8d, 0x2a,
0x53, 0x87, 0x05, 0xc4, 0xb0, 0xd0, 0x25, 0x75, 0x49, 0x51, 0xb6, 0x9a, 0x0a, 0xa2, 0xf4, 0xff,
0x82, 0x88, 0x3b, 0xb9, 0x78, 0x3a, 0x43, 0x07, 0x73, 0xf4, 0xf4, 0x39, 0x29, 0x58, 0x8e, 0xe3,
0x72, 0xd9, 0x0a, 0x4c, 0xdf, 0xac, 0x66, 0xea, 0x85, 0xbd, 0xcf, 0x97, 0xaf, 0x4e, 0x39, 0x83,
0x8d, 0x43, 0x45, 0xf1, 0xc4, 0xe1, 0xfe, 0x45, 0xe3, 0x7e, 0xe4, 0xbe, 0x90, 0xd2, 0x40, 0xda,
0x13, 0x35, 0x49, 0x5e, 0xf4, 0xec, 0x61, 0x0f, 0x1d, 0xae, 0x53, 0x39, 0x1c, 0x92, 0xd1, 0xd7,
0x8a, 0x15, 0xa0, 0x30, 0x5b, 0x9f, 0x91, 0xd2, 0xbc, 0x1b, 0x5a, 0x22, 0x99, 0x01, 0x5e, 0xc8,
0xb1, 0x9f, 0x07, 0xf1, 0x49, 0x1f, 0x90, 0xec, 0xd8, 0x1a, 0x06, 0x18, 0xce, 0x6a, 0x08, 0x0f,
0x9f, 0xdc, 0x39, 0xd0, 0x6a, 0x2f, 0x34, 0x92, 0x97, 0xd1, 0x1e, 0xd9, 0x8c, 0xd3, 0xef, 0x6f,
0x6c, 0x0d, 0x63, 0xb9, 0x14, 0x0b, 0x6b, 0xb9, 0x33, 0x4a, 0x51, 0xb4, 0xb9, 0x58, 0x92, 0xda,
0x18, 0x67, 0x24, 0x6b, 0x73, 0x1c, 0x31, 0xfd, 0x8e, 0xcc, 0xa7, 0x79, 0xcb, 0x7c, 0x36, 0xd6,
0xe3, 0x39, 0xdc, 0x14, 0x2c, 0x10, 0x92, 0xd5, 0x7e, 0xd7, 0x48, 0xf1, 0x0b, 0xdf, 0x0d, 0x3c,
0xc0, 0x70, 0xb8, 0x30, 0xfa, 0x0e, 0xc9, 0xf6, 0x84, 0x24, 0x4c, 0x81, 0xb2, 0x0b, 0x61, 0xa1,
0x4e, 0x0c, 0x2b, 0x3f, 0xb6, 0x90, 0x11, 0x45, 0xc3, 0x2a, 0xa1, 0x01, 0xa5, 0xa7, 0x8f, 0x44,
0x6b, 0x87, 0x87, 0x63, 0x6b, 0x84, 0x4c, 0xcf, 0x48, 0x83, 0xa8, 0x61, 0x53, 0x0a, 0x98, 0xc5,
0xd5, 0x7e, 0xc9, 0x90, 0x8d, 0xb9, 0x59, 0x45, 0xb7, 0x49, 0x2e, 0x06, 0x45, 0x11, 0x26, 0x59,
0x8b, 0xb9, 0x20, 0x41, 0x88, 0x92, 0x70, 0x04, 0x95, 0x67, 0x75, 0xa2, 0xff, 0xa7, 0x4a, 0xe2,
0x38, 0x56, 0x80, 0xc2, 0x88, 0xdd, 0x22, 0x0e, 0x72, 0xcb, 0xa6, 0x76, 0x8b, 0xc0, 0x82, 0xd4,
0xd0, 0x06, 0xc9, 0x04, 0x76, 0x37, 0xda, 0x95, 0x3b, 0x11, 0x20, 0xd3, 0x5a, 0x76, 0x4f, 0x0a,
0x63, 0xb1, 0xf5, 0x2c, 0xcf, 0x7e, 0x86, 0x3e, 0xb3, 0x5d, 0x27, 0x5a, 0x94, 0xc9, 0xd6, 0x3b,
0x3c, 0x69, 0x46, 0x1a, 0x48, 0xa1, 0xe8, 0x21, 0xd9, 0x88, 0xaf, 0x15, 0x1b, 0x86, 0xeb, 0xf2,
0x61, 0x64, 0xb8, 0x01, 0xb3, 0x6a, 0x98, 0xc7, 0xd3, 0x0f, 0x49, 0x81, 0x05, 0xed, 0x24, 0x7d,
0xe1, 0xfe, 0x4c, 0xfa, 0xea, 0x54, 0xa9, 0x20, 0x8d, 0xab, 0xfd, 0xa3, 0x91, 0xbb, 0x27, 0xee,
0xd0, 0xee, 0x5c, 0xbc, 0x81, 0x97, 0xd1, 0x37, 0x24, 0xeb, 0x07, 0x43, 0x8c, 0xeb, 0x7c, 0x7f,
0xf9, 0x3a, 0x0f, 0x43, 0x84, 0x60, 0x88, 0xaa, 0x68, 0xc5, 0x89, 0x41, 0xc8, 0x48, 0x1f, 0x11,
0xe2, 0x8e, 0x6c, 0x2e, 0xc7, 0x57, 0x5c, 0x84, 0x0f, 0x65, 0x20, 0x89, 0x54, 0xbd, 0x4f, 0x52,
0xd0, 0xda, 0x9f, 0x1a, 0x21, 0x21, 0xfb, 0x1b, 0x68, 0xf4, 0xd6, 0x6c, 0xa3, 0xef, 0xdc, 0x36,
0x01, 0x0b, 0x3a, 0xfd, 0x45, 0x26, 0xbe, 0x83, 0xc8, 0x89, 0x7a, 0x80, 0x6a, 0xcb, 0x3c, 0x40,
0x2b, 0x24, 0x2b, 0xa6, 0x66, 0xdc, 0xea, 0x79, 0x81, 0x14, 0x13, 0x95, 0x41, 0x28, 0xa7, 0x06,
0x21, 0xe2, 0x43, 0xce, 0x88, 0x38, 0xb5, 0x45, 0x91, 0xda, 0x56, 0x22, 0x85, 0x14, 0x42, 0x10,
0x8a, 0x87, 0x1a, 0xd3, 0x57, 0x15, 0xa1, 0x78, 0xbf, 0x31, 0x08, 0xe5, 0xd4, 0x4e, 0x0f, 0x98,
0xac, 0xcc, 0xc4, 0xc1, 0xf2, 0x99, 0x98, 0x1d, 0x69, 0xaa, 0xe5, 0x5f, 0x3b, 0x9e, 0x0c, 0x42,
0x92, 0xfe, 0x67, 0xfa, 0x5d, 0x15, 0x7b, 0x32, 0x20, 0x18, 0xa4, 0x10, 0xf4, 0x53, 0xb2, 0xe1,
0xb8, 0x4e, 0x4c, 0xd5, 0x82, 0x23, 0xa6, 0xaf, 0x49, 0xa3, 0xfb, 0xa2, 0x09, 0x8f, 0x67, 0x55,
0x30, 0x8f, 0x9d, 0xab, 0xc2, 0xdc, 0xd2, 0x55, 0xd8, 0x30, 0x2e, 0xaf, 0xca, 0x2b, 0x2f, 0xaf,
0xca, 0x2b, 0xaf, 0xae, 0xca, 0x2b, 0x3f, 0x4f, 0xcb, 0xda, 0xe5, 0xb4, 0xac, 0xbd, 0x9c, 0x96,
0xb5, 0x57, 0xd3, 0xb2, 0xf6, 0xd7, 0xb4, 0xac, 0xfd, 0xf6, 0x77, 0x79, 0xe5, 0xdb, 0x5c, 0x9c,
0x84, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xfc, 0xbf, 0xfd, 0x49, 0x0e, 0x00, 0x00,
}

View file

@ -65,6 +65,11 @@ message Event {
// +optional
repeated string sourceIPs = 10;
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
optional string userAgent = 18;
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
@ -99,9 +104,10 @@ message Event {
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Keys should uniquely identify the informing component to avoid name
// collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values should be short. Annotations
// are included in the Metadata level.
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
map<string, string> annotations = 17;
}
@ -122,17 +128,17 @@ message GroupResources {
optional string group = 1;
// Resources is a list of resources this rule applies to.
//
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
//
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
//
// An empty list implies all resources and subresources in this API groups apply.
// +optional
repeated string resources = 2;

View file

@ -105,6 +105,10 @@ type Event struct {
// Source IPs, from where the request originated and intermediate proxies.
// +optional
SourceIPs []string `json:"sourceIPs,omitempty" protobuf:"bytes,10,rep,name=sourceIPs"`
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
UserAgent string `json:"userAgent,omitempty" protobuf:"bytes,18,opt,name=userAgent"`
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
@ -135,9 +139,10 @@ type Event struct {
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Keys should uniquely identify the informing component to avoid name
// collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values should be short. Annotations
// are included in the Metadata level.
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,17,rep,name=annotations"`
}

View file

@ -23,7 +23,7 @@ package v1alpha1
import (
unsafe "unsafe"
authentication_v1 "k8s.io/api/authentication/v1"
authenticationv1 "k8s.io/api/authentication/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -37,23 +37,98 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_Event_To_audit_Event,
Convert_audit_Event_To_v1alpha1_Event,
Convert_v1alpha1_EventList_To_audit_EventList,
Convert_audit_EventList_To_v1alpha1_EventList,
Convert_v1alpha1_GroupResources_To_audit_GroupResources,
Convert_audit_GroupResources_To_v1alpha1_GroupResources,
Convert_v1alpha1_ObjectReference_To_audit_ObjectReference,
Convert_audit_ObjectReference_To_v1alpha1_ObjectReference,
Convert_v1alpha1_Policy_To_audit_Policy,
Convert_audit_Policy_To_v1alpha1_Policy,
Convert_v1alpha1_PolicyList_To_audit_PolicyList,
Convert_audit_PolicyList_To_v1alpha1_PolicyList,
Convert_v1alpha1_PolicyRule_To_audit_PolicyRule,
Convert_audit_PolicyRule_To_v1alpha1_PolicyRule,
)
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*Event)(nil), (*audit.Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Event_To_audit_Event(a.(*Event), b.(*audit.Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Event)(nil), (*Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Event_To_v1alpha1_Event(a.(*audit.Event), b.(*Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*EventList)(nil), (*audit.EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_EventList_To_audit_EventList(a.(*EventList), b.(*audit.EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.EventList)(nil), (*EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_EventList_To_v1alpha1_EventList(a.(*audit.EventList), b.(*EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*GroupResources)(nil), (*audit.GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_GroupResources_To_audit_GroupResources(a.(*GroupResources), b.(*audit.GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.GroupResources)(nil), (*GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_GroupResources_To_v1alpha1_GroupResources(a.(*audit.GroupResources), b.(*GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ObjectReference)(nil), (*audit.ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ObjectReference_To_audit_ObjectReference(a.(*ObjectReference), b.(*audit.ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.ObjectReference)(nil), (*ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_ObjectReference_To_v1alpha1_ObjectReference(a.(*audit.ObjectReference), b.(*ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Policy)(nil), (*audit.Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Policy_To_audit_Policy(a.(*Policy), b.(*audit.Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Policy_To_v1alpha1_Policy(a.(*audit.Policy), b.(*Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyList)(nil), (*audit.PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_PolicyList_To_audit_PolicyList(a.(*PolicyList), b.(*audit.PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyList)(nil), (*PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyList_To_v1alpha1_PolicyList(a.(*audit.PolicyList), b.(*PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyRule)(nil), (*audit.PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_PolicyRule_To_audit_PolicyRule(a.(*PolicyRule), b.(*audit.PolicyRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyRule)(nil), (*PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyRule_To_v1alpha1_PolicyRule(a.(*audit.PolicyRule), b.(*PolicyRule), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*audit.Event)(nil), (*Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Event_To_v1alpha1_Event(a.(*audit.Event), b.(*Event), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*audit.ObjectReference)(nil), (*ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_ObjectReference_To_v1alpha1_ObjectReference(a.(*audit.ObjectReference), b.(*ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*Event)(nil), (*audit.Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Event_To_audit_Event(a.(*Event), b.(*audit.Event), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*ObjectReference)(nil), (*audit.ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ObjectReference_To_audit_ObjectReference(a.(*ObjectReference), b.(*audit.ObjectReference), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_Event_To_audit_Event(in *Event, out *audit.Event, s conversion.Scope) error {
@ -70,6 +145,7 @@ func autoConvert_v1alpha1_Event_To_audit_Event(in *Event, out *audit.Event, s co
}
out.ImpersonatedUser = (*audit.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
*out = new(audit.ObjectReference)
@ -98,8 +174,9 @@ func autoConvert_audit_Event_To_v1alpha1_Event(in *audit.Event, out *Event, s co
if err := s.Convert(&in.User, &out.User, 0); err != nil {
return err
}
out.ImpersonatedUser = (*authentication_v1.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.ImpersonatedUser = (*authenticationv1.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
*out = new(ObjectReference)

View file

@ -22,7 +22,7 @@ package v1alpha1
import (
v1 "k8s.io/api/authentication/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -35,12 +35,8 @@ func (in *Event) DeepCopyInto(out *Event) {
in.User.DeepCopyInto(&out.User)
if in.ImpersonatedUser != nil {
in, out := &in.ImpersonatedUser, &out.ImpersonatedUser
if *in == nil {
*out = nil
} else {
*out = new(v1.UserInfo)
(*in).DeepCopyInto(*out)
}
*out = new(v1.UserInfo)
(*in).DeepCopyInto(*out)
}
if in.SourceIPs != nil {
in, out := &in.SourceIPs, &out.SourceIPs
@ -49,39 +45,23 @@ func (in *Event) DeepCopyInto(out *Event) {
}
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
if *in == nil {
*out = nil
} else {
*out = new(ObjectReference)
**out = **in
}
*out = new(ObjectReference)
**out = **in
}
if in.ResponseStatus != nil {
in, out := &in.ResponseStatus, &out.ResponseStatus
if *in == nil {
*out = nil
} else {
*out = new(meta_v1.Status)
(*in).DeepCopyInto(*out)
}
*out = new(metav1.Status)
(*in).DeepCopyInto(*out)
}
if in.RequestObject != nil {
in, out := &in.RequestObject, &out.RequestObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
if in.ResponseObject != nil {
in, out := &in.ResponseObject, &out.ResponseObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
in.RequestReceivedTimestamp.DeepCopyInto(&out.RequestReceivedTimestamp)
in.StageTimestamp.DeepCopyInto(&out.StageTimestamp)

View file

@ -15,9 +15,11 @@ limitations under the License.
*/
// +k8s:deepcopy-gen=package
// +k8s:protobuf-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/apis/audit
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +groupName=audit.k8s.io
package v1beta1 // import "k8s.io/apiserver/pkg/apis/audit/v1beta1"

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1/generated.proto
// DO NOT EDIT!
/*
Package v1beta1 is a generated protocol buffer package.
@ -266,6 +265,12 @@ func (m *Event) MarshalTo(dAtA []byte) (int, error) {
i += copy(dAtA[i:], v)
}
}
dAtA[i] = 0x92
i++
dAtA[i] = 0x1
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.UserAgent)))
i += copy(dAtA[i:], m.UserAgent)
return i, nil
}
@ -624,24 +629,6 @@ func (m *PolicyRule) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
@ -708,6 +695,8 @@ func (m *Event) Size() (n int) {
n += mapEntrySize + 2 + sovGenerated(uint64(mapEntrySize))
}
}
l = len(m.UserAgent)
n += 2 + l + sovGenerated(uint64(l))
return n
}
@ -896,6 +885,7 @@ func (this *Event) String() string {
`RequestReceivedTimestamp:` + strings.Replace(strings.Replace(this.RequestReceivedTimestamp.String(), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1), `&`, ``, 1) + `,`,
`StageTimestamp:` + strings.Replace(strings.Replace(this.StageTimestamp.String(), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1), `&`, ``, 1) + `,`,
`Annotations:` + mapStringForAnnotations + `,`,
`UserAgent:` + fmt.Sprintf("%v", this.UserAgent) + `,`,
`}`,
}, "")
return s
@ -1532,51 +1522,14 @@ func (m *Event) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.Annotations == nil {
m.Annotations = make(map[string]string)
}
if iNdEx < postIndex {
var valuekey uint64
var mapkey string
var mapvalue string
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
@ -1586,41 +1539,109 @@ func (m *Event) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if iNdEx >= l {
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
return io.ErrUnexpectedEOF
}
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
} else {
iNdEx = entryPreIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthGenerated
}
m.Annotations[mapkey] = mapvalue
iNdEx = postIndex
case 18:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field UserAgent", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
m.Annotations[mapkey] = mapvalue
} else {
var mapvalue string
m.Annotations[mapkey] = mapvalue
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.UserAgent = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
@ -2818,84 +2839,85 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 1258 bytes of a gzipped FileDescriptorProto
// 1278 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
0x14, 0xcf, 0xd6, 0x71, 0x62, 0x8f, 0x1b, 0xc7, 0x99, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x04,
0x11, 0xa4, 0xbb, 0x4d, 0x28, 0x24, 0x42, 0x02, 0x14, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x34, 0x8e,
0x14, 0xcf, 0xd6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x9d, 0x56, 0x74, 0x95, 0x83, 0x6d, 0x8c, 0x04,
0x11, 0xa4, 0xbb, 0x4d, 0x28, 0x24, 0x42, 0x02, 0x64, 0xab, 0x15, 0x58, 0x4a, 0x43, 0x34, 0x8e,
0x2b, 0x04, 0x1c, 0x58, 0xdb, 0x2f, 0xf6, 0x62, 0x7b, 0x77, 0xd9, 0x99, 0x35, 0xca, 0x8d, 0x2f,
0x80, 0xc4, 0x9d, 0x6f, 0xc1, 0x07, 0xa8, 0x38, 0xe6, 0xd8, 0x63, 0x4f, 0x16, 0x31, 0xdf, 0x22,
0x02, 0x09, 0xcd, 0x9f, 0xdd, 0x59, 0x3b, 0xb5, 0x70, 0x38, 0xf4, 0xb6, 0xf3, 0xde, 0xef, 0xfd,
0xde, 0x9b, 0xb7, 0xef, 0xcf, 0xa0, 0xd3, 0xc1, 0x21, 0xb5, 0x5c, 0xdf, 0x1e, 0x44, 0x6d, 0x08,
0x3d, 0x60, 0x40, 0xed, 0x31, 0x78, 0x5d, 0x3f, 0xb4, 0x95, 0xc2, 0x09, 0x5c, 0x0a, 0xe1, 0x18,
0x42, 0x3b, 0x18, 0xf4, 0xc4, 0xc9, 0x76, 0xa2, 0xae, 0xcb, 0xec, 0xf1, 0x5e, 0x1b, 0x98, 0xb3,
0x67, 0xf7, 0xc0, 0x83, 0xd0, 0x61, 0xd0, 0xb5, 0x82, 0xd0, 0x67, 0x3e, 0x7e, 0x4f, 0x1a, 0x5a,
0x89, 0xa1, 0x15, 0x0c, 0x7a, 0xe2, 0x64, 0x09, 0x43, 0x4b, 0x19, 0x6e, 0x3f, 0xec, 0xb9, 0xac,
0x1f, 0xb5, 0xad, 0x8e, 0x3f, 0xb2, 0x7b, 0x7e, 0xcf, 0xb7, 0x85, 0x7d, 0x3b, 0x3a, 0x17, 0x27,
0x71, 0x10, 0x5f, 0x92, 0x77, 0x7b, 0x57, 0x07, 0x64, 0x3b, 0x11, 0xeb, 0x83, 0xc7, 0xdc, 0x8e,
0xc3, 0x5c, 0xdf, 0xb3, 0xc7, 0x37, 0xa2, 0xd8, 0x7e, 0xac, 0xd1, 0x23, 0xa7, 0xd3, 0x77, 0x3d,
0x08, 0x2f, 0xf4, 0x0d, 0x46, 0xc0, 0x9c, 0xd7, 0x59, 0xd9, 0x8b, 0xac, 0xc2, 0xc8, 0x63, 0xee,
0x08, 0x6e, 0x18, 0x7c, 0xfc, 0x5f, 0x06, 0xb4, 0xd3, 0x87, 0x91, 0x33, 0x6f, 0x57, 0xfb, 0xbb,
0x80, 0xb2, 0x4f, 0xc7, 0xe0, 0x31, 0xfc, 0x3d, 0xca, 0xf1, 0x68, 0xba, 0x0e, 0x73, 0x4c, 0xa3,
0x6a, 0xec, 0x14, 0xf6, 0x1f, 0x59, 0x3a, 0x83, 0x09, 0xa9, 0x4e, 0x22, 0x47, 0x5b, 0xe3, 0x3d,
0xeb, 0xab, 0xf6, 0x0f, 0xd0, 0x61, 0xcf, 0x80, 0x39, 0x75, 0x7c, 0x39, 0xa9, 0xac, 0x4c, 0x27,
0x15, 0xa4, 0x65, 0x24, 0x61, 0xc5, 0xbb, 0x28, 0x3b, 0x84, 0x31, 0x0c, 0xcd, 0x3b, 0x55, 0x63,
0x27, 0x5f, 0x7f, 0x4b, 0x81, 0xb3, 0xc7, 0x5c, 0x78, 0x1d, 0x7f, 0x10, 0x09, 0xc2, 0xdf, 0xa2,
0x3c, 0x0f, 0x9c, 0x32, 0x67, 0x14, 0x98, 0x19, 0x11, 0xd0, 0xfb, 0xcb, 0x05, 0x74, 0xe6, 0x8e,
0xa0, 0xbe, 0xa5, 0xd8, 0xf3, 0x67, 0x31, 0x09, 0xd1, 0x7c, 0xf8, 0x04, 0xad, 0x8b, 0x1a, 0x68,
0x3c, 0x31, 0x57, 0x45, 0x30, 0x8f, 0x15, 0x7c, 0xfd, 0x48, 0x8a, 0xaf, 0x27, 0x95, 0xb7, 0x17,
0xa5, 0x94, 0x5d, 0x04, 0x40, 0xad, 0x56, 0xe3, 0x09, 0x89, 0x49, 0xf8, 0xd5, 0x28, 0x73, 0x7a,
0x60, 0x66, 0x67, 0xaf, 0xd6, 0xe4, 0xc2, 0xeb, 0xf8, 0x83, 0x48, 0x10, 0xde, 0x47, 0x28, 0x84,
0x1f, 0x23, 0xa0, 0xac, 0x45, 0x1a, 0xe6, 0x9a, 0x30, 0x49, 0x52, 0x47, 0x12, 0x0d, 0x49, 0xa1,
0x70, 0x15, 0xad, 0x8e, 0x21, 0x6c, 0x9b, 0xeb, 0x02, 0x7d, 0x57, 0xa1, 0x57, 0x9f, 0x43, 0xd8,
0x26, 0x42, 0x83, 0xbf, 0x44, 0xab, 0x11, 0x85, 0xd0, 0xcc, 0x89, 0x5c, 0xbd, 0x9b, 0xca, 0x95,
0x35, 0x5b, 0xa6, 0x3c, 0x47, 0x2d, 0x0a, 0x61, 0xc3, 0x3b, 0xf7, 0x35, 0x13, 0x97, 0x10, 0xc1,
0x80, 0xfb, 0xa8, 0xe4, 0x8e, 0x02, 0x08, 0xa9, 0xef, 0xf1, 0x52, 0xe1, 0x1a, 0x33, 0x7f, 0x2b,
0xd6, 0xfb, 0xd3, 0x49, 0xa5, 0xd4, 0x98, 0xe3, 0x20, 0x37, 0x58, 0xf1, 0x07, 0x28, 0x4f, 0xfd,
0x28, 0xec, 0x40, 0xe3, 0x94, 0x9a, 0xa8, 0x9a, 0xd9, 0xc9, 0xd7, 0x37, 0xf8, 0x4f, 0x6b, 0xc6,
0x42, 0xa2, 0xf5, 0x18, 0x50, 0xde, 0x17, 0x75, 0x45, 0xe0, 0xdc, 0x2c, 0x88, 0x78, 0x0e, 0xad,
0x25, 0x9b, 0x5c, 0x55, 0x29, 0x81, 0x73, 0x08, 0xc1, 0xeb, 0x80, 0x74, 0x93, 0x08, 0x89, 0x66,
0xc6, 0x7d, 0x54, 0x0c, 0x81, 0x06, 0xbe, 0x47, 0xa1, 0xc9, 0x1c, 0x16, 0x51, 0xf3, 0xae, 0xf0,
0xb5, 0xbb, 0x5c, 0xf5, 0x49, 0x9b, 0x3a, 0x9e, 0x4e, 0x2a, 0x45, 0x32, 0xc3, 0x43, 0xe6, 0x78,
0xb1, 0x83, 0x36, 0xd4, 0x1f, 0x96, 0x81, 0x98, 0x1b, 0xc2, 0xd1, 0xce, 0x42, 0x47, 0xaa, 0x99,
0xad, 0x96, 0x37, 0xf0, 0xfc, 0x9f, 0xbc, 0xfa, 0xd6, 0x74, 0x52, 0xd9, 0x20, 0x69, 0x0a, 0x32,
0xcb, 0x88, 0xbb, 0xfa, 0x32, 0xca, 0x47, 0xf1, 0x96, 0x3e, 0x66, 0x2e, 0xa2, 0x9c, 0xcc, 0x71,
0xe2, 0x5f, 0x0c, 0x64, 0x2a, 0xbf, 0x04, 0x3a, 0xe0, 0x8e, 0xa1, 0x9b, 0xb4, 0x9d, 0xb9, 0x29,
0x1c, 0xda, 0xcb, 0x65, 0xef, 0x99, 0xdb, 0x09, 0x7d, 0xd1, 0xc0, 0x55, 0x55, 0x98, 0x26, 0x59,
0x40, 0x4c, 0x16, 0xba, 0xc4, 0x3e, 0x2a, 0x8a, 0x4e, 0xd3, 0x41, 0x94, 0xfe, 0x5f, 0x10, 0x71,
0x23, 0x17, 0x9b, 0x33, 0x74, 0x64, 0x8e, 0x1e, 0x8f, 0x51, 0xc1, 0xf1, 0x3c, 0x9f, 0x89, 0x4e,
0xa0, 0xe6, 0x56, 0x35, 0xb3, 0x53, 0xd8, 0xff, 0x7c, 0xe9, 0xe2, 0x14, 0x13, 0xd8, 0x3a, 0xd2,
0x0c, 0x4f, 0x3d, 0x16, 0x5e, 0xd4, 0xef, 0x29, 0xef, 0x85, 0x94, 0x86, 0xa4, 0x1d, 0x6d, 0x7f,
0x86, 0x4a, 0xf3, 0x56, 0xb8, 0x84, 0x32, 0x03, 0xb8, 0x10, 0x33, 0x3c, 0x4f, 0xf8, 0x27, 0xbe,
0x8f, 0xb2, 0x63, 0x67, 0x18, 0x81, 0x1c, 0xbc, 0x44, 0x1e, 0x3e, 0xb9, 0x73, 0x68, 0xd4, 0x5e,
0x18, 0x28, 0x2f, 0x9c, 0x1f, 0xbb, 0x94, 0xe1, 0xef, 0x6e, 0xac, 0x00, 0x6b, 0xb9, 0x84, 0x71,
0x6b, 0xb1, 0x00, 0x4a, 0x2a, 0xe2, 0x5c, 0x2c, 0x49, 0x8d, 0xff, 0x26, 0xca, 0xba, 0x0c, 0x46,
0xd4, 0xbc, 0x23, 0xb2, 0x63, 0xdd, 0x2e, 0x3b, 0xf5, 0x8d, 0x78, 0xa6, 0x36, 0x38, 0x09, 0x91,
0x5c, 0xb5, 0xdf, 0x0c, 0x54, 0xfc, 0x22, 0xf4, 0xa3, 0x80, 0x80, 0x1c, 0x14, 0x14, 0xbf, 0x83,
0xb2, 0x3d, 0x2e, 0x91, 0x19, 0xd0, 0x76, 0x12, 0x26, 0x75, 0x7c, 0xf0, 0x84, 0xb1, 0x85, 0x08,
0x48, 0x0d, 0x9e, 0x84, 0x86, 0x68, 0x3d, 0x3e, 0xe0, 0x7d, 0x2a, 0x0f, 0x27, 0xce, 0x08, 0xa8,
0x99, 0x11, 0x06, 0xaa, 0xfb, 0x52, 0x0a, 0x32, 0x8b, 0xab, 0xfd, 0x9e, 0x41, 0x9b, 0x73, 0x83,
0x07, 0xef, 0xa2, 0x5c, 0x0c, 0x52, 0x11, 0x26, 0x49, 0x8b, 0xb9, 0x48, 0x82, 0xc0, 0x36, 0xca,
0x7b, 0x9c, 0x2a, 0x70, 0x3a, 0xea, 0xf7, 0xe9, 0xcd, 0x76, 0x12, 0x2b, 0x88, 0xc6, 0xf0, 0x3d,
0xc1, 0x0f, 0x62, 0x63, 0xa6, 0xf6, 0x04, 0xc7, 0x12, 0xa1, 0xc1, 0x75, 0x94, 0x89, 0xdc, 0xae,
0xda, 0x7b, 0x8f, 0x14, 0x20, 0xd3, 0x5a, 0x76, 0xe7, 0x71, 0x63, 0x7e, 0x09, 0x27, 0x70, 0x45,
0x46, 0xd5, 0xca, 0x4b, 0x2e, 0x71, 0x74, 0xda, 0x90, 0x99, 0x4e, 0x10, 0x7c, 0xdf, 0x39, 0x81,
0xfb, 0x1c, 0x42, 0xea, 0xfa, 0xde, 0xfc, 0xbe, 0x3b, 0x3a, 0x6d, 0x28, 0x0d, 0x49, 0xa1, 0xf0,
0x11, 0xda, 0x8c, 0x93, 0x10, 0x1b, 0xca, 0xd5, 0xf7, 0x40, 0x19, 0x6e, 0x92, 0x59, 0x35, 0x99,
0xc7, 0xe3, 0x8f, 0x50, 0x81, 0x46, 0xed, 0x24, 0xd9, 0x39, 0x61, 0x9e, 0xf4, 0x54, 0x53, 0xab,
0x48, 0x1a, 0x57, 0xfb, 0xc7, 0x40, 0x6b, 0xa7, 0xfe, 0xd0, 0xed, 0x5c, 0xbc, 0x81, 0x37, 0xd1,
0xd7, 0x28, 0x1b, 0x46, 0x43, 0x88, 0x9b, 0xe2, 0xc3, 0xa5, 0x9b, 0x42, 0x46, 0x48, 0xa2, 0x21,
0xe8, 0x0a, 0xe7, 0x27, 0x4a, 0x24, 0x21, 0x3e, 0x40, 0xc8, 0x1f, 0xb9, 0x4c, 0x0c, 0xae, 0xb8,
0x62, 0x1f, 0x88, 0x38, 0x12, 0xa9, 0x7e, 0x98, 0xa4, 0xa0, 0xb5, 0x3f, 0x0c, 0x84, 0x24, 0xfb,
0x1b, 0x18, 0x0a, 0x67, 0xb3, 0x43, 0xc1, 0xbe, 0xe5, 0xfd, 0x17, 0x4c, 0x85, 0x17, 0x99, 0xf8,
0x0a, 0x3c, 0x25, 0xfa, 0xe1, 0x69, 0x2c, 0xf3, 0xf0, 0xac, 0xa0, 0x2c, 0x7f, 0x05, 0xc5, 0x63,
0x21, 0xcf, 0x91, 0xfc, 0xb1, 0x42, 0x89, 0x94, 0x63, 0x0b, 0x21, 0xfe, 0x21, 0x6a, 0x3b, 0xce,
0x6c, 0x91, 0x67, 0xb6, 0x95, 0x48, 0x49, 0x0a, 0xc1, 0x09, 0xf9, 0x03, 0x8d, 0x9a, 0xab, 0x9a,
0x90, 0xbf, 0xdb, 0x28, 0x91, 0x72, 0xdc, 0x4f, 0x0f, 0xa3, 0xac, 0x48, 0xc4, 0xc1, 0xd2, 0x89,
0x98, 0x9d, 0x7e, 0x7a, 0x3a, 0xbc, 0x76, 0x92, 0x59, 0x08, 0x25, 0xa3, 0x82, 0x9a, 0x6b, 0x3a,
0xf4, 0x64, 0x96, 0x50, 0x92, 0x42, 0xe0, 0x4f, 0xd1, 0xa6, 0xe7, 0x7b, 0x31, 0x55, 0x8b, 0x1c,
0x53, 0x73, 0x5d, 0x18, 0xdd, 0xe3, 0x1d, 0x78, 0x32, 0xab, 0x22, 0xf3, 0xd8, 0xb9, 0x1a, 0xcc,
0x2d, 0x5d, 0x83, 0xf5, 0x87, 0x97, 0x57, 0xe5, 0x95, 0x97, 0x57, 0xe5, 0x95, 0x57, 0x57, 0xe5,
0x95, 0x9f, 0xa7, 0x65, 0xe3, 0x72, 0x5a, 0x36, 0x5e, 0x4e, 0xcb, 0xc6, 0xab, 0x69, 0xd9, 0xf8,
0x73, 0x5a, 0x36, 0x7e, 0xfd, 0xab, 0xbc, 0xf2, 0xcd, 0xba, 0xca, 0xc1, 0xbf, 0x01, 0x00, 0x00,
0xff, 0xff, 0x8e, 0x08, 0x0c, 0xa0, 0x3d, 0x0e, 0x00, 0x00,
0x80, 0xc4, 0x9d, 0xcf, 0xc0, 0x85, 0x0f, 0x50, 0x71, 0xcc, 0xb1, 0xc7, 0x9e, 0x2c, 0x62, 0xbe,
0x45, 0x24, 0x24, 0x34, 0x7f, 0x76, 0x67, 0xed, 0xd4, 0xc2, 0xe1, 0xd0, 0xdb, 0xce, 0x7b, 0xbf,
0xf7, 0x7b, 0x6f, 0xde, 0xbe, 0x3f, 0x83, 0x4e, 0x86, 0x87, 0xd4, 0x72, 0x7d, 0x7b, 0x18, 0x75,
0x20, 0xf4, 0x80, 0x01, 0xb5, 0x27, 0xe0, 0xf5, 0xfc, 0xd0, 0x56, 0x0a, 0x27, 0x70, 0x29, 0x84,
0x13, 0x08, 0xed, 0x60, 0xd8, 0x17, 0x27, 0xdb, 0x89, 0x7a, 0x2e, 0xb3, 0x27, 0x7b, 0x1d, 0x60,
0xce, 0x9e, 0xdd, 0x07, 0x0f, 0x42, 0x87, 0x41, 0xcf, 0x0a, 0x42, 0x9f, 0xf9, 0xf8, 0x3d, 0x69,
0x68, 0x25, 0x86, 0x56, 0x30, 0xec, 0x8b, 0x93, 0x25, 0x0c, 0x2d, 0x65, 0xb8, 0xfd, 0xb0, 0xef,
0xb2, 0x41, 0xd4, 0xb1, 0xba, 0xfe, 0xd8, 0xee, 0xfb, 0x7d, 0xdf, 0x16, 0xf6, 0x9d, 0xe8, 0x4c,
0x9c, 0xc4, 0x41, 0x7c, 0x49, 0xde, 0xed, 0x5d, 0x1d, 0x90, 0xed, 0x44, 0x6c, 0x00, 0x1e, 0x73,
0xbb, 0x0e, 0x73, 0x7d, 0xcf, 0x9e, 0x5c, 0x8b, 0x62, 0xfb, 0xb1, 0x46, 0x8f, 0x9d, 0xee, 0xc0,
0xf5, 0x20, 0x3c, 0xd7, 0x37, 0x18, 0x03, 0x73, 0x5e, 0x67, 0x65, 0x2f, 0xb3, 0x0a, 0x23, 0x8f,
0xb9, 0x63, 0xb8, 0x66, 0xf0, 0xf1, 0x7f, 0x19, 0xd0, 0xee, 0x00, 0xc6, 0xce, 0xa2, 0x5d, 0xed,
0xf7, 0x3b, 0x28, 0xfb, 0x74, 0x02, 0x1e, 0xc3, 0xdf, 0xa3, 0x1c, 0x8f, 0xa6, 0xe7, 0x30, 0xc7,
0x34, 0xaa, 0xc6, 0x4e, 0x61, 0xff, 0x91, 0xa5, 0x33, 0x98, 0x90, 0xea, 0x24, 0x72, 0xb4, 0x35,
0xd9, 0xb3, 0xbe, 0xea, 0xfc, 0x00, 0x5d, 0xf6, 0x0c, 0x98, 0xd3, 0xc0, 0x17, 0xd3, 0xca, 0xda,
0x6c, 0x5a, 0x41, 0x5a, 0x46, 0x12, 0x56, 0xbc, 0x8b, 0xb2, 0x23, 0x98, 0xc0, 0xc8, 0xbc, 0x55,
0x35, 0x76, 0xf2, 0x8d, 0xb7, 0x14, 0x38, 0x7b, 0xc4, 0x85, 0x57, 0xf1, 0x07, 0x91, 0x20, 0xfc,
0x2d, 0xca, 0xf3, 0xc0, 0x29, 0x73, 0xc6, 0x81, 0x99, 0x11, 0x01, 0xbd, 0xbf, 0x5a, 0x40, 0xa7,
0xee, 0x18, 0x1a, 0x77, 0x15, 0x7b, 0xfe, 0x34, 0x26, 0x21, 0x9a, 0x0f, 0x1f, 0xa3, 0x0d, 0x51,
0x03, 0xcd, 0x27, 0xe6, 0xba, 0x08, 0xe6, 0xb1, 0x82, 0x6f, 0xd4, 0xa5, 0xf8, 0x6a, 0x5a, 0x79,
0x7b, 0x59, 0x4a, 0xd9, 0x79, 0x00, 0xd4, 0x6a, 0x37, 0x9f, 0x90, 0x98, 0x84, 0x5f, 0x8d, 0x32,
0xa7, 0x0f, 0x66, 0x76, 0xfe, 0x6a, 0x2d, 0x2e, 0xbc, 0x8a, 0x3f, 0x88, 0x04, 0xe1, 0x7d, 0x84,
0x42, 0xf8, 0x31, 0x02, 0xca, 0xda, 0xa4, 0x69, 0xde, 0x16, 0x26, 0x49, 0xea, 0x48, 0xa2, 0x21,
0x29, 0x14, 0xae, 0xa2, 0xf5, 0x09, 0x84, 0x1d, 0x73, 0x43, 0xa0, 0xef, 0x28, 0xf4, 0xfa, 0x73,
0x08, 0x3b, 0x44, 0x68, 0xf0, 0x97, 0x68, 0x3d, 0xa2, 0x10, 0x9a, 0x39, 0x91, 0xab, 0x77, 0x53,
0xb9, 0xb2, 0xe6, 0xcb, 0x94, 0xe7, 0xa8, 0x4d, 0x21, 0x6c, 0x7a, 0x67, 0xbe, 0x66, 0xe2, 0x12,
0x22, 0x18, 0xf0, 0x00, 0x95, 0xdc, 0x71, 0x00, 0x21, 0xf5, 0x3d, 0x5e, 0x2a, 0x5c, 0x63, 0xe6,
0x6f, 0xc4, 0x7a, 0x7f, 0x36, 0xad, 0x94, 0x9a, 0x0b, 0x1c, 0xe4, 0x1a, 0x2b, 0xfe, 0x00, 0xe5,
0xa9, 0x1f, 0x85, 0x5d, 0x68, 0x9e, 0x50, 0x13, 0x55, 0x33, 0x3b, 0xf9, 0xc6, 0x26, 0xff, 0x69,
0xad, 0x58, 0x48, 0xb4, 0x1e, 0x03, 0xca, 0xfb, 0xa2, 0xae, 0x08, 0x9c, 0x99, 0x05, 0x11, 0xcf,
0xa1, 0xb5, 0x62, 0x93, 0xab, 0x2a, 0x25, 0x70, 0x06, 0x21, 0x78, 0x5d, 0x90, 0x6e, 0x12, 0x21,
0xd1, 0xcc, 0x78, 0x80, 0x8a, 0x21, 0xd0, 0xc0, 0xf7, 0x28, 0xb4, 0x98, 0xc3, 0x22, 0x6a, 0xde,
0x11, 0xbe, 0x76, 0x57, 0xab, 0x3e, 0x69, 0xd3, 0xc0, 0xb3, 0x69, 0xa5, 0x48, 0xe6, 0x78, 0xc8,
0x02, 0x2f, 0x76, 0xd0, 0xa6, 0xfa, 0xc3, 0x32, 0x10, 0x73, 0x53, 0x38, 0xda, 0x59, 0xea, 0x48,
0x35, 0xb3, 0xd5, 0xf6, 0x86, 0x9e, 0xff, 0x93, 0xd7, 0xb8, 0x3b, 0x9b, 0x56, 0x36, 0x49, 0x9a,
0x82, 0xcc, 0x33, 0xe2, 0x9e, 0xbe, 0x8c, 0xf2, 0x51, 0xbc, 0xa1, 0x8f, 0xb9, 0x8b, 0x28, 0x27,
0x0b, 0x9c, 0xf8, 0x17, 0x03, 0x99, 0xca, 0x2f, 0x81, 0x2e, 0xb8, 0x13, 0xe8, 0x25, 0x6d, 0x67,
0x6e, 0x09, 0x87, 0xf6, 0x6a, 0xd9, 0x7b, 0xe6, 0x76, 0x43, 0x5f, 0x34, 0x70, 0x55, 0x15, 0xa6,
0x49, 0x96, 0x10, 0x93, 0xa5, 0x2e, 0xb1, 0x8f, 0x8a, 0xa2, 0xd3, 0x74, 0x10, 0xa5, 0xff, 0x17,
0x44, 0xdc, 0xc8, 0xc5, 0xd6, 0x1c, 0x1d, 0x59, 0xa0, 0xc7, 0x13, 0x54, 0x70, 0x3c, 0xcf, 0x67,
0xa2, 0x13, 0xa8, 0x79, 0xb7, 0x9a, 0xd9, 0x29, 0xec, 0x7f, 0xbe, 0x72, 0x71, 0x8a, 0x09, 0x6c,
0xd5, 0x35, 0xc3, 0x53, 0x8f, 0x85, 0xe7, 0x8d, 0x7b, 0xca, 0x7b, 0x21, 0xa5, 0x21, 0x69, 0x47,
0xd8, 0x46, 0x79, 0xde, 0xb1, 0xf5, 0x3e, 0x78, 0xcc, 0xc4, 0x62, 0x34, 0x24, 0x83, 0xaf, 0x1d,
0x2b, 0x88, 0xc6, 0x6c, 0x7f, 0x86, 0x4a, 0x8b, 0x6e, 0x70, 0x09, 0x65, 0x86, 0x70, 0x2e, 0x86,
0x7e, 0x9e, 0xf0, 0x4f, 0x7c, 0x1f, 0x65, 0x27, 0xce, 0x28, 0x02, 0x39, 0xa9, 0x89, 0x3c, 0x7c,
0x72, 0xeb, 0xd0, 0xa8, 0xbd, 0x30, 0x50, 0x5e, 0x44, 0x7b, 0xe4, 0x52, 0x86, 0xbf, 0xbb, 0xb6,
0x33, 0xac, 0xd5, 0x32, 0xcc, 0xad, 0xc5, 0xc6, 0x28, 0xa9, 0x68, 0x73, 0xb1, 0x24, 0xb5, 0x2f,
0x5a, 0x28, 0xeb, 0x32, 0x18, 0x53, 0xf3, 0x96, 0x48, 0xa7, 0x75, 0xb3, 0x74, 0x36, 0x36, 0xe3,
0x21, 0xdc, 0xe4, 0x24, 0x44, 0x72, 0xd5, 0x7e, 0x33, 0x50, 0xf1, 0x8b, 0xd0, 0x8f, 0x02, 0x02,
0x72, 0xb2, 0x50, 0xfc, 0x0e, 0xca, 0xf6, 0xb9, 0x44, 0x66, 0x40, 0xdb, 0x49, 0x98, 0xd4, 0xf1,
0x49, 0x15, 0xc6, 0x16, 0x22, 0x20, 0x35, 0xa9, 0x12, 0x1a, 0xa2, 0xf5, 0xf8, 0x80, 0x37, 0xb6,
0x3c, 0x1c, 0x3b, 0x63, 0xa0, 0x66, 0x46, 0x18, 0xa8, 0x76, 0x4d, 0x29, 0xc8, 0x3c, 0xae, 0xf6,
0x47, 0x06, 0x6d, 0x2d, 0x4c, 0x2a, 0xbc, 0x8b, 0x72, 0x31, 0x48, 0x45, 0x98, 0x24, 0x2d, 0xe6,
0x22, 0x09, 0x82, 0x57, 0x84, 0xc7, 0xa9, 0x02, 0xa7, 0xab, 0x7e, 0x9f, 0xae, 0x88, 0xe3, 0x58,
0x41, 0x34, 0x86, 0x2f, 0x16, 0x7e, 0x10, 0x2b, 0x36, 0xb5, 0x58, 0x38, 0x96, 0x08, 0x0d, 0x6e,
0xa0, 0x4c, 0xe4, 0xf6, 0xd4, 0xa2, 0x7c, 0xa4, 0x00, 0x99, 0xf6, 0xaa, 0x4b, 0x92, 0x1b, 0xf3,
0x4b, 0x38, 0x81, 0x2b, 0x32, 0xaa, 0x76, 0x64, 0x72, 0x89, 0xfa, 0x49, 0x53, 0x66, 0x3a, 0x41,
0xf0, 0x05, 0xe9, 0x04, 0xee, 0x73, 0x08, 0xa9, 0xeb, 0x7b, 0x8b, 0x0b, 0xb2, 0x7e, 0xd2, 0x54,
0x1a, 0x92, 0x42, 0xe1, 0x3a, 0xda, 0x8a, 0x93, 0x10, 0x1b, 0xca, 0x5d, 0xf9, 0x40, 0x19, 0x6e,
0x91, 0x79, 0x35, 0x59, 0xc4, 0xe3, 0x8f, 0x50, 0x81, 0x46, 0x9d, 0x24, 0xd9, 0x39, 0x61, 0x9e,
0x34, 0x61, 0x4b, 0xab, 0x48, 0x1a, 0x57, 0xfb, 0xc7, 0x40, 0xb7, 0x4f, 0xfc, 0x91, 0xdb, 0x3d,
0x7f, 0x03, 0x8f, 0xa8, 0xaf, 0x51, 0x36, 0x8c, 0x46, 0x10, 0x37, 0xc5, 0x87, 0x2b, 0x37, 0x85,
0x8c, 0x90, 0x44, 0x23, 0xd0, 0x15, 0xce, 0x4f, 0x94, 0x48, 0x42, 0x7c, 0x80, 0x90, 0x3f, 0x76,
0x99, 0x98, 0x74, 0x71, 0xc5, 0x3e, 0x10, 0x71, 0x24, 0x52, 0xfd, 0x92, 0x49, 0x41, 0x6b, 0x7f,
0x1a, 0x08, 0x49, 0xf6, 0x37, 0x30, 0x14, 0x4e, 0xe7, 0x87, 0x82, 0x7d, 0xc3, 0xfb, 0x2f, 0x99,
0x0a, 0x2f, 0x32, 0xf1, 0x15, 0x78, 0x4a, 0xf4, 0x4b, 0xd5, 0x58, 0xe5, 0xa5, 0x5a, 0x41, 0x59,
0x3e, 0x60, 0xe3, 0xb1, 0x90, 0xe7, 0x48, 0x3e, 0x7c, 0x29, 0x91, 0x72, 0x6c, 0x21, 0xc4, 0x3f,
0x44, 0x6d, 0xc7, 0x99, 0x2d, 0xf2, 0xcc, 0xb6, 0x13, 0x29, 0x49, 0x21, 0x38, 0x21, 0x7f, 0xd1,
0x51, 0x73, 0x5d, 0x13, 0xf2, 0x87, 0x1e, 0x25, 0x52, 0x8e, 0x07, 0xe9, 0x61, 0x94, 0x15, 0x89,
0x38, 0x58, 0x39, 0x11, 0xf3, 0xd3, 0x4f, 0x4f, 0x87, 0xd7, 0x4e, 0x32, 0x0b, 0xa1, 0x64, 0x54,
0x50, 0xf3, 0xb6, 0x0e, 0x3d, 0x99, 0x25, 0x94, 0xa4, 0x10, 0xf8, 0x53, 0xb4, 0xe5, 0xf9, 0x5e,
0x4c, 0xd5, 0x26, 0x47, 0xd4, 0xdc, 0x10, 0x46, 0xf7, 0x78, 0x07, 0x1e, 0xcf, 0xab, 0xc8, 0x22,
0x76, 0xa1, 0x06, 0x73, 0x2b, 0xd7, 0x60, 0xe3, 0xe1, 0xc5, 0x65, 0x79, 0xed, 0xe5, 0x65, 0x79,
0xed, 0xd5, 0x65, 0x79, 0xed, 0xe7, 0x59, 0xd9, 0xb8, 0x98, 0x95, 0x8d, 0x97, 0xb3, 0xb2, 0xf1,
0x6a, 0x56, 0x36, 0xfe, 0x9a, 0x95, 0x8d, 0x5f, 0xff, 0x2e, 0xaf, 0x7d, 0xb3, 0xa1, 0x72, 0xf0,
0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0xe5, 0x7c, 0x52, 0x6e, 0x0e, 0x00, 0x00,
}

View file

@ -68,6 +68,11 @@ message Event {
// +optional
repeated string sourceIPs = 10;
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
optional string userAgent = 18;
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
@ -102,9 +107,10 @@ message Event {
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Keys should uniquely identify the informing component to avoid name
// collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values should be short. Annotations
// are included in the Metadata level.
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
map<string, string> annotations = 17;
}
@ -125,17 +131,17 @@ message GroupResources {
optional string group = 1;
// Resources is a list of resources this rule applies to.
//
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
//
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
//
// An empty list implies all resources and subresources in this API groups apply.
// +optional
repeated string resources = 2;

View file

@ -101,6 +101,10 @@ type Event struct {
// Source IPs, from where the request originated and intermediate proxies.
// +optional
SourceIPs []string `json:"sourceIPs,omitempty" protobuf:"bytes,10,rep,name=sourceIPs"`
// UserAgent records the user agent string reported by the client.
// Note that the UserAgent is provided by the client, and must not be trusted.
// +optional
UserAgent string `json:"userAgent,omitempty" protobuf:"bytes,18,opt,name=userAgent"`
// Object reference this request is targeted at.
// Does not apply for List-type requests, or non-resource requests.
// +optional
@ -131,9 +135,10 @@ type Event struct {
// Annotations is an unstructured key value map stored with an audit event that may be set by
// plugins invoked in the request serving chain, including authentication, authorization and
// admission plugins. Keys should uniquely identify the informing component to avoid name
// collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values should be short. Annotations
// are included in the Metadata level.
// admission plugins. Note that these annotations are for the audit event, and do not correspond
// to the metadata.annotations of the submitted object. Keys should uniquely identify the informing
// component to avoid name collisions (e.g. podsecuritypolicy.admission.k8s.io/policy). Values
// should be short. Annotations are included in the Metadata level.
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,17,rep,name=annotations"`
}

View file

@ -23,7 +23,7 @@ package v1beta1
import (
unsafe "unsafe"
authentication_v1 "k8s.io/api/authentication/v1"
authenticationv1 "k8s.io/api/authentication/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -37,23 +37,88 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1beta1_Event_To_audit_Event,
Convert_audit_Event_To_v1beta1_Event,
Convert_v1beta1_EventList_To_audit_EventList,
Convert_audit_EventList_To_v1beta1_EventList,
Convert_v1beta1_GroupResources_To_audit_GroupResources,
Convert_audit_GroupResources_To_v1beta1_GroupResources,
Convert_v1beta1_ObjectReference_To_audit_ObjectReference,
Convert_audit_ObjectReference_To_v1beta1_ObjectReference,
Convert_v1beta1_Policy_To_audit_Policy,
Convert_audit_Policy_To_v1beta1_Policy,
Convert_v1beta1_PolicyList_To_audit_PolicyList,
Convert_audit_PolicyList_To_v1beta1_PolicyList,
Convert_v1beta1_PolicyRule_To_audit_PolicyRule,
Convert_audit_PolicyRule_To_v1beta1_PolicyRule,
)
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*Event)(nil), (*audit.Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Event_To_audit_Event(a.(*Event), b.(*audit.Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Event)(nil), (*Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Event_To_v1beta1_Event(a.(*audit.Event), b.(*Event), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*EventList)(nil), (*audit.EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_EventList_To_audit_EventList(a.(*EventList), b.(*audit.EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.EventList)(nil), (*EventList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_EventList_To_v1beta1_EventList(a.(*audit.EventList), b.(*EventList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*GroupResources)(nil), (*audit.GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_GroupResources_To_audit_GroupResources(a.(*GroupResources), b.(*audit.GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.GroupResources)(nil), (*GroupResources)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_GroupResources_To_v1beta1_GroupResources(a.(*audit.GroupResources), b.(*GroupResources), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ObjectReference)(nil), (*audit.ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ObjectReference_To_audit_ObjectReference(a.(*ObjectReference), b.(*audit.ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.ObjectReference)(nil), (*ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_ObjectReference_To_v1beta1_ObjectReference(a.(*audit.ObjectReference), b.(*ObjectReference), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Policy)(nil), (*audit.Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Policy_To_audit_Policy(a.(*Policy), b.(*audit.Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.Policy)(nil), (*Policy)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Policy_To_v1beta1_Policy(a.(*audit.Policy), b.(*Policy), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyList)(nil), (*audit.PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_PolicyList_To_audit_PolicyList(a.(*PolicyList), b.(*audit.PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyList)(nil), (*PolicyList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyList_To_v1beta1_PolicyList(a.(*audit.PolicyList), b.(*PolicyList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PolicyRule)(nil), (*audit.PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_PolicyRule_To_audit_PolicyRule(a.(*PolicyRule), b.(*audit.PolicyRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*audit.PolicyRule)(nil), (*PolicyRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_PolicyRule_To_v1beta1_PolicyRule(a.(*audit.PolicyRule), b.(*PolicyRule), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*audit.Event)(nil), (*Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_audit_Event_To_v1beta1_Event(a.(*audit.Event), b.(*Event), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*Event)(nil), (*audit.Event)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Event_To_audit_Event(a.(*Event), b.(*audit.Event), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1beta1_Event_To_audit_Event(in *Event, out *audit.Event, s conversion.Scope) error {
@ -70,6 +135,7 @@ func autoConvert_v1beta1_Event_To_audit_Event(in *Event, out *audit.Event, s con
}
out.ImpersonatedUser = (*audit.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
out.ObjectRef = (*audit.ObjectReference)(unsafe.Pointer(in.ObjectRef))
out.ResponseStatus = (*v1.Status)(unsafe.Pointer(in.ResponseStatus))
out.RequestObject = (*runtime.Unknown)(unsafe.Pointer(in.RequestObject))
@ -90,8 +156,9 @@ func autoConvert_audit_Event_To_v1beta1_Event(in *audit.Event, out *Event, s con
if err := s.Convert(&in.User, &out.User, 0); err != nil {
return err
}
out.ImpersonatedUser = (*authentication_v1.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.ImpersonatedUser = (*authenticationv1.UserInfo)(unsafe.Pointer(in.ImpersonatedUser))
out.SourceIPs = *(*[]string)(unsafe.Pointer(&in.SourceIPs))
out.UserAgent = in.UserAgent
out.ObjectRef = (*ObjectReference)(unsafe.Pointer(in.ObjectRef))
out.ResponseStatus = (*v1.Status)(unsafe.Pointer(in.ResponseStatus))
out.RequestObject = (*runtime.Unknown)(unsafe.Pointer(in.RequestObject))

View file

@ -22,7 +22,7 @@ package v1beta1
import (
v1 "k8s.io/api/authentication/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -35,12 +35,8 @@ func (in *Event) DeepCopyInto(out *Event) {
in.User.DeepCopyInto(&out.User)
if in.ImpersonatedUser != nil {
in, out := &in.ImpersonatedUser, &out.ImpersonatedUser
if *in == nil {
*out = nil
} else {
*out = new(v1.UserInfo)
(*in).DeepCopyInto(*out)
}
*out = new(v1.UserInfo)
(*in).DeepCopyInto(*out)
}
if in.SourceIPs != nil {
in, out := &in.SourceIPs, &out.SourceIPs
@ -49,39 +45,23 @@ func (in *Event) DeepCopyInto(out *Event) {
}
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
if *in == nil {
*out = nil
} else {
*out = new(ObjectReference)
**out = **in
}
*out = new(ObjectReference)
**out = **in
}
if in.ResponseStatus != nil {
in, out := &in.ResponseStatus, &out.ResponseStatus
if *in == nil {
*out = nil
} else {
*out = new(meta_v1.Status)
(*in).DeepCopyInto(*out)
}
*out = new(metav1.Status)
(*in).DeepCopyInto(*out)
}
if in.RequestObject != nil {
in, out := &in.RequestObject, &out.RequestObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
if in.ResponseObject != nil {
in, out := &in.ResponseObject, &out.ResponseObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
in.RequestReceivedTimestamp.DeepCopyInto(&out.RequestReceivedTimestamp)
in.StageTimestamp.DeepCopyInto(&out.StageTimestamp)

View file

@ -24,6 +24,7 @@ import (
"k8s.io/apiserver/pkg/apis/audit"
)
// ValidatePolicy validates the audit policy
func ValidatePolicy(policy *audit.Policy) field.ErrorList {
var allErrs field.ErrorList
allErrs = append(allErrs, validateOmitStages(policy.OmitStages, field.NewPath("omitStages"))...)
@ -99,7 +100,7 @@ func validateResources(groupResources []audit.GroupResources, fldPath *field.Pat
// The empty string represents the core API group.
if len(groupResource.Group) != 0 {
// Group names must be lower case and be valid DNS subdomains.
// reference: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md
// reference: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md
// an error is returned for group name like rbac.authorization.k8s.io/v1beta1
// rbac.authorization.k8s.io is the valid one
if msgs := validation.NameIsDNSSubdomain(groupResource.Group, false); len(msgs) != 0 {

View file

@ -32,12 +32,8 @@ func (in *Event) DeepCopyInto(out *Event) {
in.User.DeepCopyInto(&out.User)
if in.ImpersonatedUser != nil {
in, out := &in.ImpersonatedUser, &out.ImpersonatedUser
if *in == nil {
*out = nil
} else {
*out = new(UserInfo)
(*in).DeepCopyInto(*out)
}
*out = new(UserInfo)
(*in).DeepCopyInto(*out)
}
if in.SourceIPs != nil {
in, out := &in.SourceIPs, &out.SourceIPs
@ -46,39 +42,23 @@ func (in *Event) DeepCopyInto(out *Event) {
}
if in.ObjectRef != nil {
in, out := &in.ObjectRef, &out.ObjectRef
if *in == nil {
*out = nil
} else {
*out = new(ObjectReference)
**out = **in
}
*out = new(ObjectReference)
**out = **in
}
if in.ResponseStatus != nil {
in, out := &in.ResponseStatus, &out.ResponseStatus
if *in == nil {
*out = nil
} else {
*out = new(v1.Status)
(*in).DeepCopyInto(*out)
}
*out = new(v1.Status)
(*in).DeepCopyInto(*out)
}
if in.RequestObject != nil {
in, out := &in.RequestObject, &out.RequestObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
if in.ResponseObject != nil {
in, out := &in.ResponseObject, &out.ResponseObject
if *in == nil {
*out = nil
} else {
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
*out = new(runtime.Unknown)
(*in).DeepCopyInto(*out)
}
in.RequestReceivedTimestamp.DeepCopyInto(&out.RequestReceivedTimestamp)
in.StageTimestamp.DeepCopyInto(&out.StageTimestamp)
@ -341,12 +321,15 @@ func (in *UserInfo) DeepCopyInto(out *UserInfo) {
in, out := &in.Extra, &out.Extra
*out = make(map[string]ExtraValue, len(*in))
for key, val := range *in {
var outVal []string
if val == nil {
(*out)[key] = nil
} else {
(*out)[key] = make([]string, len(val))
copy((*out)[key], val)
in, out := &val, &outVal
*out = make(ExtraValue, len(*in))
copy(*out, *in)
}
(*out)[key] = outVal
}
}
return

9
vendor/k8s.io/apiserver/pkg/audit/OWNERS generated vendored Normal file
View file

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

147
vendor/k8s.io/apiserver/pkg/audit/event/attributes.go generated vendored Normal file
View file

@ -0,0 +1,147 @@
/*
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 event
import (
"fmt"
"net/url"
"k8s.io/apiserver/pkg/apis/audit"
authuser "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
var _ authorizer.Attributes = &attributes{}
// attributes implements the authorizer attributes interface
// with event data. This is used for enforced audit backends
type attributes struct {
event *audit.Event
path string
}
// NewAttributes returns a new attributes struct and parsed request uri
// if needed
func NewAttributes(event *audit.Event) (authorizer.Attributes, error) {
a := attributes{
event: event,
}
if event.ObjectRef == nil {
u, err := url.ParseRequestURI(a.event.RequestURI)
if err != nil {
return nil, fmt.Errorf("could not parse url: %v", err)
}
a.path = u.Path
}
return &a, nil
}
// GetUser returns the user. This is only used for checking audit policy,
// and the audit policy user check is based off the original user,
// not the impersonated user.
func (a *attributes) GetUser() authuser.Info {
return user(a.event.User)
}
// GetVerb returns the verb
func (a *attributes) GetVerb() string {
return a.event.Verb
}
// IsReadOnly determines if the verb is a read only action
func (a *attributes) IsReadOnly() bool {
return a.event.Verb == "get" || a.event.Verb == "list" || a.event.Verb == "watch"
}
// GetNamespace returns the object namespace if present
func (a *attributes) GetNamespace() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.Namespace
}
// GetResource returns the object resource if present
func (a *attributes) GetResource() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.Resource
}
// GetSubresource returns the object subresource if present
func (a *attributes) GetSubresource() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.Subresource
}
// GetName returns the object name if present
func (a *attributes) GetName() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.Name
}
// GetAPIGroup returns the object api group if present
func (a *attributes) GetAPIGroup() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.APIGroup
}
// GetAPIVersion returns the object api version if present
func (a *attributes) GetAPIVersion() string {
if a.event.ObjectRef == nil {
return ""
}
return a.event.ObjectRef.APIVersion
}
// IsResourceRequest determines if the request was acted on a resource
func (a *attributes) IsResourceRequest() bool {
return a.event.ObjectRef != nil
}
// GetPath returns the path uri accessed
func (a *attributes) GetPath() string {
return a.path
}
// user represents the event user
type user audit.UserInfo
// GetName returns the user name
func (u user) GetName() string { return u.Username }
// GetUID returns the user uid
func (u user) GetUID() string { return u.UID }
// GetGroups returns the user groups
func (u user) GetGroups() []string { return u.Groups }
// GetExtra returns the user extra data
func (u user) GetExtra() map[string][]string {
m := map[string][]string{}
for k, v := range u.Extra {
m[k] = []string(v)
}
return m
}

View file

@ -19,9 +19,9 @@ package audit
import (
"fmt"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/klog"
)
const (
@ -52,12 +52,22 @@ var (
},
[]string{"level"},
)
ApiserverAuditDroppedCounter = prometheus.NewCounter(
prometheus.CounterOpts{
Subsystem: subsystem,
Name: "requests_rejected_total",
Help: "Counter of apiserver requests rejected due to an error " +
"in audit logging backend.",
},
)
)
func init() {
prometheus.MustRegister(eventCounter)
prometheus.MustRegister(errorCounter)
prometheus.MustRegister(levelCounter)
prometheus.MustRegister(ApiserverAuditDroppedCounter)
}
// ObserveEvent updates the relevant prometheus metrics for the generated audit event.
@ -83,5 +93,5 @@ func HandlePluginError(plugin string, err error, impacted ...*auditinternal.Even
for _, ev := range impacted {
msg = msg + EventString(ev) + "\n"
}
glog.Error(msg)
klog.Error(msg)
}

54
vendor/k8s.io/apiserver/pkg/audit/policy/dynamic.go generated vendored Normal file
View file

@ -0,0 +1,54 @@
/*
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 (
"k8s.io/api/auditregistration/v1alpha1"
"k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
// ConvertDynamicPolicyToInternal constructs an internal policy type from a
// v1alpha1 dynamic type
func ConvertDynamicPolicyToInternal(p *v1alpha1.Policy) *audit.Policy {
stages := make([]audit.Stage, len(p.Stages))
for i, stage := range p.Stages {
stages[i] = audit.Stage(stage)
}
return &audit.Policy{
Rules: []audit.PolicyRule{
{
Level: audit.Level(p.Level),
},
},
OmitStages: InvertStages(stages),
}
}
// NewDynamicChecker returns a new dynamic policy checker
func NewDynamicChecker() Checker {
return &dynamicPolicyChecker{}
}
type dynamicPolicyChecker struct{}
// LevelAndStages returns returns a fixed level of the full event, this is so that the downstream policy
// can be applied per sink.
// TODO: this needs benchmarking before the API moves to beta to determine the effect this has on the apiserver
func (d *dynamicPolicyChecker) LevelAndStages(authorizer.Attributes) (audit.Level, []audit.Stage) {
return audit.LevelRequestResponse, []audit.Stage{}
}

53
vendor/k8s.io/apiserver/pkg/audit/policy/enforce.go generated vendored Normal file
View file

@ -0,0 +1,53 @@
/*
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

@ -22,18 +22,20 @@ 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"
"github.com/golang/glog"
"k8s.io/klog"
)
var (
apiGroupVersions = []schema.GroupVersion{
auditv1beta1.SchemeGroupVersion,
auditv1alpha1.SchemeGroupVersion,
auditv1.SchemeGroupVersion,
}
apiGroupVersionSet = map[schema.GroupVersion]bool{}
)
@ -53,17 +55,26 @@ func LoadPolicyFromFile(filePath string) (*auditinternal.Policy, error) {
return nil, fmt.Errorf("failed to read file path %q: %+v", filePath, err)
}
ret, err := LoadPolicyFromBytes(policyDef)
if err != nil {
return nil, fmt.Errorf("%v: from file %v", err.Error(), filePath)
}
return ret, nil
}
func LoadPolicyFromBytes(policyDef []byte) (*auditinternal.Policy, error) {
policy := &auditinternal.Policy{}
decoder := audit.Codecs.UniversalDecoder(apiGroupVersions...)
_, gvk, err := decoder.Decode(policyDef, nil, policy)
if err != nil {
return nil, fmt.Errorf("failed decoding file %q: %v", filePath, err)
return nil, fmt.Errorf("failed decoding: %v", err)
}
// Ensure the policy file contained an apiVersion and kind.
if !apiGroupVersionSet[schema.GroupVersion{Group: gvk.Group, Version: gvk.Version}] {
return nil, fmt.Errorf("unknown group version field %v in policy file %s", gvk, filePath)
return nil, fmt.Errorf("unknown group version field %v in policy", gvk)
}
if err := validation.ValidatePolicy(policy); err != nil {
@ -72,8 +83,8 @@ func LoadPolicyFromFile(filePath string) (*auditinternal.Policy, error) {
policyCnt := len(policy.Rules)
if policyCnt == 0 {
return nil, fmt.Errorf("loaded illegal policy with 0 rules from file %s", filePath)
return nil, fmt.Errorf("loaded illegal policy with 0 rules")
}
glog.V(4).Infof("Loaded %d audit policy rules from file %s", policyCnt, filePath)
klog.V(4).Infof("Loaded %d audit policy rules", policyCnt)
return policy, nil
}

68
vendor/k8s.io/apiserver/pkg/audit/policy/util.go generated vendored Normal file
View file

@ -0,0 +1,68 @@
/*
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 (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/apis/audit"
)
// AllStages returns all possible stages
func AllStages() sets.String {
return sets.NewString(
audit.StageRequestReceived,
audit.StageResponseStarted,
audit.StageResponseComplete,
audit.StagePanic,
)
}
// AllLevels returns all possible levels
func AllLevels() sets.String {
return sets.NewString(
string(audit.LevelNone),
string(audit.LevelMetadata),
string(audit.LevelRequest),
string(audit.LevelRequestResponse),
)
}
// InvertStages subtracts the given array of stages from all stages
func InvertStages(stages []audit.Stage) []audit.Stage {
s := ConvertStagesToStrings(stages)
a := AllStages()
a.Delete(s...)
return ConvertStringSetToStages(a)
}
// ConvertStagesToStrings converts an array of stages to a string array
func ConvertStagesToStrings(stages []audit.Stage) []string {
s := make([]string, len(stages))
for i, stage := range stages {
s[i] = string(stage)
}
return s
}
// ConvertStringSetToStages converts a string set to an array of stages
func ConvertStringSetToStages(set sets.String) []audit.Stage {
stages := make([]audit.Stage, len(set))
for i, stage := range set.List() {
stages[i] = audit.Stage(stage)
}
return stages
}

View file

@ -20,13 +20,13 @@ import (
"bytes"
"fmt"
"net/http"
"reflect"
"time"
"github.com/golang/glog"
"github.com/pborman/uuid"
"k8s.io/klog"
"reflect"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -37,15 +37,20 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
)
const (
maxUserAgentLength = 1024
userAgentTruncateSuffix = "...TRUNCATED"
)
func NewEventFromRequest(req *http.Request, level auditinternal.Level, attribs authorizer.Attributes) (*auditinternal.Event, error) {
ev := &auditinternal.Event{
RequestReceivedTimestamp: metav1.NewMicroTime(time.Now()),
Verb: attribs.GetVerb(),
RequestURI: req.URL.RequestURI(),
Verb: attribs.GetVerb(),
RequestURI: req.URL.RequestURI(),
UserAgent: maybeTruncateUserAgent(req),
Level: level,
}
ev.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)
@ -112,8 +117,9 @@ func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.Gr
if ae.ObjectRef == nil {
ae.ObjectRef = &auditinternal.ObjectReference{}
}
if acc, ok := obj.(metav1.ObjectMetaAccessor); ok {
meta := acc.GetObjectMeta()
// meta.Accessor is more general than ObjectMetaAccessor, but if it fails, we can just skip setting these bits
if meta, err := meta.Accessor(obj); err == nil {
if len(ae.ObjectRef.Namespace) == 0 {
ae.ObjectRef.Namespace = meta.GetNamespace()
}
@ -147,7 +153,7 @@ func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.Gr
ae.RequestObject, err = encodeObject(obj, gvr.GroupVersion(), s)
if err != nil {
// TODO(audit): add error slice to audit event struct
glog.Warningf("Auditing failed of %v request: %v", reflect.TypeOf(obj).Name(), err)
klog.Warningf("Auditing failed of %v request: %v", reflect.TypeOf(obj).Name(), err)
return
}
}
@ -186,7 +192,7 @@ func LogResponseObject(ae *auditinternal.Event, obj runtime.Object, gv schema.Gr
var err error
ae.ResponseObject, err = encodeObject(obj, gv, s)
if err != nil {
glog.Warningf("Audit failed for %q response: %v", reflect.TypeOf(obj).Name(), err)
klog.Warningf("Audit failed for %q response: %v", reflect.TypeOf(obj).Name(), err)
}
}
@ -218,7 +224,7 @@ func LogAnnotation(ae *auditinternal.Event, key, value string) {
ae.Annotations = make(map[string]string)
}
if v, ok := ae.Annotations[key]; ok && v != value {
glog.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])
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
@ -233,3 +239,13 @@ func LogAnnotations(ae *auditinternal.Event, annotations map[string]string) {
LogAnnotation(ae, key, value)
}
}
// truncate User-Agent if too long, otherwise return it directly.
func maybeTruncateUserAgent(req *http.Request) string {
ua := req.UserAgent()
if len(ua) > maxUserAgentLength {
ua = ua[:maxUserAgentLength] + userAgentTruncateSuffix
}
return ua
}

View file

@ -18,10 +18,13 @@ limitations under the License.
package audit
import (
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
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"
)
@ -30,7 +33,10 @@ var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
v1alpha1.AddToScheme(Scheme)
v1beta1.AddToScheme(Scheme)
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))
}

View file

@ -25,7 +25,8 @@ type Sink interface {
// Errors might be logged by the sink itself. If an error should be fatal, leading to an internal
// error, ProcessEvents is supposed to panic. The event must not be mutated and is reused by the caller
// after the call returns, i.e. the sink has to make a deepcopy to keep a copy around if necessary.
ProcessEvents(events ...*auditinternal.Event)
// Returns true on success, may return false on error.
ProcessEvents(events ...*auditinternal.Event) bool
}
type Backend interface {
@ -39,4 +40,7 @@ type Backend interface {
// events are delivered. It can be assumed that this method is called after
// the stopCh channel passed to the Run method has been closed.
Shutdown()
// Returns the backend PluginName.
String() string
}

View file

@ -37,10 +37,12 @@ type union struct {
backends []Backend
}
func (u union) ProcessEvents(events ...*auditinternal.Event) {
func (u union) ProcessEvents(events ...*auditinternal.Event) bool {
success := true
for _, backend := range u.backends {
backend.ProcessEvents(events...)
success = backend.ProcessEvents(events...) && success
}
return success
}
func (u union) Run(stopCh <-chan struct{}) error {

43
vendor/k8s.io/apiserver/pkg/audit/util/conversion.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
/*
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 util
import (
"k8s.io/api/auditregistration/v1alpha1"
"k8s.io/apiserver/pkg/util/webhook"
)
// HookClientConfigForSink constructs a webhook.ClientConfig using a v1alpha1.AuditSink API object.
// webhook.ClientConfig is used to create a HookClient and the purpose of the config struct is to
// share that with other packages that need to create a HookClient.
func HookClientConfigForSink(a *v1alpha1.AuditSink) webhook.ClientConfig {
c := a.Spec.Webhook.ClientConfig
ret := webhook.ClientConfig{Name: a.Name, CABundle: c.CABundle}
if c.URL != nil {
ret.URL = *c.URL
}
if c.Service != nil {
ret.Service = &webhook.ClientConfigService{
Name: c.Service.Name,
Namespace: c.Service.Namespace,
}
if c.Service.Path != nil {
ret.Service.Path = *c.Service.Path
}
}
return ret
}

View file

@ -0,0 +1,90 @@
/*
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 authenticator
import (
"context"
"fmt"
"net/http"
)
func authenticate(ctx context.Context, implicitAuds Audiences, authenticate func() (*Response, bool, error)) (*Response, bool, error) {
targetAuds, ok := AudiencesFrom(ctx)
// We can remove this once api audiences is never empty. That will probably
// be N releases after TokenRequest is GA.
if !ok {
return authenticate()
}
auds := implicitAuds.Intersect(targetAuds)
if len(auds) == 0 {
return nil, false, nil
}
resp, ok, err := authenticate()
if err != nil || !ok {
return nil, false, err
}
if len(resp.Audiences) > 0 {
// maybe the authenticator was audience aware after all.
return nil, false, fmt.Errorf("audience agnostic authenticator wrapped an authenticator that returned audiences: %q", resp.Audiences)
}
resp.Audiences = auds
return resp, true, nil
}
type audAgnosticRequestAuthenticator struct {
implicit Audiences
delegate Request
}
var _ = Request(&audAgnosticRequestAuthenticator{})
func (a *audAgnosticRequestAuthenticator) AuthenticateRequest(req *http.Request) (*Response, bool, error) {
return authenticate(req.Context(), a.implicit, func() (*Response, bool, error) {
return a.delegate.AuthenticateRequest(req)
})
}
// WrapAudienceAgnosticRequest wraps an audience agnostic request authenticator
// to restrict its accepted audiences to a set of implicit audiences.
func WrapAudienceAgnosticRequest(implicit Audiences, delegate Request) Request {
return &audAgnosticRequestAuthenticator{
implicit: implicit,
delegate: delegate,
}
}
type audAgnosticTokenAuthenticator struct {
implicit Audiences
delegate Token
}
var _ = Token(&audAgnosticTokenAuthenticator{})
func (a *audAgnosticTokenAuthenticator) AuthenticateToken(ctx context.Context, tok string) (*Response, bool, error) {
return authenticate(ctx, a.implicit, func() (*Response, bool, error) {
return a.delegate.AuthenticateToken(ctx, tok)
})
}
// WrapAudienceAgnosticToken wraps an audience agnostic token authenticator to
// restrict its accepted audiences to a set of implicit audiences.
func WrapAudienceAgnosticToken(implicit Audiences, delegate Token) Token {
return &audAgnosticTokenAuthenticator{
implicit: implicit,
delegate: delegate,
}
}

View file

@ -0,0 +1,63 @@
/*
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 authenticator
import "context"
// Audiences is a container for the Audiences of a token.
type Audiences []string
// The key type is unexported to prevent collisions
type key int
const (
// audiencesKey is the context key for request audiences.
audiencesKey key = iota
)
// WithAudiences returns a context that stores a request's expected audiences.
func WithAudiences(ctx context.Context, auds Audiences) context.Context {
return context.WithValue(ctx, audiencesKey, auds)
}
// AudiencesFrom returns a request's expected audiences stored in the request context.
func AudiencesFrom(ctx context.Context) (Audiences, bool) {
auds, ok := ctx.Value(audiencesKey).(Audiences)
return auds, ok
}
// Has checks if Audiences contains a specific audiences.
func (a Audiences) Has(taud string) bool {
for _, aud := range a {
if aud == taud {
return true
}
}
return false
}
// Intersect intersects Audiences with a target Audiences and returns all
// elements in both.
func (a Audiences) Intersect(tauds Audiences) Audiences {
selected := Audiences{}
for _, taud := range tauds {
if a.Has(taud) {
selected = append(selected, taud)
}
}
return selected
}

View file

@ -17,52 +17,64 @@ limitations under the License.
package authenticator
import (
"context"
"net/http"
"k8s.io/apiserver/pkg/authentication/user"
)
// Token checks a string value against a backing authentication store and returns
// information about the current user and true if successful, false if not successful,
// or an error if the token could not be checked.
// Token checks a string value against a backing authentication store and
// returns a Response or an error if the token could not be checked.
type Token interface {
AuthenticateToken(token string) (user.Info, bool, error)
AuthenticateToken(ctx context.Context, token string) (*Response, bool, error)
}
// Request attempts to extract authentication information from a request and returns
// information about the current user and true if successful, false if not successful,
// or an error if the request could not be checked.
// Request attempts to extract authentication information from a request and
// returns a Response or an error if the request could not be checked.
type Request interface {
AuthenticateRequest(req *http.Request) (user.Info, bool, error)
AuthenticateRequest(req *http.Request) (*Response, bool, error)
}
// Password checks a username and password against a backing authentication store and
// returns information about the user and true if successful, false if not successful,
// or an error if the username and password could not be checked
// Password checks a username and password against a backing authentication
// store and returns a Response or an error if the password could not be
// checked.
type Password interface {
AuthenticatePassword(user, password string) (user.Info, bool, error)
AuthenticatePassword(ctx context.Context, user, password string) (*Response, bool, error)
}
// TokenFunc is a function that implements the Token interface.
type TokenFunc func(token string) (user.Info, bool, error)
type TokenFunc func(ctx context.Context, token string) (*Response, bool, error)
// AuthenticateToken implements authenticator.Token.
func (f TokenFunc) AuthenticateToken(token string) (user.Info, bool, error) {
return f(token)
func (f TokenFunc) AuthenticateToken(ctx context.Context, token string) (*Response, bool, error) {
return f(ctx, token)
}
// RequestFunc is a function that implements the Request interface.
type RequestFunc func(req *http.Request) (user.Info, bool, error)
type RequestFunc func(req *http.Request) (*Response, bool, error)
// AuthenticateRequest implements authenticator.Request.
func (f RequestFunc) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (f RequestFunc) AuthenticateRequest(req *http.Request) (*Response, bool, error) {
return f(req)
}
// PasswordFunc is a function that implements the Password interface.
type PasswordFunc func(user, password string) (user.Info, bool, error)
type PasswordFunc func(ctx context.Context, user, password string) (*Response, bool, error)
// AuthenticatePassword implements authenticator.Password.
func (f PasswordFunc) AuthenticatePassword(user, password string) (user.Info, bool, error) {
return f(user, password)
func (f PasswordFunc) AuthenticatePassword(ctx context.Context, user, password string) (*Response, bool, error) {
return f(ctx, user, password)
}
// Response is the struct returned by authenticator interfaces upon successful
// authentication. It contains information about whether the authenticator
// authenticated the request, information about the context of the
// authentication, and information about the authenticated user.
type Response struct {
// Audiences is the set of audiences the authenticator was able to validate
// the token against. If the authenticator is not audience aware, this field
// will be empty.
Audiences Audiences
// User is the UserInfo associated with the authentication context.
User user.Info
}

View file

@ -31,6 +31,7 @@ import (
unionauth "k8s.io/apiserver/pkg/authentication/request/union"
"k8s.io/apiserver/pkg/authentication/request/websocket"
"k8s.io/apiserver/pkg/authentication/request/x509"
"k8s.io/apiserver/pkg/authentication/token/cache"
webhooktoken "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
"k8s.io/client-go/util/cert"
@ -41,6 +42,7 @@ import (
type DelegatingAuthenticatorConfig struct {
Anonymous bool
// TokenAccessReviewClient is a client to do token review. It can be nil. Then every token is ignored.
TokenAccessReviewClient authenticationclient.TokenReviewInterface
// CacheTTL is the length of time that a token authentication answer will be cached.
@ -49,6 +51,8 @@ type DelegatingAuthenticatorConfig struct {
// ClientCAFile is the CA bundle file used to authenticate client certificates
ClientCAFile string
APIAudiences authenticator.Audiences
RequestHeaderConfig *RequestHeaderConfig
}
@ -84,11 +88,12 @@ func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.Secur
}
if c.TokenAccessReviewClient != nil {
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.CacheTTL)
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.APIAudiences)
if err != nil {
return nil, nil, err
}
authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
cachingTokenAuth := cache.New(tokenAuth, false, c.CacheTTL, c.CacheTTL)
authenticators = append(authenticators, bearertoken.New(cachingTokenAuth), websocket.NewProtocolAuthenticator(cachingTokenAuth))
securityDefinitions["BearerToken"] = &spec.SecurityScheme{
SecuritySchemeProps: spec.SecuritySchemeProps{

View file

@ -36,25 +36,26 @@ func NewAuthenticatedGroupAdder(auth authenticator.Request) authenticator.Reques
return &AuthenticatedGroupAdder{auth}
}
func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
u, ok, err := g.Authenticator.AuthenticateRequest(req)
func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
r, ok, err := g.Authenticator.AuthenticateRequest(req)
if err != nil || !ok {
return nil, ok, err
}
if u.GetName() == user.Anonymous {
return u, true, nil
if r.User.GetName() == user.Anonymous {
return r, true, nil
}
for _, group := range u.GetGroups() {
for _, group := range r.User.GetGroups() {
if group == user.AllAuthenticated || group == user.AllUnauthenticated {
return u, true, nil
return r, true, nil
}
}
return &user.DefaultInfo{
Name: u.GetName(),
UID: u.GetUID(),
Groups: append(u.GetGroups(), user.AllAuthenticated),
Extra: u.GetExtra(),
}, true, nil
r.User = &user.DefaultInfo{
Name: r.User.GetName(),
UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), user.AllAuthenticated),
Extra: r.User.GetExtra(),
}
return r, true, nil
}

View file

@ -36,15 +36,16 @@ func NewGroupAdder(auth authenticator.Request, groups []string) authenticator.Re
return &GroupAdder{auth, groups}
}
func (g *GroupAdder) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
u, ok, err := g.Authenticator.AuthenticateRequest(req)
func (g *GroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
r, ok, err := g.Authenticator.AuthenticateRequest(req)
if err != nil || !ok {
return nil, ok, err
}
return &user.DefaultInfo{
Name: u.GetName(),
UID: u.GetUID(),
Groups: append(u.GetGroups(), g.Groups...),
Extra: u.GetExtra(),
}, true, nil
r.User = &user.DefaultInfo{
Name: r.User.GetName(),
UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), g.Groups...),
Extra: r.User.GetExtra(),
}
return r, true, nil
}

View file

@ -17,6 +17,8 @@ limitations under the License.
package group
import (
"context"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
)
@ -34,15 +36,16 @@ func NewTokenGroupAdder(auth authenticator.Token, groups []string) authenticator
return &TokenGroupAdder{auth, groups}
}
func (g *TokenGroupAdder) AuthenticateToken(token string) (user.Info, bool, error) {
u, ok, err := g.Authenticator.AuthenticateToken(token)
func (g *TokenGroupAdder) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
r, ok, err := g.Authenticator.AuthenticateToken(ctx, token)
if err != nil || !ok {
return nil, ok, err
}
return &user.DefaultInfo{
Name: u.GetName(),
UID: u.GetUID(),
Groups: append(u.GetGroups(), g.Groups...),
Extra: u.GetExtra(),
}, true, nil
r.User = &user.DefaultInfo{
Name: r.User.GetName(),
UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), g.Groups...),
Extra: r.User.GetExtra(),
}
return r, true, nil
}

View file

@ -30,7 +30,14 @@ const (
)
func NewAuthenticator() authenticator.Request {
return authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
return &user.DefaultInfo{Name: anonymousUser, Groups: []string{unauthenticatedGroup}}, true, nil
return authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
auds, _ := authenticator.AudiencesFrom(req.Context())
return &authenticator.Response{
User: &user.DefaultInfo{
Name: anonymousUser,
Groups: []string{unauthenticatedGroup},
},
Audiences: auds,
}, true, nil
})
}

View file

@ -22,7 +22,6 @@ import (
"strings"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
)
type Authenticator struct {
@ -35,7 +34,7 @@ func New(auth authenticator.Token) *Authenticator {
var invalidToken = errors.New("invalid bearer token")
func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
auth := strings.TrimSpace(req.Header.Get("Authorization"))
if auth == "" {
return nil, false, nil
@ -52,7 +51,7 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool,
return nil, false, nil
}
user, ok, err := a.auth.AuthenticateToken(token)
resp, ok, err := a.auth.AuthenticateToken(req.Context(), token)
// if we authenticated successfully, go ahead and remove the bearer token so that no one
// is ever tempted to use it inside of the API server
if ok {
@ -64,5 +63,5 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool,
err = invalidToken
}
return user, ok, err
return resp, ok, err
}

View file

@ -105,7 +105,7 @@ func NewSecure(clientCA string, proxyClientNames []string, nameHeaders []string,
return x509request.NewVerifier(opts, headerAuthenticator, sets.NewString(proxyClientNames...)), nil
}
func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
name := headerValue(req.Header, a.nameHeaders)
if len(name) == 0 {
return nil, false, nil
@ -126,10 +126,12 @@ func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request)
}
}
return &user.DefaultInfo{
Name: name,
Groups: groups,
Extra: extra,
return &authenticator.Response{
User: &user.DefaultInfo{
Name: name,
Groups: groups,
Extra: extra,
},
}, true, nil
}

View file

@ -21,7 +21,6 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
)
// unionAuthRequestHandler authenticates requests using a chain of authenticator.Requests
@ -51,20 +50,20 @@ func NewFailOnError(authRequestHandlers ...authenticator.Request) authenticator.
}
// AuthenticateRequest authenticates the request using a chain of authenticator.Request objects.
func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
var errlist []error
for _, currAuthRequestHandler := range authHandler.Handlers {
info, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
resp, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
if err != nil {
if authHandler.FailOnError {
return info, ok, err
return resp, ok, err
}
errlist = append(errlist, err)
continue
}
if ok {
return info, ok, err
return resp, ok, err
}
}

View file

@ -25,7 +25,6 @@ import (
"unicode/utf8"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/util/wsstream"
)
@ -46,7 +45,7 @@ func NewProtocolAuthenticator(auth authenticator.Token) *ProtocolAuthenticator {
return &ProtocolAuthenticator{auth}
}
func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
// Only accept websocket connections
if !wsstream.IsWebSocketRequest(req) {
return nil, false, nil
@ -91,7 +90,7 @@ func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Inf
return nil, false, nil
}
user, ok, err := a.auth.AuthenticateToken(token)
resp, ok, err := a.auth.AuthenticateToken(req.Context(), token)
// on success, remove the protocol with the token
if ok {
@ -105,5 +104,5 @@ func (a *ProtocolAuthenticator) AuthenticateRequest(req *http.Request) (user.Inf
err = errInvalidToken
}
return user, ok, err
return resp, ok, err
}

View file

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

View file

@ -19,12 +19,10 @@ package x509
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"net/http"
"time"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -41,6 +39,9 @@ var clientCertificateExpirationHistogram = prometheus.NewHistogram(
Help: "Distribution of the remaining lifetime on the certificate used to authenticate a request.",
Buckets: []float64{
0,
(30 * time.Minute).Seconds(),
(1 * time.Hour).Seconds(),
(2 * time.Hour).Seconds(),
(6 * time.Hour).Seconds(),
(12 * time.Hour).Seconds(),
(24 * time.Hour).Seconds(),
@ -61,14 +62,14 @@ func init() {
// UserConversion defines an interface for extracting user info from a client certificate chain
type UserConversion interface {
User(chain []*x509.Certificate) (user.Info, bool, error)
User(chain []*x509.Certificate) (*authenticator.Response, bool, error)
}
// UserConversionFunc is a function that implements the UserConversion interface.
type UserConversionFunc func(chain []*x509.Certificate) (user.Info, bool, error)
type UserConversionFunc func(chain []*x509.Certificate) (*authenticator.Response, bool, error)
// User implements x509.UserConversion
func (f UserConversionFunc) User(chain []*x509.Certificate) (user.Info, bool, error) {
func (f UserConversionFunc) User(chain []*x509.Certificate) (*authenticator.Response, bool, error) {
return f(chain)
}
@ -85,7 +86,7 @@ func New(opts x509.VerifyOptions, user UserConversion) *Authenticator {
}
// AuthenticateRequest authenticates the request using presented client certificates
func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 {
return nil, false, nil
}
@ -137,7 +138,7 @@ func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request, allowedCom
}
// AuthenticateRequest verifies the presented client certificate, then delegates to the wrapped auth
func (a *Verifier) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
func (a *Verifier) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
if req.TLS == nil || len(req.TLS.PeerCertificates) == 0 {
return nil, false, nil
}
@ -169,8 +170,7 @@ func (a *Verifier) verifySubject(subject pkix.Name) error {
if a.allowedCommonNames.Has(subject.CommonName) {
return nil
}
glog.Warningf("x509: subject with cn=%s is not in the allowed list: %v", subject.CommonName, a.allowedCommonNames.List())
return fmt.Errorf("x509: subject with cn=%s is not allowed", subject.CommonName)
return fmt.Errorf("x509: subject with cn=%s is not in the allowed list", subject.CommonName)
}
// DefaultVerifyOptions returns VerifyOptions that use the system root certificates, current time,
@ -182,34 +182,14 @@ func DefaultVerifyOptions() x509.VerifyOptions {
}
// CommonNameUserConversion builds user info from a certificate chain using the subject's CommonName
var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (*authenticator.Response, bool, error) {
if len(chain[0].Subject.CommonName) == 0 {
return nil, false, nil
}
return &user.DefaultInfo{
Name: chain[0].Subject.CommonName,
Groups: chain[0].Subject.Organization,
return &authenticator.Response{
User: &user.DefaultInfo{
Name: chain[0].Subject.CommonName,
Groups: chain[0].Subject.Organization,
},
}, true, nil
})
// DNSNameUserConversion builds user info from a certificate chain using the first DNSName on the certificate
var DNSNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
if len(chain[0].DNSNames) == 0 {
return nil, false, nil
}
return &user.DefaultInfo{Name: chain[0].DNSNames[0]}, true, nil
})
// EmailAddressUserConversion builds user info from a certificate chain using the first EmailAddress on the certificate
var EmailAddressUserConversion = UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) {
var emailAddressOID asn1.ObjectIdentifier = []int{1, 2, 840, 113549, 1, 9, 1}
if len(chain[0].EmailAddresses) == 0 {
for _, name := range chain[0].Subject.Names {
if name.Type.Equal(emailAddressOID) {
return &user.DefaultInfo{Name: name.Value.(string)}, true, nil
}
}
return nil, false, nil
}
return &user.DefaultInfo{Name: chain[0].EmailAddresses[0]}, true, nil
})

View file

@ -0,0 +1,49 @@
/*
Copyright 2017 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 cache
import (
"time"
lrucache "k8s.io/apimachinery/pkg/util/cache"
"k8s.io/apimachinery/pkg/util/clock"
)
type simpleCache struct {
lru *lrucache.LRUExpireCache
}
func newSimpleCache(size int, clock clock.Clock) cache {
return &simpleCache{lru: lrucache.NewLRUExpireCacheWithClock(size, clock)}
}
func (c *simpleCache) get(key string) (*cacheRecord, bool) {
record, ok := c.lru.Get(key)
if !ok {
return nil, false
}
value, ok := record.(*cacheRecord)
return value, ok
}
func (c *simpleCache) set(key string, value *cacheRecord, ttl time.Duration) {
c.lru.Add(key, value, ttl)
}
func (c *simpleCache) remove(key string) {
c.lru.Remove(key)
}

View file

@ -0,0 +1,60 @@
/*
Copyright 2017 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 cache
import (
"hash/fnv"
"time"
)
// split cache lookups across N striped caches
type stripedCache struct {
stripeCount uint32
hashFunc func(string) uint32
caches []cache
}
type hashFunc func(string) uint32
type newCacheFunc func() cache
func newStripedCache(stripeCount int, hash hashFunc, newCacheFunc newCacheFunc) cache {
caches := []cache{}
for i := 0; i < stripeCount; i++ {
caches = append(caches, newCacheFunc())
}
return &stripedCache{
stripeCount: uint32(stripeCount),
hashFunc: hash,
caches: caches,
}
}
func (c *stripedCache) get(key string) (*cacheRecord, bool) {
return c.caches[c.hashFunc(key)%c.stripeCount].get(key)
}
func (c *stripedCache) set(key string, value *cacheRecord, ttl time.Duration) {
c.caches[c.hashFunc(key)%c.stripeCount].set(key, value, ttl)
}
func (c *stripedCache) remove(key string) {
c.caches[c.hashFunc(key)%c.stripeCount].remove(key)
}
func fnvHashFunc(key string) uint32 {
f := fnv.New32()
f.Write([]byte(key))
return f.Sum32()
}

View file

@ -0,0 +1,95 @@
/*
Copyright 2017 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 cache
import (
"context"
"fmt"
"time"
utilclock "k8s.io/apimachinery/pkg/util/clock"
"k8s.io/apiserver/pkg/authentication/authenticator"
)
// cacheRecord holds the three return values of the authenticator.Token AuthenticateToken method
type cacheRecord struct {
resp *authenticator.Response
ok bool
err error
}
type cachedTokenAuthenticator struct {
authenticator authenticator.Token
cacheErrs bool
successTTL time.Duration
failureTTL time.Duration
cache cache
}
type cache interface {
// given a key, return the record, and whether or not it existed
get(key string) (value *cacheRecord, exists bool)
// caches the record for the key
set(key string, value *cacheRecord, ttl time.Duration)
// removes the record for the key
remove(key string)
}
// New returns a token authenticator that caches the results of the specified authenticator. A ttl of 0 bypasses the cache.
func New(authenticator authenticator.Token, cacheErrs bool, successTTL, failureTTL time.Duration) authenticator.Token {
return newWithClock(authenticator, cacheErrs, successTTL, failureTTL, utilclock.RealClock{})
}
func newWithClock(authenticator authenticator.Token, cacheErrs bool, successTTL, failureTTL time.Duration, clock utilclock.Clock) authenticator.Token {
return &cachedTokenAuthenticator{
authenticator: authenticator,
cacheErrs: cacheErrs,
successTTL: successTTL,
failureTTL: failureTTL,
cache: newStripedCache(32, fnvHashFunc, func() cache { return newSimpleCache(128, clock) }),
}
}
// AuthenticateToken implements authenticator.Token
func (a *cachedTokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
auds, _ := authenticator.AudiencesFrom(ctx)
key := keyFunc(auds, token)
if record, ok := a.cache.get(key); ok {
return record.resp, record.ok, record.err
}
resp, ok, err := a.authenticator.AuthenticateToken(ctx, token)
if !a.cacheErrs && err != nil {
return resp, ok, err
}
switch {
case ok && a.successTTL > 0:
a.cache.set(key, &cacheRecord{resp: resp, ok: ok, err: err}, a.successTTL)
case !ok && a.failureTTL > 0:
a.cache.set(key, &cacheRecord{resp: resp, ok: ok, err: err}, a.failureTTL)
}
return resp, ok, err
}
func keyFunc(auds []string, token string) string {
return fmt.Sprintf("%#v|%v", auds, token)
}

View file

@ -17,14 +17,16 @@ limitations under the License.
package tokenfile
import (
"context"
"encoding/csv"
"fmt"
"io"
"os"
"strings"
"github.com/golang/glog"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog"
)
type TokenAuthenticator struct {
@ -65,7 +67,7 @@ func NewCSV(path string) (*TokenAuthenticator, error) {
recordNum++
if record[0] == "" {
glog.Warningf("empty token has been found in token file '%s', record number '%d'", path, recordNum)
klog.Warningf("empty token has been found in token file '%s', record number '%d'", path, recordNum)
continue
}
@ -74,7 +76,7 @@ func NewCSV(path string) (*TokenAuthenticator, error) {
UID: record[2],
}
if _, exist := tokens[record[0]]; exist {
glog.Warningf("duplicate token has been found in token file '%s', record number '%d'", path, recordNum)
klog.Warningf("duplicate token has been found in token file '%s', record number '%d'", path, recordNum)
}
tokens[record[0]] = obj
@ -88,10 +90,10 @@ func NewCSV(path string) (*TokenAuthenticator, error) {
}, nil
}
func (a *TokenAuthenticator) AuthenticateToken(value string) (user.Info, bool, error) {
func (a *TokenAuthenticator) AuthenticateToken(ctx context.Context, value string) (*authenticator.Response, bool, error) {
user, ok := a.tokens[value]
if !ok {
return nil, false, nil
}
return user, true, nil
return &authenticator.Response{User: user}, true, nil
}

View file

@ -16,4 +16,4 @@ limitations under the License.
// Package user contains utilities for dealing with simple user exchange in the auth
// packages. The user.Info interface defines an interface for exchanging that info.
package user
package user // import "k8s.io/apiserver/pkg/authentication/user"

View file

@ -56,7 +56,7 @@ type Attributes interface {
GetAPIVersion() string
// IsResourceRequest returns true for requests to API resources, like /api/v1/nodes,
// and false for non-resource endpoints like /api, /healthz, and /swaggerapi
// and false for non-resource endpoints like /api, /healthz
IsResourceRequest() bool
// GetPath returns the path of the request

3
vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory/OWNERS generated vendored Executable file → Normal file
View file

@ -1,4 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- deads2k
- dims
- ericchiang

View file

@ -20,9 +20,8 @@ import (
"time"
"k8s.io/apiserver/pkg/authorization/authorizer"
authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
)
// DelegatingAuthorizerConfig is the minimal configuration needed to create an authenticator

View file

@ -1,5 +1,5 @@
/*
Copyright 2015 The Kubernetes Authors.
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.
@ -14,6 +14,5 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package util holds generic etcd-related utility functions that any user of ectd might want to
// use, without pulling in kubernetes-specific code.
package util // import "k8s.io/apiserver/pkg/storage/etcd/util"
// Package path contains an authorizer that allows certain paths and path prefixes.
package path // import "k8s.io/apiserver/pkg/authorization/path"

67
vendor/k8s.io/apiserver/pkg/authorization/path/path.go generated vendored Normal file
View file

@ -0,0 +1,67 @@
/*
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 path
import (
"fmt"
"strings"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
// NewAuthorizer returns an authorizer which accepts a given set of paths.
// Each path is either a fully matching path or it ends in * in case a prefix match is done. A leading / is optional.
func NewAuthorizer(alwaysAllowPaths []string) (authorizer.Authorizer, error) {
var prefixes []string
paths := sets.NewString()
for _, p := range alwaysAllowPaths {
p = strings.TrimPrefix(p, "/")
if len(p) == 0 {
// matches "/"
paths.Insert(p)
continue
}
if strings.ContainsRune(p[:len(p)-1], '*') {
return nil, fmt.Errorf("only trailing * allowed in %q", p)
}
if strings.HasSuffix(p, "*") {
prefixes = append(prefixes, p[:len(p)-1])
} else {
paths.Insert(p)
}
}
return authorizer.AuthorizerFunc(func(a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.IsResourceRequest() {
return authorizer.DecisionNoOpinion, "", nil
}
pth := strings.TrimPrefix(a.GetPath(), "/")
if paths.Has(pth) {
return authorizer.DecisionAllow, "", nil
}
for _, prefix := range prefixes {
if strings.HasPrefix(pth, prefix) {
return authorizer.DecisionAllow, "", nil
}
}
return authorizer.DecisionNoOpinion, "", nil
}), nil
}

View file

@ -32,23 +32,21 @@ import (
// legacyRootAPIHandler creates a webservice serving api group discovery.
type legacyRootAPIHandler struct {
// addresses is used to build cluster IPs for discovery.
addresses Addresses
apiPrefix string
serializer runtime.NegotiatedSerializer
apiVersions []string
addresses Addresses
apiPrefix string
serializer runtime.NegotiatedSerializer
}
func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string) *legacyRootAPIHandler {
func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string) *legacyRootAPIHandler {
// Because in release 1.1, /apis returns response with empty APIVersion, we
// use stripVersionNegotiatedSerializer to keep the response backwards
// compatible.
serializer = stripVersionNegotiatedSerializer{serializer}
return &legacyRootAPIHandler{
addresses: addresses,
apiPrefix: apiPrefix,
serializer: serializer,
apiVersions: apiVersions,
addresses: addresses,
apiPrefix: apiPrefix,
serializer: serializer,
}
}
@ -71,7 +69,7 @@ func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Respon
clientIP := utilnet.GetClientIP(req.Request)
apiVersions := &metav1.APIVersions{
ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP),
Versions: s.apiVersions,
Versions: []string{"v1"},
}
responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions)

View file

@ -0,0 +1,40 @@
/*
Copyright 2019 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 discovery
import (
"crypto/sha256"
"encoding/base64"
)
// StorageVersionHash calculates the storage version hash for a
// <group/version/kind> tuple.
// WARNING: this function is subject to change. Clients shouldn't depend on
// this function.
func StorageVersionHash(group, version, kind string) string {
gvk := group + "/" + version + "/" + kind
if gvk == "" {
return ""
}
bytes := sha256.Sum256([]byte(gvk))
// Assuming there are N kinds in the cluster, and the hash is X-byte long,
// the chance of colliding hash P(N,X) approximates to 1-e^(-(N^2)/2^(8X+1)).
// P(10,000, 8) ~= 2.7*10^(-12), which is low enough.
// See https://en.wikipedia.org/wiki/Birthday_problem#Approximations.
return base64.StdEncoding.EncodeToString(
bytes[:8])
}

2
vendor/k8s.io/apiserver/pkg/endpoints/filters/OWNERS generated vendored Executable file → Normal file
View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- deads2k
- sttts

View file

@ -56,7 +56,11 @@ func WithAudit(handler http.Handler, sink audit.Sink, policy policy.Checker, lon
}
ev.Stage = auditinternal.StageRequestReceived
processAuditEvent(sink, ev, omitStages)
if processed := processAuditEvent(sink, ev, omitStages); !processed {
audit.ApiserverAuditDroppedCounter.Inc()
responsewriters.InternalError(w, req, errors.New("failed to store audit event"))
return
}
// intercept the status code
var longRunningSink audit.Sink
@ -137,10 +141,10 @@ func createAuditEventAndAttachToContext(req *http.Request, policy policy.Checker
return req, ev, omitStages, nil
}
func processAuditEvent(sink audit.Sink, ev *auditinternal.Event, omitStages []auditinternal.Stage) {
func processAuditEvent(sink audit.Sink, ev *auditinternal.Event, omitStages []auditinternal.Stage) bool {
for _, stage := range omitStages {
if ev.Stage == stage {
return
return true
}
}
@ -150,7 +154,7 @@ func processAuditEvent(sink audit.Sink, ev *auditinternal.Event, omitStages []au
ev.StageTimestamp = metav1.NewMicroTime(time.Now())
}
audit.ObserveEvent()
sink.ProcessEvents(ev)
return sink.ProcessEvents(ev)
}
func decorateResponseWriter(responseWriter http.ResponseWriter, ev *auditinternal.Event, sink audit.Sink, omitStages []auditinternal.Stage) http.ResponseWriter {

View file

@ -21,8 +21,8 @@ import (
"net/http"
"strings"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/klog"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
@ -50,27 +50,33 @@ func init() {
// stores any such user found onto the provided context for the request. If authentication fails or returns an error
// the failed handler is used. On success, "Authorization" header is removed from the request and handler
// is invoked to serve the request.
func WithAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler) http.Handler {
func WithAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler, apiAuds authenticator.Audiences) http.Handler {
if auth == nil {
glog.Warningf("Authentication is disabled")
klog.Warningf("Authentication is disabled")
return handler
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
user, ok, err := auth.AuthenticateRequest(req)
if len(apiAuds) > 0 {
req = req.WithContext(authenticator.WithAudiences(req.Context(), apiAuds))
}
resp, ok, err := auth.AuthenticateRequest(req)
if err != nil || !ok {
if err != nil {
glog.Errorf("Unable to authenticate the request due to an error: %v", err)
klog.Errorf("Unable to authenticate the request due to an error: %v", err)
}
failed.ServeHTTP(w, req)
return
}
// TODO(mikedanese): verify the response audience matches one of apiAuds if
// non-empty
// authorization header is not required anymore in case of a successful authentication.
req.Header.Del("Authorization")
req = req.WithContext(genericapirequest.WithUser(req.Context(), user))
req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User))
authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc()
authenticatedUserCounter.WithLabelValues(compressUsername(resp.User.GetName())).Inc()
handler.ServeHTTP(w, req)
})

View file

@ -21,7 +21,7 @@ import (
"errors"
"net/http"
"github.com/golang/glog"
"k8s.io/klog"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/audit"
@ -44,7 +44,7 @@ const (
// WithAuthorizationCheck passes all authorized requests on to handler, and returns a forbidden error otherwise.
func WithAuthorization(handler http.Handler, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler {
if a == nil {
glog.Warningf("Authorization is disabled")
klog.Warningf("Authorization is disabled")
return handler
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
@ -70,7 +70,7 @@ func WithAuthorization(handler http.Handler, a authorizer.Authorizer, s runtime.
return
}
glog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason)
klog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason)
audit.LogAnnotation(ae, decisionAnnotationKey, decisionForbid)
audit.LogAnnotation(ae, reasonAnnotationKey, reason)
responsewriters.Forbidden(ctx, attributes, w, req, reason, s)

Some files were not shown because too many files have changed in this diff Show more