diff --git a/README.md b/README.md index 28f67da..41d8187 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,10 @@ sync: path: /source/credentials/query-data/ key: regexp: (username|password) + flatten: true target: key: /target/example-5 - + template: data: user: '{{ .Data.username }}' diff --git a/cmd/testdata/syncjob.yaml b/cmd/testdata/syncjob.yaml index 16bc78d..db7aaf6 100644 --- a/cmd/testdata/syncjob.yaml +++ b/cmd/testdata/syncjob.yaml @@ -53,9 +53,9 @@ sync: path: /source/credentials/query-data/ key: regexp: (username|password) + flatten: true target: key: /target/example-5 - template: data: user: '{{ .Data.username }}' @@ -63,19 +63,19 @@ sync: ## 6. Usage: Sync single key from multiple sources with templating - secretSources: - - name: username # Username mapping, available as ".Data.username" - secretRef: - key: /source/credentials/username - - - name: password # Password mapping, available as ".Data.password" - secretRef: - key: /source/credentials/password - - - name: dynamic_query # Query mapping, available as "Data.dynamic_query." - secretQuery: - path: /source/credentials - key: - regexp: .* + - name: username # Username mapping, available as ".Data.username" + secretRef: + key: /source/credentials/username + + - name: password # Password mapping, available as ".Data.password" + secretRef: + key: /source/credentials/password + + - name: dynamic_query # Query mapping, available as "Data.dynamic_query." + secretQuery: + path: /source/credentials + key: + regexp: .* target: key: /target/example-6 diff --git a/pkg/apis/v1alpha1/syncjob_types.go b/pkg/apis/v1alpha1/syncjob_types.go index 38871c0..9609fe7 100644 --- a/pkg/apis/v1alpha1/syncjob_types.go +++ b/pkg/apis/v1alpha1/syncjob_types.go @@ -92,6 +92,9 @@ type SyncRequest struct { // SyncTarget.KeyPrefix means that multiple secrets will be synced. Target SyncTarget `json:"target,omitempty"` + // Flatten indicates secrets FromQuery will be synced to a single SyncTarget.Key. + Flatten *bool `json:"flatten,omitempty"` + // Template defines how the fetched key(s) will be transformed to create a new // SecretRef that will be synced to target. // When using FromRef, {{ .Data }} defines given secrets raw value. diff --git a/pkg/storesync/processor.go b/pkg/storesync/processor.go index 3495566..8932c16 100644 --- a/pkg/storesync/processor.go +++ b/pkg/storesync/processor.go @@ -99,6 +99,10 @@ func (p *processor) GetSyncPlan(ctx context.Context, reqID int, req v1alpha1.Syn // Handle FromQuery => Key if req.Target.Key != nil { + if req.Flatten == nil || !*req.Flatten { + return nil, fmt.Errorf("requires 'flatten' for 'fromQuery' and 'target.key'") + } + syncRef := v1alpha1.SecretRef{ Key: *req.Target.Key, Version: nil, @@ -126,6 +130,10 @@ func (p *processor) GetSyncPlan(ctx context.Context, reqID int, req v1alpha1.Syn } // Handle FromQuery => KeyPrefix or empty + if req.Flatten != nil && *req.Flatten { + return nil, fmt.Errorf("cannot use 'flatten' for 'fromQuery' and 'target.key'") + } + syncMap := make(map[v1alpha1.SecretRef]SyncPlan) for ref, resp := range fetchResps { syncRef := ref