SecretsManager: Limit of 24kiB for raw input for secure value (#107403)
* SecureValues: Add limit of 24kiB for raw input Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Fix lint --------- Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com>
This commit is contained in:
co-authored by
Matheus Macabu
parent
0a90b7b5e9
commit
d28594d2f9
@@ -59,7 +59,9 @@ type SecureValueSpec struct {
|
|||||||
|
|
||||||
// The raw value is only valid for write. Read/List will always be empty.
|
// The raw value is only valid for write. Read/List will always be empty.
|
||||||
// There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`.
|
// There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`.
|
||||||
|
// Minimum and maximum lengths in bytes.
|
||||||
// +k8s:validation:minLength=1
|
// +k8s:validation:minLength=1
|
||||||
|
// +k8s:validation:maxLength=24576
|
||||||
Value ExposedSecureValue `json:"value,omitempty"`
|
Value ExposedSecureValue `json:"value,omitempty"`
|
||||||
|
|
||||||
// When using a third-party keeper, the `ref` is used to reference a value inside the remote storage.
|
// When using a third-party keeper, the `ref` is used to reference a value inside the remote storage.
|
||||||
|
|||||||
@@ -641,8 +641,9 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueSpec(ref common.ReferenceCallbac
|
|||||||
},
|
},
|
||||||
"value": {
|
"value": {
|
||||||
SchemaProps: spec.SchemaProps{
|
SchemaProps: spec.SchemaProps{
|
||||||
Description: "The raw value is only valid for write. Read/List will always be empty. There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`.",
|
Description: "The raw value is only valid for write. Read/List will always be empty. There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`. Minimum and maximum lengths in bytes.",
|
||||||
MinLength: ptr.To[int64](1),
|
MinLength: ptr.To[int64](1),
|
||||||
|
MaxLength: ptr.To[int64](24576),
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The maximum size of a secure value in bytes when written as raw input.
|
||||||
|
const SECURE_VALUE_RAW_INPUT_MAX_SIZE_BYTES = 24576 // 24 KiB
|
||||||
|
|
||||||
type DecryptSecureValue struct {
|
type DecryptSecureValue struct {
|
||||||
Keeper *string
|
Keeper *string
|
||||||
Ref string
|
Ref string
|
||||||
|
|||||||
@@ -245,6 +245,13 @@ func ValidateSecureValue(sv, oldSv *secretv0alpha1.SecureValue, operation admiss
|
|||||||
}
|
}
|
||||||
|
|
||||||
// General validations.
|
// General validations.
|
||||||
|
if len(sv.Spec.Value) > contracts.SECURE_VALUE_RAW_INPUT_MAX_SIZE_BYTES {
|
||||||
|
errs = append(
|
||||||
|
errs,
|
||||||
|
field.TooLong(field.NewPath("spec", "value"), len(sv.Spec.Value), contracts.SECURE_VALUE_RAW_INPUT_MAX_SIZE_BYTES),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errs := validateDecrypters(sv.Spec.Decrypters, decryptersAllowList); len(errs) > 0 {
|
if errs := validateDecrypters(sv.Spec.Decrypters, decryptersAllowList); len(errs) > 0 {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
|
||||||
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||||
|
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateSecureValue(t *testing.T) {
|
func TestValidateSecureValue(t *testing.T) {
|
||||||
@@ -50,6 +52,16 @@ func TestValidateSecureValue(t *testing.T) {
|
|||||||
require.Len(t, errs, 1)
|
require.Len(t, errs, 1)
|
||||||
require.Equal(t, "spec", errs[0].Field)
|
require.Equal(t, "spec", errs[0].Field)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("`value` cannot exceed 24576 bytes", func(t *testing.T) {
|
||||||
|
sv := validSecureValue.DeepCopy()
|
||||||
|
sv.Spec.Value = secretv0alpha1.NewExposedSecureValue(strings.Repeat("a", contracts.SECURE_VALUE_RAW_INPUT_MAX_SIZE_BYTES+1))
|
||||||
|
sv.Spec.Ref = nil
|
||||||
|
|
||||||
|
errs := ValidateSecureValue(sv, nil, admission.Create, nil)
|
||||||
|
require.Len(t, errs, 1)
|
||||||
|
require.Equal(t, "spec.value", errs[0].Field)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("when updating a securevalue", func(t *testing.T) {
|
t.Run("when updating a securevalue", func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user