feat: add RedactSecrets method to v1alpha1.Config

Add a way to strip away the secrets from a config.

Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
This commit is contained in:
Utku Ozdemir 2022-12-07 22:01:16 +01:00
parent 4c31b9b1a3
commit cf7adc51c9
No known key found for this signature in database
GPG Key ID: 65933E76F0549B0D
4 changed files with 117 additions and 0 deletions

View File

@ -19,6 +19,8 @@ import (
) )
// Provider defines the configuration consumption interface. // Provider defines the configuration consumption interface.
//
//nolint:interfacebloat
type Provider interface { type Provider interface {
// Config parts accessor. // Config parts accessor.
Version() string Version() string
@ -33,6 +35,9 @@ type Provider interface {
// Bytes returns source YAML representation (if available) or does default encoding. // Bytes returns source YAML representation (if available) or does default encoding.
Bytes() ([]byte, error) Bytes() ([]byte, error)
// RedactSecrets returns a copy of the Provider with all secrets replaced with the given string.
RedactSecrets(string) Provider
// Encode configuration to YAML using the provided options. // Encode configuration to YAML using the provided options.
EncodeString(encoderOptions ...encoder.Option) (string, error) EncodeString(encoderOptions ...encoder.Option) (string, error)
EncodeBytes(encoderOptions ...encoder.Option) ([]byte, error) EncodeBytes(encoderOptions ...encoder.Option) ([]byte, error)

View File

@ -102,6 +102,55 @@ func (c *Config) Bytes() ([]byte, error) {
return c.EncodeBytes() return c.EncodeBytes()
} }
// RedactSecrets implements the config.Provider interface.
func (c *Config) RedactSecrets(replacement string) config.Provider {
if c == nil {
return nil
}
redactBytes := func(b []byte) []byte {
if len(b) == 0 {
return b
}
return []byte(replacement)
}
redactStr := func(s string) string {
return string(redactBytes([]byte(s)))
}
clone := c.DeepCopy()
if clone.MachineConfig != nil {
clone.MachineConfig.MachineToken = redactStr(clone.MachineConfig.MachineToken)
if clone.MachineConfig.MachineCA != nil {
clone.MachineConfig.MachineCA.Key = redactBytes(clone.MachineConfig.MachineCA.Key)
}
}
if clone.ClusterConfig != nil {
clone.ClusterConfig.ClusterSecret = redactStr(clone.ClusterConfig.ClusterSecret)
clone.ClusterConfig.BootstrapToken = redactStr(clone.ClusterConfig.BootstrapToken)
clone.ClusterConfig.ClusterAESCBCEncryptionSecret = redactStr(clone.ClusterConfig.ClusterAESCBCEncryptionSecret)
clone.ClusterConfig.ClusterSecretboxEncryptionSecret = redactStr(clone.ClusterConfig.ClusterSecretboxEncryptionSecret)
if clone.ClusterConfig.ClusterCA != nil {
clone.ClusterConfig.ClusterCA.Key = redactBytes(clone.ClusterConfig.ClusterCA.Key)
}
if clone.ClusterConfig.ClusterAggregatorCA != nil {
clone.ClusterConfig.ClusterAggregatorCA.Key = redactBytes(clone.ClusterConfig.ClusterAggregatorCA.Key)
}
if clone.ClusterConfig.EtcdConfig != nil && clone.ClusterConfig.EtcdConfig.RootCA != nil {
clone.ClusterConfig.EtcdConfig.RootCA.Key = redactBytes(clone.ClusterConfig.EtcdConfig.RootCA.Key)
}
}
return clone
}
// Raw implements the config.Provider interface. // Raw implements the config.Provider interface.
func (c *Config) Raw() interface{} { func (c *Config) Raw() interface{} {
return c return c

View File

@ -66,6 +66,11 @@ func (r *ReadonlyProvider) Bytes() ([]byte, error) {
return r.bytes, nil return r.bytes, nil
} }
// RedactSecrets implements the config.Provider interface.
func (r *ReadonlyProvider) RedactSecrets(replacement string) config.Provider {
return r.cfg.RedactSecrets(replacement)
}
// EncodeString implements the config.Provider interface. // EncodeString implements the config.Provider interface.
func (r *ReadonlyProvider) EncodeString(encoderOptions ...encoder.Option) (string, error) { func (r *ReadonlyProvider) EncodeString(encoderOptions ...encoder.Option) (string, error) {
return r.cfg.EncodeString(encoderOptions...) return r.cfg.EncodeString(encoderOptions...)

View File

@ -0,0 +1,58 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package v1alpha1_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1/generate"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1/machine"
"github.com/siderolabs/talos/pkg/machinery/constants"
)
func TestRedactSecrets(t *testing.T) {
bundle, err := generate.NewSecretsBundle(generate.NewClock())
require.NoError(t, err)
input, err := generate.NewInput("test", "https://doesntmatter:6443", constants.DefaultKubernetesVersion, bundle)
require.NoError(t, err)
config, err := generate.Config(machine.TypeControlPlane, input)
if err != nil {
return
}
require.NotEmpty(t, config.MachineConfig.MachineToken)
require.NotEmpty(t, config.MachineConfig.MachineCA.Key)
require.NotEmpty(t, config.ClusterConfig.ClusterSecret)
require.NotEmpty(t, config.ClusterConfig.BootstrapToken)
require.Empty(t, config.ClusterConfig.ClusterAESCBCEncryptionSecret)
require.NotEmpty(t, config.ClusterConfig.ClusterSecretboxEncryptionSecret)
require.NotEmpty(t, config.ClusterConfig.ClusterCA.Key)
require.NotEmpty(t, config.ClusterConfig.EtcdConfig.RootCA.Key)
replacement := "**.***"
configBytesBefore, err := config.Bytes()
require.NoError(t, err)
redacted := config.RedactSecrets(replacement)
configBytesAfter, err := config.Bytes()
require.NoError(t, err)
require.Equal(t, string(configBytesBefore), string(configBytesAfter), "original config is modified")
require.Equal(t, replacement, redacted.Machine().Security().Token())
require.Equal(t, replacement, string(redacted.Machine().Security().CA().Key))
require.Equal(t, replacement, redacted.Cluster().Secret())
require.Equal(t, "***", redacted.Cluster().Token().Secret())
require.Equal(t, "", redacted.Cluster().AESCBCEncryptionSecret())
require.Equal(t, replacement, redacted.Cluster().SecretboxEncryptionSecret())
require.Equal(t, replacement, string(redacted.Cluster().CA().Key))
require.Equal(t, replacement, string(redacted.Cluster().Etcd().CA().Key))
}