Skip to content

Commit

Permalink
jsonDataLimit#4055
Browse files Browse the repository at this point in the history
Signed-off-by: rickr <cr22rc@users.noreply.github.com>
  • Loading branch information
cr22rc committed Oct 8, 2020
1 parent 56a0822 commit b83317d
Show file tree
Hide file tree
Showing 13 changed files with 425 additions and 1 deletion.
5 changes: 4 additions & 1 deletion cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (
messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1"
messagingv1beta1 "knative.dev/eventing/pkg/apis/messaging/v1beta1"
"knative.dev/eventing/pkg/apis/sources"
pingdefaultconfig "knative.dev/eventing/pkg/apis/sources/config/pingconfig/config"
sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1"
sourcesv1alpha1 "knative.dev/eventing/pkg/apis/sources/v1alpha1"
sourcesv1alpha2 "knative.dev/eventing/pkg/apis/sources/v1alpha2"
Expand Down Expand Up @@ -152,9 +153,11 @@ func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher
channelStore := channeldefaultconfig.NewStore(logging.FromContext(ctx).Named("channel-config-store"))
channelStore.WatchConfigs(cmw)

pingstore := pingdefaultconfig.NewStore(logging.FromContext(ctx).Named("ping-config-store"))
pingstore.WatchConfigs(cmw)
// Decorate contexts with the current state of the config.
ctxFunc := func(ctx context.Context) context.Context {
return channelStore.ToContext(store.ToContext(ctx))
return channelStore.ToContext(pingstore.ToContext(store.ToContext(ctx)))
}

return validation.NewAdmissionController(ctx,
Expand Down
1 change: 1 addition & 0 deletions config/400-config-ping-defaults.yaml
26 changes: 26 additions & 0 deletions config/core/configmaps/default-pingsource.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2020 The Knative 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
#
# https://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.

apiVersion: v1
kind: ConfigMap
metadata:
name: default-ping-webhook
namespace: knative-eventing
labels:
eventing.knative.dev/release: devel
annotations:
knative.dev/example-checksum: "6eaeecba"
data:
default-ping-config: |
jsonDataMaxBytes: 4096 # Max number of bytes allowed in jsonData in Pingsource
1 change: 1 addition & 0 deletions hack/update-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ ${GOPATH}/bin/deepcopy-gen \
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
-i knative.dev/eventing/pkg/apis/config \
-i knative.dev/eventing/pkg/apis/messaging/config \
-i knative.dev/eventing/pkg/apis/sources/config/pingconfig/config \

# Only deepcopy the Duck types, as they are not real resources.
${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/sources/config/pingconfig/config/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2020 The Knative 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.
*/

// +k8s:deepcopy-gen=package

// Package config holds the typed objects that define the schemas for
// ConfigMap objects that pertain to our API objects.
package config
76 changes: 76 additions & 0 deletions pkg/apis/sources/config/pingconfig/config/ping_defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright 2020 The Knative 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 config

import (
"encoding/json"
"fmt"

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
)

const (
// PingDefaultsConfigName is the name of config map for the default
// configs that pings should use.
PingDefaultsConfigName = "default-ping-webhook"

// PingDefaulterKey is the key in the ConfigMap to get the name of the default
// Ping CRD.
PingDefaulterKey = "default-ping-config"
)

// NewPingDefaultsConfigFromMap creates a Defaults from the supplied Map
func NewPingDefaultsConfigFromMap(data map[string]string) (*PingDefaults, error) {
nc := &PingDefaults{}

// Parse out the Broker Configuration Cluster default section
value, present := data[PingDefaulterKey]
if !present || value == "" {
return nil, fmt.Errorf("ConfigMap is missing (or empty) key: %q : %v", PingDefaulterKey, data)
}
if err := parseEntry(value, nc); err != nil {
return nil, fmt.Errorf("Failed to parse the entry: %s", err)
}
return nc, nil
}

func parseEntry(entry string, out interface{}) error {
j, err := yaml.YAMLToJSON([]byte(entry))
if err != nil {
return fmt.Errorf("ConfigMap's value could not be converted to JSON: %s : %v", err, entry)
}
return json.Unmarshal(j, &out)
}

// NewPingDefaultsConfigFromConfigMap creates a PingDefaults from the supplied configMap
func NewPingDefaultsConfigFromConfigMap(config *corev1.ConfigMap) (*PingDefaults, error) {
return NewPingDefaultsConfigFromMap(config.Data)
}

// PingDefaults includes the default values to be populated by the webhook.
type PingDefaults struct {
JsonDataMaxBytes int `json:"jsonDataMaxBytes"`
}

func (d *PingDefaults) GetPingConfig() *PingDefaults {
if d.JsonDataMaxBytes < 1 {
d.JsonDataMaxBytes = 4096
}
return d

}
37 changes: 37 additions & 0 deletions pkg/apis/sources/config/pingconfig/config/ping_template_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2020 The Knative 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 config

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

// This is a verbatim copy from messaging/v1beta1/ping_template_types.go
// but we can not import v1beta1 since we use this there as well, so
// replicate it here.

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type PingTemplateSpec struct {
JsonDataMaxBytes int `json:"jsonDataMaxBytes"`
metav1.TypeMeta `json:",inline"`

// Spec defines the Spec to use for each ping created. Passed
// in verbatim to the Ping CRD as Spec section.
// +optional
Spec *runtime.RawExtension `json:"spec,omitempty"`
}
97 changes: 97 additions & 0 deletions pkg/apis/sources/config/pingconfig/config/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
Copyright 2020 The Knative 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 config

import (
"context"

"knative.dev/pkg/configmap"
)

type pingCfgKey struct{}

// Config holds the collection of configurations that we attach to contexts.
// +k8s:deepcopy-gen=false
type Config struct {
PingDefaults *PingDefaults
}

// FromContext extracts a Config from the provided context.
func FromContext(ctx context.Context) *Config {
x, ok := ctx.Value(pingCfgKey{}).(*Config)
if ok {
return x
}
return nil
}

// FromContextOrDefaults is like FromContext, but when no Config is attached it
// returns a Config populated with the defaults for each of the Config fields.
func FromContextOrDefaults(ctx context.Context) *Config {
if cfg := FromContext(ctx); cfg != nil {
return cfg
}
pingDefaults, err := NewPingDefaultsConfigFromMap(map[string]string{})
if err != nil || pingDefaults == nil {
pingDefaults = &PingDefaults{}
pingDefaults.GetPingConfig()
}

return &Config{
PingDefaults: pingDefaults,
}
}

// ToContext attaches the provided Config to the provided context, returning the
// new context with the Config attached.
func ToContext(ctx context.Context, c *Config) context.Context {
return context.WithValue(ctx, pingCfgKey{}, c)
}

// Store is a typed wrapper around configmap.Untyped store to handle our configmaps.
// +k8s:deepcopy-gen=false
type Store struct {
*configmap.UntypedStore
}

// NewStore creates a new store of Configs and optionally calls functions when ConfigMaps are updated.
func NewStore(logger configmap.Logger, onAfterStore ...func(name string, value interface{})) *Store {
store := &Store{
UntypedStore: configmap.NewUntypedStore(
"pingdefaults",
logger,
configmap.Constructors{
PingDefaultsConfigName: NewPingDefaultsConfigFromConfigMap,
},
onAfterStore...,
),
}

return store
}

// ToContext attaches the current Config state to the provided context.
func (s *Store) ToContext(ctx context.Context) context.Context {
return ToContext(ctx, s.Load())
}

// Load creates a Config from the current config state of the Store.
func (s *Store) Load() *Config {
return &Config{
PingDefaults: s.UntypedLoad(PingDefaultsConfigName).(*PingDefaults).DeepCopy(),
}
}
71 changes: 71 additions & 0 deletions pkg/apis/sources/config/pingconfig/config/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions pkg/apis/sources/v1alpha2/ping_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ package v1alpha2

import (
"context"
"fmt"

"github.com/robfig/cron/v3"

"knative.dev/pkg/apis"

"knative.dev/eventing/pkg/apis/eventing"
"knative.dev/eventing/pkg/apis/sources/config/pingconfig/config"
)

func (c *PingSource) Validate(ctx context.Context) *apis.FieldError {
Expand All @@ -38,6 +41,14 @@ func (cs *PingSourceSpec) Validate(ctx context.Context) *apis.FieldError {
errs = errs.Also(fe)
}

pingConfig := config.FromContextOrDefaults(ctx)
pingDefaults := pingConfig.PingDefaults.GetPingConfig()

if bsize := len(cs.JsonData); bsize > pingDefaults.JsonDataMaxBytes {
fe := apis.ErrInvalidValue(fmt.Sprintf("the jsonData length of %d bytes exceeds limit set at %d.", bsize, pingDefaults.JsonDataMaxBytes), "jsonData")
errs = errs.Also(fe)
}

if fe := cs.Sink.Validate(ctx); fe != nil {
errs = errs.Also(fe.ViaField("sink"))
}
Expand Down

0 comments on commit b83317d

Please sign in to comment.