Skip to content

Commit a6cb7a0

Browse files
committed
WIP: Re-enable Secret cache for VSO managed secrets.
1 parent 754bad0 commit a6cb7a0

File tree

7 files changed

+121
-10
lines changed

7 files changed

+121
-10
lines changed

controllers/hcpvaultsecretsapp_controller.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ type HCPVaultSecretsAppReconciler struct {
8888
referenceCache ResourceReferenceCache
8989
GlobalTransformationOptions *helpers.GlobalTransformationOptions
9090
BackOffRegistry *BackOffRegistry
91+
SecretsClient client.Client
9192
}
9293

9394
// +kubebuilder:rbac:groups=secrets.hashicorp.com,resources=hcpvaultsecretsapps,verbs=get;list;watch;create;update;patch;delete
@@ -239,7 +240,7 @@ func (r *HCPVaultSecretsAppReconciler) Reconcile(ctx context.Context, req ctrl.R
239240
doSync := true
240241
// doRolloutRestart only if this is not the first time this secret has been synced
241242
doRolloutRestart := o.Status.SecretMAC != ""
242-
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.Client, r.HMACValidator, o, data)
243+
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.SecretsClient, r.HMACValidator, o, data)
243244
if err != nil {
244245
return ctrl.Result{
245246
RequeueAfter: computeHorizonWithJitter(requeueDurationOnError),
@@ -431,7 +432,7 @@ func (r *HCPVaultSecretsAppReconciler) getShadowSecretData(ctx context.Context,
431432
return nil, fmt.Errorf("failed to marshal shadow secret data %s/%s: %w",
432433
o.Namespace, o.Name, err)
433434
}
434-
valid, _, err := r.HMACValidator.Validate(ctx, r.Client, dataBytes, lastHMAC)
435+
valid, _, err := r.HMACValidator.Validate(ctx, r.SecretsClient, dataBytes, lastHMAC)
435436
if err != nil {
436437
return nil, fmt.Errorf("failed to validate HMAC of HVS shadow secret data for %s/%s: %w",
437438
o.Namespace, o.Name, err)
@@ -504,7 +505,7 @@ func (r *HCPVaultSecretsAppReconciler) storeShadowSecretData(ctx context.Context
504505
return fmt.Errorf("failed to marshal shadow secret data %s/%s: %w",
505506
o.Namespace, o.Name, err)
506507
}
507-
h, err := r.HMACValidator.HMAC(ctx, r.Client, b)
508+
h, err := r.HMACValidator.HMAC(ctx, r.SecretsClient, b)
508509
if err != nil {
509510
return fmt.Errorf("failed to HMAC shadow secret data %s/%s: %w",
510511
o.Namespace, o.Name, err)

controllers/vaultdynamicsecret_controller.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type VaultDynamicSecretReconciler struct {
7272
// This is done via the downwardAPI. We get the current Pod's UID from either the
7373
// OPERATOR_POD_UID environment variable, or the /var/run/podinfo/uid file; in that order.
7474
runtimePodUID types.UID
75+
SecretsClient client.Client
7576
}
7677

7778
// +kubebuilder:rbac:groups=secrets.hashicorp.com,resources=vaultdynamicsecrets,verbs=get;list;watch;create;update;patch;delete
@@ -423,7 +424,7 @@ func (r *VaultDynamicSecretReconciler) syncSecret(ctx context.Context, c vault.C
423424
delete(dataToMAC, k)
424425
}
425426

426-
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.Client, r.HMACValidator, o, dataToMAC)
427+
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.SecretsClient, r.HMACValidator, o, dataToMAC)
427428
if err != nil {
428429
return nil, false, err
429430
}

controllers/vaultpkisecret_controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type VaultPKISecretReconciler struct {
4949
BackOffRegistry *BackOffRegistry
5050
referenceCache ResourceReferenceCache
5151
GlobalTransformationOptions *helpers.GlobalTransformationOptions
52+
SecretsClient client.Client
5253
}
5354

5455
// +kubebuilder:rbac:groups=secrets.hashicorp.com,resources=vaultpkisecrets,verbs=get;list;watch;create;update;patch;delete
@@ -134,7 +135,7 @@ func (r *VaultPKISecretReconciler) Reconcile(ctx context.Context, req ctrl.Reque
134135
syncReason = consts.ReasonInexistentDestination
135136
case destinationExists:
136137
if schemaEpoch > 0 {
137-
if matched, err := helpers.HMACDestinationSecret(ctx, r.Client,
138+
if matched, err := helpers.HMACDestinationSecret(ctx, r.SecretsClient,
138139
r.HMACValidator, o); err == nil && !matched {
139140
syncReason = consts.ReasonSecretDataDrift
140141
} else if err != nil {
@@ -252,7 +253,7 @@ func (r *VaultPKISecretReconciler) Reconcile(ctx context.Context, req ctrl.Reque
252253
}
253254

254255
if b, err := json.Marshal(data); err == nil {
255-
newMAC, err := r.HMACValidator.HMAC(ctx, r.Client, b)
256+
newMAC, err := r.HMACValidator.HMAC(ctx, r.SecretsClient, b)
256257
if err != nil {
257258
logger.Error(err, "HMAC data")
258259
o.Status.Error = consts.ReasonHMACDataError

controllers/vaultstaticsecret_controller.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type VaultStaticSecretReconciler struct {
4848
Recorder record.EventRecorder
4949
ClientFactory vault.ClientFactory
5050
SecretDataBuilder *helpers.SecretDataBuilder
51+
SecretsClient client.Client
5152
HMACValidator helpers.HMACValidator
5253
referenceCache ResourceReferenceCache
5354
GlobalTransformationOptions *helpers.GlobalTransformationOptions
@@ -160,7 +161,7 @@ func (r *VaultStaticSecretReconciler) Reconcile(ctx context.Context, req ctrl.Re
160161
// doRolloutRestart only if this is not the first time this secret has been synced
161162
doRolloutRestart = o.Status.SecretMAC != ""
162163

163-
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.Client, r.HMACValidator, o, data)
164+
macsEqual, messageMAC, err := helpers.HandleSecretHMAC(ctx, r.SecretsClient, r.HMACValidator, o, data)
164165
if err != nil {
165166
return ctrl.Result{RequeueAfter: computeHorizonWithJitter(requeueDurationOnError)}, nil
166167
}

helpers/client.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package helpers
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
corev1 "k8s.io/api/core/v1"
11+
"k8s.io/apimachinery/pkg/labels"
12+
ctrl "sigs.k8s.io/controller-runtime"
13+
"sigs.k8s.io/controller-runtime/pkg/cache"
14+
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
15+
)
16+
17+
// NewSecretsClientForManager creates a new client for interacting with secrets that match
18+
// the given selector. This client is useful to avoid caching all secrets in a
19+
// cluster. The client will cache only secrets that match the selector.
20+
// The ctrl.Manager needs to be started before client can be used.
21+
func NewSecretsClientForManager(ctx context.Context, mgr ctrl.Manager, selector labels.Selector) (ctrlclient.Client, error) {
22+
if selector.Empty() {
23+
return nil, fmt.Errorf("selector cannot be empty")
24+
}
25+
26+
scheme := mgr.GetScheme()
27+
httpClient := mgr.GetHTTPClient()
28+
restMapper := mgr.GetRESTMapper()
29+
cacheOpts := cache.Options{
30+
ReaderFailOnMissingInformer: true,
31+
HTTPClient: httpClient,
32+
Scheme: scheme,
33+
Mapper: restMapper,
34+
ByObject: map[ctrlclient.Object]cache.ByObject{
35+
&corev1.Secret{}: {
36+
Label: selector,
37+
},
38+
},
39+
}
40+
41+
newCache, err := cache.New(mgr.GetConfig(), cacheOpts)
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
if _, err := newCache.GetInformer(ctx, &corev1.Secret{}); err != nil {
47+
return nil, err
48+
}
49+
50+
if err := mgr.Add(newCache); err != nil {
51+
return nil, err
52+
}
53+
54+
client, err := ctrlclient.New(mgr.GetConfig(), ctrlclient.Options{
55+
HTTPClient: httpClient,
56+
Scheme: scheme,
57+
Mapper: restMapper,
58+
Cache: &ctrlclient.CacheOptions{
59+
Reader: newCache,
60+
},
61+
})
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
return client, nil
67+
}

helpers/secrets.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ const (
3434
HVSSecretTypeKV = "kv"
3535
HVSSecretTypeRotating = "rotating"
3636
HVSSecretTypeDynamic = "dynamic"
37+
38+
ManagedByLabel = "app.kubernetes.io/managed-by"
39+
AppNameLabel = "app.kubernetes.io/name"
40+
ComponentLabel = "app.kubernetes.io/component"
3741
)
3842

3943
var SecretDataErrorContainsRaw = fmt.Errorf("key '%s' not permitted in Secret data", SecretDataKeyRaw)
@@ -48,10 +52,11 @@ var labelOwnerRefUID = fmt.Sprintf("%s/vso-ownerRefUID", secretsv1beta1.GroupVer
4852
// intersects with that of other components of the system, since this could lead to data loss.
4953
//
5054
// Make OwnerLabels public so that they can be accessed from tests.
55+
5156
var OwnerLabels = map[string]string{
52-
"app.kubernetes.io/name": "vault-secrets-operator",
53-
"app.kubernetes.io/managed-by": "hashicorp-vso",
54-
"app.kubernetes.io/component": "secret-sync",
57+
ManagedByLabel: "hashicorp-vso",
58+
AppNameLabel: "vault-secrets-operator",
59+
ComponentLabel: "secret-sync",
5560
}
5661

5762
// OwnerLabelsForObj returns the canonical set of labels that should be set on

main.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"github.com/prometheus/client_golang/prometheus"
2121
corev1 "k8s.io/api/core/v1"
2222
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
23+
"k8s.io/apimachinery/pkg/labels"
2324
"k8s.io/apimachinery/pkg/runtime"
25+
"k8s.io/apimachinery/pkg/selection"
2426
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2527
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2628
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -435,6 +437,35 @@ func main() {
435437
}
436438
ctx := ctrl.SetupSignalHandler()
437439

440+
var requirements []labels.Requirement
441+
for _, k := range []string{helpers.ManagedByLabel, helpers.AppNameLabel} {
442+
val, ok := helpers.OwnerLabels[k]
443+
if !ok || val == "" {
444+
setupLog.Error(errors.New("invalid option"),
445+
fmt.Sprintf("Expected Owner label %q is not present, this is a bug", k))
446+
os.Exit(1)
447+
}
448+
449+
if r, err := labels.NewRequirement(
450+
k, selection.Equals, []string{
451+
val,
452+
}); err != nil {
453+
setupLog.Error(err, "Failed to create label requirement")
454+
os.Exit(1)
455+
} else {
456+
requirements = append(requirements, *r)
457+
}
458+
}
459+
460+
// secretsClient is used to interact with secrets that match the selector. This
461+
// client is useful to avoid caching all secrets in a cluster. The client will
462+
// cache only secrets that match the selector.
463+
secretsClient, err := helpers.NewSecretsClientForManager(ctx, mgr, labels.NewSelector().Add(requirements...))
464+
if err != nil {
465+
setupLog.Error(err, "Failed to create a Secrets client")
466+
os.Exit(1)
467+
}
468+
438469
var clientFactory vclient.CachingClientFactory
439470
{
440471
switch clientCachePersistenceModel {
@@ -467,6 +498,7 @@ func main() {
467498
Scheme: mgr.GetScheme(),
468499
Recorder: mgr.GetEventRecorderFor("VaultStaticSecret"),
469500
SecretDataBuilder: secretDataBuilder,
501+
SecretsClient: secretsClient,
470502
HMACValidator: hmacValidator,
471503
ClientFactory: clientFactory,
472504
BackOffRegistry: controllers.NewBackOffRegistry(backoffOpts...),
@@ -479,6 +511,7 @@ func main() {
479511
Client: mgr.GetClient(),
480512
Scheme: mgr.GetScheme(),
481513
ClientFactory: clientFactory,
514+
SecretsClient: secretsClient,
482515
HMACValidator: hmacValidator,
483516
SyncRegistry: controllers.NewSyncRegistry(),
484517
Recorder: mgr.GetEventRecorderFor("VaultPKISecret"),
@@ -524,6 +557,7 @@ func main() {
524557
Scheme: mgr.GetScheme(),
525558
Recorder: mgr.GetEventRecorderFor("VaultDynamicSecret"),
526559
ClientFactory: clientFactory,
560+
SecretsClient: secretsClient,
527561
HMACValidator: hmacValidator,
528562
SyncRegistry: controllers.NewSyncRegistry(),
529563
BackOffRegistry: controllers.NewBackOffRegistry(backoffOpts...),
@@ -551,6 +585,7 @@ func main() {
551585
Scheme: mgr.GetScheme(),
552586
Recorder: mgr.GetEventRecorderFor("HCPVaultSecretsApp"),
553587
SecretDataBuilder: secretDataBuilder,
588+
SecretsClient: secretsClient,
554589
HMACValidator: hmacValidator,
555590
MinRefreshAfter: minRefreshAfterHVSA,
556591
BackOffRegistry: controllers.NewBackOffRegistry(backoffOpts...),

0 commit comments

Comments
 (0)