Merge pull request #118988 from nilekhc/hash-keyid
[KMSv2] chore: hashes keyID being logged
This commit is contained in:
		@@ -380,18 +380,21 @@ func (h *kmsv2PluginProbe) rotateDEKOnKeyIDChange(ctx context.Context, statusKey
 | 
				
			|||||||
		// it should be logically impossible for the new state to be invalid but check just in case
 | 
							// it should be logically impossible for the new state to be invalid but check just in case
 | 
				
			||||||
		_, errGen = h.getCurrentState()
 | 
							_, errGen = h.getCurrentState()
 | 
				
			||||||
		if errGen == nil {
 | 
							if errGen == nil {
 | 
				
			||||||
			klog.V(6).InfoS("successfully rotated DEK",
 | 
								klogV6 := klog.V(6)
 | 
				
			||||||
				"uid", uid,
 | 
								if klogV6.Enabled() {
 | 
				
			||||||
				"newKeyID", resp.KeyID,
 | 
									klogV6.InfoS("successfully rotated DEK",
 | 
				
			||||||
				"oldKeyID", state.KeyID,
 | 
										"uid", uid,
 | 
				
			||||||
				"expirationTimestamp", expirationTimestamp.Format(time.RFC3339),
 | 
										"newKeyIDHash", envelopekmsv2.GetHashIfNotEmpty(resp.KeyID),
 | 
				
			||||||
			)
 | 
										"oldKeyIDHash", envelopekmsv2.GetHashIfNotEmpty(state.KeyID),
 | 
				
			||||||
 | 
										"expirationTimestamp", expirationTimestamp.Format(time.RFC3339),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return fmt.Errorf("failed to rotate DEK uid=%q, errState=%v, errGen=%v, statusKeyID=%q, encryptKeyID=%q, stateKeyID=%q, expirationTimestamp=%s",
 | 
						return fmt.Errorf("failed to rotate DEK uid=%q, errState=%v, errGen=%v, statusKeyIDHash=%q, encryptKeyIDHash=%q, stateKeyIDHash=%q, expirationTimestamp=%s",
 | 
				
			||||||
		uid, errState, errGen, statusKeyID, resp.KeyID, state.KeyID, state.ExpirationTimestamp.Format(time.RFC3339))
 | 
							uid, errState, errGen, envelopekmsv2.GetHashIfNotEmpty(statusKeyID), envelopekmsv2.GetHashIfNotEmpty(resp.KeyID), envelopekmsv2.GetHashIfNotEmpty(state.KeyID), state.ExpirationTimestamp.Format(time.RFC3339))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getCurrentState returns the latest state from the last status and encrypt calls.
 | 
					// getCurrentState returns the latest state from the last status and encrypt calls.
 | 
				
			||||||
@@ -434,7 +437,7 @@ func (h *kmsv2PluginProbe) isKMSv2ProviderHealthyAndMaybeRotateDEK(ctx context.C
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if errCode, err := envelopekmsv2.ValidateKeyID(response.KeyID); err != nil {
 | 
						if errCode, err := envelopekmsv2.ValidateKeyID(response.KeyID); err != nil {
 | 
				
			||||||
		metrics.RecordInvalidKeyIDFromStatus(h.name, string(errCode))
 | 
							metrics.RecordInvalidKeyIDFromStatus(h.name, string(errCode))
 | 
				
			||||||
		errs = append(errs, fmt.Errorf("got invalid KMSv2 KeyID %q: %w", response.KeyID, err))
 | 
							errs = append(errs, fmt.Errorf("got invalid KMSv2 KeyID hash %q: %w", envelopekmsv2.GetHashIfNotEmpty(response.KeyID), err))
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		metrics.RecordKeyIDFromStatus(h.name, response.KeyID)
 | 
							metrics.RecordKeyIDFromStatus(h.name, response.KeyID)
 | 
				
			||||||
		// unconditionally append as we filter out nil errors below
 | 
							// unconditionally append as we filter out nil errors below
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1729,7 +1729,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
 | 
				
			|||||||
			wantEncryptCalls: 1,
 | 
								wantEncryptCalls: 1,
 | 
				
			||||||
			wantLogs: []string{
 | 
								wantLogs: []string{
 | 
				
			||||||
				`"encrypting content using envelope service" uid="panda"`,
 | 
									`"encrypting content using envelope service" uid="panda"`,
 | 
				
			||||||
				fmt.Sprintf(`"successfully rotated DEK" uid="panda" newKeyID="1" oldKeyID="" expirationTimestamp="%s"`,
 | 
									fmt.Sprintf(`"successfully rotated DEK" uid="panda" newKeyIDHash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" oldKeyIDHash="" expirationTimestamp="%s"`,
 | 
				
			||||||
					now.Add(3*time.Minute).Format(time.RFC3339)),
 | 
										now.Add(3*time.Minute).Format(time.RFC3339)),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: "",
 | 
								wantErr: "",
 | 
				
			||||||
@@ -1772,7 +1772,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
 | 
				
			|||||||
			wantEncryptCalls: 1,
 | 
								wantEncryptCalls: 1,
 | 
				
			||||||
			wantLogs: []string{
 | 
								wantLogs: []string{
 | 
				
			||||||
				`"encrypting content using envelope service" uid="panda"`,
 | 
									`"encrypting content using envelope service" uid="panda"`,
 | 
				
			||||||
				fmt.Sprintf(`"successfully rotated DEK" uid="panda" newKeyID="4" oldKeyID="3" expirationTimestamp="%s"`,
 | 
									fmt.Sprintf(`"successfully rotated DEK" uid="panda" newKeyIDHash="sha256:4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a" oldKeyIDHash="sha256:4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce" expirationTimestamp="%s"`,
 | 
				
			||||||
					now.Add(3*time.Minute).Format(time.RFC3339)),
 | 
										now.Add(3*time.Minute).Format(time.RFC3339)),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: "",
 | 
								wantErr: "",
 | 
				
			||||||
@@ -1791,8 +1791,8 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
 | 
				
			|||||||
				`"encrypting content using envelope service" uid="panda"`,
 | 
									`"encrypting content using envelope service" uid="panda"`,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: `failed to rotate DEK uid="panda", ` +
 | 
								wantErr: `failed to rotate DEK uid="panda", ` +
 | 
				
			||||||
				`errState=<nil>, errGen=failed to encrypt DEK, error: broken, statusKeyID="5", ` +
 | 
									`errState=<nil>, errGen=failed to encrypt DEK, error: broken, statusKeyIDHash="sha256:ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d", ` +
 | 
				
			||||||
				`encryptKeyID="", stateKeyID="4", expirationTimestamp=` + now.Add(7*time.Minute).Format(time.RFC3339),
 | 
									`encryptKeyIDHash="", stateKeyIDHash="sha256:4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a", expirationTimestamp=` + now.Add(7*time.Minute).Format(time.RFC3339),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:             "invalid service response, no previous state",
 | 
								name:             "invalid service response, no previous state",
 | 
				
			||||||
@@ -1806,8 +1806,8 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: `failed to rotate DEK uid="panda", ` +
 | 
								wantErr: `failed to rotate DEK uid="panda", ` +
 | 
				
			||||||
				`errState=got unexpected nil transformer, errGen=failed to validate annotations: annotations: Invalid value: "panda": ` +
 | 
									`errState=got unexpected nil transformer, errGen=failed to validate annotations: annotations: Invalid value: "panda": ` +
 | 
				
			||||||
				`should be a domain with at least two segments separated by dots, statusKeyID="1", ` +
 | 
									`should be a domain with at least two segments separated by dots, statusKeyIDHash="sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b", ` +
 | 
				
			||||||
				`encryptKeyID="", stateKeyID="", expirationTimestamp=` + (time.Time{}).Format(time.RFC3339),
 | 
									`encryptKeyIDHash="", stateKeyIDHash="", expirationTimestamp=` + (time.Time{}).Format(time.RFC3339),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:        "invalid service response, with previous state",
 | 
								name:        "invalid service response, with previous state",
 | 
				
			||||||
@@ -1824,8 +1824,8 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			wantErr: `failed to rotate DEK uid="panda", ` +
 | 
								wantErr: `failed to rotate DEK uid="panda", ` +
 | 
				
			||||||
				`errState=<nil>, errGen=failed to validate annotations: annotations: Invalid value: "panda": ` +
 | 
									`errState=<nil>, errGen=failed to validate annotations: annotations: Invalid value: "panda": ` +
 | 
				
			||||||
				`should be a domain with at least two segments separated by dots, statusKeyID="3", ` +
 | 
									`should be a domain with at least two segments separated by dots, statusKeyIDHash="sha256:4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce", ` +
 | 
				
			||||||
				`encryptKeyID="", stateKeyID="2", expirationTimestamp=` + now.Format(time.RFC3339),
 | 
									`encryptKeyIDHash="", stateKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35", expirationTimestamp=` + now.Format(time.RFC3339),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ package kmsv2
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"crypto/aes"
 | 
						"crypto/aes"
 | 
				
			||||||
 | 
						"crypto/sha256"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -97,8 +98,8 @@ type State struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (s *State) ValidateEncryptCapability() error {
 | 
					func (s *State) ValidateEncryptCapability() error {
 | 
				
			||||||
	if now := NowFunc(); now.After(s.ExpirationTimestamp) {
 | 
						if now := NowFunc(); now.After(s.ExpirationTimestamp) {
 | 
				
			||||||
		return fmt.Errorf("EDEK with keyID %q expired at %s (current time is %s)",
 | 
							return fmt.Errorf("EDEK with keyID hash %q expired at %s (current time is %s)",
 | 
				
			||||||
			s.KeyID, s.ExpirationTimestamp.Format(time.RFC3339), now.Format(time.RFC3339))
 | 
								GetHashIfNotEmpty(s.KeyID), s.ExpirationTimestamp.Format(time.RFC3339), now.Format(time.RFC3339))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -422,3 +423,11 @@ func toBytes(s string) []byte {
 | 
				
			|||||||
	// https://github.com/golang/go/blob/202a1a57064127c3f19d96df57b9f9586145e21c/src/os/file.go#L246
 | 
						// https://github.com/golang/go/blob/202a1a57064127c3f19d96df57b9f9586145e21c/src/os/file.go#L246
 | 
				
			||||||
	return unsafe.Slice(unsafe.StringData(s), len(s))
 | 
						return unsafe.Slice(unsafe.StringData(s), len(s))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetHashIfNotEmpty returns the sha256 hash of the data if it is not empty.
 | 
				
			||||||
 | 
					func GetHashIfNotEmpty(data string) string {
 | 
				
			||||||
 | 
						if len(data) > 0 {
 | 
				
			||||||
 | 
							return fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(data)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -401,7 +401,7 @@ func TestEnvelopeTransformerStateFunc(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	t.Run("writes fail when the plugin is down and the state is invalid", func(t *testing.T) {
 | 
						t.Run("writes fail when the plugin is down and the state is invalid", func(t *testing.T) {
 | 
				
			||||||
		_, err := transformer.TransformToStorage(ctx, originalText, dataCtx)
 | 
							_, err := transformer.TransformToStorage(ctx, originalText, dataCtx)
 | 
				
			||||||
		if !strings.Contains(errString(err), `EDEK with keyID "1" expired at`) {
 | 
							if !strings.Contains(errString(err), `EDEK with keyID hash "sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" expired at`) {
 | 
				
			||||||
			t.Fatalf("expected expiration error, got: %v", err)
 | 
								t.Fatalf("expected expiration error, got: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -378,7 +378,7 @@ resources:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// 6. when kms-plugin is down, expect creation of new pod and encryption to fail because the DEK is invalid
 | 
						// 6. when kms-plugin is down, expect creation of new pod and encryption to fail because the DEK is invalid
 | 
				
			||||||
	_, err = test.createPod(testNamespace, dynamicClient)
 | 
						_, err = test.createPod(testNamespace, dynamicClient)
 | 
				
			||||||
	if err == nil || !strings.Contains(err.Error(), `EDEK with keyID "2" expired at 2`) {
 | 
						if err == nil || !strings.Contains(err.Error(), `EDEK with keyID hash "sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" expired at 2`) {
 | 
				
			||||||
		t.Fatalf("Create test pod should have failed due to encryption, ns: %s, got: %v", testNamespace, err)
 | 
							t.Fatalf("Create test pod should have failed due to encryption, ns: %s, got: %v", testNamespace, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user