summaryrefslogtreecommitdiffhomepage
path: root/cmd/k8s-operator/tailnet.go
blob: 57c749bec31eeacbbd2558424e3cec1a2dce950b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

//go:build !plan9

package main

import (
	"context"
	"fmt"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/clientcredentials"
	corev1 "k8s.io/api/core/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"tailscale.com/internal/client/tailscale"
	"tailscale.com/ipn"
	operatorutils "tailscale.com/k8s-operator"
	tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
)

func clientForTailnet(ctx context.Context, cl client.Client, namespace, name string) (tsClient, error) {
	var tn tsapi.Tailnet
	if err := cl.Get(ctx, client.ObjectKey{Name: name}, &tn); err != nil {
		return nil, fmt.Errorf("failed to get tailnet %q: %w", name, err)
	}

	if !operatorutils.TailnetIsReady(&tn) {
		return nil, fmt.Errorf("tailnet %q is not ready", name)
	}

	var secret corev1.Secret
	if err := cl.Get(ctx, client.ObjectKey{Name: tn.Spec.Credentials.SecretName, Namespace: namespace}, &secret); err != nil {
		return nil, fmt.Errorf("failed to get Secret %q in namespace %q: %w", tn.Spec.Credentials.SecretName, namespace, err)
	}

	baseURL := ipn.DefaultControlURL
	if tn.Spec.LoginURL != "" {
		baseURL = tn.Spec.LoginURL
	}

	credentials := clientcredentials.Config{
		ClientID:     string(secret.Data["client_id"]),
		ClientSecret: string(secret.Data["client_secret"]),
		TokenURL:     baseURL + "/api/v2/oauth/token",
	}

	source := credentials.TokenSource(ctx)
	httpClient := oauth2.NewClient(ctx, source)

	ts := tailscale.NewClient(defaultTailnet, nil)
	ts.UserAgent = "tailscale-k8s-operator"
	ts.HTTPClient = httpClient
	ts.BaseURL = baseURL

	return ts, nil
}