Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7042f47
pr that implement sensitive config
henderiw May 6, 2026
d8eec28
updated artifacts + fix resource for targetsnapshots
henderiw May 7, 2026
9de65a1
updated registration
henderiw May 7, 2026
f03cb6c
updated validation for target snapshots
henderiw May 7, 2026
7212d1d
update target conditions in configset
henderiw May 7, 2026
a9509d7
updated transaction validation
henderiw May 7, 2026
9fbaa90
update logging
henderiw May 7, 2026
292f267
update validation for targetsnapshots
henderiw May 7, 2026
e800369
always encrypt
henderiw May 7, 2026
fe9d32e
update sc delete
henderiw May 7, 2026
308250c
update sc delete
henderiw May 7, 2026
b1c3728
update sc delete
henderiw May 7, 2026
17b25d0
watch config for dlete
henderiw May 7, 2026
6b5b868
fix lint error
henderiw May 7, 2026
cb2f4f0
updated openapi
henderiw May 7, 2026
1a513d4
updated openapi
henderiw May 7, 2026
25dd1d3
updated openapi
henderiw May 7, 2026
910b007
updated openapi
henderiw May 8, 2026
5f472d9
updated openapi
henderiw May 8, 2026
5b8358a
updated openapi
henderiw May 8, 2026
8112ef5
sensitive paths to DS
henderiw Jun 22, 2026
d1e2ef5
update the config CR for secretrefs
henderiw Jun 22, 2026
b3ae4d8
Merge branch 'main' into sensitive
henderiw Jun 22, 2026
a78e8f2
updated go sum
henderiw Jun 22, 2026
070aafd
Fix panic when resolving secrets on first reconcile.
steiler Jun 29, 2026
9070056
Merge pull request #459 from sdcio/fix/configresolver-nil-fetched-map
henderiw Jun 30, 2026
4b27971
Fix BuildGRPCIntents to use resolved secret blobs on apply.
steiler Jun 30, 2026
213d8ca
fix: include resolverOK in ready gate in SetOverallStatus
steiler Jun 30, 2026
e0639cc
fix: correct protobuf wire type for ConfigHash and SecretKeyHashes
steiler Jun 30, 2026
bc84a54
Merge pull request #460 from sdcio/fix/build-grpc-intents-resolved-blobs
henderiw Jun 30, 2026
0d97288
Merge pull request #462 from sdcio/fix/sensitive-config-protobuf-wire…
henderiw Jun 30, 2026
e0b11b8
Merge pull request #461 from sdcio/fix/resolver-ok-ready-condition
henderiw Jun 30, 2026
d6246fe
Merge remote-tracking branch 'origin/main' into sensitive
steiler Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions apis/condition/v1alpha1/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,9 @@ type UnrecoverableMessage struct {
Message string `json:"message" protobuf:"bytes,2,opt,name=message"`
}


// dedupeConditions returns conditions deduplicated by type; last value wins.
// This is needed because WithConditions is a generated append-only method and
// cannot protect against duplicate list-map keys itself.
// DedupeConditions returns conditions deduplicated by type; last value wins.
// Needed because WithConditions is a generated append-only method and
// cannot protect against duplicate list-map keys itself (issue #431).
func DedupeConditions(conds ...Condition) []Condition {
index := make(map[string]int, len(conds))
out := make([]Condition, 0, len(conds))
Expand All @@ -251,4 +250,4 @@ func DedupeConditions(conds ...Condition) []Condition {
}
}
return out
}
}
18 changes: 4 additions & 14 deletions apis/condition/v1alpha1/generated.proto

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

31 changes: 8 additions & 23 deletions apis/config/config_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ package config

