From a567f56445d523a89922253ae4902ad19e71c1be Mon Sep 17 00:00:00 2001 From: Irbe Krumina Date: Mon, 3 Mar 2025 08:04:18 -0800 Subject: [PATCH] ipn/store/kubestore: sanitize keys loaded to in-memory store (#15178) Reads use the sanitized form, so unsanitized keys being stored in memory resulted lookup failures, for example for serve config. Updates tailscale/tailscale#15134 Signed-off-by: Irbe Krumina --- ipn/store/kubestore/store_kube.go | 9 +++++++-- ipn/store/kubestore/store_kube_test.go | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ipn/store/kubestore/store_kube.go b/ipn/store/kubestore/store_kube.go index b4e14c6d3..ecd101c57 100644 --- a/ipn/store/kubestore/store_kube.go +++ b/ipn/store/kubestore/store_kube.go @@ -98,7 +98,11 @@ func (s *Store) updateStateSecret(data map[string][]byte) (err error) { defer func() { if err == nil { for id, bs := range data { - s.memory.WriteState(ipn.StateKey(id), bs) + // The in-memory store does not distinguish between values read from state Secret on + // init and values written to afterwards. Values read from the state + // Secret will always be sanitized, so we also need to sanitize values written to store + // later, so that the Read logic can just lookup keys in sanitized form. + s.memory.WriteState(ipn.StateKey(sanitizeKey(id)), bs) } } if err != nil { @@ -198,8 +202,9 @@ func (s *Store) loadState() (err error) { return nil } -// sanitizeKey converts any value that can be converted to a string into a valid Kubernetes secret key. +// sanitizeKey converts any value that can be converted to a string into a valid Kubernetes Secret key. // Valid characters are alphanumeric, -, _, and . +// https://kubernetes.io/docs/concepts/configuration/secret/#restriction-names-data. func sanitizeKey[T ~string](k T) string { return strings.Map(func(r rune) rune { if r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || r == '-' || r == '_' || r == '.' { diff --git a/ipn/store/kubestore/store_kube_test.go b/ipn/store/kubestore/store_kube_test.go index f3c5ac9fb..351458efb 100644 --- a/ipn/store/kubestore/store_kube_test.go +++ b/ipn/store/kubestore/store_kube_test.go @@ -169,7 +169,7 @@ func TestUpdateStateSecret(t *testing.T) { // Verify memory store was updated for k, v := range tt.updates { - got, err := s.memory.ReadState(ipn.StateKey(k)) + got, err := s.memory.ReadState(ipn.StateKey(sanitizeKey(k))) if err != nil { t.Errorf("reading from memory store: %v", err) continue