tailscale/ipn/conffile/cloudconf.go
Brad Fitzpatrick 1ea100e2e5 cmd/tailscaled, ipn/conffile: support ec2 user-data config file
Updates #1412
Updates #1866

Change-Id: I4d08fb233b80c2078b3b28ffc18559baabb4a081
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-05-30 09:49:18 -07:00

60 lines
1.5 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package conffile
import (
"errors"
"fmt"
"io"
"net/http"
"strings"
"tailscale.com/omit"
)
func getEC2MetadataToken() (string, error) {
if omit.AWS {
return "", omit.Err
}
req, _ := http.NewRequest("PUT", "http://169.254.169.254/latest/api/token", nil)
req.Header.Add("X-aws-ec2-metadata-token-ttl-seconds", "300")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("failed to get metadata token: %w", err)
}
defer res.Body.Close()
if res.StatusCode != 200 {
return "", fmt.Errorf("failed to get metadata token: %v", res.Status)
}
all, err := io.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("failed to read metadata token: %w", err)
}
return strings.TrimSpace(string(all)), nil
}
func readVMUserData() ([]byte, error) {
// TODO(bradfitz): support GCP, Azure, Proxmox/cloud-init
// (NoCloud/ConfigDrive ISO), etc.
if omit.AWS {
return nil, omit.Err
}
token, tokErr := getEC2MetadataToken()
req, _ := http.NewRequest("GET", "http://169.254.169.254/latest/user-data", nil)
req.Header.Add("X-aws-ec2-metadata-token", token)
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != 200 {
if tokErr != nil {
return nil, fmt.Errorf("failed to get VM user data: %v; also failed to get metadata token: %v", res.Status, tokErr)
}
return nil, errors.New(res.Status)
}
return io.ReadAll(res.Body)
}