mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-07 10:17:51 +00:00
vendor dependencies
This commit is contained in:
parent
604208ef4f
commit
72abf135d6
1156 changed files with 78178 additions and 105799 deletions
3
vendor/k8s.io/apiserver/pkg/server/options/OWNERS
generated
vendored
Executable file → Normal file
3
vendor/k8s.io/apiserver/pkg/server/options/OWNERS
generated
vendored
Executable file → Normal file
|
|
@ -1,3 +1,5 @@
|
|||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
reviewers:
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
|
|
@ -9,7 +11,6 @@ reviewers:
|
|||
- soltysh
|
||||
- dims
|
||||
- cjcullen
|
||||
- ericchiang
|
||||
- ping035627
|
||||
- xiangpengzhao
|
||||
- enj
|
||||
|
|
|
|||
43
vendor/k8s.io/apiserver/pkg/server/options/admission.go
generated
vendored
43
vendor/k8s.io/apiserver/pkg/server/options/admission.go
generated
vendored
|
|
@ -23,11 +23,11 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/initialization"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
|
||||
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
|
||||
validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
|
||||
|
|
@ -42,8 +42,8 @@ import (
|
|||
var configScheme = runtime.NewScheme()
|
||||
|
||||
func init() {
|
||||
apiserverapi.AddToScheme(configScheme)
|
||||
apiserverapiv1alpha1.AddToScheme(configScheme)
|
||||
utilruntime.Must(apiserverapi.AddToScheme(configScheme))
|
||||
utilruntime.Must(apiserverapiv1alpha1.AddToScheme(configScheme))
|
||||
}
|
||||
|
||||
// AdmissionOptions holds the admission options
|
||||
|
|
@ -61,6 +61,8 @@ type AdmissionOptions struct {
|
|||
ConfigFile string
|
||||
// Plugins contains all registered plugins.
|
||||
Plugins *admission.Plugins
|
||||
// Decorators is a list of admission decorator to wrap around the admission plugins
|
||||
Decorators admission.Decorators
|
||||
}
|
||||
|
||||
// NewAdmissionOptions creates a new instance of AdmissionOptions
|
||||
|
|
@ -73,13 +75,14 @@ type AdmissionOptions struct {
|
|||
// Servers that do care can overwrite/append that field after creation.
|
||||
func NewAdmissionOptions() *AdmissionOptions {
|
||||
options := &AdmissionOptions{
|
||||
Plugins: admission.NewPlugins(),
|
||||
Plugins: admission.NewPlugins(),
|
||||
Decorators: admission.Decorators{admission.DecoratorFunc(admissionmetrics.WithControllerMetrics)},
|
||||
// This list is mix of mutating admission plugins and validating
|
||||
// admission plugins. The apiserver always runs the validating ones
|
||||
// after all the mutating ones, so their relative order in this list
|
||||
// doesn't matter.
|
||||
RecommendedPluginOrder: []string{lifecycle.PluginName, initialization.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
|
||||
DefaultOffPlugins: sets.NewString(initialization.PluginName),
|
||||
RecommendedPluginOrder: []string{lifecycle.PluginName, mutatingwebhook.PluginName, validatingwebhook.PluginName},
|
||||
DefaultOffPlugins: sets.NewString(),
|
||||
}
|
||||
server.RegisterAllAdmissionPlugins(options.Plugins)
|
||||
return options
|
||||
|
|
@ -92,11 +95,13 @@ func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
fs.StringSliceVar(&a.EnablePlugins, "enable-admission-plugins", a.EnablePlugins, ""+
|
||||
"admission plugins that should be enabled in addition to default enabled ones. "+
|
||||
"admission plugins that should be enabled in addition to default enabled ones ("+
|
||||
strings.Join(a.defaultEnabledPluginNames(), ", ")+"). "+
|
||||
"Comma-delimited list of admission plugins: "+strings.Join(a.Plugins.Registered(), ", ")+". "+
|
||||
"The order of plugins in this flag does not matter.")
|
||||
fs.StringSliceVar(&a.DisablePlugins, "disable-admission-plugins", a.DisablePlugins, ""+
|
||||
"admission plugins that should be disabled although they are in the default enabled plugins list. "+
|
||||
"admission plugins that should be disabled although they are in the default enabled plugins list ("+
|
||||
strings.Join(a.defaultEnabledPluginNames(), ", ")+"). "+
|
||||
"Comma-delimited list of admission plugins: "+strings.Join(a.Plugins.Registered(), ", ")+". "+
|
||||
"The order of plugins in this flag does not matter.")
|
||||
fs.StringVar(&a.ConfigFile, "admission-control-config-file", a.ConfigFile,
|
||||
|
|
@ -112,18 +117,12 @@ func (a *AdmissionOptions) ApplyTo(
|
|||
c *server.Config,
|
||||
informers informers.SharedInformerFactory,
|
||||
kubeAPIServerClientConfig *rest.Config,
|
||||
scheme *runtime.Scheme,
|
||||
pluginInitializers ...admission.PluginInitializer,
|
||||
) error {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Admission need scheme to construct admission initializer.
|
||||
if scheme == nil {
|
||||
return fmt.Errorf("admission depends on a scheme, it cannot be nil")
|
||||
}
|
||||
|
||||
// Admission depends on CoreAPI to set SharedInformerFactory and ClientConfig.
|
||||
if informers == nil {
|
||||
return fmt.Errorf("admission depends on a Kubernetes core API shared informer, it cannot be nil")
|
||||
|
|
@ -140,12 +139,12 @@ func (a *AdmissionOptions) ApplyTo(
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer, scheme)
|
||||
genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer)
|
||||
initializersChain := admission.PluginInitializers{}
|
||||
pluginInitializers = append(pluginInitializers, genericInitializer)
|
||||
initializersChain = append(initializersChain, pluginInitializers...)
|
||||
|
||||
admissionChain, err := a.Plugins.NewFromPlugins(pluginNames, pluginsConfigProvider, initializersChain, admission.DecoratorFunc(admissionmetrics.WithControllerMetrics))
|
||||
admissionChain, err := a.Plugins.NewFromPlugins(pluginNames, pluginsConfigProvider, initializersChain, a.Decorators)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -217,3 +216,15 @@ func (a *AdmissionOptions) enabledPluginNames() []string {
|
|||
|
||||
return orderedPlugins
|
||||
}
|
||||
|
||||
//Return names of plugins which are enabled by default
|
||||
func (a *AdmissionOptions) defaultEnabledPluginNames() []string {
|
||||
defaultOnPluginNames := []string{}
|
||||
for _, pluginName := range a.RecommendedPluginOrder {
|
||||
if !a.DefaultOffPlugins.Has(pluginName) {
|
||||
defaultOnPluginNames = append(defaultOnPluginNames, pluginName)
|
||||
}
|
||||
}
|
||||
|
||||
return defaultOnPluginNames
|
||||
}
|
||||
|
|
|
|||
9
vendor/k8s.io/apiserver/pkg/server/options/api_enablement.go
generated
vendored
9
vendor/k8s.io/apiserver/pkg/server/options/api_enablement.go
generated
vendored
|
|
@ -25,18 +25,18 @@ import (
|
|||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/resourceconfig"
|
||||
serverstore "k8s.io/apiserver/pkg/server/storage"
|
||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
)
|
||||
|
||||
// APIEnablementOptions contains the options for which resources to turn on and off.
|
||||
// Given small aggregated API servers, this option isn't required for "normal" API servers
|
||||
type APIEnablementOptions struct {
|
||||
RuntimeConfig utilflag.ConfigurationMap
|
||||
RuntimeConfig cliflag.ConfigurationMap
|
||||
}
|
||||
|
||||
func NewAPIEnablementOptions() *APIEnablementOptions {
|
||||
return &APIEnablementOptions{
|
||||
RuntimeConfig: make(utilflag.ConfigurationMap),
|
||||
RuntimeConfig: make(cliflag.ConfigurationMap),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ func (s *APIEnablementOptions) Validate(registries ...GroupRegisty) []error {
|
|||
errors := []error{}
|
||||
if s.RuntimeConfig["api/all"] == "false" && len(s.RuntimeConfig) == 1 {
|
||||
// Do not allow only set api/all=false, in such case apiserver startup has no meaning.
|
||||
return append(errors, fmt.Errorf("invliad key with only api/all=false"))
|
||||
return append(errors, fmt.Errorf("invalid key with only api/all=false"))
|
||||
}
|
||||
|
||||
groups, err := resourceconfig.ParseGroups(s.RuntimeConfig)
|
||||
|
|
@ -84,6 +84,7 @@ func (s *APIEnablementOptions) Validate(registries ...GroupRegisty) []error {
|
|||
|
||||
// ApplyTo override MergedResourceConfig with defaults and registry
|
||||
func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *serverstore.ResourceConfig, registry resourceconfig.GroupVersionRegistry) error {
|
||||
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
390
vendor/k8s.io/apiserver/pkg/server/options/audit.go
generated
vendored
390
vendor/k8s.io/apiserver/pkg/server/options/audit.go
generated
vendored
|
|
@ -23,11 +23,14 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"k8s.io/klog"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"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/audit"
|
||||
|
|
@ -36,31 +39,46 @@ import (
|
|||
"k8s.io/apiserver/pkg/server"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
pluginbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
||||
plugindynamic "k8s.io/apiserver/plugin/pkg/audit/dynamic"
|
||||
pluginenforced "k8s.io/apiserver/plugin/pkg/audit/dynamic/enforced"
|
||||
pluginlog "k8s.io/apiserver/plugin/pkg/audit/log"
|
||||
plugintruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
||||
pluginwebhook "k8s.io/apiserver/plugin/pkg/audit/webhook"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
const (
|
||||
// Default configuration values for ModeBatch.
|
||||
defaultBatchBufferSize = 10000 // Buffer up to 10000 events before starting discarding.
|
||||
// These batch parameters are only used by the webhook backend.
|
||||
defaultBatchMaxSize = 400 // Only send up to 400 events at a time.
|
||||
defaultBatchMaxWait = 30 * time.Second // Send events at least twice a minute.
|
||||
defaultBatchThrottleQPS = 10 // Limit the send rate by 10 QPS.
|
||||
defaultBatchThrottleBurst = 15 // Allow up to 15 QPS burst.
|
||||
)
|
||||
|
||||
func appendBackend(existing, newBackend audit.Backend) audit.Backend {
|
||||
if existing == nil {
|
||||
return newBackend
|
||||
}
|
||||
if newBackend == nil {
|
||||
return existing
|
||||
}
|
||||
return audit.Union(existing, newBackend)
|
||||
}
|
||||
|
||||
func advancedAuditingEnabled() bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing)
|
||||
}
|
||||
|
||||
type AuditOptions struct {
|
||||
// Policy configuration file for filtering audit events that are captured.
|
||||
// If unspecified, a default is provided.
|
||||
PolicyFile string
|
||||
|
||||
// Plugin options
|
||||
|
||||
LogOptions AuditLogOptions
|
||||
WebhookOptions AuditWebhookOptions
|
||||
DynamicOptions AuditDynamicOptions
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -72,12 +90,17 @@ const (
|
|||
// a set of events. This causes requests to the API server to wait for the
|
||||
// flush before sending a response.
|
||||
ModeBlocking = "blocking"
|
||||
// ModeBlockingStrict is the same as ModeBlocking, except when there is
|
||||
// a failure during audit logging at RequestReceived stage, the whole
|
||||
// request to apiserver will fail.
|
||||
ModeBlockingStrict = "blocking-strict"
|
||||
)
|
||||
|
||||
// AllowedModes is the modes known for audit backends.
|
||||
var AllowedModes = []string{
|
||||
ModeBatch,
|
||||
ModeBlocking,
|
||||
ModeBlockingStrict,
|
||||
}
|
||||
|
||||
type AuditBatchOptions struct {
|
||||
|
|
@ -99,8 +122,6 @@ type AuditTruncateOptions struct {
|
|||
}
|
||||
|
||||
// AuditLogOptions determines the output of the structured audit log by default.
|
||||
// If the AdvancedAuditing feature is set to false, AuditLogOptions holds the legacy
|
||||
// audit log writer.
|
||||
type AuditLogOptions struct {
|
||||
Path string
|
||||
MaxAge int
|
||||
|
|
@ -127,28 +148,39 @@ type AuditWebhookOptions struct {
|
|||
GroupVersionString string
|
||||
}
|
||||
|
||||
func NewAuditOptions() *AuditOptions {
|
||||
defaultLogBatchConfig := pluginbuffered.NewDefaultBatchConfig()
|
||||
defaultLogBatchConfig.ThrottleEnable = false
|
||||
// AuditDynamicOptions control the configuration of dynamic backends for audit events
|
||||
type AuditDynamicOptions struct {
|
||||
// Enabled tells whether the dynamic audit capability is enabled.
|
||||
Enabled bool
|
||||
|
||||
// Configuration for batching backend. This is currently only used as an override
|
||||
// for integration tests
|
||||
BatchConfig *pluginbuffered.BatchConfig
|
||||
}
|
||||
|
||||
func NewAuditOptions() *AuditOptions {
|
||||
return &AuditOptions{
|
||||
WebhookOptions: AuditWebhookOptions{
|
||||
InitialBackoff: pluginwebhook.DefaultInitialBackoff,
|
||||
BatchOptions: AuditBatchOptions{
|
||||
Mode: ModeBatch,
|
||||
BatchConfig: pluginbuffered.NewDefaultBatchConfig(),
|
||||
BatchConfig: defaultWebhookBatchConfig(),
|
||||
},
|
||||
TruncateOptions: NewAuditTruncateOptions(),
|
||||
GroupVersionString: "audit.k8s.io/v1beta1",
|
||||
GroupVersionString: "audit.k8s.io/v1",
|
||||
},
|
||||
LogOptions: AuditLogOptions{
|
||||
Format: pluginlog.FormatJson,
|
||||
BatchOptions: AuditBatchOptions{
|
||||
Mode: ModeBlocking,
|
||||
BatchConfig: defaultLogBatchConfig,
|
||||
BatchConfig: defaultLogBatchConfig(),
|
||||
},
|
||||
TruncateOptions: NewAuditTruncateOptions(),
|
||||
GroupVersionString: "audit.k8s.io/v1beta1",
|
||||
GroupVersionString: "audit.k8s.io/v1",
|
||||
},
|
||||
DynamicOptions: AuditDynamicOptions{
|
||||
Enabled: false,
|
||||
BatchConfig: plugindynamic.NewDefaultWebhookBatchConfig(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -169,19 +201,10 @@ func (o *AuditOptions) Validate() []error {
|
|||
return nil
|
||||
}
|
||||
|
||||
allErrors := []error{}
|
||||
|
||||
if !advancedAuditingEnabled() {
|
||||
if len(o.PolicyFile) > 0 {
|
||||
allErrors = append(allErrors, fmt.Errorf("feature '%s' must be enabled to set option --audit-policy-file", features.AdvancedAuditing))
|
||||
}
|
||||
if len(o.WebhookOptions.ConfigFile) > 0 {
|
||||
allErrors = append(allErrors, fmt.Errorf("feature '%s' must be enabled to set option --audit-webhook-config-file", features.AdvancedAuditing))
|
||||
}
|
||||
}
|
||||
|
||||
var allErrors []error
|
||||
allErrors = append(allErrors, o.LogOptions.Validate()...)
|
||||
allErrors = append(allErrors, o.WebhookOptions.Validate()...)
|
||||
allErrors = append(allErrors, o.DynamicOptions.Validate()...)
|
||||
|
||||
return allErrors
|
||||
}
|
||||
|
|
@ -210,11 +233,13 @@ func validateBackendBatchOptions(pluginName string, options AuditBatchOptions) e
|
|||
if config.MaxBatchSize <= 0 {
|
||||
return fmt.Errorf("invalid audit batch %s max batch size %v, must be a positive number", pluginName, config.MaxBatchSize)
|
||||
}
|
||||
if config.ThrottleQPS <= 0 {
|
||||
return fmt.Errorf("invalid audit batch %s throttle QPS %v, must be a positive number", pluginName, config.ThrottleQPS)
|
||||
}
|
||||
if config.ThrottleBurst <= 0 {
|
||||
return fmt.Errorf("invalid audit batch %s throttle burst %v, must be a positive number", pluginName, config.ThrottleBurst)
|
||||
if config.ThrottleEnable {
|
||||
if config.ThrottleQPS <= 0 {
|
||||
return fmt.Errorf("invalid audit batch %s throttle QPS %v, must be a positive number", pluginName, config.ThrottleQPS)
|
||||
}
|
||||
if config.ThrottleBurst <= 0 {
|
||||
return fmt.Errorf("invalid audit batch %s throttle burst %v, must be a positive number", pluginName, config.ThrottleBurst)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -222,6 +247,7 @@ func validateBackendBatchOptions(pluginName string, options AuditBatchOptions) e
|
|||
var knownGroupVersions = []schema.GroupVersion{
|
||||
auditv1alpha1.SchemeGroupVersion,
|
||||
auditv1beta1.SchemeGroupVersion,
|
||||
auditv1.SchemeGroupVersion,
|
||||
}
|
||||
|
||||
func validateGroupVersionString(groupVersion string) error {
|
||||
|
|
@ -250,8 +276,7 @@ func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
fs.StringVar(&o.PolicyFile, "audit-policy-file", o.PolicyFile,
|
||||
"Path to the file that defines the audit policy configuration. Requires the 'AdvancedAuditing' feature gate."+
|
||||
" With AdvancedAuditing, a profile is required to enable auditing.")
|
||||
"Path to the file that defines the audit policy configuration.")
|
||||
|
||||
o.LogOptions.AddFlags(fs)
|
||||
o.LogOptions.BatchOptions.AddFlags(pluginlog.PluginName, fs)
|
||||
|
|
@ -259,49 +284,102 @@ func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
o.WebhookOptions.AddFlags(fs)
|
||||
o.WebhookOptions.BatchOptions.AddFlags(pluginwebhook.PluginName, fs)
|
||||
o.WebhookOptions.TruncateOptions.AddFlags(pluginwebhook.PluginName, fs)
|
||||
o.DynamicOptions.AddFlags(fs)
|
||||
}
|
||||
|
||||
func (o *AuditOptions) ApplyTo(c *server.Config) error {
|
||||
func (o *AuditOptions) ApplyTo(
|
||||
c *server.Config,
|
||||
kubeClientConfig *restclient.Config,
|
||||
informers informers.SharedInformerFactory,
|
||||
processInfo *ProcessInfo,
|
||||
webhookOptions *WebhookOptions,
|
||||
) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply legacy audit options if advanced audit is not enabled.
|
||||
if !advancedAuditingEnabled() {
|
||||
return o.LogOptions.legacyApplyTo(c)
|
||||
if c == nil {
|
||||
return fmt.Errorf("server config must be non-nil")
|
||||
}
|
||||
|
||||
// Apply advanced options if advanced audit is enabled.
|
||||
// 1. Apply generic options.
|
||||
if err := o.applyTo(c); err != nil {
|
||||
// 1. Build policy checker
|
||||
checker, err := o.newPolicyChecker()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. Apply plugin options.
|
||||
if err := o.LogOptions.advancedApplyTo(c); err != nil {
|
||||
return err
|
||||
// 2. Build log backend
|
||||
var logBackend audit.Backend
|
||||
if w := o.LogOptions.getWriter(); w != nil {
|
||||
if checker == nil {
|
||||
klog.V(2).Info("No audit policy file provided, no events will be recorded for log backend")
|
||||
} else {
|
||||
logBackend = o.LogOptions.newBackend(w)
|
||||
}
|
||||
}
|
||||
if err := o.WebhookOptions.applyTo(c); err != nil {
|
||||
|
||||
// 3. Build webhook backend
|
||||
var webhookBackend audit.Backend
|
||||
if o.WebhookOptions.enabled() {
|
||||
if checker == nil {
|
||||
klog.V(2).Info("No audit policy file provided, no events will be recorded for webhook backend")
|
||||
} else {
|
||||
webhookBackend, err = o.WebhookOptions.newUntruncatedBackend()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
groupVersion, err := schema.ParseGroupVersion(o.WebhookOptions.GroupVersionString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.AuditBackend != nil && c.AuditPolicyChecker == nil {
|
||||
glog.V(2).Info("No audit policy file provided for AdvancedAuditing, no events will be recorded.")
|
||||
// 4. Apply dynamic options.
|
||||
var dynamicBackend audit.Backend
|
||||
if o.DynamicOptions.enabled() {
|
||||
// if dynamic is enabled the webhook and log backends need to be wrapped in an enforced backend with the static policy
|
||||
if webhookBackend != nil {
|
||||
webhookBackend = pluginenforced.NewBackend(webhookBackend, checker)
|
||||
}
|
||||
if logBackend != nil {
|
||||
logBackend = pluginenforced.NewBackend(logBackend, checker)
|
||||
}
|
||||
// build dynamic backend
|
||||
dynamicBackend, checker, err = o.DynamicOptions.newBackend(c.ExternalAddress, kubeClientConfig, informers, processInfo, webhookOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// union dynamic and webhook backends so that truncate options can be applied to both
|
||||
dynamicBackend = appendBackend(webhookBackend, dynamicBackend)
|
||||
dynamicBackend = o.WebhookOptions.TruncateOptions.wrapBackend(dynamicBackend, groupVersion)
|
||||
} else if webhookBackend != nil {
|
||||
// if only webhook is enabled wrap it in the truncate options
|
||||
dynamicBackend = o.WebhookOptions.TruncateOptions.wrapBackend(webhookBackend, groupVersion)
|
||||
}
|
||||
|
||||
// 5. Set the policy checker
|
||||
c.AuditPolicyChecker = checker
|
||||
|
||||
// 6. Join the log backend with the webhooks
|
||||
c.AuditBackend = appendBackend(logBackend, dynamicBackend)
|
||||
|
||||
if c.AuditBackend != nil {
|
||||
klog.V(2).Infof("Using audit backend: %s", c.AuditBackend)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *AuditOptions) applyTo(c *server.Config) error {
|
||||
func (o *AuditOptions) newPolicyChecker() (policy.Checker, error) {
|
||||
if o.PolicyFile == "" {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
p, err := policy.LoadPolicyFromFile(o.PolicyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading audit policy file: %v", err)
|
||||
return nil, fmt.Errorf("loading audit policy file: %v", err)
|
||||
}
|
||||
c.AuditPolicyChecker = policy.NewChecker(p)
|
||||
return nil
|
||||
return policy.NewChecker(p), nil
|
||||
}
|
||||
|
||||
func (o *AuditBatchOptions) AddFlags(pluginName string, fs *pflag.FlagSet) {
|
||||
|
|
@ -327,10 +405,26 @@ func (o *AuditBatchOptions) AddFlags(pluginName string, fs *pflag.FlagSet) {
|
|||
"moment if ThrottleQPS was not utilized before. Only used in batch mode.")
|
||||
}
|
||||
|
||||
type ignoreErrorsBackend struct {
|
||||
audit.Backend
|
||||
}
|
||||
|
||||
func (i *ignoreErrorsBackend) ProcessEvents(ev ...*auditinternal.Event) bool {
|
||||
i.Backend.ProcessEvents(ev...)
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *ignoreErrorsBackend) String() string {
|
||||
return fmt.Sprintf("ignoreErrors<%s>", i.Backend)
|
||||
}
|
||||
|
||||
func (o *AuditBatchOptions) wrapBackend(delegate audit.Backend) audit.Backend {
|
||||
if o.Mode == ModeBlocking {
|
||||
if o.Mode == ModeBlockingStrict {
|
||||
return delegate
|
||||
}
|
||||
if o.Mode == ModeBlocking {
|
||||
return &ignoreErrorsBackend{Backend: delegate}
|
||||
}
|
||||
return pluginbuffered.NewBackend(delegate, o.BatchConfig)
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +449,7 @@ func (o *AuditTruncateOptions) AddFlags(pluginName string, fs *pflag.FlagSet) {
|
|||
"it is split into several batches of smaller size.")
|
||||
fs.Int64Var(&o.TruncateConfig.MaxEventSize, fmt.Sprintf("audit-%s-truncate-max-event-size", pluginName),
|
||||
o.TruncateConfig.MaxEventSize, "Maximum size of the audit event sent to the underlying backend. "+
|
||||
"If the size of an event is greater than this number, first request and response are removed, and"+
|
||||
"If the size of an event is greater than this number, first request and response are removed, and "+
|
||||
"if this doesn't reduce the size enough, event is discarded.")
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +463,7 @@ func (o *AuditTruncateOptions) wrapBackend(delegate audit.Backend, gv schema.Gro
|
|||
func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&o.Path, "audit-log-path", o.Path,
|
||||
"If set, all requests coming to the apiserver will be logged to this file. '-' means standard out.")
|
||||
fs.IntVar(&o.MaxAge, "audit-log-maxage", o.MaxBackups,
|
||||
fs.IntVar(&o.MaxAge, "audit-log-maxage", o.MaxAge,
|
||||
"The maximum number of days to retain old audit log files based on the timestamp encoded in their filename.")
|
||||
fs.IntVar(&o.MaxBackups, "audit-log-maxbackup", o.MaxBackups,
|
||||
"The maximum number of old audit log files to retain.")
|
||||
|
|
@ -377,8 +471,8 @@ func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
"The maximum size in megabytes of the audit log file before it gets rotated.")
|
||||
fs.StringVar(&o.Format, "audit-log-format", o.Format,
|
||||
"Format of saved audits. \"legacy\" indicates 1-line text format for each event."+
|
||||
" \"json\" indicates structured json format. Requires the 'AdvancedAuditing' feature"+
|
||||
" gate. Known formats are "+strings.Join(pluginlog.AllowedFormats, ",")+".")
|
||||
" \"json\" indicates structured json format. Known formats are "+
|
||||
strings.Join(pluginlog.AllowedFormats, ",")+".")
|
||||
fs.StringVar(&o.GroupVersionString, "audit-log-version", o.GroupVersionString,
|
||||
"API group and version used for serializing audit events written to log.")
|
||||
}
|
||||
|
|
@ -390,30 +484,29 @@ func (o *AuditLogOptions) Validate() []error {
|
|||
}
|
||||
|
||||
var allErrors []error
|
||||
if advancedAuditingEnabled() {
|
||||
if err := validateBackendBatchOptions(pluginlog.PluginName, o.BatchOptions); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := o.TruncateOptions.Validate(pluginlog.PluginName); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
|
||||
if err := validateGroupVersionString(o.GroupVersionString); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := validateBackendBatchOptions(pluginlog.PluginName, o.BatchOptions); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := o.TruncateOptions.Validate(pluginlog.PluginName); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
|
||||
// Check log format
|
||||
validFormat := false
|
||||
for _, f := range pluginlog.AllowedFormats {
|
||||
if f == o.Format {
|
||||
validFormat = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !validFormat {
|
||||
allErrors = append(allErrors, fmt.Errorf("invalid audit log format %s, allowed formats are %q", o.Format, strings.Join(pluginlog.AllowedFormats, ",")))
|
||||
if err := validateGroupVersionString(o.GroupVersionString); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
|
||||
// Check log format
|
||||
validFormat := false
|
||||
for _, f := range pluginlog.AllowedFormats {
|
||||
if f == o.Format {
|
||||
validFormat = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !validFormat {
|
||||
allErrors = append(allErrors, fmt.Errorf("invalid audit log format %s, allowed formats are %q", o.Format, strings.Join(pluginlog.AllowedFormats, ",")))
|
||||
}
|
||||
|
||||
// Check validities of MaxAge, MaxBackups and MaxSize of log options, if file log backend is enabled.
|
||||
if o.MaxAge < 0 {
|
||||
|
|
@ -451,26 +544,17 @@ func (o *AuditLogOptions) getWriter() io.Writer {
|
|||
return w
|
||||
}
|
||||
|
||||
func (o *AuditLogOptions) advancedApplyTo(c *server.Config) error {
|
||||
if w := o.getWriter(); w != nil {
|
||||
groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString)
|
||||
log := pluginlog.NewBackend(w, o.Format, groupVersion)
|
||||
log = o.BatchOptions.wrapBackend(log)
|
||||
log = o.TruncateOptions.wrapBackend(log, groupVersion)
|
||||
c.AuditBackend = appendBackend(c.AuditBackend, log)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *AuditLogOptions) legacyApplyTo(c *server.Config) error {
|
||||
c.LegacyAuditWriter = o.getWriter()
|
||||
return nil
|
||||
func (o *AuditLogOptions) newBackend(w io.Writer) audit.Backend {
|
||||
groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString)
|
||||
log := pluginlog.NewBackend(w, o.Format, groupVersion)
|
||||
log = o.BatchOptions.wrapBackend(log)
|
||||
log = o.TruncateOptions.wrapBackend(log, groupVersion)
|
||||
return log
|
||||
}
|
||||
|
||||
func (o *AuditWebhookOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&o.ConfigFile, "audit-webhook-config-file", o.ConfigFile,
|
||||
"Path to a kubeconfig formatted file that defines the audit webhook configuration."+
|
||||
" Requires the 'AdvancedAuditing' feature gate.")
|
||||
"Path to a kubeconfig formatted file that defines the audit webhook configuration.")
|
||||
fs.DurationVar(&o.InitialBackoff, "audit-webhook-initial-backoff",
|
||||
o.InitialBackoff, "The amount of time to wait before retrying the first failed request.")
|
||||
fs.DurationVar(&o.InitialBackoff, "audit-webhook-batch-initial-backoff",
|
||||
|
|
@ -487,17 +571,15 @@ func (o *AuditWebhookOptions) Validate() []error {
|
|||
}
|
||||
|
||||
var allErrors []error
|
||||
if advancedAuditingEnabled() {
|
||||
if err := validateBackendBatchOptions(pluginwebhook.PluginName, o.BatchOptions); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := o.TruncateOptions.Validate(pluginwebhook.PluginName); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := validateBackendBatchOptions(pluginwebhook.PluginName, o.BatchOptions); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := o.TruncateOptions.Validate(pluginwebhook.PluginName); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
|
||||
if err := validateGroupVersionString(o.GroupVersionString); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
if err := validateGroupVersionString(o.GroupVersionString); err != nil {
|
||||
allErrors = append(allErrors, err)
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
|
@ -506,18 +588,102 @@ func (o *AuditWebhookOptions) enabled() bool {
|
|||
return o != nil && o.ConfigFile != ""
|
||||
}
|
||||
|
||||
func (o *AuditWebhookOptions) applyTo(c *server.Config) error {
|
||||
if !o.enabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// newUntruncatedBackend returns a webhook backend without the truncate options applied
|
||||
// this is done so that the same trucate backend can wrap both the webhook and dynamic backends
|
||||
func (o *AuditWebhookOptions) newUntruncatedBackend() (audit.Backend, error) {
|
||||
groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString)
|
||||
webhook, err := pluginwebhook.NewBackend(o.ConfigFile, groupVersion, o.InitialBackoff)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing audit webhook: %v", err)
|
||||
return nil, fmt.Errorf("initializing audit webhook: %v", err)
|
||||
}
|
||||
webhook = o.BatchOptions.wrapBackend(webhook)
|
||||
webhook = o.TruncateOptions.wrapBackend(webhook, groupVersion)
|
||||
c.AuditBackend = appendBackend(c.AuditBackend, webhook)
|
||||
return nil
|
||||
return webhook, nil
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&o.Enabled, "audit-dynamic-configuration", o.Enabled,
|
||||
"Enables dynamic audit configuration. This feature also requires the DynamicAuditing feature flag")
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) enabled() bool {
|
||||
return o.Enabled && utilfeature.DefaultFeatureGate.Enabled(features.DynamicAuditing)
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) Validate() []error {
|
||||
var allErrors []error
|
||||
if o.Enabled && !utilfeature.DefaultFeatureGate.Enabled(features.DynamicAuditing) {
|
||||
allErrors = append(allErrors, fmt.Errorf("--audit-dynamic-configuration set, but DynamicAuditing feature gate is not enabled"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) newBackend(
|
||||
hostname string,
|
||||
kubeClientConfig *restclient.Config,
|
||||
informers informers.SharedInformerFactory,
|
||||
processInfo *ProcessInfo,
|
||||
webhookOptions *WebhookOptions,
|
||||
) (audit.Backend, policy.Checker, error) {
|
||||
if err := validateProcessInfo(processInfo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(kubeClientConfig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if webhookOptions == nil {
|
||||
webhookOptions = NewWebhookOptions()
|
||||
}
|
||||
checker := policy.NewDynamicChecker()
|
||||
informer := informers.Auditregistration().V1alpha1().AuditSinks()
|
||||
eventSink := &v1core.EventSinkImpl{Interface: clientset.CoreV1().Events(processInfo.Namespace)}
|
||||
|
||||
dc := &plugindynamic.Config{
|
||||
Informer: informer,
|
||||
BufferedConfig: o.BatchConfig,
|
||||
EventConfig: plugindynamic.EventConfig{
|
||||
Sink: eventSink,
|
||||
Source: corev1.EventSource{
|
||||
Component: processInfo.Name,
|
||||
Host: hostname,
|
||||
},
|
||||
},
|
||||
WebhookConfig: plugindynamic.WebhookConfig{
|
||||
AuthInfoResolverWrapper: webhookOptions.AuthInfoResolverWrapper,
|
||||
ServiceResolver: webhookOptions.ServiceResolver,
|
||||
},
|
||||
}
|
||||
backend, err := plugindynamic.NewBackend(dc)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not create dynamic audit backend: %v", err)
|
||||
}
|
||||
return backend, checker, nil
|
||||
}
|
||||
|
||||
// defaultWebhookBatchConfig returns the default BatchConfig used by the Webhook backend.
|
||||
func defaultWebhookBatchConfig() pluginbuffered.BatchConfig {
|
||||
return pluginbuffered.BatchConfig{
|
||||
BufferSize: defaultBatchBufferSize,
|
||||
MaxBatchSize: defaultBatchMaxSize,
|
||||
MaxBatchWait: defaultBatchMaxWait,
|
||||
|
||||
ThrottleEnable: true,
|
||||
ThrottleQPS: defaultBatchThrottleQPS,
|
||||
ThrottleBurst: defaultBatchThrottleBurst,
|
||||
|
||||
AsyncDelegate: true,
|
||||
}
|
||||
}
|
||||
|
||||
// defaultLogBatchConfig returns the default BatchConfig used by the Log backend.
|
||||
func defaultLogBatchConfig() pluginbuffered.BatchConfig {
|
||||
return pluginbuffered.BatchConfig{
|
||||
BufferSize: defaultBatchBufferSize,
|
||||
// Batching is not useful for the log-file backend.
|
||||
// MaxBatchWait ignored.
|
||||
MaxBatchSize: 1,
|
||||
ThrottleEnable: false,
|
||||
// Asynchronous log threads just create lock contention.
|
||||
AsyncDelegate: false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
255
vendor/k8s.io/apiserver/pkg/server/options/authentication.go
generated
vendored
255
vendor/k8s.io/apiserver/pkg/server/options/authentication.go
generated
vendored
|
|
@ -22,24 +22,28 @@ import (
|
|||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
|
||||
coreclient "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
)
|
||||
|
||||
type RequestHeaderAuthenticationOptions struct {
|
||||
// ClientCAFile is the root certificate bundle to verify client certificates on incoming requests
|
||||
// before trusting usernames in headers.
|
||||
ClientCAFile string
|
||||
|
||||
UsernameHeaders []string
|
||||
GroupHeaders []string
|
||||
ExtraHeaderPrefixes []string
|
||||
ClientCAFile string
|
||||
AllowedNames []string
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +107,9 @@ type DelegatingAuthenticationOptions struct {
|
|||
// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
|
||||
// TokenAccessReview.authentication.k8s.io endpoint for checking tokens.
|
||||
RemoteKubeConfigFile string
|
||||
// RemoteKubeConfigFileOptional is specifying whether not specifying the kubeconfig or
|
||||
// a missing in-cluster config will be fatal.
|
||||
RemoteKubeConfigFileOptional bool
|
||||
|
||||
// CacheTTL is the length of time that a token authentication answer will be cached.
|
||||
CacheTTL time.Duration
|
||||
|
|
@ -110,7 +117,12 @@ type DelegatingAuthenticationOptions struct {
|
|||
ClientCert ClientCertAuthenticationOptions
|
||||
RequestHeader RequestHeaderAuthenticationOptions
|
||||
|
||||
// SkipInClusterLookup indicates missing authentication configuration should not be retrieved from the cluster configmap
|
||||
SkipInClusterLookup bool
|
||||
|
||||
// TolerateInClusterLookupFailure indicates failures to look up authentication configuration from the cluster configmap should not be fatal.
|
||||
// Setting this can result in an authenticator that will reject all requests.
|
||||
TolerateInClusterLookupFailure bool
|
||||
}
|
||||
|
||||
func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
|
||||
|
|
@ -136,9 +148,13 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
return
|
||||
}
|
||||
|
||||
var optionalKubeConfigSentence string
|
||||
if s.RemoteKubeConfigFileOptional {
|
||||
optionalKubeConfigSentence = " This is optional. If empty, all token requests are considered to be anonymous and no client CA is looked up in the cluster."
|
||||
}
|
||||
fs.StringVar(&s.RemoteKubeConfigFile, "authentication-kubeconfig", s.RemoteKubeConfigFile, ""+
|
||||
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
|
||||
"tokenaccessreviews.authentication.k8s.io.")
|
||||
"tokenaccessreviews.authentication.k8s.io."+optionalKubeConfigSentence)
|
||||
|
||||
fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL,
|
||||
"The duration to cache responses from the webhook token authenticator.")
|
||||
|
|
@ -149,7 +165,9 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
fs.BoolVar(&s.SkipInClusterLookup, "authentication-skip-lookup", s.SkipInClusterLookup, ""+
|
||||
"If false, the authentication-kubeconfig will be used to lookup missing authentication "+
|
||||
"configuration from the cluster.")
|
||||
|
||||
fs.BoolVar(&s.TolerateInClusterLookupFailure, "authentication-tolerate-lookup-failure", s.TolerateInClusterLookupFailure, ""+
|
||||
"If true, failures to look up missing authentication configuration from the cluster are not considered fatal. "+
|
||||
"Note that this can result in authentication that treats all requests as anonymous.")
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, servingInfo *server.SecureServingInfo, openAPIConfig *openapicommon.Config) error {
|
||||
|
|
@ -158,35 +176,51 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo,
|
|||
return nil
|
||||
}
|
||||
|
||||
clientCA, err := s.getClientCA()
|
||||
cfg := authenticatorfactory.DelegatingAuthenticatorConfig{
|
||||
Anonymous: true,
|
||||
CacheTTL: s.CacheTTL,
|
||||
}
|
||||
|
||||
client, err := s.getClient()
|
||||
if err != nil {
|
||||
if _, ignorable := err.(ignorableError); !ignorable {
|
||||
return err
|
||||
} else {
|
||||
glog.Warning(err)
|
||||
return fmt.Errorf("failed to get delegated authentication kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// configure token review
|
||||
if client != nil {
|
||||
cfg.TokenAccessReviewClient = client.AuthenticationV1beta1().TokenReviews()
|
||||
}
|
||||
|
||||
// look into configmaps/external-apiserver-authentication for missing authn info
|
||||
if !s.SkipInClusterLookup {
|
||||
err := s.lookupMissingConfigInCluster(client)
|
||||
if err != nil {
|
||||
if s.TolerateInClusterLookupFailure {
|
||||
klog.Warningf("Error looking up in-cluster authentication configuration: %v", err)
|
||||
klog.Warningf("Continuing without authentication configuration. This may treat all requests as anonymous.")
|
||||
klog.Warningf("To require authentication configuration lookup to succeed, set --authentication-tolerate-lookup-failure=false")
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = c.ApplyClientCert(clientCA.ClientCA, servingInfo); err != nil {
|
||||
|
||||
// configure AuthenticationInfo config
|
||||
cfg.ClientCAFile = s.ClientCert.ClientCA
|
||||
if err = c.ApplyClientCert(s.ClientCert.ClientCA, servingInfo); err != nil {
|
||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
||||
}
|
||||
|
||||
requestHeader, err := s.getRequestHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = c.ApplyClientCert(requestHeader.ClientCAFile, servingInfo); err != nil {
|
||||
cfg.RequestHeaderConfig = s.RequestHeader.ToAuthenticationRequestHeaderConfig()
|
||||
if err = c.ApplyClientCert(s.RequestHeader.ClientCAFile, servingInfo); err != nil {
|
||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
||||
}
|
||||
|
||||
cfg, err := s.ToAuthenticationConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// create authenticator
|
||||
authenticator, securityDefinitions, err := cfg.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Authenticator = authenticator
|
||||
if openAPIConfig != nil {
|
||||
openAPIConfig.SecurityDefinitions = securityDefinitions
|
||||
|
|
@ -196,35 +230,6 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticatorfactory.DelegatingAuthenticatorConfig, error) {
|
||||
tokenClient, err := s.newTokenAccessReview()
|
||||
if err != nil {
|
||||
return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
|
||||
}
|
||||
|
||||
clientCA, err := s.getClientCA()
|
||||
if err != nil {
|
||||
if _, ignorable := err.(ignorableError); !ignorable {
|
||||
return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
|
||||
} else {
|
||||
glog.Warning(err)
|
||||
}
|
||||
}
|
||||
requestHeader, err := s.getRequestHeader()
|
||||
if err != nil {
|
||||
return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
|
||||
}
|
||||
|
||||
ret := authenticatorfactory.DelegatingAuthenticatorConfig{
|
||||
Anonymous: true,
|
||||
TokenAccessReviewClient: tokenClient,
|
||||
CacheTTL: s.CacheTTL,
|
||||
ClientCAFile: clientCA.ClientCA,
|
||||
RequestHeaderConfig: requestHeader.ToAuthenticationRequestHeaderConfig(),
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
const (
|
||||
authenticationConfigMapNamespace = metav1.NamespaceSystem
|
||||
// authenticationConfigMapName is the name of ConfigMap in the kube-system namespace holding the root certificate
|
||||
|
|
@ -235,59 +240,70 @@ const (
|
|||
authenticationRoleName = "extension-apiserver-authentication-reader"
|
||||
)
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticationOptions, error) {
|
||||
if len(s.ClientCert.ClientCA) > 0 || s.SkipInClusterLookup {
|
||||
return &s.ClientCert, nil
|
||||
func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client kubernetes.Interface) error {
|
||||
if len(s.ClientCert.ClientCA) > 0 && len(s.RequestHeader.ClientCAFile) > 0 {
|
||||
return nil
|
||||
}
|
||||
if client == nil {
|
||||
if len(s.ClientCert.ClientCA) == 0 {
|
||||
klog.Warningf("No authentication-kubeconfig provided in order to lookup client-ca-file in configmap/%s in %s, so client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
|
||||
}
|
||||
if len(s.RequestHeader.ClientCAFile) == 0 {
|
||||
klog.Warningf("No authentication-kubeconfig provided in order to lookup requestheader-client-ca-file in configmap/%s in %s, so request-header client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
incluster, err := s.lookupInClusterClientCA()
|
||||
if err != nil {
|
||||
glog.Warningf("Unable to get configmap/%s in %s. Usually fixed by "+
|
||||
"'kubectl create rolebinding -n %s ROLE_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
|
||||
authConfigMap, err := client.CoreV1().ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
|
||||
switch {
|
||||
case errors.IsNotFound(err):
|
||||
// ignore, authConfigMap is nil now
|
||||
case errors.IsForbidden(err):
|
||||
klog.Warningf("Unable to get configmap/%s in %s. Usually fixed by "+
|
||||
"'kubectl create rolebinding -n %s ROLEBINDING_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
|
||||
authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName)
|
||||
return nil, err
|
||||
return err
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
if incluster == nil {
|
||||
return &s.ClientCert, ignorableError{fmt.Errorf("cluster doesn't provide client-ca-file in configmap/%s in %s, so client certificate authentication to extension api-server won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)}
|
||||
|
||||
if len(s.ClientCert.ClientCA) == 0 {
|
||||
if authConfigMap != nil {
|
||||
opt, err := inClusterClientCA(authConfigMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if opt != nil {
|
||||
s.ClientCert = *opt
|
||||
}
|
||||
}
|
||||
if len(s.ClientCert.ClientCA) == 0 {
|
||||
klog.Warningf("Cluster doesn't provide client-ca-file in configmap/%s in %s, so client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
|
||||
}
|
||||
}
|
||||
return incluster, nil
|
||||
|
||||
if len(s.RequestHeader.ClientCAFile) == 0 {
|
||||
if authConfigMap != nil {
|
||||
opt, err := inClusterRequestHeader(authConfigMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if opt != nil {
|
||||
s.RequestHeader = *opt
|
||||
}
|
||||
}
|
||||
if len(s.RequestHeader.ClientCAFile) == 0 {
|
||||
klog.Warningf("Cluster doesn't provide requestheader-client-ca-file in configmap/%s in %s, so request-header client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) getRequestHeader() (*RequestHeaderAuthenticationOptions, error) {
|
||||
if len(s.RequestHeader.ClientCAFile) > 0 || s.SkipInClusterLookup {
|
||||
return &s.RequestHeader, nil
|
||||
}
|
||||
|
||||
incluster, err := s.lookupInClusterRequestHeader()
|
||||
if err != nil {
|
||||
glog.Warningf("Unable to get configmap/%s in %s. Usually fixed by "+
|
||||
"'kubectl create rolebinding -n %s ROLE_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
|
||||
authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName)
|
||||
return nil, err
|
||||
}
|
||||
if incluster == nil {
|
||||
return nil, fmt.Errorf("cluster doesn't provide requestheader-client-ca-file")
|
||||
}
|
||||
return incluster, nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) lookupInClusterClientCA() (*ClientCertAuthenticationOptions, error) {
|
||||
clientConfig, err := s.getClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := coreclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authConfigMap, err := client.ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func inClusterClientCA(authConfigMap *v1.ConfigMap) (*ClientCertAuthenticationOptions, error) {
|
||||
clientCA, ok := authConfigMap.Data["client-ca-file"]
|
||||
if !ok {
|
||||
// not having a client-ca is fine, return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
@ -301,23 +317,10 @@ func (s *DelegatingAuthenticationOptions) lookupInClusterClientCA() (*ClientCert
|
|||
return &ClientCertAuthenticationOptions{ClientCA: f.Name()}, nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) lookupInClusterRequestHeader() (*RequestHeaderAuthenticationOptions, error) {
|
||||
clientConfig, err := s.getClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := coreclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authConfigMap, err := client.ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func inClusterRequestHeader(authConfigMap *v1.ConfigMap) (*RequestHeaderAuthenticationOptions, error) {
|
||||
requestHeaderCA, ok := authConfigMap.Data["requestheader-client-ca-file"]
|
||||
if !ok {
|
||||
// not having a requestheader-client-ca is fine, return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +368,9 @@ func deserializeStrings(in string) ([]string, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) getClientConfig() (*rest.Config, error) {
|
||||
// getClient returns a Kubernetes clientset. If s.RemoteKubeConfigFileOptional is true, nil will be returned
|
||||
// if no kubeconfig is specified by the user and the in-cluster config is not found.
|
||||
func (s *DelegatingAuthenticationOptions) getClient() (kubernetes.Interface, error) {
|
||||
var clientConfig *rest.Config
|
||||
var err error
|
||||
if len(s.RemoteKubeConfigFile) > 0 {
|
||||
|
|
@ -373,34 +378,24 @@ func (s *DelegatingAuthenticationOptions) getClientConfig() (*rest.Config, error
|
|||
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||
|
||||
clientConfig, err = loader.ClientConfig()
|
||||
|
||||
} else {
|
||||
// without the remote kubeconfig file, try to use the in-cluster config. Most addon API servers will
|
||||
// use this path
|
||||
// use this path. If it is optional, ignore errors.
|
||||
clientConfig, err = rest.InClusterConfig()
|
||||
if err != nil && s.RemoteKubeConfigFileOptional {
|
||||
if err != rest.ErrNotInCluster {
|
||||
klog.Warningf("failed to read in-cluster kubeconfig for delegated authentication: %v", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to get delegated authentication kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// set high qps/burst limits since this will effectively limit API server responsiveness
|
||||
clientConfig.QPS = 200
|
||||
clientConfig.Burst = 400
|
||||
|
||||
return clientConfig, nil
|
||||
return kubernetes.NewForConfig(clientConfig)
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authenticationclient.TokenReviewInterface, error) {
|
||||
clientConfig, err := s.getClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := authenticationclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.TokenReviews(), nil
|
||||
}
|
||||
|
||||
type ignorableError struct{ error }
|
||||
|
|
|
|||
108
vendor/k8s.io/apiserver/pkg/server/options/authorization.go
generated
vendored
108
vendor/k8s.io/apiserver/pkg/server/options/authorization.go
generated
vendored
|
|
@ -17,13 +17,18 @@ limitations under the License.
|
|||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||
"k8s.io/apiserver/pkg/authorization/path"
|
||||
"k8s.io/apiserver/pkg/authorization/union"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
|
@ -37,6 +42,9 @@ type DelegatingAuthorizationOptions struct {
|
|||
// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
|
||||
// SubjectAccessReview.authorization.k8s.io endpoint for checking tokens.
|
||||
RemoteKubeConfigFile string
|
||||
// RemoteKubeConfigFileOptional is specifying whether not specifying the kubeconfig or
|
||||
// a missing in-cluster config will be fatal.
|
||||
RemoteKubeConfigFileOptional bool
|
||||
|
||||
// AllowCacheTTL is the length of time that a successful authorization response will be cached
|
||||
AllowCacheTTL time.Duration
|
||||
|
|
@ -44,6 +52,13 @@ type DelegatingAuthorizationOptions struct {
|
|||
// DenyCacheTTL is the length of time that an unsuccessful authorization response will be cached.
|
||||
// You generally want more responsive, "deny, try again" flows.
|
||||
DenyCacheTTL time.Duration
|
||||
|
||||
// AlwaysAllowPaths are HTTP paths which are excluded from authorization. They can be plain
|
||||
// paths or end in * in which case prefix-match is applied. A leading / is optional.
|
||||
AlwaysAllowPaths []string
|
||||
|
||||
// AlwaysAllowGroups are groups which are allowed to take any actions. In kube, this is system:masters.
|
||||
AlwaysAllowGroups []string
|
||||
}
|
||||
|
||||
func NewDelegatingAuthorizationOptions() *DelegatingAuthorizationOptions {
|
||||
|
|
@ -54,6 +69,18 @@ func NewDelegatingAuthorizationOptions() *DelegatingAuthorizationOptions {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAlwaysAllowGroups appends the list of paths to AlwaysAllowGroups
|
||||
func (s *DelegatingAuthorizationOptions) WithAlwaysAllowGroups(groups ...string) *DelegatingAuthorizationOptions {
|
||||
s.AlwaysAllowGroups = append(s.AlwaysAllowGroups, groups...)
|
||||
return s
|
||||
}
|
||||
|
||||
// WithAlwaysAllowPaths appends the list of paths to AlwaysAllowPaths
|
||||
func (s *DelegatingAuthorizationOptions) WithAlwaysAllowPaths(paths ...string) *DelegatingAuthorizationOptions {
|
||||
s.AlwaysAllowPaths = append(s.AlwaysAllowPaths, paths...)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) Validate() []error {
|
||||
allErrors := []error{}
|
||||
return allErrors
|
||||
|
|
@ -64,9 +91,13 @@ func (s *DelegatingAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
return
|
||||
}
|
||||
|
||||
fs.StringVar(&s.RemoteKubeConfigFile, "authorization-kubeconfig", s.RemoteKubeConfigFile, ""+
|
||||
var optionalKubeConfigSentence string
|
||||
if s.RemoteKubeConfigFileOptional {
|
||||
optionalKubeConfigSentence = " This is optional. If empty, all requests not skipped by authorization are forbidden."
|
||||
}
|
||||
fs.StringVar(&s.RemoteKubeConfigFile, "authorization-kubeconfig", s.RemoteKubeConfigFile,
|
||||
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
|
||||
" subjectaccessreviews.authorization.k8s.io.")
|
||||
"subjectaccessreviews.authorization.k8s.io."+optionalKubeConfigSentence)
|
||||
|
||||
fs.DurationVar(&s.AllowCacheTTL, "authorization-webhook-cache-authorized-ttl",
|
||||
s.AllowCacheTTL,
|
||||
|
|
@ -75,6 +106,10 @@ func (s *DelegatingAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
fs.DurationVar(&s.DenyCacheTTL,
|
||||
"authorization-webhook-cache-unauthorized-ttl", s.DenyCacheTTL,
|
||||
"The duration to cache 'unauthorized' responses from the webhook authorizer.")
|
||||
|
||||
fs.StringSliceVar(&s.AlwaysAllowPaths, "authorization-always-allow-paths", s.AlwaysAllowPaths,
|
||||
"A list of HTTP paths to skip during authorization, i.e. these are authorized without "+
|
||||
"contacting the 'core' kubernetes server.")
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) ApplyTo(c *server.AuthorizationInfo) error {
|
||||
|
|
@ -83,34 +118,49 @@ func (s *DelegatingAuthorizationOptions) ApplyTo(c *server.AuthorizationInfo) er
|
|||
return nil
|
||||
}
|
||||
|
||||
cfg, err := s.ToAuthorizationConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authorizer, err := cfg.New()
|
||||
client, err := s.getClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Authorizer = authorizer
|
||||
return nil
|
||||
c.Authorizer, err = s.toAuthorizer(client)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) ToAuthorizationConfig() (authorizerfactory.DelegatingAuthorizerConfig, error) {
|
||||
sarClient, err := s.newSubjectAccessReview()
|
||||
if err != nil {
|
||||
return authorizerfactory.DelegatingAuthorizerConfig{}, err
|
||||
func (s *DelegatingAuthorizationOptions) toAuthorizer(client kubernetes.Interface) (authorizer.Authorizer, error) {
|
||||
var authorizers []authorizer.Authorizer
|
||||
|
||||
if len(s.AlwaysAllowGroups) > 0 {
|
||||
authorizers = append(authorizers, authorizerfactory.NewPrivilegedGroups(s.AlwaysAllowGroups...))
|
||||
}
|
||||
|
||||
ret := authorizerfactory.DelegatingAuthorizerConfig{
|
||||
SubjectAccessReviewClient: sarClient,
|
||||
AllowCacheTTL: s.AllowCacheTTL,
|
||||
DenyCacheTTL: s.DenyCacheTTL,
|
||||
if len(s.AlwaysAllowPaths) > 0 {
|
||||
a, err := path.NewAuthorizer(s.AlwaysAllowPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authorizers = append(authorizers, a)
|
||||
}
|
||||
return ret, nil
|
||||
|
||||
if client == nil {
|
||||
klog.Warningf("No authorization-kubeconfig provided, so SubjectAccessReview of authorization tokens won't work.")
|
||||
} else {
|
||||
cfg := authorizerfactory.DelegatingAuthorizerConfig{
|
||||
SubjectAccessReviewClient: client.AuthorizationV1beta1().SubjectAccessReviews(),
|
||||
AllowCacheTTL: s.AllowCacheTTL,
|
||||
DenyCacheTTL: s.DenyCacheTTL,
|
||||
}
|
||||
delegatedAuthorizer, err := cfg.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authorizers = append(authorizers, delegatedAuthorizer)
|
||||
}
|
||||
|
||||
return union.New(authorizers...), nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) newSubjectAccessReview() (authorizationclient.SubjectAccessReviewInterface, error) {
|
||||
func (s *DelegatingAuthorizationOptions) getClient() (kubernetes.Interface, error) {
|
||||
var clientConfig *rest.Config
|
||||
var err error
|
||||
if len(s.RemoteKubeConfigFile) > 0 {
|
||||
|
|
@ -118,24 +168,24 @@ func (s *DelegatingAuthorizationOptions) newSubjectAccessReview() (authorization
|
|||
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||
|
||||
clientConfig, err = loader.ClientConfig()
|
||||
|
||||
} else {
|
||||
// without the remote kubeconfig file, try to use the in-cluster config. Most addon API servers will
|
||||
// use this path
|
||||
// use this path. If it is optional, ignore errors.
|
||||
clientConfig, err = rest.InClusterConfig()
|
||||
if err != nil && s.RemoteKubeConfigFileOptional {
|
||||
if err != rest.ErrNotInCluster {
|
||||
klog.Warningf("failed to read in-cluster kubeconfig for delegated authorization: %v", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to get delegated authorization kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// set high qps/burst limits since this will effectively limit API server responsiveness
|
||||
clientConfig.QPS = 200
|
||||
clientConfig.Burst = 400
|
||||
|
||||
client, err := authorizationclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.SubjectAccessReviews(), nil
|
||||
return kubernetes.NewForConfig(clientConfig)
|
||||
}
|
||||
|
|
|
|||
169
vendor/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go
generated
vendored
Normal file
169
vendor/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go
generated
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// DeprecatedInsecureServingOptions are for creating an unauthenticated, unauthorized, insecure port.
|
||||
// No one should be using these anymore.
|
||||
// DEPRECATED: all insecure serving options are removed in a future version
|
||||
type DeprecatedInsecureServingOptions struct {
|
||||
BindAddress net.IP
|
||||
BindPort int
|
||||
// BindNetwork is the type of network to bind to - defaults to "tcp", accepts "tcp",
|
||||
// "tcp4", and "tcp6".
|
||||
BindNetwork string
|
||||
|
||||
// Listener is the secure server network listener.
|
||||
// either Listener or BindAddress/BindPort/BindNetwork is set,
|
||||
// if Listener is set, use it and omit BindAddress/BindPort/BindNetwork.
|
||||
Listener net.Listener
|
||||
|
||||
// ListenFunc can be overridden to create a custom listener, e.g. for mocking in tests.
|
||||
// It defaults to options.CreateListener.
|
||||
ListenFunc func(network, addr string) (net.Listener, int, error)
|
||||
}
|
||||
|
||||
// Validate ensures that the insecure port values within the range of the port.
|
||||
func (s *DeprecatedInsecureServingOptions) Validate() []error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
errors := []error{}
|
||||
|
||||
if s.BindPort < 0 || s.BindPort > 65335 {
|
||||
errors = append(errors, fmt.Errorf("insecure port %v must be between 0 and 65335, inclusive. 0 for turning off insecure (HTTP) port", s.BindPort))
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
// AddFlags adds flags related to insecure serving to the specified FlagSet.
|
||||
func (s *DeprecatedInsecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.IPVar(&s.BindAddress, "insecure-bind-address", s.BindAddress, ""+
|
||||
"The IP address on which to serve the --insecure-port (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).")
|
||||
// Though this flag is deprecated, we discovered security concerns over how to do health checks without it e.g. #43784
|
||||
fs.MarkDeprecated("insecure-bind-address", "This flag will be removed in a future version.")
|
||||
fs.Lookup("insecure-bind-address").Hidden = false
|
||||
|
||||
fs.IntVar(&s.BindPort, "insecure-port", s.BindPort, ""+
|
||||
"The port on which to serve unsecured, unauthenticated access.")
|
||||
// Though this flag is deprecated, we discovered security concerns over how to do health checks without it e.g. #43784
|
||||
fs.MarkDeprecated("insecure-port", "This flag will be removed in a future version.")
|
||||
fs.Lookup("insecure-port").Hidden = false
|
||||
}
|
||||
|
||||
// AddUnqualifiedFlags adds flags related to insecure serving without the --insecure prefix to the specified FlagSet.
|
||||
func (s *DeprecatedInsecureServingOptions) AddUnqualifiedFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.IPVar(&s.BindAddress, "address", s.BindAddress,
|
||||
"The IP address on which to serve the insecure --port (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).")
|
||||
fs.MarkDeprecated("address", "see --bind-address instead.")
|
||||
fs.Lookup("address").Hidden = false
|
||||
|
||||
fs.IntVar(&s.BindPort, "port", s.BindPort, "The port on which to serve unsecured, unauthenticated access. Set to 0 to disable.")
|
||||
fs.MarkDeprecated("port", "see --secure-port instead.")
|
||||
fs.Lookup("port").Hidden = false
|
||||
}
|
||||
|
||||
// ApplyTo adds DeprecatedInsecureServingOptions to the insecureserverinfo and kube-controller manager configuration.
|
||||
// Note: the double pointer allows to set the *DeprecatedInsecureServingInfo to nil without referencing the struct hosting this pointer.
|
||||
func (s *DeprecatedInsecureServingOptions) ApplyTo(c **server.DeprecatedInsecureServingInfo) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
if s.BindPort <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.Listener == nil {
|
||||
var err error
|
||||
listen := CreateListener
|
||||
if s.ListenFunc != nil {
|
||||
listen = s.ListenFunc
|
||||
}
|
||||
addr := net.JoinHostPort(s.BindAddress.String(), fmt.Sprintf("%d", s.BindPort))
|
||||
s.Listener, s.BindPort, err = listen(s.BindNetwork, addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create listener: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
*c = &server.DeprecatedInsecureServingInfo{
|
||||
Listener: s.Listener,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithLoopback adds loopback functionality to the serving options.
|
||||
func (o *DeprecatedInsecureServingOptions) WithLoopback() *DeprecatedInsecureServingOptionsWithLoopback {
|
||||
return &DeprecatedInsecureServingOptionsWithLoopback{o}
|
||||
}
|
||||
|
||||
// DeprecatedInsecureServingOptionsWithLoopback adds loopback functionality to the DeprecatedInsecureServingOptions.
|
||||
// DEPRECATED: all insecure serving options will be removed in a future version, however note that
|
||||
// there are security concerns over how health checks can work here - see e.g. #43784
|
||||
type DeprecatedInsecureServingOptionsWithLoopback struct {
|
||||
*DeprecatedInsecureServingOptions
|
||||
}
|
||||
|
||||
// ApplyTo fills up serving information in the server configuration.
|
||||
func (s *DeprecatedInsecureServingOptionsWithLoopback) ApplyTo(insecureServingInfo **server.DeprecatedInsecureServingInfo, loopbackClientConfig **rest.Config) error {
|
||||
if s == nil || s.DeprecatedInsecureServingOptions == nil || insecureServingInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := s.DeprecatedInsecureServingOptions.ApplyTo(insecureServingInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if *insecureServingInfo == nil || loopbackClientConfig == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
secureLoopbackClientConfig, err := (*insecureServingInfo).NewLoopbackClientConfig()
|
||||
switch {
|
||||
// if we failed and there's no fallback loopback client config, we need to fail
|
||||
case err != nil && *loopbackClientConfig == nil:
|
||||
return err
|
||||
|
||||
// if we failed, but we already have a fallback loopback client config (usually insecure), allow it
|
||||
case err != nil && *loopbackClientConfig != nil:
|
||||
|
||||
default:
|
||||
*loopbackClientConfig = secureLoopbackClientConfig
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
71
vendor/k8s.io/apiserver/pkg/server/options/etcd.go
generated
vendored
71
vendor/k8s.io/apiserver/pkg/server/options/etcd.go
generated
vendored
|
|
@ -32,8 +32,8 @@ import (
|
|||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
"k8s.io/apiserver/pkg/storage/etcd3/preflight"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
storagefactory "k8s.io/apiserver/pkg/storage/storagebackend/factory"
|
||||
)
|
||||
|
||||
type EtcdOptions struct {
|
||||
|
|
@ -59,8 +59,6 @@ type EtcdOptions struct {
|
|||
}
|
||||
|
||||
var storageTypes = sets.NewString(
|
||||
storagebackend.StorageTypeUnset,
|
||||
storagebackend.StorageTypeETCD2,
|
||||
storagebackend.StorageTypeETCD3,
|
||||
)
|
||||
|
||||
|
|
@ -83,12 +81,12 @@ func (s *EtcdOptions) Validate() []error {
|
|||
}
|
||||
|
||||
allErrors := []error{}
|
||||
if len(s.StorageConfig.ServerList) == 0 {
|
||||
if len(s.StorageConfig.Transport.ServerList) == 0 {
|
||||
allErrors = append(allErrors, fmt.Errorf("--etcd-servers must be specified"))
|
||||
}
|
||||
|
||||
if !storageTypes.Has(s.StorageConfig.Type) {
|
||||
allErrors = append(allErrors, fmt.Errorf("--storage-backend invalid, must be 'etcd3' or 'etcd2'. If not specified, it will default to 'etcd3'"))
|
||||
if s.StorageConfig.Type != storagebackend.StorageTypeUnset && !storageTypes.Has(s.StorageConfig.Type) {
|
||||
allErrors = append(allErrors, fmt.Errorf("--storage-backend invalid, allowed values: %s. If not specified, it will default to 'etcd3'", strings.Join(storageTypes.List(), ", ")))
|
||||
}
|
||||
|
||||
for _, override := range s.EtcdServersOverrides {
|
||||
|
|
@ -136,39 +134,41 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
"Default watch cache size. If zero, watch cache will be disabled for resources that do not have a default watch size set.")
|
||||
|
||||
fs.StringSliceVar(&s.WatchCacheSizes, "watch-cache-sizes", s.WatchCacheSizes, ""+
|
||||
"List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. "+
|
||||
"The individual override format: resource[.group]#size, where resource is lowercase plural (no version), "+
|
||||
"group is optional, and size is a number. It takes effect when watch-cache is enabled. "+
|
||||
"Watch cache size settings for some resources (pods, nodes, etc.), comma separated. "+
|
||||
"The individual setting format: resource[.group]#size, where resource is lowercase plural (no version), "+
|
||||
"group is omitted for resources of apiVersion v1 (the legacy core API) and included for others, "+
|
||||
"and size is a number. It takes effect when watch-cache is enabled. "+
|
||||
"Some resources (replicationcontrollers, endpoints, nodes, pods, services, apiservices.apiregistration.k8s.io) "+
|
||||
"have system defaults set by heuristics, others default to default-watch-cache-size")
|
||||
|
||||
fs.StringVar(&s.StorageConfig.Type, "storage-backend", s.StorageConfig.Type,
|
||||
"The storage backend for persistence. Options: 'etcd3' (default), 'etcd2'.")
|
||||
"The storage backend for persistence. Options: 'etcd3' (default).")
|
||||
|
||||
fs.IntVar(&s.StorageConfig.DeserializationCacheSize, "deserialization-cache-size", s.StorageConfig.DeserializationCacheSize,
|
||||
"Number of deserialized json objects to cache in memory.")
|
||||
dummyCacheSize := 0
|
||||
fs.IntVar(&dummyCacheSize, "deserialization-cache-size", 0, "Number of deserialized json objects to cache in memory.")
|
||||
fs.MarkDeprecated("deserialization-cache-size", "the deserialization cache was dropped in 1.13 with support for etcd2")
|
||||
|
||||
fs.StringSliceVar(&s.StorageConfig.ServerList, "etcd-servers", s.StorageConfig.ServerList,
|
||||
fs.StringSliceVar(&s.StorageConfig.Transport.ServerList, "etcd-servers", s.StorageConfig.Transport.ServerList,
|
||||
"List of etcd servers to connect with (scheme://ip:port), comma separated.")
|
||||
|
||||
fs.StringVar(&s.StorageConfig.Prefix, "etcd-prefix", s.StorageConfig.Prefix,
|
||||
"The prefix to prepend to all resource paths in etcd.")
|
||||
|
||||
fs.StringVar(&s.StorageConfig.KeyFile, "etcd-keyfile", s.StorageConfig.KeyFile,
|
||||
fs.StringVar(&s.StorageConfig.Transport.KeyFile, "etcd-keyfile", s.StorageConfig.Transport.KeyFile,
|
||||
"SSL key file used to secure etcd communication.")
|
||||
|
||||
fs.StringVar(&s.StorageConfig.CertFile, "etcd-certfile", s.StorageConfig.CertFile,
|
||||
fs.StringVar(&s.StorageConfig.Transport.CertFile, "etcd-certfile", s.StorageConfig.Transport.CertFile,
|
||||
"SSL certification file used to secure etcd communication.")
|
||||
|
||||
fs.StringVar(&s.StorageConfig.CAFile, "etcd-cafile", s.StorageConfig.CAFile,
|
||||
fs.StringVar(&s.StorageConfig.Transport.CAFile, "etcd-cafile", s.StorageConfig.Transport.CAFile,
|
||||
"SSL Certificate Authority file used to secure etcd communication.")
|
||||
|
||||
fs.BoolVar(&s.StorageConfig.Quorum, "etcd-quorum-read", s.StorageConfig.Quorum,
|
||||
"If true, enable quorum read. It defaults to true and is strongly recommended not setting to false.")
|
||||
fs.MarkDeprecated("etcd-quorum-read", "This flag is deprecated and the ability to switch off quorum read will be removed in a future release.")
|
||||
|
||||
fs.StringVar(&s.EncryptionProviderConfigFilepath, "experimental-encryption-provider-config", s.EncryptionProviderConfigFilepath,
|
||||
"The file containing configuration for encryption providers to be used for storing secrets in etcd")
|
||||
fs.MarkDeprecated("experimental-encryption-provider-config", "use --encryption-provider-config.")
|
||||
|
||||
fs.StringVar(&s.EncryptionProviderConfigFilepath, "encryption-provider-config", s.EncryptionProviderConfigFilepath,
|
||||
"The file containing configuration for encryption providers to be used for storing secrets in etcd")
|
||||
|
||||
fs.DurationVar(&s.StorageConfig.CompactionInterval, "etcd-compaction-interval", s.StorageConfig.CompactionInterval,
|
||||
"The interval of compaction requests. If 0, the compaction request from apiserver is disabled.")
|
||||
|
|
@ -181,29 +181,30 @@ func (s *EtcdOptions) ApplyTo(c *server.Config) error {
|
|||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.addEtcdHealthEndpoint(c)
|
||||
if err := s.addEtcdHealthEndpoint(c); err != nil {
|
||||
return err
|
||||
}
|
||||
c.RESTOptionsGetter = &SimpleRestOptionsFactory{Options: *s}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *EtcdOptions) ApplyWithStorageFactoryTo(factory serverstorage.StorageFactory, c *server.Config) error {
|
||||
s.addEtcdHealthEndpoint(c)
|
||||
c.RESTOptionsGetter = &storageFactoryRestOptionsFactory{Options: *s, StorageFactory: factory}
|
||||
if err := s.addEtcdHealthEndpoint(c); err != nil {
|
||||
return err
|
||||
}
|
||||
c.RESTOptionsGetter = &StorageFactoryRestOptionsFactory{Options: *s, StorageFactory: factory}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *EtcdOptions) addEtcdHealthEndpoint(c *server.Config) {
|
||||
func (s *EtcdOptions) addEtcdHealthEndpoint(c *server.Config) error {
|
||||
healthCheck, err := storagefactory.CreateHealthCheck(s.StorageConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.HealthzChecks = append(c.HealthzChecks, healthz.NamedCheck("etcd", func(r *http.Request) error {
|
||||
done, err := preflight.EtcdConnection{ServerList: s.StorageConfig.ServerList}.CheckEtcdServers()
|
||||
if !done {
|
||||
return fmt.Errorf("etcd failed")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return healthCheck()
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
|
||||
type SimpleRestOptionsFactory struct {
|
||||
|
|
@ -233,12 +234,12 @@ func (f *SimpleRestOptionsFactory) GetRESTOptions(resource schema.GroupResource)
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
type storageFactoryRestOptionsFactory struct {
|
||||
type StorageFactoryRestOptionsFactory struct {
|
||||
Options EtcdOptions
|
||||
StorageFactory serverstorage.StorageFactory
|
||||
}
|
||||
|
||||
func (f *storageFactoryRestOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
|
||||
func (f *StorageFactoryRestOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
|
||||
storageConfig, err := f.StorageFactory.NewConfig(resource)
|
||||
if err != nil {
|
||||
return generic.RESTOptions{}, fmt.Errorf("unable to find storage destination for %v, due to %v", resource, err.Error())
|
||||
|
|
|
|||
56
vendor/k8s.io/apiserver/pkg/server/options/events.go
generated
vendored
Normal file
56
vendor/k8s.io/apiserver/pkg/server/options/events.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
8
vendor/k8s.io/apiserver/pkg/server/options/feature.go
generated
vendored
8
vendor/k8s.io/apiserver/pkg/server/options/feature.go
generated
vendored
|
|
@ -26,7 +26,6 @@ import (
|
|||
type FeatureOptions struct {
|
||||
EnableProfiling bool
|
||||
EnableContentionProfiling bool
|
||||
EnableSwaggerUI bool
|
||||
}
|
||||
|
||||
func NewFeatureOptions() *FeatureOptions {
|
||||
|
|
@ -35,7 +34,6 @@ func NewFeatureOptions() *FeatureOptions {
|
|||
return &FeatureOptions{
|
||||
EnableProfiling: defaults.EnableProfiling,
|
||||
EnableContentionProfiling: defaults.EnableContentionProfiling,
|
||||
EnableSwaggerUI: defaults.EnableSwaggerUI,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,8 +46,9 @@ func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
"Enable profiling via web interface host:port/debug/pprof/")
|
||||
fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling,
|
||||
"Enable lock contention profiling, if profiling is enabled")
|
||||
fs.BoolVar(&o.EnableSwaggerUI, "enable-swagger-ui", o.EnableSwaggerUI,
|
||||
"Enables swagger ui on the apiserver at /swagger-ui")
|
||||
dummy := false
|
||||
fs.BoolVar(&dummy, "enable-swagger-ui", dummy, "Enables swagger ui on the apiserver at /swagger-ui")
|
||||
fs.MarkDeprecated("enable-swagger-ui", "swagger 1.2 support has been removed")
|
||||
}
|
||||
|
||||
func (o *FeatureOptions) ApplyTo(c *server.Config) error {
|
||||
|
|
@ -59,7 +58,6 @@ func (o *FeatureOptions) ApplyTo(c *server.Config) error {
|
|||
|
||||
c.EnableProfiling = o.EnableProfiling
|
||||
c.EnableContentionProfiling = o.EnableContentionProfiling
|
||||
c.EnableSwaggerUI = o.EnableSwaggerUI
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
18
vendor/k8s.io/apiserver/pkg/server/options/recommended.go
generated
vendored
18
vendor/k8s.io/apiserver/pkg/server/options/recommended.go
generated
vendored
|
|
@ -41,9 +41,12 @@ type RecommendedOptions struct {
|
|||
// admission plugin initializers to Admission.ApplyTo.
|
||||
ExtraAdmissionInitializers func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error)
|
||||
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()
|
||||
|
||||
// We are composing recommended options for an aggregated api-server,
|
||||
|
|
@ -54,7 +57,7 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio
|
|||
|
||||
return &RecommendedOptions{
|
||||
Etcd: NewEtcdOptions(storagebackend.NewDefaultConfig(prefix, codec)),
|
||||
SecureServing: WithLoopback(sso),
|
||||
SecureServing: sso.WithLoopback(),
|
||||
Authentication: NewDelegatingAuthenticationOptions(),
|
||||
Authorization: NewDelegatingAuthorizationOptions(),
|
||||
Audit: NewAuditOptions(),
|
||||
|
|
@ -62,6 +65,8 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio
|
|||
CoreAPI: NewCoreAPIOptions(),
|
||||
ExtraAdmissionInitializers: func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error) { return nil, nil },
|
||||
Admission: NewAdmissionOptions(),
|
||||
ProcessInfo: processInfo,
|
||||
Webhook: NewWebhookOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,13 +82,12 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
// ApplyTo adds RecommendedOptions to the server configuration.
|
||||
// scheme is the scheme of the apiserver types that are sent to the admission chain.
|
||||
// pluginInitializers can be empty, it is only need for additional initializers.
|
||||
func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *runtime.Scheme) error {
|
||||
func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig) error {
|
||||
if err := o.Etcd.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.SecureServing.ApplyTo(&config.Config); err != nil {
|
||||
if err := o.SecureServing.ApplyTo(&config.Config.SecureServing, &config.Config.LoopbackClientConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Authentication.ApplyTo(&config.Config.Authentication, config.SecureServing, config.OpenAPIConfig); err != nil {
|
||||
|
|
@ -92,7 +96,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
|
|||
if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil {
|
||||
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
|
||||
}
|
||||
if err := o.Features.ApplyTo(&config.Config); err != nil {
|
||||
|
|
@ -103,7 +107,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
|
|||
}
|
||||
if initializers, err := o.ExtraAdmissionInitializers(config); err != nil {
|
||||
return err
|
||||
} else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, scheme, initializers...); err != nil {
|
||||
} else if err := o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, initializers...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
26
vendor/k8s.io/apiserver/pkg/server/options/server_run_options.go
generated
vendored
26
vendor/k8s.io/apiserver/pkg/server/options/server_run_options.go
generated
vendored
|
|
@ -42,7 +42,15 @@ type ServerRunOptions struct {
|
|||
MaxMutatingRequestsInFlight int
|
||||
RequestTimeout time.Duration
|
||||
MinRequestTimeout int
|
||||
TargetRAMMB int
|
||||
// We intentionally did not add a flag for this option. Users of the
|
||||
// apiserver library can wire it to a flag.
|
||||
JSONPatchMaxCopyBytes int64
|
||||
// The limit on the request body size that would be accepted and
|
||||
// decoded in a write request. 0 means no limit.
|
||||
// We intentionally did not add a flag for this option. Users of the
|
||||
// apiserver library can wire it to a flag.
|
||||
MaxRequestBodyBytes int64
|
||||
TargetRAMMB int
|
||||
}
|
||||
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
|
|
@ -52,6 +60,8 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
|
||||
RequestTimeout: defaults.RequestTimeout,
|
||||
MinRequestTimeout: defaults.MinRequestTimeout,
|
||||
JSONPatchMaxCopyBytes: defaults.JSONPatchMaxCopyBytes,
|
||||
MaxRequestBodyBytes: defaults.MaxRequestBodyBytes,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +73,8 @@ func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
|||
c.MaxMutatingRequestsInFlight = s.MaxMutatingRequestsInFlight
|
||||
c.RequestTimeout = s.RequestTimeout
|
||||
c.MinRequestTimeout = s.MinRequestTimeout
|
||||
c.JSONPatchMaxCopyBytes = s.JSONPatchMaxCopyBytes
|
||||
c.MaxRequestBodyBytes = s.MaxRequestBodyBytes
|
||||
c.PublicAddress = s.AdvertiseAddress
|
||||
|
||||
return nil
|
||||
|
|
@ -107,10 +119,18 @@ func (s *ServerRunOptions) Validate() []error {
|
|||
errors = append(errors, fmt.Errorf("--min-request-timeout can not be negative value"))
|
||||
}
|
||||
|
||||
if s.JSONPatchMaxCopyBytes < 0 {
|
||||
errors = append(errors, fmt.Errorf("--json-patch-max-copy-bytes can not be negative value"))
|
||||
}
|
||||
|
||||
if s.MaxRequestBodyBytes < 0 {
|
||||
errors = append(errors, fmt.Errorf("--max-resource-write-bytes can not be negative value"))
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
// AddFlags adds flags for a specific APIServer to the specified FlagSet
|
||||
// AddUniversalFlags adds flags for a specific APIServer to the specified FlagSet
|
||||
func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
||||
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
|
||||
// arrange these text blocks sensibly. Grrr.
|
||||
|
|
@ -154,5 +174,5 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||
"handler, which picks a randomized value above this number as the connection timeout, "+
|
||||
"to spread out load.")
|
||||
|
||||
utilfeature.DefaultFeatureGate.AddFlag(fs)
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(fs)
|
||||
}
|
||||
|
|
|
|||
102
vendor/k8s.io/apiserver/pkg/server/options/serving.go
generated
vendored
102
vendor/k8s.io/apiserver/pkg/server/options/serving.go
generated
vendored
|
|
@ -24,13 +24,14 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/client-go/util/keyutil"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
)
|
||||
|
||||
type SecureServingOptions struct {
|
||||
|
|
@ -40,6 +41,11 @@ type SecureServingOptions struct {
|
|||
// BindNetwork is the type of network to bind to - defaults to "tcp", accepts "tcp",
|
||||
// "tcp4", and "tcp6".
|
||||
BindNetwork string
|
||||
// Required set to true means that BindPort cannot be zero.
|
||||
Required bool
|
||||
// ExternalAddress is the address advertised, even if BindAddress is a loopback. By default this
|
||||
// is set to BindAddress if the later no loopback, or to the first host interface address.
|
||||
ExternalAddress net.IP
|
||||
|
||||
// Listener is the secure server network listener.
|
||||
// either Listener or BindAddress/BindPort/BindNetwork is set,
|
||||
|
|
@ -49,7 +55,7 @@ type SecureServingOptions struct {
|
|||
// ServerCert is the TLS cert info for serving secure traffic
|
||||
ServerCert GeneratableKeyCert
|
||||
// SNICertKeys are named CertKeys for serving secure traffic with SNI support.
|
||||
SNICertKeys []utilflag.NamedCertKey
|
||||
SNICertKeys []cliflag.NamedCertKey
|
||||
// CipherSuites is the list of allowed cipher suites for the server.
|
||||
// Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants).
|
||||
CipherSuites []string
|
||||
|
|
@ -70,14 +76,25 @@ type CertKey struct {
|
|||
}
|
||||
|
||||
type GeneratableKeyCert struct {
|
||||
// CertKey allows setting an explicit cert/key file to use.
|
||||
CertKey CertKey
|
||||
|
||||
// CertDirectory is a directory that will contain the certificates. If the cert and key aren't specifically set
|
||||
// this will be used to derive a match with the "pair-name"
|
||||
// CertDirectory specifies a directory to write generated certificates to if CertFile/KeyFile aren't explicitly set.
|
||||
// PairName is used to determine the filenames within CertDirectory.
|
||||
// If CertDirectory and PairName are not set, an in-memory certificate will be generated.
|
||||
CertDirectory string
|
||||
// PairName is the name which will be used with CertDirectory to make a cert and key names
|
||||
// It becomes CertDirector/PairName.crt and CertDirector/PairName.key
|
||||
// PairName is the name which will be used with CertDirectory to make a cert and key filenames.
|
||||
// It becomes CertDirectory/PairName.crt and CertDirectory/PairName.key
|
||||
PairName string
|
||||
|
||||
// GeneratedCert holds an in-memory generated certificate if CertFile/KeyFile aren't explicitly set, and CertDirectory/PairName are not set.
|
||||
GeneratedCert *tls.Certificate
|
||||
|
||||
// FixtureDirectory is a directory that contains test fixture used to avoid regeneration of certs during tests.
|
||||
// The format is:
|
||||
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.crt
|
||||
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.key
|
||||
FixtureDirectory string
|
||||
}
|
||||
|
||||
func NewSecureServingOptions() *SecureServingOptions {
|
||||
|
|
@ -92,6 +109,9 @@ func NewSecureServingOptions() *SecureServingOptions {
|
|||
}
|
||||
|
||||
func (s *SecureServingOptions) DefaultExternalAddress() (net.IP, error) {
|
||||
if !s.ExternalAddress.IsUnspecified() {
|
||||
return s.ExternalAddress, nil
|
||||
}
|
||||
return utilnet.ChooseBindAddress(s.BindAddress)
|
||||
}
|
||||
|
||||
|
|
@ -102,10 +122,16 @@ func (s *SecureServingOptions) Validate() []error {
|
|||
|
||||
errors := []error{}
|
||||
|
||||
if s.BindPort < 0 || s.BindPort > 65535 {
|
||||
if s.Required && s.BindPort < 1 || s.BindPort > 65535 {
|
||||
errors = append(errors, fmt.Errorf("--secure-port %v must be between 1 and 65535, inclusive. It cannot be turned off with 0", s.BindPort))
|
||||
} else if s.BindPort < 0 || s.BindPort > 65535 {
|
||||
errors = append(errors, fmt.Errorf("--secure-port %v must be between 0 and 65535, inclusive. 0 for turning off secure port", s.BindPort))
|
||||
}
|
||||
|
||||
if (len(s.ServerCert.CertKey.CertFile) != 0 || len(s.ServerCert.CertKey.KeyFile) != 0) && s.ServerCert.GeneratedCert != nil {
|
||||
errors = append(errors, fmt.Errorf("cert/key file and in-memory certificate cannot both be set"))
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
|
|
@ -118,9 +144,14 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
"The IP address on which to listen for the --secure-port port. The "+
|
||||
"associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+
|
||||
"clients. If blank, all interfaces will be used (0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).")
|
||||
fs.IntVar(&s.BindPort, "secure-port", s.BindPort, ""+
|
||||
"The port on which to serve HTTPS with authentication and authorization. If 0, "+
|
||||
"don't serve HTTPS at all.")
|
||||
|
||||
desc := "The port on which to serve HTTPS with authentication and authorization."
|
||||
if s.Required {
|
||||
desc += "It cannot be switched off with 0."
|
||||
} else {
|
||||
desc += "If 0, don't serve HTTPS at all."
|
||||
}
|
||||
fs.IntVar(&s.BindPort, "secure-port", s.BindPort, desc)
|
||||
|
||||
fs.StringVar(&s.ServerCert.CertDirectory, "cert-dir", s.ServerCert.CertDirectory, ""+
|
||||
"The directory where the TLS certs are located. "+
|
||||
|
|
@ -135,18 +166,18 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile,
|
||||
"File containing the default x509 private key matching --tls-cert-file.")
|
||||
|
||||
tlsCipherPossibleValues := utilflag.TLSCipherPossibleValues()
|
||||
tlsCipherPossibleValues := cliflag.TLSCipherPossibleValues()
|
||||
fs.StringSliceVar(&s.CipherSuites, "tls-cipher-suites", s.CipherSuites,
|
||||
"Comma-separated list of cipher suites for the server. "+
|
||||
"If omitted, the default Go cipher suites will be use. "+
|
||||
"Possible values: "+strings.Join(tlsCipherPossibleValues, ","))
|
||||
|
||||
tlsPossibleVersions := utilflag.TLSPossibleVersions()
|
||||
tlsPossibleVersions := cliflag.TLSPossibleVersions()
|
||||
fs.StringVar(&s.MinTLSVersion, "tls-min-version", s.MinTLSVersion,
|
||||
"Minimum TLS version supported. "+
|
||||
"Possible values: "+strings.Join(tlsPossibleVersions, ", "))
|
||||
|
||||
fs.Var(utilflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+
|
||||
fs.Var(cliflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+
|
||||
"A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+
|
||||
"domain patterns which are fully qualified domain names, possibly with prefixed wildcard "+
|
||||
"segments. If no domain patterns are provided, the names of the certificate are "+
|
||||
|
|
@ -199,10 +230,12 @@ func (s *SecureServingOptions) ApplyTo(config **server.SecureServingInfo) error
|
|||
return fmt.Errorf("unable to load server certificate: %v", err)
|
||||
}
|
||||
c.Cert = &tlsCert
|
||||
} else if s.ServerCert.GeneratedCert != nil {
|
||||
c.Cert = s.ServerCert.GeneratedCert
|
||||
}
|
||||
|
||||
if len(s.CipherSuites) != 0 {
|
||||
cipherSuites, err := utilflag.TLSCipherSuites(s.CipherSuites)
|
||||
cipherSuites, err := cliflag.TLSCipherSuites(s.CipherSuites)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -210,7 +243,7 @@ func (s *SecureServingOptions) ApplyTo(config **server.SecureServingInfo) error
|
|||
}
|
||||
|
||||
var err error
|
||||
c.MinTLSVersion, err = utilflag.TLSVersion(s.MinTLSVersion)
|
||||
c.MinTLSVersion, err = cliflag.TLSVersion(s.MinTLSVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -236,7 +269,7 @@ func (s *SecureServingOptions) ApplyTo(config **server.SecureServingInfo) error
|
|||
}
|
||||
|
||||
func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress string, alternateDNS []string, alternateIPs []net.IP) error {
|
||||
if s == nil {
|
||||
if s == nil || (s.BindPort == 0 && s.Listener == nil) {
|
||||
return nil
|
||||
}
|
||||
keyCert := &s.ServerCert.CertKey
|
||||
|
|
@ -244,13 +277,20 @@ func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress str
|
|||
return nil
|
||||
}
|
||||
|
||||
keyCert.CertFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".crt")
|
||||
keyCert.KeyFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".key")
|
||||
|
||||
canReadCertAndKey, err := certutil.CanReadCertAndKey(keyCert.CertFile, keyCert.KeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
canReadCertAndKey := false
|
||||
if len(s.ServerCert.CertDirectory) > 0 {
|
||||
if len(s.ServerCert.PairName) == 0 {
|
||||
return fmt.Errorf("PairName is required if CertDirectory is set")
|
||||
}
|
||||
keyCert.CertFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".crt")
|
||||
keyCert.KeyFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".key")
|
||||
if canRead, err := certutil.CanReadCertAndKey(keyCert.CertFile, keyCert.KeyFile); err != nil {
|
||||
return err
|
||||
} else {
|
||||
canReadCertAndKey = canRead
|
||||
}
|
||||
}
|
||||
|
||||
if !canReadCertAndKey {
|
||||
// add either the bind address or localhost to the valid alternates
|
||||
bindIP := s.BindAddress.String()
|
||||
|
|
@ -260,17 +300,23 @@ func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress str
|
|||
alternateIPs = append(alternateIPs, s.BindAddress)
|
||||
}
|
||||
|
||||
if cert, key, err := certutil.GenerateSelfSignedCertKey(publicAddress, alternateIPs, alternateDNS); err != nil {
|
||||
if cert, key, err := certutil.GenerateSelfSignedCertKeyWithFixtures(publicAddress, alternateIPs, alternateDNS, s.ServerCert.FixtureDirectory); err != nil {
|
||||
return fmt.Errorf("unable to generate self signed cert: %v", err)
|
||||
} else {
|
||||
} else if len(keyCert.CertFile) > 0 && len(keyCert.KeyFile) > 0 {
|
||||
if err := certutil.WriteCert(keyCert.CertFile, cert); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := certutil.WriteKey(keyCert.KeyFile, key); err != nil {
|
||||
if err := keyutil.WriteKey(keyCert.KeyFile, key); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infof("Generated self-signed cert (%s, %s)", keyCert.CertFile, keyCert.KeyFile)
|
||||
klog.Infof("Generated self-signed cert (%s, %s)", keyCert.CertFile, keyCert.KeyFile)
|
||||
} else {
|
||||
tlsCert, err := tls.X509KeyPair(cert, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to generate self signed cert: %v", err)
|
||||
}
|
||||
s.ServerCert.GeneratedCert = &tlsCert
|
||||
klog.Infof("Generated self-signed cert in-memory")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
23
vendor/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go
generated
vendored
23
vendor/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go
generated
vendored
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/pborman/uuid"
|
||||
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/client-go/rest"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
)
|
||||
|
||||
|
|
@ -30,26 +31,24 @@ type SecureServingOptionsWithLoopback struct {
|
|||
*SecureServingOptions
|
||||
}
|
||||
|
||||
func WithLoopback(o *SecureServingOptions) *SecureServingOptionsWithLoopback {
|
||||
func (o *SecureServingOptions) WithLoopback() *SecureServingOptionsWithLoopback {
|
||||
return &SecureServingOptionsWithLoopback{o}
|
||||
}
|
||||
|
||||
// ApplyTo fills up serving information in the server configuration.
|
||||
func (s *SecureServingOptionsWithLoopback) ApplyTo(c *server.Config) error {
|
||||
if s == nil || s.SecureServingOptions == nil {
|
||||
func (s *SecureServingOptionsWithLoopback) ApplyTo(secureServingInfo **server.SecureServingInfo, loopbackClientConfig **rest.Config) error {
|
||||
if s == nil || s.SecureServingOptions == nil || secureServingInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := s.SecureServingOptions.ApplyTo(&c.SecureServing); err != nil {
|
||||
if err := s.SecureServingOptions.ApplyTo(secureServingInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.SecureServing == nil {
|
||||
if *secureServingInfo == nil || loopbackClientConfig == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.ReadWritePort = s.BindPort
|
||||
|
||||
// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
|
||||
// let the server return it when the loopback client connects.
|
||||
certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
|
||||
|
|
@ -61,18 +60,18 @@ func (s *SecureServingOptionsWithLoopback) ApplyTo(c *server.Config) error {
|
|||
return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
|
||||
}
|
||||
|
||||
secureLoopbackClientConfig, err := c.SecureServing.NewLoopbackClientConfig(uuid.NewRandom().String(), certPem)
|
||||
secureLoopbackClientConfig, err := (*secureServingInfo).NewLoopbackClientConfig(uuid.NewRandom().String(), certPem)
|
||||
switch {
|
||||
// if we failed and there's no fallback loopback client config, we need to fail
|
||||
case err != nil && c.LoopbackClientConfig == nil:
|
||||
case err != nil && *loopbackClientConfig == nil:
|
||||
return err
|
||||
|
||||
// if we failed, but we already have a fallback loopback client config (usually insecure), allow it
|
||||
case err != nil && c.LoopbackClientConfig != nil:
|
||||
case err != nil && *loopbackClientConfig != nil:
|
||||
|
||||
default:
|
||||
c.LoopbackClientConfig = secureLoopbackClientConfig
|
||||
c.SecureServing.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
|
||||
*loopbackClientConfig = secureLoopbackClientConfig
|
||||
(*secureServingInfo).SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
34
vendor/k8s.io/apiserver/pkg/server/options/webhook.go
generated
vendored
Normal file
34
vendor/k8s.io/apiserver/pkg/server/options/webhook.go
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
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(),
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue