kmsv2: fix race in simpleCache.set when setting cache size metric

Signed-off-by: Monis Khan <mok@microsoft.com>
This commit is contained in:
Monis Khan
2023-08-27 15:14:04 -04:00
parent d4572d58db
commit b10697c788
3 changed files with 111 additions and 6 deletions

View File

@@ -27,17 +27,20 @@ import (
"encoding/binary"
"fmt"
"io"
"regexp"
"strings"
"testing"
"time"
"github.com/gogo/protobuf/proto"
"github.com/google/go-cmp/cmp"
clientv3 "go.etcd.io/etcd/client/v3"
corev1 "k8s.io/api/core/v1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilrand "k8s.io/apimachinery/pkg/util/rand"
@@ -58,6 +61,7 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/klog/v2"
kmsv2api "k8s.io/kms/apis/v2"
@@ -201,6 +205,53 @@ resources:
}
defer test.cleanUp()
ctx := testContext(t)
// the global metrics registry persists across test runs - reset it here so we can make assertions
copyConfig := rest.CopyConfig(test.kubeAPIServer.ClientConfig)
copyConfig.GroupVersion = &schema.GroupVersion{}
copyConfig.NegotiatedSerializer = unstructuredscheme.NewUnstructuredNegotiatedSerializer()
rc, err := rest.RESTClientFor(copyConfig)
if err != nil {
t.Fatal(err)
}
if err := rc.Delete().AbsPath("/metrics").Do(ctx).Error(); err != nil {
t.Fatal(err)
}
// assert that the metrics we collect during the test run match expectations
wantMetricStrings := []string{
`apiserver_envelope_encryption_dek_source_cache_size{provider_name="kms-provider"} 1`,
`apiserver_envelope_encryption_key_id_hash_last_timestamp_seconds{key_id_hash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",provider_name="kms-provider",transformation_type="from_storage"} FP`,
`apiserver_envelope_encryption_key_id_hash_last_timestamp_seconds{key_id_hash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",provider_name="kms-provider",transformation_type="to_storage"} FP`,
`apiserver_envelope_encryption_key_id_hash_total{key_id_hash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",provider_name="kms-provider",transformation_type="from_storage"} 2`,
`apiserver_envelope_encryption_key_id_hash_total{key_id_hash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",provider_name="kms-provider",transformation_type="to_storage"} 1`,
}
defer func() {
body, err := rc.Get().AbsPath("/metrics").DoRaw(ctx)
if err != nil {
t.Fatal(err)
}
var gotMetricStrings []string
trimFP := regexp.MustCompile(`(.*)(} \d+\.\d+.*)`)
for _, line := range strings.Split(string(body), "\n") {
if strings.HasPrefix(line, "apiserver_envelope_") {
if strings.HasPrefix(line, "apiserver_envelope_encryption_dek_cache_fill_percent") {
continue // this can be ignored as it is KMS v1 only
}
if strings.Contains(line, "_seconds") {
line = trimFP.ReplaceAllString(line, `$1`) + "} FP" // ignore floating point metric values
}
gotMetricStrings = append(gotMetricStrings, line)
}
}
if diff := cmp.Diff(wantMetricStrings, gotMetricStrings); diff != "" {
t.Errorf("unexpected metrics diff (-want +got): %s", diff)
}
}()
test.secret, err = test.createSecret(testSecret, testNamespace)
if err != nil {
t.Fatalf("Failed to create test secret, error: %v", err)
@@ -226,8 +277,6 @@ resources:
t.Fatalf("expected secret to be prefixed with %s, but got %s", wantPrefix, rawEnvelope)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
ciphertext, err := envelopeData.cipherTextDEKSource()
if err != nil {
t.Fatalf("failed to get ciphertext DEK/seed from KMSv2 Plugin: %v", err)