Merge pull request #121325 from benluddy/check-apiserver-serializers

KEP-4222: Restrict supported media types for new apiservers.
This commit is contained in:
Kubernetes Prow Robot 2023-10-23 17:27:49 +02:00 committed by GitHub
commit 2014ce2313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 0 deletions

View File

@ -724,6 +724,12 @@ func (c *RecommendedConfig) Complete() CompletedConfig {
return c.Config.Complete(c.SharedInformerFactory)
}
var allowedMediaTypes = []string{
runtime.ContentTypeJSON,
runtime.ContentTypeYAML,
runtime.ContentTypeProtobuf,
}
// New creates a new server which logically combines the handling chain with the passed server.
// name is used to differentiate for logging. The handler chain in particular can be difficult as it starts delegating.
// delegationTarget may not be nil.
@ -731,6 +737,18 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
if c.Serializer == nil {
return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil")
}
for _, info := range c.Serializer.SupportedMediaTypes() {
var ok bool
for _, mt := range allowedMediaTypes {
if info.MediaType == mt {
ok = true
break
}
}
if !ok {
return nil, fmt.Errorf("refusing to create new apiserver %q with support for media type %q (allowed media types are: %s)", name, info.MediaType, strings.Join(allowedMediaTypes, ", "))
}
}
if c.LoopbackClientConfig == nil {
return nil, fmt.Errorf("Genericapiserver.New() called with config.LoopbackClientConfig == nil")
}

View File

@ -26,6 +26,7 @@ import (
"testing"
"time"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
@ -362,3 +363,21 @@ func (b *testBackend) ProcessEvents(events ...*auditinternal.Event) bool {
b.events = append(b.events, events...)
return true
}
func TestNewErrorForbiddenSerializer(t *testing.T) {
config := CompletedConfig{
&completedConfig{
Config: &Config{
Serializer: runtime.NewSimpleNegotiatedSerializer(runtime.SerializerInfo{
MediaType: "application/cbor",
}),
},
},
}
_, err := config.New("test", NewEmptyDelegate())
if err == nil {
t.Error("successfully created a new server configured with cbor support")
} else if err.Error() != `refusing to create new apiserver "test" with support for media type "application/cbor" (allowed media types are: application/json, application/yaml, application/vnd.kubernetes.protobuf)` {
t.Errorf("unexpected error: %v", err)
}
}

View File

@ -26,6 +26,7 @@ import (
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
@ -87,6 +88,12 @@ func NewEtcdOptions(backendConfig *storagebackend.Config) *EtcdOptions {
return options
}
var storageMediaTypes = sets.New(
runtime.ContentTypeJSON,
runtime.ContentTypeYAML,
runtime.ContentTypeProtobuf,
)
func (s *EtcdOptions) Validate() []error {
if s == nil {
return nil
@ -120,6 +127,10 @@ func (s *EtcdOptions) Validate() []error {
allErrors = append(allErrors, fmt.Errorf("--encryption-provider-config-automatic-reload must be set with --encryption-provider-config"))
}
if s.DefaultStorageMediaType != "" && !storageMediaTypes.Has(s.DefaultStorageMediaType) {
allErrors = append(allErrors, fmt.Errorf("--storage-media-type %q invalid, allowed values: %s", s.DefaultStorageMediaType, strings.Join(sets.List(storageMediaTypes), ", ")))
}
return allErrors
}

View File

@ -160,6 +160,40 @@ func TestEtcdOptionsValidate(t *testing.T) {
EtcdServersOverrides: []string{"/events#http://127.0.0.1:4002"},
},
},
{
name: "empty storage-media-type",
testOptions: &EtcdOptions{
StorageConfig: storagebackend.Config{
Transport: storagebackend.TransportConfig{
ServerList: []string{"http://127.0.0.1"},
},
},
DefaultStorageMediaType: "",
},
},
{
name: "recognized storage-media-type",
testOptions: &EtcdOptions{
StorageConfig: storagebackend.Config{
Transport: storagebackend.TransportConfig{
ServerList: []string{"http://127.0.0.1"},
},
},
DefaultStorageMediaType: "application/json",
},
},
{
name: "unrecognized storage-media-type",
testOptions: &EtcdOptions{
StorageConfig: storagebackend.Config{
Transport: storagebackend.TransportConfig{
ServerList: []string{"http://127.0.0.1"},
},
},
DefaultStorageMediaType: "foo/bar",
},
expectErr: `--storage-media-type "foo/bar" invalid, allowed values: application/json, application/vnd.kubernetes.protobuf, application/yaml`,
},
}
for _, testcase := range testCases {