This fixes another long-standing bug with the Apple client: Keychain
groups.
Apple's Keychain docs are woefully unclear and lacking on the Keychain.
These are the main takeaways:
- Apple wants you to use the "[Data protection
keychain](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain)"
on macOS which allows it to behave like an iOS keychain. That opens up
the door for possible to sync to iCloud (which we don't use).
- Data protection keychain items, [it
appears](https://forums.developer.apple.com/forums/thread/710758),
cannot be created by Network Extensions.
- However, we _can_ save to the regular keychain (by default the system
keychain for root procs like us), which is file-based.
- Keychain items can be shared (both read/write) between apps, but **not
between users**. The tunnel process and gui process run as different
users. The only way for this to happen is to use the old file-based
Keychain and use [very
deprecated](https://developer.apple.com/documentation/technotes/tn3137-on-mac-keychains)
APIs to allow both "users" access, which is what we were doing before.
- To fix this, we limit all keychain operations to the tunnel proc only.
The GUI passes the auth token in during the `startTunnel` call, which
the system then passes to our `PacketTunnelProvider` class.
This uses the file-based Keychain, but since we need to use that
keychain as the root tunnel proc, we don't have much choice. The "Allow
access" dialog bug on macOS 12 is fixed by the fact that we are only
accessing it from the same user (tunnel proc) that created it now.
This was a race condition that was covered up by the long connecting
time of the old tunnel, and is now more prevalent because we connect
much more quickly.
The issue was that we respond to changes in the tunnel's status and
resource list separately, which can cause an issue where the view moved
to the `connected` state before the resource list is initialized. Since
those vars don't get updated after that, the view gets stuck in that
state.
This PR fixes that by combining those handlers into a single one that
responds to either so we'll end up at a view that's populated and
connected.
If it's not in CLI / env var
This is more convenient for development, and it's a step towards getting
the systemd service to work.
The token:
- Can't go in `/usr/lib/systemd/system/firezone-client.service` because
that file is updated by `dpkg`
- Probably shouldn't be in the CLI because CLI args can be seen by other
processes
- Could go in env vars, but those can also be snooped in theory
It has to be stored on disk somewhere for headless operation, so we can
just read it directly from disk.
Tried to organize this PR into commits so that it's a bit easier to
review.
1. Involves simplifying the logic in Adapter.swift so that us mortals
can maintain it confidently:
- The `.stoppingTunnel`, `.stoppedTunnelTemporarily`, and
`.stoppingTunnelTemporarily` states have been removed.
- I also removed the `self.` prefix from local vars when it's not
necessary to use it, to be more consistent.
- `onTunnelReady` and `getSystemDefaultResolvers` has been removed, and
`onUpdateRoutes` wired up, along with cleanup necessary to support that.
2. Involves adding the `reconnect` and `set_dns` stubs in the FFI and
fixing the log filter so that we can log them (see #4182 )
3. Involves getting the path update handler working well on macOS using
`SystemConfiguration` to read DNS servers.
4. Involves getting the path update handler working well on iOS by
employing careful trickery to prevent path update cycles by detecting if
`path.gateways` has changed, and avoid setting new DNS if it hasn't.
Refs #4028Fixes#4297Fixes#3565Fixes#3429Fixes#4175Fixes#4176Fixes#4309
---------
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
- [x] Updated log level string for client and gateways to info or higher
- [x] Update logs to hide DNS information
I also removed `hickory_resolve` errors which could contain sensitive
info from our general error and hide the logs that specifically relates
to them.
@bmanifold double checking that the log levels in the gateway's `*.tf`
files are just used for our own gateways.
Also, the relays still have `debug`, since only we see that I think that
makes sense but double checking with @jamilbk
Fixes: #3618.
---------
Signed-off-by: Gabi <gabrielalejandro7@gmail.com>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
On ice until after GA
```[tasklist]
# Before merging
- [x] Re-frame it as upgrading the Linux CLI to add IPC / systemd autostart support instead of replacing the CLI (thanks Thomas)
```
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.78
to 0.1.79.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/async-trait/releases">async-trait's
releases</a>.</em></p>
<blockquote>
<h2>0.1.79</h2>
<ul>
<li>Clean up some dead code</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1eb21ed8bd"><code>1eb21ed</code></a>
Release 0.1.79</li>
<li><a
href="82cb95c484"><code>82cb95c</code></a>
Resolve unused field of ReplaceSelf syntax tree visitor</li>
<li><a
href="cd8286bfac"><code>cd8286b</code></a>
Update ui test suite to nightly-2024-03-22</li>
<li>See full diff in <a
href="https://github.com/dtolnay/async-trait/compare/0.1.78...0.1.79">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>
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.27 to
0.12.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/seanmonstar/reqwest/releases">reqwest's
releases</a>.</em></p>
<blockquote>
<h2>v0.12.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix <code>ClientBuilder::interface()</code> when no TLS is
enabled.</li>
<li>Fix <code>TlsInfo::peer_certificate()</code> being truncated with
rustls.</li>
<li>Fix panic if <code>http2</code> feature disabled but TLS negotiated
h2 in ALPN.</li>
<li>Fix <code>Display</code> for <code>Error</code> to not include its
source error.</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/atouchet"><code>@atouchet</code></a>
made their first contribution in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2193">seanmonstar/reqwest#2193</a></li>
<li><a href="https://github.com/mbme"><code>@mbme</code></a> made their
first contribution in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2195">seanmonstar/reqwest#2195</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seanmonstar/reqwest/compare/v0.12.0...v0.12.1">https://github.com/seanmonstar/reqwest/compare/v0.12.0...v0.12.1</a></p>
<h2>v0.12.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Upgrade to <code>hyper</code>, <code>http</code>, and
<code>http-body</code> v1.</li>
<li>Add better support for converting to and from
<code>http::Request</code> and <code>http::Response</code>.</li>
<li>Add <code>http2</code> optional cargo feature, default on.</li>
<li>Add <code>charset</code> optional cargo feature, default on.</li>
<li>Add <code>macos-system-configuration</code> cargo feature, default
on.</li>
<li>Change all optional dependencies to no longer be exposed as implicit
features.</li>
<li>Add <code>ClientBuilder::interface(str)</code> to specify the local
interface to bind to.</li>
<li>Experimental: disables the <code>http3</code> feature
temporarily.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seanmonstar/reqwest/compare/v0.11.27...v0.12.0">https://github.com/seanmonstar/reqwest/compare/v0.11.27...v0.12.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md">reqwest's
changelog</a>.</em></p>
<blockquote>
<h2>v0.12.1</h2>
<ul>
<li>Fix <code>ClientBuilder::interface()</code> when no TLS is
enabled.</li>
<li>Fix <code>TlsInfo::peer_certificate()</code> being truncated with
rustls.</li>
<li>Fix panic if <code>http2</code> feature disabled but TLS negotiated
h2 in ALPN.</li>
<li>Fix <code>Display</code> for <code>Error</code> to not include its
source error.</li>
</ul>
<h1>v0.12.0</h1>
<ul>
<li>Upgrade to <code>hyper</code>, <code>http</code>, and
<code>http-body</code> v1.</li>
<li>Add better support for converting to and from
<code>http::Request</code> and <code>http::Response</code>.</li>
<li>Add <code>http2</code> optional cargo feature, default on.</li>
<li>Add <code>charset</code> optional cargo feature, default on.</li>
<li>Add <code>macos-system-configuration</code> cargo feature, default
on.</li>
<li>Change all optional dependencies to no longer be exposed as implicit
features.</li>
<li>Add <code>ClientBuilder::interface(str)</code> to specify the local
interface to bind to.</li>
<li>Experimental: disables the <code>http3</code> feature
temporarily.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e0ea15bd65"><code>e0ea15b</code></a>
v0.12.1</li>
<li><a
href="3d78fcbbb5"><code>3d78fcb</code></a>
fix: Display for Error shouldn't include source (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2199">#2199</a>)</li>
<li><a
href="c53572410d"><code>c535724</code></a>
Fix binding interface when no TLS is used (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2200">#2200</a>)</li>
<li><a
href="d5adcba6a2"><code>d5adcba</code></a>
fix: rustls extraction of <code>TlsInfo::peer_certificate()</code> being
truncated (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2195">#2195</a>)</li>
<li><a
href="7a5df21260"><code>7a5df21</code></a>
fix: could panic if http2 disabled but TLS negotiated h2 (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2194">#2194</a>)</li>
<li><a
href="d5051f9bee"><code>d5051f9</code></a>
Update version number in Readme</li>
<li><a
href="92aa28caab"><code>92aa28c</code></a>
v0.12.0</li>
<li><a
href="6c6170b1a7"><code>6c6170b</code></a>
feat: Make encoding_rs an optional dependency called
<code>charset</code></li>
<li><a
href="d1022b3b9f"><code>d1022b3</code></a>
Support conversion to http::Response</li>
<li><a
href="a29c7f9011"><code>a29c7f9</code></a>
Add macos-system-configuration feature flag</li>
<li>Additional commits viewable in <a
href="https://github.com/seanmonstar/reqwest/compare/v0.11.27...v0.12.1">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>
This adds an integration test that downloads a 10MB file from a server
and simulates the client roaming to another network while the download
is active.
We use a DNS resource for this to ensure it also doesn't take too long
in that case. DNS resources are what most users will be using and we
clear some internal DNS caches on connection failures. Hence, using a
DNS resource here is a somewhat roundabout way to test that we aren't
failing and re-establishing the connection but migrate it to a new
network path.
This PR fixes a bug and adds a missing feature to `phoenix-channel`.
1. Previously, we used to erroneously reset the heartbeat state on all
sorts of empty replies, not just the specific one from the heartbeat.
2. We only failed on missing heartbeats when it was time to send the
next one.
With this PR, we correct the first bug and add a dedicated timeout of 5s
for the heartbeat reply.
Kotlin's `spottlessApply` uses the EOL in this file, so it messes up all
line endings if running it from windows without this change.
I don't see a down-side on standardizing this to something fixed for all
platforms and since we're already using LF everywhere I think keeping it
seems like the best.
Our sockets need to be initialized within a tokio runtime context. To
achieve this, we don't actually initialize anything on `Sockets::new`.
Instead, we call `rebind` within the constructor of `Tunnel` which
already runs in a tokio context.
Fixes: #4282
---------
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
```[tasklist]
### Before merging
- [x] Manual test of MSI from CI
```
Bumps
[tauri-winrt-notification](https://github.com/tauri-apps/winrt-notification)
from 0.1.3 to 0.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tauri-apps/winrt-notification/releases">tauri-winrt-notification's
releases</a>.</em></p>
<blockquote>
<h2>tauri-winrt-notification v0.2.0</h2>
<p>Updating crates.io index</p>
<!-- raw HTML omitted -->
<pre><code>Fetching advisory database from
`https://github.com/RustSec/advisory-db.git`
Loaded 613 security advisories (from /home/runner/.cargo/advisory-db)
Updating crates.io index
Scanning Cargo.lock for vulnerabilities (15 crate dependencies)
</code></pre>
<!-- raw HTML omitted -->
<h2>[0.2.0]</h2>
<ul>
<li><a
href="1427bbfadc"><code>1427bbf</code></a>(<a
href="https://redirect.github.com/tauri-apps/winrt-notification/pull/18">#18</a>)
Update MSRV to <code>1.62</code></li>
<li><a
href="1427bbfadc"><code>1427bbf</code></a>(<a
href="https://redirect.github.com/tauri-apps/winrt-notification/pull/18">#18</a>)
Update <code>windows</code> crate to <code>0.54</code></li>
</ul>
<!-- raw HTML omitted -->
<pre><code>`\`\`
Updating crates.io index
Packaging tauri-winrt-notification v0.2.0
(/home/runner/work/winrt-notification/winrt-notification)
Updating crates.io index
Packaged 29 files, 82.9KiB (40.8KiB compressed)
Uploading tauri-winrt-notification v0.2.0
(/home/runner/work/winrt-notification/winrt-notification)
Uploaded tauri-winrt-notification v0.2.0 to registry `crates-io`
note: Waiting for `tauri-winrt-notification v0.2.0` to be available at
registry `crates-io`.
You may press ctrl-c to skip waiting; the crate should be available
shortly.
Published tauri-winrt-notification v0.2.0 at registry `crates-io`
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tauri-apps/winrt-notification/blob/dev/CHANGELOG.md">tauri-winrt-notification's
changelog</a>.</em></p>
<blockquote>
<h2>[0.2.0]</h2>
<ul>
<li><a
href="1427bbfadc"><code>1427bbf</code></a>(<a
href="https://redirect.github.com/tauri-apps/winrt-notification/pull/18">#18</a>)
Update MSRV to <code>1.62</code></li>
<li><a
href="1427bbfadc"><code>1427bbf</code></a>(<a
href="https://redirect.github.com/tauri-apps/winrt-notification/pull/18">#18</a>)
Update <code>windows</code> crate to <code>0.54</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e43754023c"><code>e437540</code></a>
Publish New Versions (<a
href="https://redirect.github.com/tauri-apps/winrt-notification/issues/19">#19</a>)</li>
<li><a
href="1427bbfadc"><code>1427bbf</code></a>
chore(deps): update <code>windows</code> crate to 0.54 (<a
href="https://redirect.github.com/tauri-apps/winrt-notification/issues/18">#18</a>)</li>
<li>See full diff in <a
href="https://github.com/tauri-apps/winrt-notification/compare/tauri-winrt-notification-v0.1.3...tauri-winrt-notification-v0.2">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>
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ReactorScram <ReactorScram@users.noreply.github.com>
```[tasklist]
- [x] Ensure whatever method we use to read the DNS servers actually works here, and doesn't have a strange memory ordering problem. If it does, read them from the registry by hand.
- [x] Graceful exit
- [x] Error handling
- [x] Clean it up and integrate it with the Tauri client
- [x] Replace `Notify` with channel of size one
- [x] Remove `Arc`
- [x] Replace `close` with panics
- [x] Remove `Pin`
- [x] Unit-test what happens if we register with RegNotify, close the handle, then modify our key
- [x] Merge with main and call `set_dns`
```
Previously, we would lose one message to the portal upon failing to send
it. We now mitigate this in two ways:
1. We also check the error from `poll_ready` and don't even pop a
message off from our buffer.
2. If sending still fails, we re-queue it to the front of the buffer.
In certain scenarios as discovered in logs from #4058, this might have
caused a loss of the "answer" message from a gateway to the client,
resulting in a state mismatch where the gateway thinks the connection is
established and the client times out on waiting for the answer.
This updates connlib to follow the new guidelines described in #4262. I
only made the bare-minimum changes to the clients. With these changes
`reconnect` should only be called when the network interface actually
changed, meaning clients have to be updated to reflect that.
Currently, a failure during DNS resolution results in the client hanging
during the connection setup. Instead, we fall back to an empty list
which results in an empty DNS query result for the client.
That in turn will make most application consider the DNS request failed.
As far as I know, we don't currently retry these DNS requests, meaning a
user would have to sign-in and out again to fix this state.
Whilst not ideal, I think this is a better behaviour and what we
currently have where the initial connection just hangs.
Currently, we need to wait for the timeout of the current candidate pair
during `reconnect` before we nominate a new one. To speed this up, we
can preemptively invalidate candidates we have previously discovered via
our `Allocation`s, i.e. relay candidates and srflx candidates.
This is done to fix a bug where the file descriptor is unregistered from
the reactor after the new `Tun` struct is created if the old one is
dropped after.
You know what I want, when I'm waiting 15-60 minutes on a CI job?
I want a stringly-typed language
I want the compiler to do
as
little
work
as
possible
If there even _is_ a compile step. Cause I love waiting and squinting at
underscores.
Running as sudo / root causes a lot of problems for GUI programs, so
we're unwinding that. In this case we can go back to using Tauri's "open
URL" function, which is great.
Closes#4103
Refs #3713
Affects #3972 - I was finally able to debug it because it came up
constantly during this PR
Refs #3713
```[tasklist]
### Before merging
- [ ] Is 'firezone-client-tunnel' okay for the binary name?
- [ ] Using a library and building it as two binaries is correct, right? `cargo run -p firezone-client-tunnel` takes 1 second. `cargo run -p firezone-gui-client --bin firezone-client-tunnel` takes 1m42s because it builds all the GUI deps.
```
Fixes#4042
The serial number of the device is blocked behind a permission. There's
a couple ways we can go about this:
-----
### (1) Ask the user to (optionally) grant the permission
When we show the grant VPN permission activity, we also mention the
optional READ_PRIVILEGED_PHONE_STATE permission. Here, the user can
decide to grant it or not, and if they decide not to, they can grant it
in the future in the app settings. When the permission is not granted,
the `deviceName` falls back to the `Build.MODEL`
### (2) Force the user to grant the permission
We keep asking them to grant the permission in the splash view.
`deviceName` is always the serial number of the device.
### (3) Let MDM grant the permission
We don't provide a UI to grant the permission in the application.
Instead, the `deviceName` is the `Build.MODEL` by default, unless
advanced users or admins using MDM set the permission, in which case
it's the serial number of the device.
### (4) Let MDM set a custom/override device name
This could be an alternative to (3) if it is easier for customers using
MDM software to manage it this way. Though I doubt it...
-----
Going with option (3) is safe, and the other options can be added
incrementally in the future. However, it requires communicating to the
customer that they should set this permission for the `deviceName` to be
the serial of the device. That's not a problem yet, since the relevant
customer is using MDM to manage the app; it's trivial to set this
permission via that UI.
If we did want to show this permission to the user, I think option (1)
is most likely going to be better than option (2) in most cases.
---------
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>