Files
grafana/pkg/apimachinery/apis/common/v0alpha1/secure_values_test.go
T
2025-11-19 15:20:32 -05:00

122 lines
3.3 KiB
Go

package v0alpha1_test
import (
"bytes"
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"go.yaml.in/yaml/v3"
"k8s.io/kube-openapi/pkg/validation/strfmt"
"k8s.io/kube-openapi/pkg/validation/validate"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
)
func TestSecureValues(t *testing.T) {
t.Run("redaction", func(t *testing.T) {
expected := "[REDACTED]"
rawValue := "a-password"
esv := common.NewSecretValue(rawValue)
// String must not return the exposed secure value.
require.Equal(t, expected, esv.String())
require.Equal(t, expected, esv.GoString())
// Format/GoString must not return the exposed secure value.
require.Equal(t, expected, fmt.Sprintf("%+#v", esv))
require.Equal(t, expected, fmt.Sprintf("%v", esv))
require.Equal(t, expected, fmt.Sprintf("%s", esv))
buf := new(bytes.Buffer)
_, err := fmt.Fprintf(buf, "%#v", esv)
require.NoError(t, err)
require.Equal(t, expected, buf.String())
// MarshalJSON must not return the exposed secure value.
bytes, err := json.Marshal(esv)
require.NoError(t, err)
require.Equal(t, `"`+expected+`"`, string(bytes))
// MarshalYAML must not return the exposed secure value.
bytes, err = yaml.Marshal(esv)
require.NoError(t, err)
require.Equal(t, "'"+expected+"'\n", string(bytes))
// DangerouslyExposeAndConsumeValue returns the raw value.
require.Equal(t, rawValue, esv.DangerouslyExposeAndConsumeValue())
// Further calls to DangerouslyExposeAndConsumeValue will panic.
require.Panics(t, func() { esv.DangerouslyExposeAndConsumeValue() })
})
t.Run("Inline", func(t *testing.T) {
t.Run("IsZero", func(t *testing.T) {
require.True(t, common.InlineSecureValue{}.IsZero())
require.True(t, common.NewSecretValue("").IsZero())
require.True(t, common.InlineSecureValue{Remove: false}.IsZero())
require.False(t, common.NewSecretValue("X").IsZero())
require.False(t, common.InlineSecureValue{Name: "X"}.IsZero())
require.False(t, common.InlineSecureValue{Remove: true}.IsZero())
})
t.Run("Validate OneOf", func(t *testing.T) {
def := common.InlineSecureValue{}.OpenAPIDefinition()
// jj, _ := json.MarshalIndent(def.Schema, "", " ")
// fmt.Printf("%s", string(jj))
// t.FailNow()
validator := validate.NewSchemaValidator(&def.Schema, nil, "", strfmt.Default)
tests := []struct {
name string
input map[string]any
valid bool
err string
}{
{
name: "with name",
input: map[string]any{"name": "x"},
valid: true,
},
{
name: "with create",
input: map[string]any{"create": "x"},
valid: true,
},
{
name: "with remove",
input: map[string]any{"remove": true},
valid: true,
},
{
name: "empty",
input: map[string]any{},
valid: false,
err: "must validate one and only one",
},
{
name: "with unknown property",
input: map[string]any{"unknown": "property"},
valid: false,
err: "unknown",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := validator.Validate(tt.input)
require.Equal(t, tt.valid, result.IsValid())
if tt.err == "" {
require.NoError(t, result.AsError())
} else {
require.ErrorContains(t, result.AsError(), tt.err)
}
})
}
})
})
}