tailscale/cmd/k8s-operator/tsclient.go
Artem Leshchev 5652b6c9c0
cmd/k8s-operator: fix token exchange for identity federation (#19845)
tailscale-client-go-v2 natively supports identity federation authentication,
and in #19010 the required authentication provider is used, but the manual
token exchange was never removed, so we were exchanging JWT token to an auth
token, and then were trying to use that auth token for exchange once again.
This commit removes the legacy mechanism, fully relying on
tailscale-client-go-v2 to handle authentication.

Fixes #19844

Signed-off-by: Artem Leshchev <matshch@avride.ai>
2026-05-27 16:45:07 +01:00

71 lines
1.5 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
//go:build !plan9
package main
import (
"fmt"
"net/url"
"os"
"go.uber.org/zap"
"tailscale.com/client/tailscale/v2"
"tailscale.com/ipn"
)
const (
oidcJWTPath = "/var/run/secrets/tailscale/serviceaccount/token"
)
func newTSClient(logger *zap.SugaredLogger, clientID, clientIDPath, clientSecretPath, loginServer string) (*tailscale.Client, error) {
baseURL := ipn.DefaultControlURL
if loginServer != "" {
baseURL = loginServer
}
base, err := url.Parse(baseURL)
if err != nil {
return nil, err
}
client := &tailscale.Client{
UserAgent: "tailscale-k8s-operator",
BaseURL: base,
}
if clientID == "" {
// Use static client credentials mounted to disk.
clientIDBytes, err := os.ReadFile(clientIDPath)
if err != nil {
return nil, fmt.Errorf("error reading client ID %q: %w", clientIDPath, err)
}
clientSecretBytes, err := os.ReadFile(clientSecretPath)
if err != nil {
return nil, fmt.Errorf("reading client secret %q: %w", clientSecretPath, err)
}
client.Auth = &tailscale.OAuth{
ClientID: string(clientIDBytes),
ClientSecret: string(clientSecretBytes),
}
} else {
// Use workload identity federation.
client.Auth = &tailscale.IdentityFederation{
ClientID: clientID,
IDTokenFunc: func() (string, error) {
token, err := os.ReadFile(oidcJWTPath)
if err != nil {
return "", err
}
return string(token), nil
},
}
}
return client, nil
}