Commit Graph

81 Commits (b7658a4ad2d13da515daee2bd8dd7d50a9067708)

Author SHA1 Message Date
Alex Chan b7658a4ad2 tstest/integration: add integration test for Tailnet Lock
This patch adds an integration test for Tailnet Lock, checking that a node can't
talk to peers in the tailnet until it becomes signed.

This patch also introduces a new package `tstest/tkatest`, which has some helpers
for constructing a mock control server that responds to TKA requests. This allows
us to reduce boilerplate in the IPN tests.

Updates tailscale/corp#33599

Signed-off-by: Alex Chan <alexc@tailscale.com>
1 week ago
Alex Chan 976bf24f5e ipn/ipnlocal: remove the always-true CanSupportNetworkLock()
Now that we support using an in-memory backend for TKA state (#17946),
this function always returns `nil` – we can always support Network Lock.
We don't need it any more.

Plus, clean up a couple of errant TODOs from that PR.

Updates tailscale/corp#33599

Change-Id: Ief93bb9adebb82b9ad1b3e406d1ae9d2fa234877
Signed-off-by: Alex Chan <alexc@tailscale.com>
2 weeks ago
Alex Chan e1dd9222d4 ipn/ipnlocal, tka: compact TKA state after every sync
Previously a TKA compaction would only run when a node starts, which means a long-running node could use unbounded storage as it accumulates ever-increasing amounts of TKA state. This patch changes TKA so it runs a compaction after every sync.

Updates https://github.com/tailscale/corp/issues/33537

Change-Id: I91df887ea0c5a5b00cb6caced85aeffa2a4b24ee
Signed-off-by: Alex Chan <alexc@tailscale.com>
2 weeks ago
Alex Chan 1723cb83ed ipn/ipnlocal: use an in-memory TKA store if FS is unavailable
This requires making the internals of LocalBackend a bit more generic,
and implementing the `tka.CompactableChonk` interface for `tka.Mem`.

Signed-off-by: Alex Chan <alexc@tailscale.com>

Updates https://github.com/tailscale/corp/issues/33599
2 weeks ago
Alex Chan d47c697748 ipn/ipnlocal: skip TKA bootstrap request if Tailnet Lock is unavailable
If you run tailscaled without passing a `--statedir`, Tailnet Lock is
unavailable -- we don't have a folder to store the AUMs in.

This causes a lot of unnecessary requests to bootstrap TKA, because
every time the node receives a NetMap with some TKA state, it tries to
bootstrap, fetches the bootstrap TKA state from the control plane, then
fails with the error:

    TKA sync error: bootstrap: network-lock is not supported in this
    configuration, try setting --statedir

We can't prevent the error, but we can skip the control plane request
that immediately gets dropped on the floor.

In local testing, a new node joining a tailnet caused *three* control
plane requests which were unused.

Updates tailscale/corp#19441

Signed-off-by: Alex Chan <alexc@tailscale.com>
1 month ago
Alex Chan 2b448f0696 ipn, tka: improve the logging around TKA sync and AUM errors
*   When we do the TKA sync, log whether TKA is enabled and whether
    we want it to be enabled. This would help us see if a node is
    making bootstrap errors.

*   When we fail to look up an AUM locally, log the ID of the AUM
    rather than a generic "file does not exist" error.

    These AUM IDs are cryptographic hashes of the TKA state, which
    itself just contains public keys and signatures. These IDs aren't
    sensitive and logging them is safe.

Signed-off-by: Alex Chan <alexc@tailscale.com>

Updates https://github.com/tailscale/corp/issues/33594
1 month ago
Brad Fitzpatrick 3a49b7464c all: add ts_omit_tailnetlock as a start of making it build-time modular
Updates #17115

Change-Id: I6b083c0db4c4d359e49eb129d626b7f128f0a9d2
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
3 months ago
Anton Tolchanov a91fcc8813 ipn/ipnlocal: make pricing restriction message for Tailnet Lock clearer
Fixes tailscale/corp#24417

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
6 months ago
Nick Khyl 8b72dd7873 ipn/ipnlocal: add localNodeContext with netmap-related fields and methods
Updates #12614

Signed-off-by: Nick Khyl <nickk@tailscale.com>
7 months ago
Nick Khyl 4e7f4086b2 ipn: generate LoginProfileView and use it instead of *LoginProfile where appropriate
Conventionally, we use views (e.g., ipn.PrefsView, tailcfg.NodeView, etc.) when
dealing with structs that shouldn't be mutated. However, ipn.LoginProfile has been
an exception so far, with a mix of passing and returning LoginProfile by reference
(allowing accidental mutations) and by value (which is wasteful, given its
current size of 192 bytes).

In this PR, we generate an ipn.LoginProfileView and use it instead of passing/returning
LoginProfiles by mutable reference or copying them when passing/returning by value.
Now, LoginProfiles can only be mutated by (*profileManager).setProfilePrefs.

Updates #14823

Signed-off-by: Nick Khyl <nickk@tailscale.com>
10 months ago
Brad Fitzpatrick 4e0fc037e6 all: use iterators over slice views more
This gets close to all of the remaining ones.

Updates #12912

Change-Id: I9c672bbed2654a6c5cab31e0cbece6c107d8c6fa
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
1 year ago
Anton Tolchanov fd6686d81a tka: truncate long rotation signature chains
When a rotation signature chain reaches a certain size, remove the
oldest rotation signature from the chain before wrapping it in a new
rotation signature.

Since all previous rotation signatures are signed by the same wrapping
pubkey (node's own tailnet lock key), the node can re-construct the
chain, re-signing previous rotation signatures. This will satisfy the
existing certificate validation logic.

Updates #13185

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
1 year ago
Nick Khyl 2f2aeaeaeb ipn/ipnlocal: fix a nil pointer dereference when serving /localapi/v0/tka/status
Fixes #13330

Signed-off-by: Nick Khyl <nickk@tailscale.com>
1 year ago
Anton Tolchanov 151b77f9d6 cmd/tl-longchain: tool to re-sign nodes with long rotation signatures
In Tailnet Lock, there is an implicit limit on the number of rotation
signatures that can be chained before the signature becomes too long.

This program helps tailnet admins to identify nodes that have signatures
with long chains and prints commands to re-sign those node keys with a
fresh direct signature. It's a temporary mitigation measure, and we will
remove this tool as we design and implement a long-term approach for
rotation signatures.

Example output:

```
2024/08/20 18:25:03 Self: does not need re-signing
2024/08/20 18:25:03 Visible peers with valid signatures:
2024/08/20 18:25:03 Peer xxx2.yy.ts.net. (100.77.192.34) nodeid=nyDmhiZiGA11KTM59, current signature kind=direct: does not need re-signing
2024/08/20 18:25:03 Peer xxx3.yy.ts.net. (100.84.248.22) nodeid=ndQ64mDnaB11KTM59, current signature kind=direct: does not need re-signing
2024/08/20 18:25:03 Peer xxx4.yy.ts.net. (100.85.253.53) nodeid=nmZfVygzkB21KTM59, current signature kind=rotation: chain length 4, printing command to re-sign
tailscale lock sign nodekey:530bddbfbe69e91fe15758a1d6ead5337aa6307e55ac92dafad3794f8b3fc661 tlpub:4bf07597336703395f2149dce88e7c50dd8694ab5bbde3d7c2a1c7b3e231a3c2
```

To support this, the NetworkLockStatus localapi response now includes
information about signatures of all peers rather than just the invalid
ones. This is not displayed by default in `tailscale lock status`, but
will be surfaced in `tailscale lock status --json`.

Updates #13185

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
1 year ago
Kristoffer Dalby 01aa01f310 ipn/ipnlocal: network-lock, error if no pubkey instead of panic
Updates tailscale/corp#20931

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
1 year ago
Brad Fitzpatrick 4c2e978f1e cmd/tailscale/cli: support passing network lock keys via files
Fixes tailscale/corp#22356

Change-Id: I959efae716a22bcf582c20d261fb1b57bacf6dd9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
1 year ago
Anton Tolchanov 781f79408d ipn/ipnlocal: allow multiple signature chains from the same SigCredential
Detection of duplicate Network Lock signature chains added in
01847e0123 failed to account for chains
originating with a SigCredential signature, which is used for wrapped
auth keys. This results in erroneous removal of signatures that
originate from the same re-usable auth key.

This change ensures that multiple nodes created by the same re-usable
auth key are not getting filtered out by the network lock.

Updates tailscale/corp#19764

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
1 year ago
Anton Tolchanov 01847e0123 ipn/ipnlocal: discard node keys that have been rotated out
A non-signing node can be allowed to re-sign its new node keys following
key renewal/rotation (e.g. via `tailscale up --force-reauth`). To be
able to do this, node's TLK is written into WrappingPubkey field of the
initial SigDirect signature, signed by a signing node.

The intended use of this field implies that, for each WrappingPubkey, we
typically expect to have at most one active node with a signature
tracing back to that key. Multiple valid signatures referring to the
same WrappingPubkey can occur if a client's state has been cloned, but
it's something we explicitly discourage and don't support:
https://tailscale.com/s/clone

This change propagates rotation details (wrapping public key, a list
of previous node keys that have been rotated out) to netmap processing,
and adds tracking of obsolete node keys that, when found, will get
filtered out.

Updates tailscale/corp#19764

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
2 years ago
Anton Tolchanov 32120932a5 cmd/tailscale/cli: print node signature in `tailscale lock status`
- Add current node signature to `ipnstate.NetworkLockStatus`;
- Print current node signature in a human-friendly format as part
  of `tailscale lock status`.

Examples:

```
$ tailscale lock status
Tailnet lock is ENABLED.

This node is accessible under tailnet lock. Node signature:
SigKind: direct
Pubkey: [OTB3a]
KeyID: tlpub:44a0e23cd53a4b8acc02f6732813d8f5ba8b35d02d48bf94c9f1724ebe31c943
WrappingPubkey: tlpub:44a0e23cd53a4b8acc02f6732813d8f5ba8b35d02d48bf94c9f1724ebe31c943

This node's tailnet-lock key: tlpub:44a0e23cd53a4b8acc02f6732813d8f5ba8b35d02d48bf94c9f1724ebe31c943

Trusted signing keys:
	tlpub:44a0e23cd53a4b8acc02f6732813d8f5ba8b35d02d48bf94c9f1724ebe31c943	1	(self)
	tlpub:6fa21d242a202b290de85926ba3893a6861888679a73bc3a43f49539d67c9764	1	(pre-auth key kq3NzejWoS11KTM59)
```

For a node created via a signed auth key:

```
This node is accessible under tailnet lock. Node signature:
SigKind: rotation
Pubkey: [e3nAO]
Nested:
  SigKind: credential
  KeyID: tlpub:6fa21d242a202b290de85926ba3893a6861888679a73bc3a43f49539d67c9764
  WrappingPubkey: tlpub:3623b0412cab0029cb1918806435709b5947ae03554050f20caf66629f21220a
```

For a node that rotated its key a few times:

```
This node is accessible under tailnet lock. Node signature:
SigKind: rotation
Pubkey: [DOzL4]
Nested:
  SigKind: rotation
  Pubkey: [S/9yU]
  Nested:
    SigKind: rotation
    Pubkey: [9E9v4]
    Nested:
      SigKind: direct
      Pubkey: [3QHTJ]
      KeyID: tlpub:44a0e23cd53a4b8acc02f6732813d8f5ba8b35d02d48bf94c9f1724ebe31c943
      WrappingPubkey: tlpub:2faa280025d3aba0884615f710d8c50590b052c01a004c2b4c2c9434702ae9d0
```

Updates tailscale/corp#19764

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
2 years ago
Brad Fitzpatrick 6d69fc137f ipn/{ipnlocal,localapi},wgengine{,/magicsock}: plumb health.Tracker
Down to 25 health.Global users. After this remains controlclient &
net/dns & wgengine/router.

Updates #11874
Updates #4136

Change-Id: I6dd1856e3d9bf523bdd44b60fb3b8f7501d5dc0d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Brad Fitzpatrick ebc552d2e0 health: add Tracker type, in prep for removing global variables
This moves most of the health package global variables to a new
`health.Tracker` type.

But then rather than plumbing the Tracker in tsd.System everywhere,
this only goes halfway and makes one new global Tracker
(`health.Global`) that all the existing callers now use.

A future change will eliminate that global.

Updates #11874
Updates #4136

Change-Id: I6ee27e0b2e35f68cb38fecdb3b2dc4c3f2e09d68
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Brad Fitzpatrick 7c1d6e35a5 all: use Go 1.22 range-over-int
Updates #11058

Change-Id: I35e7ef9b90e83cac04ca93fd964ad00ed5b48430
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Brad Fitzpatrick e1bd7488d0 all: remove LenIter, use Go 1.22 range-over-int instead
Updates #11058
Updates golang/go#65685

Change-Id: Ibb216b346e511d486271ab3d84e4546c521e4e22
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Marwan Sulaiman 2dc0645368 ipn/ipnlocal,cmd/tailscale: persist tailnet name in user profile
This PR starts to persist the NetMap tailnet name in SetPrefs so that tailscaled
clients can use this value to disambiguate fast user switching from one tailnet
to another that are under the same exact login. We will also try to backfill
this information during backend starts and profile switches so that users don't
have to re-authenticate their profile. The first client to use this new
information is the CLI in 'tailscale switch -list' which now uses text/tabwriter
to display the ID, Tailnet, and Account. Since account names are ambiguous, we
allow the user to pass 'tailscale switch ID' to specify the exact tailnet they
want to switch to.

Updates #9286

Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
2 years ago
Sonia Appasamy 258f16f84b ipn/ipnlocal: add tailnet MagicDNS name to ipn.LoginProfile
Start backfilling MagicDNS suffixes on LoginProfiles.

Updates #9286

Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
2 years ago
Brad Fitzpatrick 84b94b3146 types/netmap, all: make NetworkMap.SelfNode a tailcfg.NodeView
Updates #1909

Change-Id: I8c470cbc147129a652c1d58eac9b790691b87606
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Maisem Ali 2548496cef types/views,cmd/viewer: add ByteSlice[T] to replace mem.RO
Add a new views.ByteSlice[T ~[]byte] to provide a better API to use
with views.

Updates #cleanup

Signed-off-by: Maisem Ali <maisem@tailscale.com>
2 years ago
Brad Fitzpatrick d8191a9813 ipn/ipnlocal: fix regression in printf arg type
I screwed this up in 58a4fd43d as I expected. I even looked out for
cases like this (because this always happens) and I still missed
it. Vet doesn't flag these because they're not the standard printf
funcs it knows about. TODO: make our vet recognize all our
"logger.Logf" types.

Updates #8948

Change-Id: Iae267d5f81da49d0876b91c0e6dc451bf7dcd721
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Brad Fitzpatrick 58a4fd43d8 types/netmap, all: use read-only tailcfg.NodeView in NetworkMap
Updates #8948

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Tom DNetto 767e839db5 all: implement lock revoke-keys command
The revoke-keys command allows nodes with tailnet lock keys
to collaborate to erase the use of a compromised key, and remove trust
in it.

Signed-off-by: Tom DNetto <tom@tailscale.com>
Updates ENG-1848
2 years ago
Tom DNetto abcb7ec1ce cmd/tailscale: warn if node is locked out on bringup
Updates https://github.com/tailscale/corp/issues/12718
Signed-off-by: Tom DNetto <tom@tailscale.com>
2 years ago
Tom DNetto 2bbedd2001 ipn: rename CapTailnetLockAlpha -> CapTailnetLock
Updates tailscale/corp#8568
Signed-off-by: Tom DNetto <tom@tailscale.com>
2 years ago
Brad Fitzpatrick e48c0bf0e7 ipn/ipnlocal: quiet some spammy network lock logging
Updates #cleanup

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2 years ago
Andrea Gottardo 99f17a7135
tka: provide verify-deeplink local API endpoint (#8303)
* tka: provide verify-deeplink local API endpoint

Fixes https://github.com/tailscale/tailscale/issues/8302

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>

Address code review comments

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>

Address code review comments by Ross

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>

* Improve error encoding, fix logic error

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>

---------

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>
3 years ago
Andrea Gottardo 66f97f4bea
tka: provide authority StateID in NetworkLockStatus response (#8200)
Fixes #8201.

Signed-off-by: Andrea Gottardo <andrea@tailscale.com>
Co-authored-by: Andrea Gottardo <andrea@tailscale.com>
3 years ago
Tom DNetto 3471fbf8dc cmd/tailscale: surface node-key for locked out tailnet-lock peers
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto ce99474317 all: implement preauth-key support with tailnet lock
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 88c7d19d54 tka: compact TKA storage on startup
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto e2d652ec4d ipn,cmd/tailscale: implement resigning nodes on tka key removal
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Will Norris 71029cea2d all: update copyright and license headers
This updates all source files to use a new standard header for copyright
and license declaration.  Notably, copyright no longer includes a date,
and we now use the standard SPDX-License-Identifier header.

This commit was done almost entirely mechanically with perl, and then
some minimal manual fixes.

Updates #6865

Signed-off-by: Will Norris <will@tailscale.com>
3 years ago
Tom DNetto 0088c5ddc0 health,ipn/ipnlocal: report the node being locked out as a health issue
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 907f85cd67 cmd/tailscale,tka: make KeyID return an error instead of panicking
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 55e0512a05 ipn/ipnlocal,cmd/tailscale: minor improvements to lock modify command
* Do not print the status at the end of a successful operation
 * Ensure the key of the current node is actually trusted to make these changes

Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 9c773af04c ipn/ipnlocal: fix use of stale profile while processing netmap
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 74c1f632f6 types/key,cmd/tailscale/cli: support tlpub prefix for tailnet-lock keys
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto f1ab11e961 ipn/ipnlocal,tailcfg: introduce capability to gate TKA init paths
Previously, `TAILSCALE_USE_WIP_CODE` was needed to hit a bunch of the TKA paths. With
this change:

 - Enablement codepaths (NetworkLockInit) and initialization codepaths (tkaBootstrapFromGenesisLocked via tkaSyncIfNeeded)
   require either the WIP envknob or CapabilityTailnetLockAlpha.
 - Normal operation codepaths (tkaSyncIfNeeded, tkaFilterNetmapLocked) require TKA to be initialized, or either-or the
   envknob / capability.
 - Auxillary commands (ie: changing tka keys) require TKA to be initialized.

The end result is that it shouldn't be possible to initialize TKA (or subsequently use any of its features) without being
sent the capability or setting the envknob on tailscaled yourself.

I've also pulled out a bunch of unnecessary checks for CanSupportNetworkLock().

Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 9a80b8fb10 cmd/tailscale,ipn: surface TKA-filtered peers in lock status command
Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto 45042a76cd cmd/tailscale,ipn: store disallowed TKA's in prefs, lock local-disable
Take 2 of https://github.com/tailscale/tailscale/pull/6546

Builds on https://github.com/tailscale/tailscale/pull/6560

Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Tom DNetto c4980f33f7 ipn,types/persist: add DisallowedTKAStateIDs, refactor as view type
Supercedes https://github.com/tailscale/tailscale/pull/6557, precursor to trying https://github.com/tailscale/tailscale/pull/6546 again

Signed-off-by: Tom DNetto <tom@tailscale.com>
3 years ago
Brad Fitzpatrick 390d1bb871 Revert "ipn,types/persist: store disallowed TKA's in prefs, lock local-disable"
This reverts commit f1130421f0.

It was submitted with failing tests (go generate checks)

Requires a lot of API changes to fix so rolling back instead of
forward.

Change-Id: I024e8885c0ed44675d3028a662f386dda811f2ad
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
3 years ago