### Pre-upgrade TODO
- [ ] Update firezone.statuspage.io with planned maintenance status
### Performing the upgrade
- [ ] Upgrade in place using the GCP UI
- [ ] Run `ANALYZE;`
- [ ] Run `REINDEX DATABASE firezone;`
- [ ] When complete, deploy production via Terraform with new version
selected
### Post-upgrade TODO
- [ ] Test application connectivity
- [ ] Monitor Cloud SQL logs for any issues
- [ ] Unmark the planned maintenance window in firezone.statuspage.io
Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
The GUI client currently has a bug that resets the favourites and the
status of the Internet Resource every time the advanced settings are
saved. This happens because those fields are annotated with
`#[serde(default)]` and are thus initialised to their default value when
the struct is deserialised from the frontend.
To mitigate this, we introduce a new `GeneralSettings` struct that holds
the status of the Internet Resource and the list of favourites. When a
client starts up, it will try to migrate the existing advanced settings
into the new split of general and advanced settings.
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.
On macOS, we need to use `mobileconfig` files to configure the client.
These are cumbersome to generate by hand and so a number of popular
tools exist to aid in generating these.
One of the more popular options is [iMazing Profile
Editor](https://imazing.com/profile-editor), which maintains a
[repository](https://github.com/ProfileManifests/ProfileManifests) of
popular "Profile Manifests" for various enterprise-managed applications
on Apple.
In addition to opening the PR for the Firezone client in this repo,
we'll want to open one there too so we can be added to the in-app list
of support applications to generate `mobileconfig` files for.
A mass upgrade of our Rust dependencies. Most crucially, these remove
several duplicated dependencies from our tree.
- The Tauri plugins have been stuck on `windows v0.60` for a while. They
are now updated to use `windows v0.61` which is what the rest of our
dependency tree uses.
- By bumping `axum`, can also bump `reqwest` which reduces a few more
duplicated dependencies.
- By removing `env_logger`, we can get rid of a few dependencies.
The padding on this screen was broken, resulting in elements flush
against the edge of the display.
While I was in here, I decided to do a quick round of polish on the
layout and sizing of elements here.
<img width="395" alt="Screenshot 2025-05-21 at 4 24 08 PM"
src="https://github.com/user-attachments/assets/db4f53a3-1ee9-41ae-8172-8cca22be742b"
/>
Recently GitHub actions seems to have installed a buggy version of
compose that [fails with
`fatalError`](https://github.com/firezone/firezone/actions/runs/15181224905/job/42691214402?pr=9203)
on this line `docker compose up -d relay-1 relay-2 --no-build`.
Since those point to the same underlying image, I speculate that
separating these out will temporary alleviate this issue for us.
Why:
* We have seen issues with Google Admin SDK API returning bad
information when requesting directory info, such as Groups and
Identities. The requests seem to return successful HTTP codes, but the
data is missing, which our sync system interprets as all
Groups/Identities have been deleted from the Google Workspace. In order
to prevent this from happening a deletion circuit breaker function has
been added to stop a sync job if a certain percentage of the identities
will be deleted on the current run. This should prevent the possibility
of mass deleting Groups/Identities if an Identity Provider hands back
incorrect info on any sync.
Fixes: #9188
Ensuring that the "Settings" window always displays the latest state is
important. At the moment, we achieve this by fetching the settings from
Rust every time we know that they changed and when the window is opened.
Currently, the settings can only change as a result of the reset button.
Once we integrate MDM-controlled configuration into the GUI client, the
settings can change at any point when administrators push a new
configuration change. The window doesn't know that though.
To simplify the code and handle dynamic changes to the settings, we now
use an event to send the settings to the frontend.
For our telemetry sessions with Sentry, we need to know which
environment we are running in, i.e. staging, production or on-prem. The
GUI client's tunnel service doesn't have a concept of an environment
until a GUI connects and sends the `StartTelemetry` message. Therefore,
we should scope a telemetry session to a GUI being connected over IPC.
Any errors around setting up / tearing down the background service are a
catch-22. Until a GUI connects, we can't initialise the telemetry
connection but if we fail to set up the background service, no GUI can
ever connect. Hence, the current setup and tear down of the `Telemetry`
module around the `ipc_listen` calls can safely be removed as they are
effectively no-ops anyway.
Why:
* We have decided to change the way we will do audit logging. Instead of
soft deleting data and keeping it in the table it was created in, we
will be moving to an audit trail table where various actions will be
recorded in a table/DB specifically for auditing purposes. Due to this
change we need to make sure that we don't have stale/dangling
references. One set of references we keep everywhere is
`created_by_identity_id` and `created_by_actor_id`. Those foreign key
references won't be able to be used after moving to the new audit
system. This commit will allow us to keep that info by pulling the
values and storing the data in a created_by_subject field on the record.
Tauri's `deb` and `rpm` bundler have support for configuring maintainer
scripts. We can therefore just use those instead of tearing apart the
`deb` file that it creates and rebuilding it ourselves.
Our `rpm` packaging is currently completely broken as well. I couldn't
get it to work on CentOS 9 at all due to missing dependencies, likely
introduced by our move to Tauri v2. It installs fine on CentOS 10
though, assuming that the user has the EPEL repository installed which
provides the WebView dependency. I extended the docs to reflect this.
Hence, with this PR, we drop support for CentOS 9 and now require CentOS
10. This allows us to remove a lot of cruft from our bundling process
and instead entirely rely on the Tauri provided bundler.
Lastly, for consistency with other platforms, the name of the
application in places like app drawers has been changed from "Firezone
Client" to just "Firezone".
---------
Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
In #9072 this variable was removed in favor of populating it via an
Xcode build script. It appears however that the script does not take
effect properly when run from CLI and we need to populate this variable
again.
The current error handling logic in the Windows service is a bit dodgy.
We first initialise the logger but then pass the logging handle into the
`try_run_service` function. This means that any failures in starting the
Windows service aren't actually logged because the handle has been
dropped by then already.
Bumps the windows group in /rust with 1 update:
[windows-core](https://github.com/microsoft/windows-rs).
Updates `windows-core` from 0.61.0 to 0.61.1
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/microsoft/windows-rs/commits">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.19.1 to
3.20.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md">tempfile's
changelog</a>.</em></p>
<blockquote>
<h2>3.20.0</h2>
<p>This release mostly unifies the behavior/capabilities around
"keeping" temporary files:</p>
<ul>
<li>Rename <code>Builder::keep(bool)</code> (via deprecation) to
<code>Builder::disable_cleanup(bool)</code> to make it clear that
behaves differently from <code>NamedTempFile::keep()</code>. The former
disables automatic cleanup while the latter <em>consumes</em> the
<code>NamedTempFile</code> object entirely and unsets the
"temporary file" attribute (on Windows).</li>
<li>Rename <code>TempDir::into_path</code> (via deprecation) to
<code>TempDir::keep</code> to mirror
<code>NamedTempFile::keep</code>.</li>
<li>Add <code>TempDir::disable_cleanup</code>,
<code>NamedTempFile::disable_cleanup</code>, and
<code>TempPath::disable_cleanup</code> making it possible to disable
automatic cleanup in-place <em>after</em> creating a temporary
file/directory (equivalent to calling
<code>Builder::disable_cleanup</code> before creating the
file/directory).</li>
</ul>
<p>Additionally, it adds a few spooled temporary file features:</p>
<ul>
<li>Add <code>SpooledTempFile::into_file</code> for turning a
<code>SpooledTempFile</code> into a regular unnamed temporary file,
writing it to the backing storage ("rolling" it) if it was
still stored in-memory.</li>
<li>Add <code>spooled_tempfile_in</code> and
<code>SpooledTempFile::new_in</code> methods for creating spooled
temporary files in a specific directory. This makes it possible to
choose the backing device for your spooled temporary file which is
rather important on Linux where the default temporary directory is
likely backed by memory (defeating the entire point of having a spooled
temporary file).</li>
</ul>
<p>Finally, this release improves documentation, especially the
top-level documentation explaining which temporary file type to use.</p>
<p><strong>BREAKING</strong> for those with
<code>deny(warnings)</code>:</p>
<ul>
<li><code>Builder::keep</code> deprecated in favor of
<code>Builder::disable_cleanup</code>.</li>
<li><code>TempDir::into_path</code> is deprecated in favor of
<code>TempDir::keep</code>.</li>
</ul>
<p><strong>BREAKING</strong>:</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="99ffea61ad"><code>99ffea6</code></a>
chore: release v3.20.0 (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/358">#358</a>)</li>
<li><a
href="bd2b267442"><code>bd2b267</code></a>
feat: make it possible to disable cleanup in-place after creation (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/355">#355</a>)</li>
<li><a
href="3b30099abd"><code>3b30099</code></a>
ci: really check docs for warnings (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/357">#357</a>)</li>
<li><a
href="f701f52456"><code>f701f52</code></a>
ci: check docs (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/356">#356</a>)</li>
<li><a
href="d34afe99fd"><code>d34afe9</code></a>
doc: improve SpooledData documentation</li>
<li><a
href="6deb42e04c"><code>6deb42e</code></a>
doc: make it easier to pick the correct tempfile constructor/type</li>
<li><a
href="e284782c6c"><code>e284782</code></a>
feat: allow creating spooled temporary files in a specific directory (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/353">#353</a>)</li>
<li><a
href="07edc310a5"><code>07edc31</code></a>
feat: implement <code>SpooledTempFile::into_file</code> (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/352">#352</a>)</li>
<li><a
href="b1223553bb"><code>b122355</code></a>
fix: add must_use attribute to TempDir::keep (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/351">#351</a>)</li>
<li><a
href="cbd1e976e1"><code>cbd1e97</code></a>
feat: rename <code>TempDir::into_path</code> to
<code>TempDir::keep</code> (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/349">#349</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
The name IPC service is not very descriptive. By nature of being
separate processes, we need to use IPC to communicate between them. The
important thing is that the service process has control over the tunnel.
Therefore, we rename everything to "Tunnel service".
The only part that is not changed are historic changelog entries.
Resolves: #9048
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.
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>
We are currently consuming the WAL on production and it has shown very
little cost in terms of resource usage.
It would be better to get a more real-world test by sending actual
broadcasts with data.
To do this, we simply send a `Domain.PubSub.broadcast` with all of the
data received in the WAL message, which represents an absolute
worst-case scenario.
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
When deploying, new Elixir nodes are spun up before the old ones are
brought down. This ensures that the state in the cluster is merge into
the new nodes between the old ones go away.
This also means, however, that the existing WAL consumer is still up
when our new one tries to come online.
Normally, this isn't an issue, because we find the old pid and return it
with `{:ok, existing_pid}`. When that VM goes away, the Supervisor(s) of
the new application notice and restart it,
However, if the cluster state diverges or is inconsistent during this
period, we may fail to find the existing pid, and try to start a new
ReplicationConnection. If the old pid is still active, this will fail
because there's a mutex on the connection. The original implementation
was designed to handle this case using the Supervisor with a
`:transient` restart policy.
What the author failed to understand is that the restart policy applies
only to _restarts_ and not initial starts, so if all of the new
application servers fail to find the old pid which is still connected,
and they all fail to come up, we won't consume the WAL.
This is fixed with a `ReplicationConnectionManager` that always comes up
fine, and then simply tries to start a `ReplicationConnection` every
30s, giving up after 5 minutes if it can't start one or find an existing
one. This will crash, causing the Supervisor to restart us, and then
notify us.
Adds a new field to `settings/identity_providers` that allows an Admin
to designate any non-email/otp provider as the `default` for client
authentication. Clients will then navigate directly to the provider's
`/redirect` endpoint when authenticating, which in many cases will
automatically sign them in.
No existing providers are updated in this PR.
https://github.com/user-attachments/assets/7b962a25-76fd-491f-a194-60ed993821fc
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
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#9156Fixes#8476
---------
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Our bump-versions script did not consider that we also have the version
stored in the `.spec` file for rpm builds and hence this did not get
bumped in a while (or ever?).
Now that we have moved all files of the Tunnel service into the
`gui-client` crate, we can directly reference the `CARGO_PKG_VERSION`
env variable instead of having to hard-code the number in the
source-code.