mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-22 02:50:42 +00:00
ipn/store: automatically migrate between plaintext and encrypted state (#16318)
Add a new `--encrypt-state` flag to `cmd/tailscaled`. Based on that flag, migrate the existing state file to/from encrypted format if needed. Updates #15830 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
@@ -64,6 +64,7 @@ import (
|
||||
"tailscale.com/util/clientmetric"
|
||||
"tailscale.com/util/multierr"
|
||||
"tailscale.com/util/osshare"
|
||||
"tailscale.com/util/syspolicy"
|
||||
"tailscale.com/version"
|
||||
"tailscale.com/version/distro"
|
||||
"tailscale.com/wgengine"
|
||||
@@ -126,6 +127,7 @@ var args struct {
|
||||
debug string
|
||||
port uint16
|
||||
statepath string
|
||||
encryptState bool
|
||||
statedir string
|
||||
socketpath string
|
||||
birdSocketPath string
|
||||
@@ -193,6 +195,7 @@ func main() {
|
||||
flag.StringVar(&args.tunname, "tun", defaultTunName(), `tunnel interface name; use "userspace-networking" (beta) to not use TUN`)
|
||||
flag.Var(flagtype.PortValue(&args.port, defaultPort()), "port", "UDP port to listen on for WireGuard and peer-to-peer traffic; 0 means automatically select")
|
||||
flag.StringVar(&args.statepath, "state", "", "absolute path of state file; use 'kube:<secret-name>' to use Kubernetes secrets or 'arn:aws:ssm:...' to store in AWS SSM; use 'mem:' to not store state and register as an ephemeral node. If empty and --statedir is provided, the default is <statedir>/tailscaled.state. Default: "+paths.DefaultTailscaledStateFile())
|
||||
flag.BoolVar(&args.encryptState, "encrypt-state", defaultEncryptState(), "encrypt the state file on disk; uses TPM on Linux and Windows, on all other platforms this flag is not supported")
|
||||
flag.StringVar(&args.statedir, "statedir", "", "path to directory for storage of config state, TLS certs, temporary incoming Taildrop files, etc. If empty, it's derived from --state when possible.")
|
||||
flag.StringVar(&args.socketpath, "socket", paths.DefaultTailscaledSocket(), "path of the service unix socket")
|
||||
flag.StringVar(&args.birdSocketPath, "bird-socket", "", "path of the bird unix socket")
|
||||
@@ -268,6 +271,28 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if args.encryptState {
|
||||
if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
|
||||
log.SetFlags(0)
|
||||
log.Fatalf("--encrypt-state is not supported on %s", runtime.GOOS)
|
||||
}
|
||||
// Check if we have TPM support in this build.
|
||||
if !store.HasKnownProviderPrefix(store.TPMPrefix + "/") {
|
||||
log.SetFlags(0)
|
||||
log.Fatal("--encrypt-state is not supported in this build of tailscaled")
|
||||
}
|
||||
// Check if we have TPM access.
|
||||
if !hostinfo.New().TPM.Present() {
|
||||
log.SetFlags(0)
|
||||
log.Fatal("--encrypt-state is not supported on this device or a TPM is not accessible")
|
||||
}
|
||||
// Check for conflicting prefix in --state, like arn: or kube:.
|
||||
if args.statepath != "" && store.HasKnownProviderPrefix(args.statepath) {
|
||||
log.SetFlags(0)
|
||||
log.Fatal("--encrypt-state can only be used with --state set to a local file path")
|
||||
}
|
||||
}
|
||||
|
||||
if args.disableLogs {
|
||||
envknob.SetNoLogsNoSupport()
|
||||
}
|
||||
@@ -315,13 +340,17 @@ func trySynologyMigration(p string) error {
|
||||
}
|
||||
|
||||
func statePathOrDefault() string {
|
||||
var path string
|
||||
if args.statepath != "" {
|
||||
return args.statepath
|
||||
path = args.statepath
|
||||
}
|
||||
if args.statedir != "" {
|
||||
return filepath.Join(args.statedir, "tailscaled.state")
|
||||
if path == "" && args.statedir != "" {
|
||||
path = filepath.Join(args.statedir, "tailscaled.state")
|
||||
}
|
||||
return ""
|
||||
if path != "" && !store.HasKnownProviderPrefix(path) && args.encryptState {
|
||||
path = store.TPMPrefix + path
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// serverOptions is the configuration of the Tailscale node agent.
|
||||
@@ -974,3 +1003,15 @@ func applyIntegrationTestEnvKnob() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func defaultEncryptState() bool {
|
||||
if runtime.GOOS != "windows" && runtime.GOOS != "linux" {
|
||||
// TPM encryption is only configurable on Windows and Linux. Other
|
||||
// platforms either use system APIs and are not configurable
|
||||
// (Android/Apple), or don't support any form of encryption yet
|
||||
// (plan9/FreeBSD/etc).
|
||||
return false
|
||||
}
|
||||
v, _ := syspolicy.GetBoolean(syspolicy.EncryptState, false)
|
||||
return v
|
||||
}
|
||||
|
Reference in New Issue
Block a user