Commit Graph

339 Commits

Author SHA1 Message Date
Jamil
a7054b8f40 ci: Bump apple to 1.4.15 (#9217) 2025-05-24 12:51:27 +00:00
Jamil
e84ba4545e feat(apple): Add supportURL as managed config item (#9202)
Adds `supportURL` as a managed configuration item so that admins may
point their workforce towards their own support Resources.
2025-05-22 16:48:35 +00:00
Jamil
6fd3493ed0 refactor(apple): Consolidate configuration to host app (#9196)
On Apple platforms, `UserDefaults` provides a convenient way to store
and fetch simple plist-compatible data for your app. Unbeknownst to the
author at the time of original implementation was the fact this these
keys are already designed for managed configurations to "mask" any
user-configured equivalents.

This means we no longer need to juggle two dicts in UserDefaults, and we
can instead check which keys are forced via a simple method call.

Additionally, the implementation was simplified in the following ways:

- The host app is the "source of truth" for app configuration now. The
tunnel service receives `setConfiguration` which applies the current
configuration, and saves it in order to start up again without the GUI
connected. The obvious caveat here is that if the GUI isn't running,
configuration such as `internetResourceEnabled` applied by the
administrator won't take effect. This is considered an edge case for the
time being since no customers have asked for this. Additionally, admins
can be advised to ensure the Firezone GUI is running on the system at
all times to prevent this.
- Settings and ConfigurationManager are now able to be removed - these
became redundant after consolidating configuration to the containing
app.
2025-05-22 16:18:00 +00:00
Jamil
745b57218b chore(apple): Remove useless IPC error log (#9201)
This error case happens during normal operation, particularly when
exiting the application and can be dropped.
2025-05-22 07:19:05 +00:00
Jamil
e14c4e1eb8 refactor(apple): Only apply MDM config when changed (#9173)
In #9169 we applied MDM configuration from MDM upon _any_ change to
UserDefaults. This is unnecessary.

Instead, we can compare new vs old and only apply the new dict if
there's changes.

In this PR we also log the old and new dicts for debugging reasons.
2025-05-16 23:21:08 +00:00
Jamil
73f334e345 feat(apple): Add start on login functionality (#9168)
Adds a new settings/configuration item `startOnLogin` which simply adds
a "Login Item" which starts Firezone after signing into the Mac.

This feature is macOS 13 and above only because otherwise we will need
to bundle a helper application to register as a service to start the
app. Given our very small footprint of macOS 12 users, and how
unsupported it is, this is ok.

When it comes time to implement MDM for this feature, note that Apple
provides a means to enforce login items via the
[`ServiceManagementLoginItems`
payload](https://developer.apple.com/documentation/devicemanagement/servicemanagementmanagedloginitems)
which is outside the scope of `com.apple.configuration.managed`. This
enforces the login item in System Settings so that the user is unable to
disable it.

We also add functionality here, but bear in mind that even if we disable
the Toggle switch in our Settings page, the user could still disable the
item in system settings unless it is being set through MDM via the
service management key above.

Another thing to note is that this setting is applied on the GUI side of
the tunnel only, because it is inherently tied to the process it is
running as. We are not able to (nor does it make sense to) enable the
login item for the tunnel service. This should be fine.

Tested to ensure enabling/disabling appropriately adds and removes the
login item (and re-adds it if I manually remove it from system
settings).


Related: #8916 
Related: #2306

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-05-16 22:15:49 +00:00
Jamil
f138d86494 feat(apple): Apply MDM changes to Configuration (#9169)
When the MDM installs a configuration payload to
`dev.firezone.firezone.network-extension`, the tunnel service will now
be notified of a change to its `managedDict`, applying the configuration
and updating `packetTunnelProvider`'s local copy so that it'll be
returned on the next configuration fetch from the UI.

Related: #4505
2025-05-16 22:00:16 +00:00
Jamil
9951e82727 feat(apple): Disable the update checker for MDM and App store (#9167)
For App Store installed macOS clients, it doesn't make sense to run an
update checker, because the system is managing the updates, and will
notify the user if there's an update available for Firezone (the user
has configured the system to manage app updates).

Related: #7664 
Related: #4505
2025-05-16 09:27:57 +00:00
Jamil
e599eb2f09 fix(apple): Ensure system extension loads after upgrade (#9166)
On macOS, after upgrading the client, the new system extension fails to
respond to IPC commands until it receives a `startTunnel` call. After
that, subsequent IPC calls will succeed across relaunches of the app.

To fix this, we introduce a dummy `startTunnel` call on macOS that
attempts to bring life into the System extension whenever we receive
`nil` configuration.

We also tidy up a few other things to make this easier to follow.


Fixes #9156 
Fixes #8476

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-16 07:17:12 +00:00
Jamil
7b4aa44f30 refactor(apple): Add Settings model (#9155)
The settings fields are getting tedious to manage individually, so a
helper class `Settings` is added which abstracts all of the view-related
logic applicable to user-defined settings.

When settings are saved, they are first applied to the `store`'s
existing Configuration, and then that configuration is saved via a new
consolidated IPC call `setConfiguration`.

`actorName` has been moved to a GUI-only cached store since it does not
need to live on `Configuration` any longer.

This greatly simplifies both the view logic and the IPC interface.

Notably, this does not handle the edge case where the configuration is
updated while the Settings window is open. That is saved for a later
time.
2025-05-15 23:25:00 +00:00
Jamil
7095974204 fix(apple): Handle tunnel starting before GUI after upgrade (#9141)
If the user tries to start the tunnel from system settings without
launching the GUI after upgrading to >= 1.4.15, the new configuration
will be empty, and we'll fail to set the accountSlug, preventing the
tunnel from starting.

To fix this, we add a simple convenience function that returns the
legacy configuration, and we use this configuration to start the tunnel
in case the GUI hasn't started.

Once the GUI starts, the legacy configuration is migrated and deleted,
so this is more of an edge case. Still, given the hundreds/thousands of
Apple device installations we have, someone is bound to hit it, and it
would be better to spend a few minutes saving potentially man-hours of
troubleshooting later.
2025-05-14 22:34:36 +00:00
Jamil
6fd5d96685 fix(apple): Isolate debug and release Keychain items (#9142)
On macOS, the token is saved in the system keychain so that the `root`
user is able to manage it. `secd`, the daemon that responds to Keychain
requests, is very strict about which binaries can access Keychain items
created by other binaries.

In development, the Firezone system extension runs from an unprivileged
directory, and isn't release-signed, which means it is not able to
manage the Keychain token for the release binary, and vice-versa.

To fix this, we isolate the Keychain items from each other with
different labels for `debug` and `release`, where the latter is
unchanged.

This is only an issue on debug, so a Changelog entry is not created.

Fixes #8917 
Fixes #8642
2025-05-14 22:34:11 +00:00
Jamil
204d1eb678 feat(apple): Allow user to configure connect on start (#9134)
Exposes a configuration toggle to connect on start, allowing it to be
overridden by MDM. Currently we assume this to be true.

Will need to refactor the settings soon to a dedicated
`ObservableObject` in the ViewModel to make these validations and field
checks less verbose.

related: #4505
2025-05-14 11:45:38 -07:00
Jamil
f19702f53e feat(apple): Allow user-configurable account slug (#9119)
Now that configuration is persisted in a more reasonable fashion, we can
expose a new `General` section to the Settings, allowing the user to
configure an account slug.

This field will automatically be populated upon the first sign in, so
that subsequent sign-ins will take the user directly to the account sign
in page.


Fixes #5119 
Related #8919

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-14 04:17:29 +00:00
Jamil
36e4a653f3 feat(apple/macOS): Add config to hide admin portal link (#9125)
Adds a `hideAdminPortalMenuItem` bool to our configuration to allow
admins to hide this from users.

Related: #4505
2025-05-14 04:00:50 +00:00
Jamil
5fae382375 feat(apple/macOS): Append account slug to admin portal URL link (#9126)
Appends the account slug to the admin portal URL when opened.

Related: #4505 
Related: #9119
2025-05-14 02:18:48 +00:00
Jamil
bee6479b96 refactor(apple): Use string for URL configuration (#9124)
In the UI, we need to use Strings to bind to the text inputs.
In the configuration dictionaries, we need to use Strings to save the
URLs.

It makes no sense to convert these to URLs in between. Instead, we can
validate upon save and then use them as Strings throughout.
2025-05-13 23:48:07 +00:00
Jamil
ccd6c265bb feat(apple): Allow MDM override of internet resource enabled (#9122)
All the MDM configuration to shadow the `internetResourceEnabled` state.

Related: #4505

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-05-13 23:41:42 +00:00
Jamil
2d3adff590 fix(apple): Actually enable/disable internet resource (#9123)
This fixes a bug recently introduced where the actual call to connlib to
enable/disable the internet resource was removed.
2025-05-13 23:17:01 +00:00
Jamil
ae224384be feat(apple): Disable advanced settings if overridden (#9108)
If `authURL`, `apiURL`, or `logFilter` are set in the managed
configuration, we disable each of these fields respectively from user
editing.

If all of them are overridden, we disable the `Apply` and `Reset to
Defaults` buttons.

Related #4505
2025-05-13 04:06:05 +00:00
Jamil
14892d0f27 fix(apple): Save settings before signing out (#9104)
This fixes a small bug where settings wouldn't be saved if signed in,
and also allows errors during saving to bubble up to the user.

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-13 02:37:09 +00:00
Jamil
7d738bc192 refactor(apple): Fix var/func scope in SettingsView (#9106)
These are incorrectly scoped. No functionality is changing.
2025-05-13 01:35:28 +00:00
Jamil
a849711525 refactor(apple): Prepare to support MDM-shadowed config (#9084)
One simple way we can tell the GUI app which configuration fields have
been overridden by MDM is to specify an `overriddenKeys` string array.
If provided, this will disable the relevant configuration from being set
/ editable in the GUI app and communicate to the user as such.

Related: #4505

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-13 00:12:17 +00:00
Jamil
4cc5963af2 fix(apple): Don't double-log errors in IPCClient (#9102)
See
https://github.com/firezone/firezone/pull/9056#discussion_r2083836491
2025-05-12 22:17:53 +00:00
Jamil
08dee37d09 feat(apple): Poll tunnel for new configuration every 1s (#9083)
Similar to how we fetch new resources, we add a Configuration poller
that fetches new configuration every 1s. If the configuration is
unchanged, we respond to the caller with a cached copy to avoid needing
to serialize the data over IPC.

Related: #4505
2025-05-12 14:27:47 +00:00
Jamil
1ceccc0da0 refactor(apple): Consolidate app configuration to UserDefaults (#9056)
We are currently storing app configuration across three places:

- UserDefaults (favorite resources)
- VPN configuration (Settings)
- Disk (firezone id)

These can be consolidated to UserDefaults, which is the standard way to
store app configuration like this.

UserDefaults is the umbrella persistence store for regular app
configuration (`plist` files which are just XML dictionaries),
iCloud-synced app configuration across a user's devices, and managed app
configuration (MDM). They provide a cached, thread-safe, and
interprocess-supported mechanism for handling app configuration. We can
also subscribe to changes on this app configuration to react to changes.

Unfortunately, the System Extension ruins some of our fun because it
runs as root, and is confined to a different group container, meaning we
cannot share configuration directly between GUI and tunnel procs.

To address this, we use the tunnel process to store all vital
configuration and introduce IPC calls to set and fetch these.

Commit-by-commit review recommended, but things got a little crazy
towards the end when I realized that we can't share a single
UserDefaults between both procs.
2025-05-12 05:27:49 +00:00
Thomas Eizinger
5566f1847f refactor(rust): move crates into a more sensical hierarchy (#9066)
The current `rust/` directory is a bit of a wild-west in terms of how
the crates are organised. Most of them are simply at the top-level when
in reality, they are all `connlib`-related. The Apple and Android FFI
crates - which are entrypoints in the Rust code are defined several
layers deep.

To improve the situation, we move around and rename several crates. The
end result is that all top-level crates / directories are:

- Either entrypoints into the Rust code, i.e. applications such as
Gateway, Relay or a Client
- Or crates shared across all those entrypoints, such as `telemetry` or
`logging`
2025-05-12 01:04:17 +00:00
Jamil
283879eeb0 docs: Remove note on disabling SIP (#9075)
When developing system extensions, Apple's
[documentation](https://developer.apple.com/documentation/DriverKit/debugging-and-testing-system-extensions)
instructs developers to disable SIP and turn on system extension
developer mode to disable certain runtime checks that allow the
extension to run.

It turns out this is completely unnecessary - any properly set up Xcode
toolchain can build a functioning macOS debug client.
2025-05-12 00:55:21 +00:00
Jamil
4e61ba9582 fix(apple): set new project version on each build (#9072)
When developing the macOS app, we always build the exact same version
and build code for each build. ~~This _may_ be one reason why we
constantly have to deactivate the extension before the new one will
launch.~~ Edit: Just tested, and I can verify that this does fix the
issue on dev builds, so no more having to uninstall the sysex between
builds.

Even if that's not the reason, this is a cleaner approach than building
it in our prod-only scripts.

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-05-12 00:55:14 +00:00
Jamil
091b52ef07 ci: Prevent having to manually update provisioning profile UUIDs (#9074)
When updating the provisioning profiles (i.e. when changing anything the
Apple Developer Portal), we needed to manually update these build
scripts to point to the new UUIDs.

This can be made simpler to automatically pull it out of the profiles in
CI.
2025-05-11 22:54:14 +00:00
Jamil
07fa91f713 chore(apple): Add file header template for xcode (#9068)
When creating new files in Xcode, it's helpful if the file header is
already formatted properly.
2025-05-10 12:26:37 +00:00
Jamil
3de8a1e405 fix(apple/iOS): Use pointer directly for libresolv API calls (#9038)
Somewhere between Xcode 16.0 and Xcode 16.3, the API for the libresolv
functions we call changed slightly, and we can now pass the return value
of `__res_9_state()` directly to the `res_9_ninit`, `res_9_ndestroy` and
`res_9_getservers` functions.
2025-05-06 03:32:35 +00:00
Jamil
6e0e7343ba chore: release Apple & Gateway with ECN fix (#9013) 2025-05-02 00:16:40 -07:00
Jamil
2650d81444 chore: release clients with GSO fix (#8936) 2025-04-29 23:52:43 -07:00
Thomas Eizinger
2ba7a87899 feat(connlib): add FFI for changing log-level on MacOS (#8927)
This isn't plugged into anything yet on the Swift side but lays the
foundation for changing the log-level at runtime without having to sign
the user out.
2025-04-29 13:51:46 +00:00
Jamil
5db8e20f3b chore: release Apple and GUI clients (#8882)
- Apple clients 1.4.12
- GUI clients 1.4.11
2025-04-21 21:45:16 +00:00
Jamil
5669c83835 ci: Bump Apple clients to 1.4.11 (#8848)
Includes a fix for auto-starting on launch when other VPN clients have
been connected previously.
2025-04-19 11:45:42 +00:00
Jamil
2f43bb9110 chore(apple): Disable Sentry debug mode on dev (#8816)
This just adds a bunch of log noise and is only helpful if we're trying
to debug the Sentry integration itself.
2025-04-18 18:07:53 +00:00
Jamil
22113f5940 chore(apple): Bump Swift dependencies (#8815)
Dependabot still fails to update these...
2025-04-18 18:07:42 +00:00
Jamil
4c1379a6bf fix(apple): Force enable VPN configuration on autoStart (#8814)
If another VPN has been activated on the system while Firezone is
active, Apple OSes will deactivate our configuration, and never
reactivate it.

We knew this already, and always activated the configuration when
starting during the sign in flow, but failed to also do this when
autoStarting on launch.

This PR updates ensures that during autoStart, we re-enable the
configuration as well.

Fixes #8813
2025-04-18 18:00:44 +00:00
Jamil
a2e32a4918 ci: Bump apple to 1.4.10 to ship PKG (#8797)
This publishes the 1.4.10 permalinks for the PKG download.
2025-04-17 15:13:44 +00:00
Jamil
54e60ca820 fix(ci): Use Developer ID Installer cert to sign pkg (#8796)
Apple requires standalone-distributed `PKG` installers to be signed with
a Developer ID Installer certificate.

Fixes
https://github.com/firezone/firezone/actions/runs/14497960810/job/40670440720#step:6:3500

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-04-16 18:29:59 +00:00
Jamil
aab691a67f ci: Release Apple clients 1.4.9 (#8793)
These contain the recent UDP thread enhancements.
2025-04-15 20:14:43 +00:00
Jamil
effe169414 chore: release apple 1.4.8 (#8499)
Introduces the autoconnect and session end fixes.
2025-03-21 11:43:00 +00:00
Thomas Eizinger
883c38cd3c fix(connlib): remove explicit Session::disconnect (#8474)
Within the event-loop, we already react to the channel being closed
which happens when the `Sender` within the `Session` gets dropped. As
such, there is no need to send an explicit `Stop` command, dropping the
`Session` is equivalent.

As it turns out, `swift-bridge` already calls `Drop` for us when the
last pointer is set to `nil`:
280a9dd999/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.swift (L24-L28)

Thus, we can also remove the explicit `disconnect` call to
`WrappedSession` entirely.
2025-03-18 04:35:57 +00:00
Jamil
a8b9e34c33 fix(apple): Try to connect on launch (#8477)
This is a regression introduced in c9f085c102. The `status` at this
point is still `nil` because we have not yet fully subscribed to VPN
status change updates from the system.

That actually shouldn't prevent us from trying to start the tunnel
anyway. If the `token` is missing from the Keychain, the tunnel process
will no-op. So we simply try to start a session on launch always.

Fixes #8456
2025-03-18 03:06:57 +00:00
Jamil
e642eefb35 chore: Cut all clients to ship search domains (#8442)
Waiting on app reviews to be approved, then this PR will be ready to
merge.
2025-03-17 17:25:11 +00:00
Jamil
da73441d6c fix(swift): Allow too many parameters in onSetInterfaceConfig (#8446)
We don't necessarily care if we slightly go over the function parameter
count lint in `onSetInterfaceConfig`.
2025-03-15 18:09:19 -05:00
Thomas Eizinger
58d241f705 feat(apple): pass-through search domain to VPN resolver config (#8421)
In order to have the system expand search domains for us, we need to set
a very peculiar combination of configuration options in the
`NEDNSSettings` of the VPN configuration:

- We need to include our search domains in the list of `matchDomains`
- We need to set `matchDomainsNoSearch = false`
- We need to set the `searchDomains` field

Technically, we don't even need to set `searchDomains` by itself.
Reading the docs in more detail for the `matchDomainsNoSearch` flag
explains why:

> A Boolean that specifies if the domains in the matchDomains list
should not be appended to the resolver’s list of search domains.

The double-negative here is confusing but essentially, what this says
is:

> If false, append the list of match domains to the resolver's search
domains.

That is exactly what we want. We want a search domain of e.g.
`example.com` to append to the list of search domains for the primary
resolver of non-scoped DNS queries.

I tested without setting `searchDomains` and it does still work: The
system will still expand the domain for us und send us a FQDN query of
e.g. `foo.example.com`. However, I figured not setting `searchDomains`
at all is quite confusing so I left it in there.

Related: #8410 (Fixes it for MacOS)

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: thomas <firezone@firezones-MacBook-Air.fritz.box>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2025-03-13 06:08:27 +00:00
Jamil
25c708fb43 ci: Bump apple clients to 1.4.6 (#8418) 2025-03-12 04:09:49 +00:00