func()

in pkg/plugin/healthz.go [53:138]


func (h *HealthZ) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
	mlog.Trace("Started health check")
	ctx, cancel := context.WithTimeout(context.Background(), h.RPCTimeout)
	defer cancel()

	conn, err := h.dialUnixSocket()
	if err != nil {
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
		return
	}
	defer conn.Close()

	// create the kms client for v1
	kmsClient := kmsv1.NewKeyManagementServiceClient(conn)

	// create the kms client for v2
	kmsV2Client := kmsv2.NewKeyManagementServiceClient(conn)

	// check version response against KMS-Plugin's gRPC endpoint.
	err = h.checkRPC(ctx, kmsClient, kmsV2Client)
	if err != nil {
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
		return
	}

	// Both encryption and decryption calls are made for each version,
	// resulting in a total of 4 calls to the keyvault.
	// Additionally, a health check is performed every 10 seconds.

	// v1 checks
	// check the configured keyvault, key, key version and permissions are still
	// valid to encrypt and decrypt with test data.
	enc, err := h.KMSv1Server.Encrypt(ctx, &kmsv1.EncryptRequest{Plain: []byte(healthCheckPlainText)})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	dec, err := h.KMSv1Server.Decrypt(ctx, &kmsv1.DecryptRequest{Cipher: enc.Cipher})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if string(dec.Plain) != healthCheckPlainText {
		http.Error(w, "plain text mismatch after decryption", http.StatusInternalServerError)
		return
	}

	// v2 checks.
	// appending a string to UUID allows us to differentiate the UUIDs generated by us from those generated by the API server.
	uid := "local-healthz-check-" + string(uuid.NewUUID())

	v2EncryptResponse, err := h.KMSv2Server.Encrypt(
		ctx,
		&kmsv2.EncryptRequest{
			Plaintext: []byte(healthCheckPlainText),
			Uid:       uid,
		},
	)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	v2DecryptResponse, err := h.KMSv2Server.Decrypt(ctx, &kmsv2.DecryptRequest{
		Ciphertext:  v2EncryptResponse.Ciphertext,
		KeyId:       v2EncryptResponse.KeyId,
		Uid:         uid, // passing the same uid to track roundtrip encrypt/decrypt calls
		Annotations: v2EncryptResponse.Annotations,
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if string(v2DecryptResponse.Plaintext) != healthCheckPlainText {
		http.Error(w, "plain text mismatch after decryption with KMSv2", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err = w.Write([]byte("ok")); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	mlog.Trace("Completed health check")
}