Skip to content

Commit 42b4638

Browse files
craig[bot]angles-n-daemons
craig[bot]
andcommitted
Merge #142682
142682: security: cache certificate expiration metrics as pointers r=angles-n-daemons a=angles-n-daemons security: cache certificate expiration metrics as pointers Changes in #130110 were added to add labelled ttl metrics to client certificates. It achieved this by changing the system which cached certificate expiries to cache on a composite struct of two metrics, rather than just an expiration metric. The struct itself housed the metrics as inline values, rather than pointers, so updates were registered in the cached values only, and not the registry in which they were reporting. This means that updates to client certificate expirations would not be reflected by the ttl or expiration metrics. This ticket modifies those elements so that they are not copied when they are pulled from the cache. Fixes: #142681 Epic: CRDB-40209 Release note (bug fix): Fixes bug in client certificate expiration metrics. Co-authored-by: Brian Dillmann <[email protected]>
2 parents 6ea0b13 + 2e872e2 commit 42b4638

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

pkg/security/BUILD.bazel

+1-15
Original file line numberDiff line numberDiff line change
@@ -107,82 +107,68 @@ go_test(
107107
"//pkg/util/uuid",
108108
"@com_github_cockroachdb_errors//:errors",
109109
"@com_github_go_ldap_ldap_v3//:ldap",
110+
"@com_github_prometheus_client_model//go",
110111
"@com_github_stretchr_testify//require",
111112
"@org_golang_x_exp//rand",
112113
] + select({
113114
"@io_bazel_rules_go//go/platform:aix": [
114115
"//pkg/util/log/eventpb",
115-
"@com_github_prometheus_client_model//go",
116116
"@org_golang_x_sys//unix",
117117
],
118118
"@io_bazel_rules_go//go/platform:android": [
119119
"//pkg/util/log/eventpb",
120-
"@com_github_prometheus_client_model//go",
121120
"@org_golang_x_sys//unix",
122121
],
123122
"@io_bazel_rules_go//go/platform:darwin": [
124123
"//pkg/util/log/eventpb",
125-
"@com_github_prometheus_client_model//go",
126124
"@org_golang_x_sys//unix",
127125
],
128126
"@io_bazel_rules_go//go/platform:dragonfly": [
129127
"//pkg/util/log/eventpb",
130-
"@com_github_prometheus_client_model//go",
131128
"@org_golang_x_sys//unix",
132129
],
133130
"@io_bazel_rules_go//go/platform:freebsd": [
134131
"//pkg/util/log/eventpb",
135-
"@com_github_prometheus_client_model//go",
136132
"@org_golang_x_sys//unix",
137133
],
138134
"@io_bazel_rules_go//go/platform:illumos": [
139135
"//pkg/util/log/eventpb",
140-
"@com_github_prometheus_client_model//go",
141136
"@org_golang_x_sys//unix",
142137
],
143138
"@io_bazel_rules_go//go/platform:ios": [
144139
"//pkg/util/log/eventpb",
145-
"@com_github_prometheus_client_model//go",
146140
"@org_golang_x_sys//unix",
147141
],
148142
"@io_bazel_rules_go//go/platform:js": [
149143
"//pkg/util/log/eventpb",
150-
"@com_github_prometheus_client_model//go",
151144
"@org_golang_x_sys//unix",
152145
],
153146
"@io_bazel_rules_go//go/platform:linux": [
154147
"//pkg/util/log/eventpb",
155-
"@com_github_prometheus_client_model//go",
156148
"@org_golang_x_sys//unix",
157149
],
158150
"@io_bazel_rules_go//go/platform:netbsd": [
159151
"//pkg/util/log/eventpb",
160-
"@com_github_prometheus_client_model//go",
161152
"@org_golang_x_sys//unix",
162153
],
163154
"@io_bazel_rules_go//go/platform:openbsd": [
164155
"//pkg/util/log/eventpb",
165-
"@com_github_prometheus_client_model//go",
166156
"@org_golang_x_sys//unix",
167157
],
168158
"@io_bazel_rules_go//go/platform:osx": [
169159
"//pkg/util/log/eventpb",
170-
"@com_github_prometheus_client_model//go",
171160
"@org_golang_x_sys//unix",
172161
],
173162
"@io_bazel_rules_go//go/platform:plan9": [
174163
"//pkg/util/log/eventpb",
175-
"@com_github_prometheus_client_model//go",
176164
"@org_golang_x_sys//unix",
177165
],
178166
"@io_bazel_rules_go//go/platform:qnx": [
179167
"//pkg/util/log/eventpb",
180-
"@com_github_prometheus_client_model//go",
181168
"@org_golang_x_sys//unix",
182169
],
183170
"@io_bazel_rules_go//go/platform:solaris": [
184171
"//pkg/util/log/eventpb",
185-
"@com_github_prometheus_client_model//go",
186172
"@org_golang_x_sys//unix",
187173
],
188174
"//conditions:default": [],

pkg/security/cert_expiry_cache.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ var ClientCertExpirationCacheCapacity = settings.RegisterIntSetting(
3535
settings.WithPublic)
3636

3737
type clientCertExpirationMetrics struct {
38-
expiration aggmetric.Gauge
39-
ttl aggmetric.Gauge
38+
expiration *aggmetric.Gauge
39+
ttl *aggmetric.Gauge
4040
}
4141

4242
// ClientCertExpirationCache contains a cache of gauge objects keyed by
@@ -189,7 +189,7 @@ func (c *ClientCertExpirationCache) MaybeUpsert(
189189
expiration := parentExpirationGauge.AddChild(key)
190190
expiration.Update(newExpiry)
191191
ttl := parentTTLGauge.AddFunctionalChild(ttlFunc(c.timeNow, newExpiry), key)
192-
c.mu.cache.Add(key, &clientCertExpirationMetrics{*expiration, *ttl})
192+
c.mu.cache.Add(key, &clientCertExpirationMetrics{expiration, ttl})
193193
}
194194
} else {
195195
log.Ops.Warningf(ctx, "no memory available to cache cert expiry: %v", err)

pkg/security/cert_expiry_cache_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/cockroachdb/cockroach/pkg/util/mon"
1919
"github.com/cockroachdb/cockroach/pkg/util/stop"
2020
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
21+
io_prometheus_client "github.com/prometheus/client_model/go"
2122
"github.com/stretchr/testify/require"
2223
)
2324

@@ -120,6 +121,55 @@ func TestEntryCache(t *testing.T) {
120121
require.Equal(t, laterExpiration-(closerExpiration+20), ttl)
121122
}
122123

124+
// TestCacheMetricsSync verifies that the cache metrics are correctly synchronized
125+
// when entries are inserted and updated. It checks that the cache length and
126+
// expiration times are properly updated and reflected in the metrics.
127+
func TestCacheMetricsSync(t *testing.T) {
128+
defer leaktest.AfterTest(t)()
129+
130+
findChildMetric := func(metrics *aggmetric.AggGauge, childName string) *io_prometheus_client.Metric {
131+
var result *io_prometheus_client.Metric
132+
metrics.Each([]*io_prometheus_client.LabelPair{}, func(metric *io_prometheus_client.Metric) {
133+
if metric.GetLabel()[0].GetValue() == childName {
134+
result = metric
135+
}
136+
})
137+
return result
138+
}
139+
140+
const (
141+
fooUser = "foo"
142+
143+
laterExpiration = int64(1684359292)
144+
closerExpiration = int64(1584359292)
145+
)
146+
147+
ctx := context.Background()
148+
149+
timesource := timeutil.NewManualTime(timeutil.Unix(0, 123))
150+
// Create a cache with a capacity of 3.
151+
cache, expMetric, ttlMetric := newCache(
152+
ctx,
153+
&cluster.Settings{},
154+
3, /* capacity */
155+
timesource,
156+
)
157+
require.Equal(t, 0, cache.Len())
158+
159+
// insert.
160+
cache.MaybeUpsert(ctx, fooUser, laterExpiration, expMetric, ttlMetric)
161+
// update.
162+
cache.MaybeUpsert(ctx, fooUser, closerExpiration, expMetric, ttlMetric)
163+
164+
metricFloat := *(findChildMetric(expMetric, fooUser).Gauge.Value)
165+
expiration, found := cache.GetExpiration(fooUser)
166+
167+
// verify that both the cache and metric are in sync.
168+
require.Equal(t, true, found)
169+
require.Equal(t, closerExpiration, expiration)
170+
require.Equal(t, closerExpiration, int64(metricFloat))
171+
}
172+
123173
func TestPurgePastEntries(t *testing.T) {
124174
defer leaktest.AfterTest(t)()
125175

0 commit comments

Comments
 (0)