cmd/tailscale: let up --authkey be of form file:/path/to/secret

Fixes #2958

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2021-09-29 08:01:27 -07:00 committed by Brad Fitzpatrick
parent e016eaf410
commit b822b5c798

View File

@ -74,7 +74,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT) *flag.FlagSet {
upf.BoolVar(&upArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node") upf.BoolVar(&upArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node")
upf.BoolVar(&upArgs.shieldsUp, "shields-up", false, "don't allow incoming connections") upf.BoolVar(&upArgs.shieldsUp, "shields-up", false, "don't allow incoming connections")
upf.StringVar(&upArgs.advertiseTags, "advertise-tags", "", "comma-separated ACL tags to request; each must start with \"tag:\" (e.g. \"tag:eng,tag:montreal,tag:ssh\")") upf.StringVar(&upArgs.advertiseTags, "advertise-tags", "", "comma-separated ACL tags to request; each must start with \"tag:\" (e.g. \"tag:eng,tag:montreal,tag:ssh\")")
upf.StringVar(&upArgs.authKey, "authkey", "", "node authorization key") upf.StringVar(&upArgs.authKeyOrFile, "authkey", "", `node authorization key; if it begins with "file:", then it's a path to a file containing the authkey`)
upf.StringVar(&upArgs.hostname, "hostname", "", "hostname to use instead of the one provided by the OS") upf.StringVar(&upArgs.hostname, "hostname", "", "hostname to use instead of the one provided by the OS")
upf.StringVar(&upArgs.advertiseRoutes, "advertise-routes", "", "routes to advertise to other nodes (comma-separated, e.g. \"10.0.0.0/8,192.168.0.0/24\") or empty string to not advertise routes") upf.StringVar(&upArgs.advertiseRoutes, "advertise-routes", "", "routes to advertise to other nodes (comma-separated, e.g. \"10.0.0.0/8,192.168.0.0/24\") or empty string to not advertise routes")
upf.BoolVar(&upArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet") upf.BoolVar(&upArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet")
@ -114,11 +114,24 @@ type upArgsT struct {
advertiseTags string advertiseTags string
snat bool snat bool
netfilterMode string netfilterMode string
authKey string authKeyOrFile string // "secret" or "file:/path/to/secret"
hostname string hostname string
opUser string opUser string
} }
func (a upArgsT) getAuthKey() (string, error) {
v := a.authKeyOrFile
if strings.HasPrefix(v, "file:") {
file := strings.TrimPrefix(v, "file:")
b, err := os.ReadFile(file)
if err != nil {
return "", err
}
return strings.TrimSpace(string(b)), nil
}
return v, nil
}
var upArgs upArgsT var upArgs upArgsT
func warnf(format string, args ...interface{}) { func warnf(format string, args ...interface{}) {
@ -280,7 +293,7 @@ func updatePrefs(prefs, curPrefs *ipn.Prefs, env upCheckEnv) (simpleUp bool, jus
justEdit := env.backendState == ipn.Running.String() && justEdit := env.backendState == ipn.Running.String() &&
!env.upArgs.forceReauth && !env.upArgs.forceReauth &&
!env.upArgs.reset && !env.upArgs.reset &&
env.upArgs.authKey == "" && env.upArgs.authKeyOrFile == "" &&
!controlURLChanged !controlURLChanged
if justEdit { if justEdit {
justEditMP = new(ipn.MaskedPrefs) justEditMP = new(ipn.MaskedPrefs)
@ -308,7 +321,7 @@ func runUp(ctx context.Context, args []string) error {
// printAuthURL reports whether we should print out the // printAuthURL reports whether we should print out the
// provided auth URL from an IPN notify. // provided auth URL from an IPN notify.
printAuthURL := func(url string) bool { printAuthURL := func(url string) bool {
if upArgs.authKey != "" { if upArgs.authKeyOrFile != "" {
// Issue 1755: when using an authkey, don't // Issue 1755: when using an authkey, don't
// show an authURL that might still be pending // show an authURL that might still be pending
// from a previous non-completed interactive // from a previous non-completed interactive
@ -452,9 +465,13 @@ func runUp(ctx context.Context, args []string) error {
return err return err
} }
} else { } else {
authKey, err := upArgs.getAuthKey()
if err != nil {
return err
}
opts := ipn.Options{ opts := ipn.Options{
StateKey: ipn.GlobalDaemonStateKey, StateKey: ipn.GlobalDaemonStateKey,
AuthKey: upArgs.authKey, AuthKey: authKey,
UpdatePrefs: prefs, UpdatePrefs: prefs,
} }
// On Windows, we still run in mostly the "legacy" way that // On Windows, we still run in mostly the "legacy" way that