Skip to content

Commit d030467

Browse files
Fix rotation enable check
1 parent 4df9a6d commit d030467

File tree

9 files changed

+97
-46
lines changed

9 files changed

+97
-46
lines changed

controllers/secretproviderclasspodstatus_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,12 @@ func (r *SecretProviderClassPodStatusReconciler) createOrUpdateK8sSecret(ctx con
419419
return err
420420
}
421421

422-
klog.InfoS("Kubernetes secret is already created", "secret", klog.ObjectRef{Namespace: namespace, Name: name})
422+
klog.V(5).InfoS("Kubernetes secret is already created", "secret", klog.ObjectRef{Namespace: namespace, Name: name})
423423
err = r.writer.Update(ctx, secret)
424424
if err != nil {
425-
klog.ErrorS(err, "Unable to update kubernetes secret", "secret", klog.ObjectRef{Namespace: namespace, Name: name})
426425
return err
427426
}
428-
klog.InfoS("successfully updated Kubernetes secret", "secret", klog.ObjectRef{Namespace: namespace, Name: name})
427+
klog.V(5).InfoS("successfully updated Kubernetes secret", "secret", klog.ObjectRef{Namespace: namespace, Name: name})
429428
return nil
430429
}
431430

manifest_staging/charts/secrets-store-csi-driver/templates/csidriver.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ spec:
1414
requiresRepublish: true
1515
tokenRequests:
1616
{{- toYaml .Values.tokenRequests | nindent 2 }}
17-
requiresRepublish: {{ .Values.requiresRepublish }}
1817
{{- end }}

manifest_staging/charts/secrets-store-csi-driver/values.yaml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,16 +232,11 @@ providerHealthCheckInterval: 2m
232232

233233
imagePullSecrets: []
234234

235-
## This allows CSI drivers to impersonate the pods that they mount the volumes for.
236-
# refer to https://kubernetes-csi.github.io/docs/token-requests.html for more details.
237-
# Supported only for Kubernetes v1.20+
238235
tokenRequests: []
239236
# - audience: aud1
240237
# - audience: aud2
241238

242-
# To set the requiresRepublish which can be used to refresh the mounted secret periodically
243-
# refer to https://kubernetes-csi.github.io/docs/token-requests.html for more details.
244-
# Supported only for Kubernetes v1.20+
239+
# this will be set to true even if enableSecretRotation is true
245240
requiresRepublish: true
246241
# -- Labels to apply to all resources
247242
commonLabels: {}

pkg/secrets-store/mocks/stats_reporter_mock.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ limitations under the License.
1616

1717
package mocks // import sigs.k8s.io/secrets-store-csi-driver/pkg/secrets-store/mocks
1818

19-
import "context"
19+
import (
20+
"context"
21+
)
2022

2123
type FakeReporter struct {
2224
reportNodePublishCtMetricInvoked int
@@ -73,3 +75,12 @@ func (f *FakeReporter) ReportSyncK8SecretCtMetricInvoked() int {
7375
func (f *FakeReporter) ReportSyncK8SecretDurationInvoked() int {
7476
return f.reportSyncK8SecretDurationInvoked
7577
}
78+
79+
func (f *FakeReporter) ReportRotationCtMetric(ctx context.Context, provider string, wasRotated bool) {
80+
}
81+
82+
func (f *FakeReporter) ReportRotationErrorCtMetric(ctx context.Context, provider, errType string, wasRotated bool) {
83+
}
84+
85+
func (f *FakeReporter) ReportRotationDuration(ctx context.Context, duration float64) {
86+
}

pkg/secrets-store/nodeserver.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,15 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
9090
}
9191
}
9292
ns.reporter.ReportNodePublishErrorCtMetric(ctx, providerName, errorReason)
93+
if isRemountRequest {
94+
ns.reporter.ReportRotationErrorCtMetric(ctx, providerName, errorReason, true)
95+
}
9396
return
9497
}
98+
if isRemountRequest {
99+
ns.reporter.ReportRotationCtMetric(ctx, providerName, true)
100+
ns.reporter.ReportRotationDuration(ctx, time.Since(startTime).Seconds())
101+
}
95102
ns.reporter.ReportNodePublishCtMetric(ctx, providerName)
96103
}()
97104

@@ -121,6 +128,16 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
121128
podNamespace = attrib[CSIPodNamespace]
122129
podUID = attrib[CSIPodUID]
123130

131+
if rotationEnabled {
132+
lastModificationTime, err := ns.getLastUpdateTime(targetPath)
133+
if err != nil {
134+
klog.InfoS("could not find last modification time for targetpath", targetPath, "error", err)
135+
} else if startTime.Before(lastModificationTime.Add(ns.rotationConfig.rotationCacheDuration)) {
136+
// if next rotation is not yet due, then skip the mount operation
137+
return &csi.NodePublishVolumeResponse{}, nil
138+
}
139+
}
140+
124141
mounted, err = ns.ensureMountPoint(targetPath)
125142
if err != nil {
126143
// kubelet will not create the CSI NodePublishVolume target directory in 1.20+, in accordance with the CSI specification.
@@ -143,16 +160,6 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
143160
return &csi.NodePublishVolumeResponse{}, nil
144161
}
145162

