cmd,feature: add identity token auto generation for workload identity (#18373)

Adds the ability to detect what provider the client is running on and tries fetch the ID token to use with Workload Identity.

Updates https://github.com/tailscale/corp/issues/33316

Signed-off-by: Danni Popova <danni@tailscale.com>
This commit is contained in:
Danni Popova
2026-01-14 15:00:59 +00:00
committed by GitHub
parent 58042e2de3
commit 6a6aa805d6
18 changed files with 592 additions and 42 deletions
@@ -16,6 +16,7 @@ func TestResolveAuthKey(t *testing.T) {
name string
clientID string
idToken string
audience string
tags []string
wantAuthKey string
wantErr string
@@ -24,6 +25,7 @@ func TestResolveAuthKey(t *testing.T) {
name: "success",
clientID: "client-123",
idToken: "token",
audience: "api://tailscale-wif",
tags: []string{"tag:test"},
wantAuthKey: "tskey-auth-xyz",
wantErr: "",
@@ -32,21 +34,24 @@ func TestResolveAuthKey(t *testing.T) {
name: "missing client id short-circuits without error",
clientID: "",
idToken: "token",
audience: "api://tailscale-wif",
tags: []string{"tag:test"},
wantAuthKey: "",
wantErr: "",
},
{
name: "missing id token",
name: "missing id token and audience",
clientID: "client-123",
idToken: "",
audience: "",
tags: []string{"tag:test"},
wantErr: "federated identity authkeys require --id-token",
wantErr: "federated identity requires either an ID token or an audience",
},
{
name: "missing tags",
clientID: "client-123",
idToken: "token",
audience: "api://tailscale-wif",
tags: []string{},
wantErr: "federated identity authkeys require --advertise-tags",
},
@@ -54,6 +59,7 @@ func TestResolveAuthKey(t *testing.T) {
name: "invalid client id attributes",
clientID: "client-123?invalid=value",
idToken: "token",
audience: "api://tailscale-wif",
tags: []string{"tag:test"},
wantErr: `failed to parse optional config attributes: unknown optional config attribute "invalid"`,
},
@@ -64,7 +70,7 @@ func TestResolveAuthKey(t *testing.T) {
srv := mockedControlServer(t)
defer srv.Close()
authKey, err := resolveAuthKey(context.Background(), srv.URL, tt.clientID, tt.idToken, tt.tags)
authKey, err := resolveAuthKey(context.Background(), srv.URL, tt.clientID, tt.idToken, tt.audience, tt.tags)
if tt.wantErr != "" {
if err == nil {
t.Errorf("resolveAuthKey() error = nil, want %q", tt.wantErr)