We update profileManager to allow registering a single state (profile+prefs) change hook.
This is to invert the dependency between the profileManager and the LocalBackend, so that
instead of LocalBackend asking profileManager for the state, we can have profileManager
call LocalBackend when the state changes.
We also update feature.Hook with a new (*feature.Hook).GetOk method to avoid calling both
IsSet and Get.
Updates tailscale/corp#28014
Updates #12614
Signed-off-by: Nick Khyl <nickk@tailscale.com>
This further minimizes the number of places where the profile manager updates the current profile and prefs.
We also document a scenario where an implicit profile switch can occur.
We should be able to address it after (partially?) inverting the dependency between
LocalBackend and profileManager, so that profileManager notifies LocalBackend
of profile changes instead of the other way around.
Updates tailscale/corp#28014
Updates #12614
Signed-off-by: Nick Khyl <nickk@tailscale.com>
The previous strategy assumed clients maintained adequate state to
understand the relationship between endpoint allocation and the server
it was allocated on.
magicsock will not have awareness of the server's disco key
pre-allocation, it only understands peerAPI address at this point. The
second client to allocate on the same server could trigger
re-allocation, breaking a functional relay server endpoint.
If magicsock needs to force reallocation we can add opt-in behaviors
for this later.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
We had an ordered set type (set.Slice) already but we occasionally want
to do the same thing with a map, preserving the order things were added,
so add that too, as mapsx.OrderedMap[K, V], and then use in ipnext.
Updates #12614
Change-Id: I85e6f5e11035571a28316441075e952aef9a0863
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Now that 25c4dc5fd70 removed unregistering hooks and made them into
slices, just expose the slices and remove the setter funcs.
This removes boilerplate ceremony around adding new hooks.
This does export the hooks and make them mutable at runtime in theory,
but that'd be a data race. If we really wanted to lock it down in the
future we could make the feature.Hooks slice type be an opaque struct
with an All() iterator and a "frozen" bool and we could freeze all the
hooks after init. But that doesn't seem worth it.
This means that hook registration is also now all in one place, rather
than being mixed into ProfilesService vs ipnext.Host vs FooService vs
BarService. I view that as a feature. When we have a ton of hooks and
the list is long, then we can rearrange the fields in the Hooks struct
as needed, or make sub-structs, or big comments.
Updates #12614
Change-Id: I05ce5baa45a61e79c04591c2043c05f3288d8587
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The typical way to implement union types in Go
is to use an interface where the set of types is limited.
However, there historically has been poor support
in v1 "encoding/json" with interface types where
you can marshal such values, but fail to unmarshal them
since type information about the concrete type is lost.
The MakeInterfaceCoders function constructs custom
marshal/unmarshal functions such that the type name
is encoded in the JSON representation.
The set of valid concrete types for an interface
must be statically specified for this to function.
Updates tailscale/corp#22024
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
These were likely added after everything else was updated to use tsd.NewSystem,
in a feature branch, and before it was merged back into main.
Updates #15160
Signed-off-by: Nick Khyl <nickk@tailscale.com>
Both are populated from the current netmap's MagicDNSSuffix.
But building a full ipnstate.Status (with peers!) is expensive and unnecessary.
Updates #cleanup
Signed-off-by: Nick Khyl <nickk@tailscale.com>
Replace all instances of interface{} with any to resolve the
golangci-lint errors that appeared in the previous tsidp PR.
Updates #cleanup
Signed-off-by: Patrick O'Doherty <patrick@tailscale.com>
tstime.GoDuration JSON serializes with time.Duration.String(), which is
more human-friendly than nanoseconds.
ServerEndpoint is currently experimental, therefore breaking changes
are tolerable.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
The encoding/json/v2 effort may end up changing
the default represention of time.Duration in JSON.
See https://go.dev/issue/71631
The GoDuration type allows us to explicitly use
the time.Duration.String representation regardless of
whether we serialize with v1 or v2 of encoding/json.
Updates tailscale/corp#27502
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
We added this helper in 1e2e319e7d26. Remove this copy.
Updates #cleanup
Change-Id: I5b0681acc23692beed35951c9902ac9ceca0a8b9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The relay server is still permanently disabled until node attribute
changes are wired up in a future commit.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
QNAP now requires builds to be signed with an HSM.
This removes support for signing with a local keypair.
This adds support for signing with a Google Cloud hosted key.
The key should be an RSA key with protection level `HSM` and that uses PSS padding and a SHA256 digest.
The GCloud project, keyring and key name are passed in as command-line arguments.
The GCloud credentials and the PEM signing certificate are passed in as Base64-encoded command-line arguments.
Updates tailscale/corp#23528
Signed-off-by: Percy Wegmann <percy@tailscale.com>
This adds a feature/taildrop package, a ts_omit_taildrop build tag,
and starts moving code to feature/taildrop. In some cases, code
remains where it was but is now behind a build tag. Future changes
will move code to an extension and out of LocalBackend, etc.
Updates #12614
Change-Id: Idf96c61144d1a5f707039ceb2ff59c99f5c1642f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
When an event bus is plumbed in, use it to subscribe and react to port mapping
updates instead of using the client's callback mechanism. For now, the callback
remains available as a fallback when an event bus is not provided.
Updates #15160
Change-Id: I026adca44bf6187692ee87ae8ec02641c12f7774
Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
When an event bus is configured publish an event each time a new port mapping
is updated. Publication is unconditional and occurs prior to calling any
callback that is registered. For now, the callback is still fired in a separate
goroutine as before -- later, those callbacks should become subscriptions to
the published event.
For now, the event type is defined as a new type here in the package. We will
want to move it to a more central package when there are subscribers. The event
wrapper is effectively a subset of the data exported by the internal mapping
interface, but on a concrete struct so the bus plumbing can inspect it.
Updates #15160
Change-Id: I951f212429ac791223af8d75b6eb39a0d2a0053a
Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
In preparation for adding more parameters (and later, moving some away), rework
the portmapper constructor to accept its arguments on a Config struct rather
than positionally.
This is a breaking change to the function signature, but one that is very easy
to update, and a search of GitHub reveals only six instances of usage outside
clones and forks of Tailscale itself, that are not direct copies of the code
fixed up here.
While we could stub in another constructor, I think it is safe to let those
folks do the update in-place, since their usage is already affected by other
changes we can't test for anyway.
Updates #15160
Change-Id: I9f8a5e12b38885074c98894b7376039261b43f43
Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
Although, at the moment, we do not yet require an event bus to be present, as
we start to add more pieces we will want to ensure it is always available. Add
a new constructor and replace existing uses of new(tsd.System) throughout.
Update generated files for import changes.
Updates #15160
Change-Id: Ie5460985571ade87b8eac8b416948c7f49f0f64b
Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
This feature is "registered" as an ipnlocal.Extension, and
conditionally linked depending on GOOS and ts_omit_relayserver build
tag.
The feature is not linked on iOS in attempt to limit the impact to
binary size and resulting effect of pushing up against NetworkExtension
limits. Eventually we will want to support the relay server on iOS,
specifically on the Apple TV. Apple TVs are well-fitted to act as
underlay relay servers as they are effectively always-on servers.
This skeleton begins to tie a PeerAPI endpoint to a net/udprelay.Server.
The PeerAPI endpoint is currently no-op as
extension.shouldRunRelayServer() always returns false. Follow-up commits
will implement extension.shouldRunRelayServer().
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Bump to latest 22.x LTS release for node as the 18.x line is going EOL this month.
Updates https://github.com/tailscale/corp/issues/27737
Signed-off-by: Mario Minardi <mario@tailscale.com>
https://github.com/tailscale/tailscale/pull/15395 changed the logic to
skip `EditPrefs` when the platform doesn't support auto-updates. But the
old logic would only fail `EditPrefs` if the auto-update value was
`true`. If it was `false`, `EditPrefs` would succeed and store `false`
in prefs. The new logic will keep the value `unset` even if the tailnet
default is `false`.
Fixes#15691
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
In this PR, we enable extensions to track changes in the current prefs. These changes can result from a profile switch
or from the user or system modifying the current profile’s prefs. Since some extensions may want to distinguish between
the two events, while others may treat them similarly, we rename the existing profile-change callback to become
a profile-state-change callback and invoke it whenever the current profile or its preferences change. Extensions can still
use the sameNode parameter to distinguish between situations where the profile information, including its preferences,
has been updated but still represents the same tailnet node, and situations where a switch to a different profile has been made.
Having dedicated prefs-change callbacks is being considered, but currently seems redundant. A single profile-state-change callback
is easier to maintain. We’ll revisit the idea of adding a separate callback as we progress on extracting existing features from LocalBackend,
but the conversion to a profile-state-change callback is intended to be permanent.
Finally, we let extensions retrieve the current prefs or profile state (profile info + prefs) at any time using the new
CurrentProfileState and CurrentPrefs methods. We also simplify the NewControlClientCallback signature to exclude
profile prefs. It’s optional, and extensions can retrieve the current prefs themselves if needed.
Updates #12614
Updates tailscale/corp#27645
Updates tailscale/corp#26435
Updates tailscale/corp#27502
Signed-off-by: Nick Khyl <nickk@tailscale.com>
This change introduces an Age column in the output for all custom
resources to enhance visibility into their lifecycle status.
Fixes#15499
Signed-off-by: satyampsoni <satyampsoni@gmail.com>
[G,S]etWindowLongPtrW are not available on 32-bit Windows, where [G,S]etWindowLongW should be used instead.
The initial revision of #14945 imported the win package for calling and other Win32 API functions, which exported
the correct API depending on the platform. However, the same logic wasn't implemented when we removed
the win package dependency in a later revision, resulting in panics on Windows 10 x86 (there's no 32-bit Windows 11).
In this PR, we update the ipn/desktop package to use either [G,S]etWindowLongPtrW or [G,S]etWindowLongW
depending on the platform.
Fixes#15684
Signed-off-by: Nick Khyl <nickk@tailscale.com>
Query for the const quad-100 reverse DNS name, for which a forward
record will also be served. This test was previously dependent on
search domain behavior, and now it is not.
Updates #15607
Signed-off-by: Jordan Whited <jordan@tailscale.com>