tailcfg,cmd/k8s-operator: moves tailscale.com/cap/kubernetes peer cap to tailcfg ()

This is done in preparation for adding kubectl
session recording rules to this capability grant that will need to
be unmarshalled by control, so will also need to be
in a shared location.

Updates 

Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
Irbe Krumina 2024-06-04 18:31:37 +01:00 committed by GitHub
parent d636407f14
commit 82576190a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 15 additions and 6 deletions
cmd/k8s-operator
tailcfg

@ -207,8 +207,11 @@ func runAPIServerProxy(s *tsnet.Server, rt http.RoundTripper, log *zap.SugaredLo
} }
const ( const (
capabilityName = "tailscale.com/cap/kubernetes" // oldCapabilityName is a legacy form of
oldCapabilityName = "https://" + capabilityName // tailfcg.PeerCapabilityKubernetes capability. The only capability rule
// that is respected for this form is group impersonation - for
// backwards compatibility reasons.
oldCapabilityName = "https://" + tailcfg.PeerCapabilityKubernetes
) )
type capRule struct { type capRule struct {
@ -229,7 +232,7 @@ type impersonateRule struct {
func addImpersonationHeaders(r *http.Request, log *zap.SugaredLogger) error { func addImpersonationHeaders(r *http.Request, log *zap.SugaredLogger) error {
log = log.With("remote", r.RemoteAddr) log = log.With("remote", r.RemoteAddr)
who := whoIsKey.Value(r.Context()) who := whoIsKey.Value(r.Context())
rules, err := tailcfg.UnmarshalCapJSON[capRule](who.CapMap, capabilityName) rules, err := tailcfg.UnmarshalCapJSON[capRule](who.CapMap, tailcfg.PeerCapabilityKubernetes)
if len(rules) == 0 && err == nil { if len(rules) == 0 && err == nil {
// Try the old capability name for backwards compatibility. // Try the old capability name for backwards compatibility.
rules, err = tailcfg.UnmarshalCapJSON[capRule](who.CapMap, oldCapabilityName) rules, err = tailcfg.UnmarshalCapJSON[capRule](who.CapMap, oldCapabilityName)

@ -49,7 +49,7 @@ func TestImpersonationHeaders(t *testing.T) {
name: "user-with-cap", name: "user-with-cap",
emailish: "foo@example.com", emailish: "foo@example.com",
capMap: tailcfg.PeerCapMap{ capMap: tailcfg.PeerCapMap{
capabilityName: { tailcfg.PeerCapabilityKubernetes: {
tailcfg.RawMessage(`{"impersonate":{"groups":["group1","group2"]}}`), tailcfg.RawMessage(`{"impersonate":{"groups":["group1","group2"]}}`),
tailcfg.RawMessage(`{"impersonate":{"groups":["group1","group3"]}}`), // One group is duplicated. tailcfg.RawMessage(`{"impersonate":{"groups":["group1","group3"]}}`), // One group is duplicated.
tailcfg.RawMessage(`{"impersonate":{"groups":["group4"]}}`), tailcfg.RawMessage(`{"impersonate":{"groups":["group4"]}}`),
@ -71,7 +71,7 @@ func TestImpersonationHeaders(t *testing.T) {
emailish: "tagged-device", emailish: "tagged-device",
tags: []string{"tag:foo", "tag:bar"}, tags: []string{"tag:foo", "tag:bar"},
capMap: tailcfg.PeerCapMap{ capMap: tailcfg.PeerCapMap{
capabilityName: { tailcfg.PeerCapabilityKubernetes: {
tailcfg.RawMessage(`{"impersonate":{"groups":["group1"]}}`), tailcfg.RawMessage(`{"impersonate":{"groups":["group1"]}}`),
}, },
}, },
@ -85,7 +85,7 @@ func TestImpersonationHeaders(t *testing.T) {
emailish: "tagged-device", emailish: "tagged-device",
tags: []string{"tag:foo", "tag:bar"}, tags: []string{"tag:foo", "tag:bar"},
capMap: tailcfg.PeerCapMap{ capMap: tailcfg.PeerCapMap{
capabilityName: { tailcfg.PeerCapabilityKubernetes: {
tailcfg.RawMessage(`[]`), tailcfg.RawMessage(`[]`),
}, },
}, },

@ -1375,6 +1375,12 @@ const (
// PeerCapabilityTaildriveSharer indicates that a peer has the ability to // PeerCapabilityTaildriveSharer indicates that a peer has the ability to
// share folders with us. // share folders with us.
PeerCapabilityTaildriveSharer PeerCapability = "tailscale.com/cap/drive-sharer" PeerCapabilityTaildriveSharer PeerCapability = "tailscale.com/cap/drive-sharer"
// PeerCapabilityKubernetes grants a peer Kubernetes-specific
// capabilities, such as the ability to impersonate specific Tailscale
// user groups as Kubernetes user groups. This capability is read by
// peers that are Tailscale Kubernetes operator instances.
PeerCapabilityKubernetes PeerCapability = "tailscale.com/cap/kubernetes"
) )
// NodeCapMap is a map of capabilities to their optional values. It is valid for // NodeCapMap is a map of capabilities to their optional values. It is valid for