146-
if rotationEnabled {
147-
lastModificationTime, err := ns.getLastUpdateTime(targetPath)
148-
if err != nil {
149-
klog.InfoS("could not find last modification time for targetpath", targetPath, "error", err)
150-
} else if startTime.Before(lastModificationTime.Add(ns.rotationConfig.rotationPollInterval)) {
151-
// if next rotation is not yet due, then skip the mount operation
152-
return &csi.NodePublishVolumeResponse{}, nil
153-
}
154-
}
155-
156163
klog.V(2).InfoS("node publish volume", "target", targetPath, "volumeId", volumeID, "mount flags", mountFlags)
157164

158165
if isMockProvider(providerName) {
@@ -192,16 +199,12 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
192199
for k, v := range attrib {
193200
parameters[k] = v
194201
}
195-
// csi.storage.k8s.io/serviceAccount.tokens is empty for Kubernetes version < 1.20.
196-
// For 1.20+, if tokenRequests is set in the CSI driver spec, kubelet will generate
197-
// a token for the pod and send it to the CSI driver.
198-
// This check is done for backward compatibility to support passing token from driver
199-
// to provider irrespective of the Kubernetes version. If the token doesn't exist in the
200-
// volume request context, the CSI driver will generate the token for the configured audience
201-
// and send it to the provider in the parameters.
202+
// If the token doesn't exist in the volume request context, the CSI driver
203+
// will generate the token for the configured audience and send it to the
204+
// provider in the parameters.
202205
if parameters[CSIPodServiceAccountTokens] == "" {
203206
// Inject pod service account token into volume attributes
204-
klog.Info(err, "csi.storage.k8s.io/serviceAccount.tokens is not populated")
207+
klog.Warning("csi.storage.k8s.io/serviceAccount.tokens is not populated")
205208
}
206209

207210
// ensure it's read-only

pkg/secrets-store/nodeserver_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ func TestNodePublishVolume(t *testing.T) {
297297
},
298298
},
299299
rotationConfig: &rotationConfig{
300-
enabled: false,
301-
rotationPollInterval: time.Minute,
300+
enabled: false,
301+
rotationCacheDuration: time.Minute,
302302
},
303303
},
304304
{
@@ -331,8 +331,8 @@ func TestNodePublishVolume(t *testing.T) {
331331
},
332332
},
333333
rotationConfig: &rotationConfig{
334-
enabled: true,
335-
rotationPollInterval: -1 * time.Minute, // Using negative interval to pass the rotation interval check in unit tests
334+
enabled: true,
335+
rotationCacheDuration: -1 * time.Minute, // Using negative interval to pass the rotation interval check in unit tests
336336
},
337337
},
338338
{
@@ -362,8 +362,8 @@ func TestNodePublishVolume(t *testing.T) {
362362
},
363363
},
364364
rotationConfig: &rotationConfig{
365-
enabled: true,
366-
rotationPollInterval: time.Minute,
365+
enabled: true,
366+
rotationCacheDuration: time.Minute,
367367
},
368368
},
369369
}
@@ -407,7 +407,7 @@ func TestNodePublishVolume(t *testing.T) {
407407
t.Fatalf("expected err to be nil, got: %v", err)
408408
}
409409
expectedMounts := 1
410-
if ns.rotationConfig.enabled && ns.rotationConfig.rotationPollInterval > 0 {
410+
if ns.rotationConfig.enabled && ns.rotationConfig.rotationCacheDuration > 0 {
411411
// If due to rotation interval, NodePublishVolume has skipped, there should not be any mount operation
412412
expectedMounts = 0
413413
}

pkg/secrets-store/secrets-store.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type SecretsStore struct {
4040

4141
// rotationConfig stores the information required to rotate the secrets.
4242
type rotationConfig struct {
43-
enabled bool
44-
rotationPollInterval time.Duration
43+
enabled bool
44+
rotationCacheDuration time.Duration // After this much duration, NodePublishVolume will be acted.
4545
}
4646

4747
func NewSecretsStoreDriver(driverName, nodeID, endpoint string,
@@ -91,8 +91,8 @@ func newNodeServer(nodeID string,
9191

9292
func newRotationConfig(enabled bool, interval time.Duration) *rotationConfig {
9393
return &rotationConfig{
94-
enabled: enabled,
95-
rotationPollInterval: interval,
94+
enabled: enabled,
95+
rotationCacheDuration: interval,
9696
}
9797
}
9898

pkg/secrets-store/stats_reporter.go

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,19 @@ var (
3434
errorKey = "error_type"
3535
osTypeKey = "os_type"
3636
runtimeOS = runtime.GOOS
37+
rotatedKey = "rotated"
3738
)
3839

3940
type reporter struct {
40-
nodePublishTotal metric.Int64Counter
41-
nodeUnPublishTotal metric.Int64Counter
42-
nodePublishErrorTotal metric.Int64Counter
43-
nodeUnPublishErrorTotal metric.Int64Counter
44-
syncK8sSecretTotal metric.Int64Counter
45-
syncK8sSecretDuration metric.Float64Histogram
41+
nodePublishTotal metric.Int64Counter
42+
nodeUnPublishTotal metric.Int64Counter
43+
nodePublishErrorTotal metric.Int64Counter
44+
nodeUnPublishErrorTotal metric.Int64Counter
45+
syncK8sSecretTotal metric.Int64Counter
46+
syncK8sSecretDuration metric.Float64Histogram
47+
rotationReconcileTotal metric.Int64Counter
48+
rotationReconcileErrorTotal metric.Int64Counter
49+
rotationReconcileDuration metric.Float64Histogram
4650
}
4751

4852
type StatsReporter interface {
@@ -52,6 +56,9 @@ type StatsReporter interface {
5256
ReportNodeUnPublishErrorCtMetric(ctx context.Context)
5357
ReportSyncK8SecretCtMetric(ctx context.Context, provider string, count int)
5458
ReportSyncK8SecretDuration(ctx context.Context, duration float64)
59+
ReportRotationCtMetric(ctx context.Context, provider string, wasRotated bool)
60+
ReportRotationErrorCtMetric(ctx context.Context, provider, errType string, wasRotated bool)
61+
ReportRotationDuration(ctx context.Context, duration float64)
5562
}
5663

5764
func NewStatsReporter() (StatsReporter, error) {
@@ -78,6 +85,16 @@ func NewStatsReporter() (StatsReporter, error) {
7885
if r.syncK8sSecretDuration, err = meter.Float64Histogram("k8s_secret_duration_sec", metric.WithDescription("Distribution of how long it took to sync k8s secret")); err != nil {
7986
return nil, err
8087
}
88+
if r.rotationReconcileTotal, err = meter.Int64Counter("rotation_reconcile", metric.WithDescription("Total number of rotation reconciles")); err != nil {
89+
return nil, err
90+
}
91+
if r.rotationReconcileErrorTotal, err = meter.Int64Counter("rotation_reconcile_error", metric.WithDescription("Total number of rotation reconciles with error")); err != nil {
92+
return nil, err
93+
}
94+
if r.rotationReconcileDuration, err = meter.Float64Histogram("rotation_reconcile_duration_sec", metric.WithDescription("Distribution of how long it took to rotate secrets-store content for pods")); err != nil {
95+
return nil, err
96+
}
97+
8198
return r, nil
8299
}
83100

@@ -126,3 +143,29 @@ func (r *reporter) ReportSyncK8SecretDuration(ctx context.Context, duration floa
126143
)
127144
r.syncK8sSecretDuration.Record(ctx, duration, opt)
128145
}
146+
147+
func (r *reporter) ReportRotationCtMetric(ctx context.Context, provider string, wasRotated bool) {
148+
opt := metric.WithAttributes(
149+
attribute.Key(providerKey).String(provider),
150+
attribute.Key(osTypeKey).String(runtimeOS),
151+
attribute.Key(rotatedKey).Bool(wasRotated),
152+
)
153+
r.rotationReconcileTotal.Add(ctx, 1, opt)
154+
}
155+
156+
func (r *reporter) ReportRotationErrorCtMetric(ctx context.Context, provider, errType string, wasRotated bool) {
157+
opt := metric.WithAttributes(
158+
attribute.Key(providerKey).String(provider),
159+
attribute.Key(errorKey).String(errType),
160+
attribute.Key(osTypeKey).String(runtimeOS),
161+
attribute.Key(rotatedKey).Bool(wasRotated),
162+
)
163+
r.rotationReconcileErrorTotal.Add(ctx, 1, opt)
164+
}
165+
166+
func (r *reporter) ReportRotationDuration(ctx context.Context, duration float64) {
167+
opt := metric.WithAttributes(
168+
attribute.Key(osTypeKey).String(runtimeOS),
169+
)
170+
r.rotationReconcileDuration.Record(ctx, duration, opt)
171+
}

test/bats/e2e-provider.bats

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ export VALIDATE_TOKENS_AUDIENCE=$(get_token_requests_audience)
418418
run kubectl exec ${curl_pod_name} -n metrics -- curl http://${pod_ip}:8095/metrics
419419
assert_match "node_publish_total" "${output}"
420420
assert_match "node_unpublish_total" "${output}"
421+
assert_match "rotation_reconcile_total" "${output}"
421422
done
422423
# keeping metrics ns in upgrade tests has no relevance
423424
# the namespace is only to run a curl pod to validate metrics

0 commit comments

Comments
 (0)