import (
"context"
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"os"
Expand Down Expand Up @@ -86,13 +87,6 @@ func (r *Config) GetNamespacedName() types.NamespacedName {
return types.NamespacedName{Name: r.Name, Namespace: r.Namespace}
}

func (r *Config) GetLastKnownGoodSchema() *ConfigStatusLastKnownGoodSchema {
if r.Status.LastKnownGoodSchema == nil {
return &ConfigStatusLastKnownGoodSchema{}
}
return r.Status.LastKnownGoodSchema
}

func (r *Config) GetTarget() string {
if len(r.GetLabels()) == 0 {
return ""
Expand Down Expand Up @@ -157,28 +151,19 @@ func BuildEmptyConfig() *Config {
}
}

func (r *Config) HashDeviationGenerationChanged(deviation Deviation) bool {
if r.Status.DeviationGeneration == nil {
// if there was no old deviation, but now we have a deviation wwe return true
return len(deviation.Spec.Deviations) != 0
} else {
return *r.Status.DeviationGeneration == deviation.GetGeneration()
}
}

type RecoveryConfig struct {
Config Config
Deviation Deviation
}

func (r *ConfigSpec) GetShaSum(ctx context.Context) [20]byte {
log := log.FromContext(ctx)
appliedSpec, err := json.Marshal(r)
// GetHash returns a SHA-256 hex hash.
func (r *ConfigSpec) GetHash() (string, error) {
raw, err := json.Marshal(r)
if err != nil {
log.Error("cannot marshal appliedConfig", "error", err)
return [20]byte{}
return "", fmt.Errorf("marshal config blobs: %w", err)
}
return sha1.Sum(appliedSpec)
h := sha256.Sum256(raw)
return hex.EncodeToString(h[:]), nil
}

func (r *Config) GetOwnerReference() metav1.OwnerReference {
Expand Down
2 changes: 0 additions & 2 deletions apis/config/config_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ func (r *Config) TableConvertor() func(gr schema.GroupResource) rest.TableConver
config.GetCondition(condition.ConditionTypeReady).Message,
config.Spec.Priority,
config.GetTarget(),
config.GetLastKnownGoodSchema().FileString(),
}
},
[]metav1.TableColumnDefinition{
Expand All @@ -195,7 +194,6 @@ func (r *Config) TableConvertor() func(gr schema.GroupResource) rest.TableConver
{Name: "Reason", Type: "string"},
{Name: "Priority", Type: "integer"},
{Name: "Target", Type: "string"},
{Name: "Schema", Type: "string"},
},
)
}
Expand Down
42 changes: 34 additions & 8 deletions apis/config/config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"reflect"

"github.com/sdcio/config-server/apis/condition"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
Expand All @@ -34,28 +35,53 @@ type ConfigSpec struct {
// Revertive defines if this CR is enabled for revertive or non revertve operation
Revertive *bool `json:"revertive,omitempty" protobuf:"varint,3,opt,name=revertive"`
// Config defines the configuration to be applied to a target device
//+kubebuilder:pruning:PreserveUnknownFields
Config []ConfigBlob `json:"config" protobuf:"bytes,4,rep,name=config"`
// Vars declares named variables referenced from Config blob values via the
// ${vars.<name>} placeholder. The controller resolves each variable and
// substitutes its value into the rendered configuration before it is sent to
// the target. Variables are the supported mechanism for injecting sensitive
// material: the referenced Secret value is resolved, encrypted into the
// SensitiveConfig payload, and every leaf it lands on is recorded as a
// sensitive path so the datastore redacts it in northbound responses.
// A Config with no variables is rendered verbatim.
// +optional
// +listType=map
// +listMapKey=name
Vars []ConfigVar `json:"vars" protobuf:"bytes,5,rep,name=vars"`
}

type ConfigBlob struct {
// Path defines the path relative to which the value is applicable
Path string `json:"path,omitempty" protobuf:"bytes,1,opt,name=config"`
//+kubebuilder:pruning:PreserveUnknownFields
// +kubebuilder:pruning:PreserveUnknownFields
// +structType=granular
Value runtime.RawExtension `json:"value" protobuf:"bytes,2,opt,name=value"`
}

