cmd/k8s-operator: use the client's authkey method to create auth keys.

Also introduces an intermediary interface for the tailscale client, in
preparation for operator tests that fake out the Tailscale API interaction.

Updates #502.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson 2022-12-12 15:37:20 -08:00 committed by Dave Anderson
parent ca08e316af
commit 3b7ae39a06

View File

@ -7,14 +7,10 @@
package main package main
import ( import (
"bytes"
"context" "context"
_ "embed" _ "embed"
"encoding/json"
"fmt" "fmt"
"io"
"log" "log"
"net/http"
"os" "os"
"strings" "strings"
"time" "time"
@ -182,7 +178,13 @@ func main() {
type ServiceReconciler struct { type ServiceReconciler struct {
client.Client client.Client
defaultTags []string defaultTags []string
tsClient *tailscale.Client tsClient tsClient
}
type tsClient interface {
DeleteDevice(ctx context.Context, id string) error
Tailnet() string
CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error)
} }
func childResourceLabels(parent *corev1.Service) map[string]string { func childResourceLabels(parent *corev1.Service) map[string]string {
@ -414,7 +416,7 @@ func (a *ServiceReconciler) createOrGetSecret(ctx context.Context, svc, hsvc *co
} }
secret.StringData = map[string]string{ secret.StringData = map[string]string{
"authkey": authKey.Key, "authkey": authKey,
} }
if err := a.Create(ctx, secret); err != nil { if err := a.Create(ctx, secret); err != nil {
return "", err return "", err
@ -463,36 +465,21 @@ type capability struct {
} `json:"devices"` } `json:"devices"`
} }
func (a *ServiceReconciler) newAuthKey(ctx context.Context, tags []string) (*authKey, error) { func (a *ServiceReconciler) newAuthKey(ctx context.Context, tags []string) (string, error) {
var nkr newKeyRequest caps := tailscale.KeyCapabilities{
nkr.Capabilities.Devices.Create.Reusable = false Devices: tailscale.KeyDeviceCapabilities{
nkr.Capabilities.Devices.Create.Preauthorized = true Create: tailscale.KeyDeviceCreateCapabilities{
nkr.Capabilities.Devices.Create.Tags = tags Reusable: false,
jc, err := json.Marshal(nkr) Preauthorized: true,
Tags: tags,
},
},
}
key, _, err := a.tsClient.CreateKey(ctx, caps)
if err != nil { if err != nil {
return nil, err return "", err
} }
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("https://unused/api/v2/tailnet/%s/keys", a.tsClient.Tailnet()), bytes.NewReader(jc)) return key, nil
if err != nil {
return nil, err
}
resp, err := a.tsClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
slurp := new(bytes.Buffer)
if _, err := io.Copy(slurp, resp.Body); err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d; %v", resp.StatusCode, slurp.String())
}
var ak authKey
if err := json.NewDecoder(slurp).Decode(&ak); err != nil {
return nil, err
}
return &ak, nil
} }
//go:embed manifests/proxy.yaml //go:embed manifests/proxy.yaml