cmd/tailscale: let certs/keys be written to stdout, warn about macOS sandbox

Fixes https://twitter.com/SeanHood/status/1443668378468720647

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/2997/head
Brad Fitzpatrick 3 years ago
parent 2d464cecd1
commit 98b3fa78aa

@ -20,6 +20,7 @@ import (
"tailscale.com/atomicfile"
"tailscale.com/client/tailscale"
"tailscale.com/ipn"
"tailscale.com/version"
)
var certCmd = &ffcli.Command{
@ -29,8 +30,8 @@ var certCmd = &ffcli.Command{
ShortUsage: "cert [flags] <domain>",
FlagSet: (func() *flag.FlagSet {
fs := flag.NewFlagSet("cert", flag.ExitOnError)
fs.StringVar(&certArgs.certFile, "cert-file", "", "output cert file; defaults to DOMAIN.crt")
fs.StringVar(&certArgs.keyFile, "key-file", "", "output cert file; defaults to DOMAIN.key")
fs.StringVar(&certArgs.certFile, "cert-file", "", "output cert file or \"-\" for stdout; defaults to DOMAIN.crt if --cert-file and --key-file are both unset")
fs.StringVar(&certArgs.keyFile, "key-file", "", "output cert file or \"-\" for stdout; defaults to DOMAIN.key if --cert-file and --key-file are both unset")
fs.BoolVar(&certArgs.serve, "serve-demo", false, "if true, serve on port :443 using the cert as a demo, instead of writing out the files to disk")
return fs
})(),
@ -79,10 +80,15 @@ func runCert(ctx context.Context, args []string) error {
}
domain := args[0]
if certArgs.certFile == "" {
certArgs.certFile = domain + ".crt"
printf := func(format string, a ...interface{}) {
fmt.Printf(format, a...)
}
if certArgs.certFile == "-" || certArgs.keyFile == "-" {
printf = log.Printf
log.SetFlags(0)
}
if certArgs.keyFile == "" {
if certArgs.certFile == "" && certArgs.keyFile == "" {
certArgs.certFile = domain + ".crt"
certArgs.keyFile = domain + ".key"
}
certPEM, keyPEM, err := tailscale.CertPair(ctx, domain)
@ -92,28 +98,54 @@ func runCert(ctx context.Context, args []string) error {
if err != nil {
return err
}
certChanged, err := writeIfChanged(certArgs.certFile, certPEM, 0644)
if err != nil {
return err
}
if certChanged {
fmt.Printf("Wrote public cert to %v\n", certArgs.certFile)
} else {
fmt.Printf("Public cert unchanged at %v\n", certArgs.certFile)
needMacWarning := version.IsSandboxedMacOS()
macWarn := func() {
if !needMacWarning {
return
}
needMacWarning = false
dir := "io.tailscale.ipn.macos"
if version.IsMacSysExt() {
dir = "io.tailscale.ipn.macsys"
}
printf("Warning: the macOS CLI runs in a sandbox; this binary's filesystem writes go to $HOME/Library/Containers/%s\n", dir)
}
keyChanged, err := writeIfChanged(certArgs.keyFile, keyPEM, 0600)
if err != nil {
return err
if certArgs.certFile != "" {
certChanged, err := writeIfChanged(certArgs.certFile, certPEM, 0644)
if err != nil {
return err
}
if certArgs.certFile != "-" {
macWarn()
if certChanged {
printf("Wrote public cert to %v\n", certArgs.certFile)
} else {
printf("Public cert unchanged at %v\n", certArgs.certFile)
}
}
}
if keyChanged {
fmt.Printf("Wrote private key to %v\n", certArgs.keyFile)
} else {
fmt.Printf("Private key unchanged at %v\n", certArgs.keyFile)
if certArgs.keyFile != "" {
keyChanged, err := writeIfChanged(certArgs.keyFile, keyPEM, 0600)
if err != nil {
return err
}
if certArgs.keyFile != "-" {
macWarn()
if keyChanged {
printf("Wrote private key to %v\n", certArgs.keyFile)
} else {
printf("Private key unchanged at %v\n", certArgs.keyFile)
}
}
}
return nil
}
func writeIfChanged(filename string, contents []byte, mode os.FileMode) (changed bool, err error) {
if filename == "-" {
os.Stdout.Write(contents)
return false, nil
}
if old, err := os.ReadFile(filename); err == nil && bytes.Equal(contents, old) {
return false, nil
}

Loading…
Cancel
Save