// ConfigVar is a named variable referenced from Config blob values as
// ${vars.<name>}. The name is the merge key for the Vars list and must be
// unique within a single Config. Exactly one value source must be set; today
// the only source is SecretRef.
type ConfigVar struct {
// Name identifies the variable for reference as ${vars.<name>}.
// Must be unique within the Config's Vars list.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9_.-]+$`
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`

// SecretRef resolves the variable's value from a key of a Secret in the
// same namespace as the Config. The resolved value is never stored in
// clear: it is encrypted into the SensitiveConfig payload, and the leaves
// it is substituted into are tracked as sensitive paths.
// +optional
SecretRef *corev1.SecretKeySelector `json:"secretRef,omitempty" protobuf:"bytes,2,opt,name=secretRef"`
}

// ConfigStatus defines the observed state of Config
type ConfigStatus struct {
// ConditionedStatus provides the status of the Readiness using conditions
// if the condition is true the other attributes in the status are meaningful
condition.ConditionedStatus `json:",inline" protobuf:"bytes,1,opt,name=conditionedStatus"`
// LastKnownGoodSchema identifies the last known good schema used to apply the config successfully
LastKnownGoodSchema *ConfigStatusLastKnownGoodSchema `json:"lastKnownGoodSchema,omitempty" protobuf:"bytes,2,opt,name=lastKnownGoodSchema"`
// AppliedConfig defines the config applied to the target
AppliedConfig *ConfigSpec `json:"appliedConfig,omitempty" protobuf:"bytes,3,opt,name=appliedConfig"`
// Deviations generation used for the latest config apply
DeviationGeneration *int64 `json:"deviationGeneration,omitempty" protobuf:"bytes,4,opt,name=deviationGeneration"`
}

type ConfigStatusLastKnownGoodSchema struct {
Expand Down
1 change: 0 additions & 1 deletion apis/config/configset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ type ConfigSetSpec struct {
// Revertive defines if this CR is enabled for revertive or non revertve operation
Revertive *bool `json:"revertive,omitempty" protobuf:"varint,4,opt,name=revertive"`
// Config defines the configuration to be applied to a target device
//+kubebuilder:pruning:PreserveUnknownFields
Config []ConfigBlob `json:"config" protobuf:"bytes,5,rep,name=config"`
}

Expand Down
4 changes: 2 additions & 2 deletions apis/config/handlers/confighandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (r *ConfigStoreHandler) DryRunCreateFn(ctx context.Context, key types.Names
return obj, err
}

updates, err := config.GetIntentUpdate(c, true)
updates, err := config.GetIntentUpdateFromBlobs(c.Spec.Config)
if err != nil {
return nil, err
}
Expand All @@ -62,7 +62,7 @@ func (r *ConfigStoreHandler) DryRunUpdateFn(ctx context.Context, key types.Names
return obj, err
}

updates, err := config.GetIntentUpdate(c, true)
updates, err := config.GetIntentUpdateFromBlobs(c.Spec.Config)
if err != nil {
return nil, err
}
Expand Down
7 changes: 7 additions & 0 deletions apis/config/label_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,11 @@ package config
const (
TargetNameKey = GroupName + "/" + "targetName"
TargetNamespaceKey = GroupName + "/" + "targetNamespace"
LabelKeyRingKey = GroupName + "/" + "keyring"
)

const (
AnnotationConfigChanged = GroupName + "/" + "change-config"
AnnotationSecretChanged = GroupName + "/" + "change-secret"
AnnotationKeyringChanged = GroupName + "/" + "change-keyring"
)
4 changes: 4 additions & 0 deletions apis/config/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&TargetRunningConfig{},
&TargetClearDeviation{},
&TargetRunningConfigOptions{},
&SensitiveConfig{},
&SensitiveConfigList{},
&TargetSnapshot{},
&TargetSnapshotList{},
)
return nil
}
47 changes: 0 additions & 47 deletions apis/config/sensitive_config_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,11 @@ import (
"strings"

"github.com/henderiw/logger/log"
"github.com/sdcio/config-server/apis/condition"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
)

// GetCondition returns the condition based on the condition kind
func (r *SensitiveConfig) GetCondition(t condition.ConditionType) condition.Condition {
return r.Status.GetCondition(t)
}

// SetConditions sets the conditions on the resource. it allows for 0, 1 or more conditions
// to be set at once
func (r *SensitiveConfig) SetConditions(c ...condition.Condition) {
r.Status.SetConditions(c...)
}

func (r *SensitiveConfig) IsConditionReady() bool {
return r.GetCondition(condition.ConditionTypeReady).Status == metav1.ConditionTrue
}

func (r *SensitiveConfig) IsRevertive() bool {
if r.Spec.Revertive != nil {
return *r.Spec.Revertive
Expand All @@ -57,32 +41,10 @@ func (r *SensitiveConfig) IsRevertive() bool {
return true
}

func (r *SensitiveConfig) IsRecoverable() bool {
c := r.GetCondition(condition.ConditionTypeReady)
if c.Reason == string(condition.ConditionReasonUnrecoverable) {
unrecoverableMessage := &condition.UnrecoverableMessage{}
if err := json.Unmarshal([]byte(c.Message), unrecoverableMessage); err != nil {
return true
}
if unrecoverableMessage.ResourceVersion != r.GetResourceVersion() {
return true
}
return false
}
return true
}

func (r *SensitiveConfig) GetNamespacedName() types.NamespacedName {
return types.NamespacedName{Name: r.Name, Namespace: r.Namespace}
}

func (r *SensitiveConfig) GetLastKnownGoodSchema() *ConfigStatusLastKnownGoodSchema {
if r.Status.LastKnownGoodSchema == nil {
return &ConfigStatusLastKnownGoodSchema{}
}
return r.Status.LastKnownGoodSchema
}

func (r *SensitiveConfig) GetTarget() string {
if len(r.GetLabels()) == 0 {
return ""
Expand Down Expand Up @@ -128,15 +90,6 @@ func BuildEmptySensitiveConfig() *SensitiveConfig {
}
}

func (r *SensitiveConfig) HashDeviationGenerationChanged(deviation Deviation) bool {
if r.Status.DeviationGeneration == nil {
// if there was no old deviation, but now we have a deviation wwe return true
return len(deviation.Spec.Deviations) != 0
} else {
return *r.Status.DeviationGeneration == deviation.GetGeneration()
}
}

type RecoverySensitiveConfig struct {
SensitiveConfig SensitiveConfig
Deviation Deviation
Expand Down
Loading
Loading