Commit eb89d3dd authored by Patrick Barker's avatar Patrick Barker

adds dynamic audit configuration

parent ce01e837
...@@ -270,6 +270,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ ...@@ -270,6 +270,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{
{Group: "scheduling.k8s.io", Version: "v1beta1"}: {group: 16600, version: 12}, {Group: "scheduling.k8s.io", Version: "v1beta1"}: {group: 16600, version: 12},
{Group: "scheduling.k8s.io", Version: "v1alpha1"}: {group: 16600, version: 9}, {Group: "scheduling.k8s.io", Version: "v1alpha1"}: {group: 16600, version: 9},
{Group: "coordination.k8s.io", Version: "v1beta1"}: {group: 16500, version: 9}, {Group: "coordination.k8s.io", Version: "v1beta1"}: {group: 16500, version: 9},
{Group: "auditregistration.k8s.io", Version: "v1alpha1"}: {group: 16400, version: 1},
// Append a new group to the end of the list if unsure. // Append a new group to the end of the list if unsure.
// You can use min(existing group)-100 as the initial value for a group. // You can use min(existing group)-100 as the initial value for a group.
// Version can be set to 9 (to have space around) for a new group. // Version can be set to 9 (to have space around) for a new group.
......
...@@ -391,9 +391,6 @@ func buildGenericConfig( ...@@ -391,9 +391,6 @@ func buildGenericConfig(
if lastErr = s.Authentication.ApplyTo(genericConfig); lastErr != nil { if lastErr = s.Authentication.ApplyTo(genericConfig); lastErr != nil {
return return
} }
if lastErr = s.Audit.ApplyTo(genericConfig); lastErr != nil {
return
}
if lastErr = s.Features.ApplyTo(genericConfig); lastErr != nil { if lastErr = s.Features.ApplyTo(genericConfig); lastErr != nil {
return return
} }
...@@ -464,6 +461,22 @@ func buildGenericConfig( ...@@ -464,6 +461,22 @@ func buildGenericConfig(
} }
serviceResolver = buildServiceResolver(s.EnableAggregatorRouting, genericConfig.LoopbackClientConfig.Host, versionedInformers) serviceResolver = buildServiceResolver(s.EnableAggregatorRouting, genericConfig.LoopbackClientConfig.Host, versionedInformers)
authInfoResolverWrapper := webhook.NewDefaultAuthenticationInfoResolverWrapper(proxyTransport, genericConfig.LoopbackClientConfig)
lastErr = s.Audit.ApplyTo(
genericConfig,
genericConfig.LoopbackClientConfig,
versionedInformers,
serveroptions.NewProcessInfo("kube-apiserver", "kube-system"),
&serveroptions.WebhookOptions{
AuthInfoResolverWrapper: authInfoResolverWrapper,
ServiceResolver: serviceResolver,
},
)
if lastErr != nil {
return
}
pluginInitializers, admissionPostStartHook, err = admissionConfig.New(proxyTransport, serviceResolver) pluginInitializers, admissionPostStartHook, err = admissionConfig.New(proxyTransport, serviceResolver)
if err != nil { if err != nil {
lastErr = fmt.Errorf("failed to create admission plugin initializer: %v", err) lastErr = fmt.Errorf("failed to create admission plugin initializer: %v", err)
......
...@@ -458,6 +458,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS ...@@ -458,6 +458,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
// unintentionally on either side: // unintentionally on either side:
genericfeatures.StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta}, genericfeatures.StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta},
genericfeatures.AdvancedAuditing: {Default: true, PreRelease: utilfeature.GA}, genericfeatures.AdvancedAuditing: {Default: true, PreRelease: utilfeature.GA},
genericfeatures.DynamicAuditing: {Default: false, PreRelease: utilfeature.Alpha},
genericfeatures.APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha}, genericfeatures.APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha},
genericfeatures.Initializers: {Default: false, PreRelease: utilfeature.Alpha}, genericfeatures.Initializers: {Default: false, PreRelease: utilfeature.Alpha},
genericfeatures.APIListChunking: {Default: true, PreRelease: utilfeature.Beta}, genericfeatures.APIListChunking: {Default: true, PreRelease: utilfeature.Beta},
......
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
...@@ -50,8 +50,12 @@ type CustomResourceDefinitionsServerOptions struct { ...@@ -50,8 +50,12 @@ type CustomResourceDefinitionsServerOptions struct {
// NewCustomResourceDefinitionsServerOptions creates default options of an apiextensions-apiserver. // NewCustomResourceDefinitionsServerOptions creates default options of an apiextensions-apiserver.
func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomResourceDefinitionsServerOptions { func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomResourceDefinitionsServerOptions {
o := &CustomResourceDefinitionsServerOptions{ o := &CustomResourceDefinitionsServerOptions{
RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, apiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion)), RecommendedOptions: genericoptions.NewRecommendedOptions(
APIEnablement: genericoptions.NewAPIEnablementOptions(), defaultEtcdPathPrefix,
apiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion),
genericoptions.NewProcessInfo("apiextensions-apiserver", "kube-system"),
),
APIEnablement: genericoptions.NewAPIEnablementOptions(),
StdOut: out, StdOut: out,
StdErr: errOut, StdErr: errOut,
......
...@@ -19,6 +19,7 @@ package policy ...@@ -19,6 +19,7 @@ package policy
import ( import (
"k8s.io/api/auditregistration/v1alpha1" "k8s.io/api/auditregistration/v1alpha1"
"k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/authorization/authorizer"
) )
// ConvertDynamicPolicyToInternal constructs an internal policy type from a // ConvertDynamicPolicyToInternal constructs an internal policy type from a
...@@ -37,3 +38,17 @@ func ConvertDynamicPolicyToInternal(p *v1alpha1.Policy) *audit.Policy { ...@@ -37,3 +38,17 @@ func ConvertDynamicPolicyToInternal(p *v1alpha1.Policy) *audit.Policy {
OmitStages: InvertStages(stages), 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{}
}
...@@ -52,6 +52,13 @@ const ( ...@@ -52,6 +52,13 @@ const (
// audited. // audited.
AdvancedAuditing utilfeature.Feature = "AdvancedAuditing" AdvancedAuditing utilfeature.Feature = "AdvancedAuditing"
// owner: @pbarker
// alpha: v1.13
//
// DynamicAuditing enables configuration of audit policy and webhook backends through an
// AuditSink API object.
DynamicAuditing utilfeature.Feature = "DynamicAuditing"
// owner: @ilackams // owner: @ilackams
// alpha: v1.7 // alpha: v1.7
// //
...@@ -94,6 +101,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS ...@@ -94,6 +101,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta}, StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta},
ValidateProxyRedirects: {Default: false, PreRelease: utilfeature.Alpha}, ValidateProxyRedirects: {Default: false, PreRelease: utilfeature.Alpha},
AdvancedAuditing: {Default: true, PreRelease: utilfeature.GA}, AdvancedAuditing: {Default: true, PreRelease: utilfeature.GA},
DynamicAuditing: {Default: false, PreRelease: utilfeature.Alpha},
APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha}, APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha},
Initializers: {Default: false, PreRelease: utilfeature.Alpha}, Initializers: {Default: false, PreRelease: utilfeature.Alpha},
APIListChunking: {Default: true, PreRelease: utilfeature.Beta}, APIListChunking: {Default: true, PreRelease: utilfeature.Beta},
......
...@@ -23,7 +23,15 @@ import ( ...@@ -23,7 +23,15 @@ import (
"os" "os"
"testing" "testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server"
utilfeature "k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd/api/v1" "k8s.io/client-go/tools/clientcmd/api/v1"
"github.com/spf13/pflag" "github.com/spf13/pflag"
...@@ -35,6 +43,15 @@ func TestAuditValidOptions(t *testing.T) { ...@@ -35,6 +43,15 @@ func TestAuditValidOptions(t *testing.T) {
webhookConfig := makeTmpWebhookConfig(t) webhookConfig := makeTmpWebhookConfig(t)
defer os.Remove(webhookConfig) defer os.Remove(webhookConfig)
policy := makeTmpPolicy(t)
defer os.Remove(policy)
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicAuditing, true)()
clientConfig := &restclient.Config{}
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(), 0)
processInfo := &ProcessInfo{"test", "test"}
testCases := []struct { testCases := []struct {
name string name string
options func() *AuditOptions options func() *AuditOptions
...@@ -47,23 +64,42 @@ func TestAuditValidOptions(t *testing.T) { ...@@ -47,23 +64,42 @@ func TestAuditValidOptions(t *testing.T) {
options: func() *AuditOptions { options: func() *AuditOptions {
o := NewAuditOptions() o := NewAuditOptions()
o.LogOptions.Path = "/audit" o.LogOptions.Path = "/audit"
o.PolicyFile = policy
return o return o
}, },
expected: "log", expected: "log",
}, { }, {
name: "default log no policy",
options: func() *AuditOptions {
o := NewAuditOptions()
o.LogOptions.Path = "/audit"
return o
},
expected: "",
}, {
name: "default webhook", name: "default webhook",
options: func() *AuditOptions { options: func() *AuditOptions {
o := NewAuditOptions() o := NewAuditOptions()
o.WebhookOptions.ConfigFile = webhookConfig o.WebhookOptions.ConfigFile = webhookConfig
o.PolicyFile = policy
return o return o
}, },
expected: "buffered<webhook>", expected: "buffered<webhook>",
}, { }, {
name: "default webhook no policy",
options: func() *AuditOptions {
o := NewAuditOptions()
o.WebhookOptions.ConfigFile = webhookConfig
return o
},
expected: "",
}, {
name: "default union", name: "default union",
options: func() *AuditOptions { options: func() *AuditOptions {
o := NewAuditOptions() o := NewAuditOptions()
o.LogOptions.Path = "/audit" o.LogOptions.Path = "/audit"
o.WebhookOptions.ConfigFile = webhookConfig o.WebhookOptions.ConfigFile = webhookConfig
o.PolicyFile = policy
return o return o
}, },
expected: "union[log,buffered<webhook>]", expected: "union[log,buffered<webhook>]",
...@@ -75,6 +111,7 @@ func TestAuditValidOptions(t *testing.T) { ...@@ -75,6 +111,7 @@ func TestAuditValidOptions(t *testing.T) {
o.LogOptions.Path = "/audit" o.LogOptions.Path = "/audit"
o.WebhookOptions.BatchOptions.Mode = ModeBlocking o.WebhookOptions.BatchOptions.Mode = ModeBlocking
o.WebhookOptions.ConfigFile = webhookConfig o.WebhookOptions.ConfigFile = webhookConfig
o.PolicyFile = policy
return o return o
}, },
expected: "union[buffered<log>,webhook]", expected: "union[buffered<log>,webhook]",
...@@ -84,10 +121,62 @@ func TestAuditValidOptions(t *testing.T) { ...@@ -84,10 +121,62 @@ func TestAuditValidOptions(t *testing.T) {
o := NewAuditOptions() o := NewAuditOptions()
o.WebhookOptions.ConfigFile = webhookConfig o.WebhookOptions.ConfigFile = webhookConfig
o.WebhookOptions.TruncateOptions.Enabled = true o.WebhookOptions.TruncateOptions.Enabled = true
o.PolicyFile = policy
return o return o
}, },
expected: "truncate<buffered<webhook>>", expected: "truncate<buffered<webhook>>",
}} }, {
name: "dynamic",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
return o
},
expected: "dynamic[]",
}, {
name: "dynamic with truncating",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
o.WebhookOptions.TruncateOptions.Enabled = true
return o
},
expected: "truncate<dynamic[]>",
}, {
name: "dynamic with log",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
o.LogOptions.Path = "/audit"
o.PolicyFile = policy
return o
},
expected: "union[enforced<log>,dynamic[]]",
}, {
name: "dynamic with truncating and webhook",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
o.WebhookOptions.TruncateOptions.Enabled = true
o.WebhookOptions.ConfigFile = webhookConfig
o.PolicyFile = policy
return o
},
expected: "truncate<union[enforced<buffered<webhook>>,dynamic[]]>",
}, {
name: "dynamic with truncating and webhook and log",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
o.WebhookOptions.TruncateOptions.Enabled = true
o.WebhookOptions.ConfigFile = webhookConfig
o.PolicyFile = policy
o.LogOptions.Path = "/audit"
return o
},
expected: "union[enforced<log>,truncate<union[enforced<buffered<webhook>>,dynamic[]]>]",
},
}
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
options := tc.options() options := tc.options()
...@@ -101,7 +190,7 @@ func TestAuditValidOptions(t *testing.T) { ...@@ -101,7 +190,7 @@ func TestAuditValidOptions(t *testing.T) {
assert.Empty(t, options.Validate(), "Options should be valid.") assert.Empty(t, options.Validate(), "Options should be valid.")
config := &server.Config{} config := &server.Config{}
require.NoError(t, options.ApplyTo(config)) require.NoError(t, options.ApplyTo(config, clientConfig, informerFactory, processInfo, nil))
if tc.expected == "" { if tc.expected == "" {
assert.Nil(t, config.AuditBackend) assert.Nil(t, config.AuditBackend)
} else { } else {
...@@ -176,7 +265,15 @@ func TestAuditInvalidOptions(t *testing.T) { ...@@ -176,7 +265,15 @@ func TestAuditInvalidOptions(t *testing.T) {
o.WebhookOptions.TruncateOptions.TruncateConfig.MaxBatchSize = 1 o.WebhookOptions.TruncateOptions.TruncateConfig.MaxBatchSize = 1
return o return o
}, },
}} }, {
name: "invalid dynamic flag group",
options: func() *AuditOptions {
o := NewAuditOptions()
o.DynamicOptions.Enabled = true
return o
},
},
}
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
options := tc.options() options := tc.options()
...@@ -198,3 +295,21 @@ func makeTmpWebhookConfig(t *testing.T) string { ...@@ -198,3 +295,21 @@ func makeTmpWebhookConfig(t *testing.T) string {
require.NoError(t, f.Close()) require.NoError(t, f.Close())
return f.Name() return f.Name()
} }
func makeTmpPolicy(t *testing.T) string {
pol := auditv1.Policy{
TypeMeta: metav1.TypeMeta{
APIVersion: "audit.k8s.io/v1",
},
Rules: []auditv1.PolicyRule{
{
Level: auditv1.LevelRequestResponse,
},
},
}
f, err := ioutil.TempFile("", "k8s_audit_policy_test_")
require.NoError(t, err, "creating temp file")
require.NoError(t, stdjson.NewEncoder(f).Encode(pol), "writing policy file")
require.NoError(t, f.Close())
return f.Name()
}
/*
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 options
import (
"fmt"
"os"
)
// ProcessInfo holds the apiserver process information used to send events
type ProcessInfo struct {
// Name of the api process to identify events
Name string
// Namespace of the api process to send events
Namespace string
}
// NewProcessInfo returns a new process info with the hostname concatenated to the name given
func NewProcessInfo(name, namespace string) *ProcessInfo {
// try to concat the hostname if available
host, _ := os.Hostname()
if host != "" {
name = fmt.Sprintf("%s-%s", name, host)
}
return &ProcessInfo{
Name: name,
Namespace: namespace,
}
}
// validateProcessInfo checks for a complete process info
func validateProcessInfo(p *ProcessInfo) error {
if p == nil {
return fmt.Errorf("ProcessInfo must be set")
} else if p.Name == "" {
return fmt.Errorf("ProcessInfo name must be set")
} else if p.Namespace == "" {
return fmt.Errorf("ProcessInfo namespace must be set")
}
return nil
}
...@@ -41,9 +41,12 @@ type RecommendedOptions struct { ...@@ -41,9 +41,12 @@ type RecommendedOptions struct {
// admission plugin initializers to Admission.ApplyTo. // admission plugin initializers to Admission.ApplyTo.
ExtraAdmissionInitializers func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error) ExtraAdmissionInitializers func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error)
Admission *AdmissionOptions Admission *AdmissionOptions
// ProcessInfo is used to identify events created by the server.
ProcessInfo *ProcessInfo
Webhook *WebhookOptions
} }
func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptions { func NewRecommendedOptions(prefix string, codec runtime.Codec, processInfo *ProcessInfo) *RecommendedOptions {
sso := NewSecureServingOptions() sso := NewSecureServingOptions()
// We are composing recommended options for an aggregated api-server, // We are composing recommended options for an aggregated api-server,
...@@ -62,6 +65,8 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio ...@@ -62,6 +65,8 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio
CoreAPI: NewCoreAPIOptions(), CoreAPI: NewCoreAPIOptions(),
ExtraAdmissionInitializers: func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error) { return nil, nil }, ExtraAdmissionInitializers: func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error) { return nil, nil },
Admission: NewAdmissionOptions(), Admission: NewAdmissionOptions(),
ProcessInfo: processInfo,
Webhook: NewWebhookOptions(),
} }
} }
...@@ -92,7 +97,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r ...@@ -92,7 +97,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil { if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil {
return err return err
} }
if err := o.Audit.ApplyTo(&config.Config); err != nil { if err := o.Audit.ApplyTo(&config.Config, config.ClientConfig, config.SharedInformerFactory, o.ProcessInfo, o.Webhook); err != nil {
return err return err
} }
if err := o.Features.ApplyTo(&config.Config); err != nil { if err := o.Features.ApplyTo(&config.Config); err != nil {
......
/*
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 options
import (
utilwebhook "k8s.io/apiserver/pkg/util/webhook"
)
// WebhookOptions holds the outgoing webhook options
type WebhookOptions struct {
ServiceResolver utilwebhook.ServiceResolver
AuthInfoResolverWrapper utilwebhook.AuthenticationInfoResolverWrapper
}
// NewWebhookOptions returns the default options for outgoing webhooks
func NewWebhookOptions() *WebhookOptions {
return &WebhookOptions{
ServiceResolver: utilwebhook.NewDefaultServiceResolver(),
}
}
...@@ -85,8 +85,12 @@ func (o *AggregatorOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -85,8 +85,12 @@ func (o *AggregatorOptions) AddFlags(fs *pflag.FlagSet) {
// NewDefaultOptions builds a "normal" set of options. You wouldn't normally expose this, but hyperkube isn't cobra compatible // NewDefaultOptions builds a "normal" set of options. You wouldn't normally expose this, but hyperkube isn't cobra compatible
func NewDefaultOptions(out, err io.Writer) *AggregatorOptions { func NewDefaultOptions(out, err io.Writer) *AggregatorOptions {
o := &AggregatorOptions{ o := &AggregatorOptions{
RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, aggregatorscheme.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion)), RecommendedOptions: genericoptions.NewRecommendedOptions(
APIEnablement: genericoptions.NewAPIEnablementOptions(), defaultEtcdPathPrefix,
aggregatorscheme.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion),
genericoptions.NewProcessInfo("kube-aggregator", "kube-system"),
),
APIEnablement: genericoptions.NewAPIEnablementOptions(),
StdOut: out, StdOut: out,
StdErr: err, StdErr: err,
......
...@@ -47,7 +47,11 @@ type WardleServerOptions struct { ...@@ -47,7 +47,11 @@ type WardleServerOptions struct {
func NewWardleServerOptions(out, errOut io.Writer) *WardleServerOptions { func NewWardleServerOptions(out, errOut io.Writer) *WardleServerOptions {
o := &WardleServerOptions{ o := &WardleServerOptions{
RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion)), RecommendedOptions: genericoptions.NewRecommendedOptions(
defaultEtcdPathPrefix,
apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion),
genericoptions.NewProcessInfo("wardle-apiserver", "wardle"),
),
StdOut: out, StdOut: out,
StdErr: errOut, StdErr: errOut,
......
...@@ -449,6 +449,13 @@ func GetEtcdStorageData() map[schema.GroupVersionResource]StorageData { ...@@ -449,6 +449,13 @@ func GetEtcdStorageData() map[schema.GroupVersionResource]StorageData {
ExpectedGVK: gvkP("awesome.bears.com", "v1", "Panda"), ExpectedGVK: gvkP("awesome.bears.com", "v1", "Panda"),
}, },
// -- // --
// k8s.io/kubernetes/pkg/apis/auditregistration/v1alpha1
gvr("auditregistration.k8s.io", "v1alpha1", "auditsinks"): {
Stub: `{"metadata":{"name":"sink1"},"spec":{"policy":{"level":"Metadata","stages":["ResponseStarted"]},"webhook":{"clientConfig":{"url":"http://localhost:4444","service":null,"caBundle":null}}}}`,
ExpectedEtcdPath: "/registry/auditsinks/sink1",
},
// --
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment