refactor(linux-client): replace client-tunnel with headless-client which is the same thing (#4516)

Unfortunately I had to keep `linux-client` to get the compatibility
tests to pass. #4578 aims to remove that package.

Please add to this list if you think of anything:

```[tasklist]
# Things that may break that CI/CD won't catch
- [ ] Github release artifacts
- [ ] Knowledge base 
- [ ] Docker images
- [ ] Docker containers
- [ ] Existing `linux-client` users
- [ ] Anything that downloads ghcr artifacts
- [ ] Nix (Not sure if it's built in CI. It had a merge conflict)
```

Refs #4515, and #3712, #3782

I think this is what Thomas and I agreed on in Slack / Github

---------

Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
Reactor Scram
2024-04-10 17:01:55 -05:00
committed by GitHub
parent fb68e90829
commit 3a67eacfbe
23 changed files with 117 additions and 105 deletions

View File

@@ -22,7 +22,7 @@ outputs:
value: ${{
(runner.os == 'Linux' && '--workspace') ||
(runner.os == 'macOS' && '-p connlib-client-apple -p connlib-client-shared -p firezone-tunnel -p snownet') ||
(runner.os == 'Windows' && '-p connlib-client-shared -p firezone-client-tunnel -p firezone-gui-client -p firezone-tunnel -p snownet') }}
(runner.os == 'Windows' && '-p connlib-client-shared -p firezone-headless-client -p firezone-gui-client -p firezone-tunnel -p snownet') }}
runs:
using: "composite"

View File

@@ -151,10 +151,10 @@ jobs:
sccache_enabled: false
targets: x86_64-unknown-linux-gnu
- run: |
cargo build --package firezone-linux-client
cargo build --package firezone-headless-client
# TODO Run tests
# ./target/debug/firezone-linux-client
# ./target/debug/firezone-headless-client
android:
needs: setup

View File

@@ -295,6 +295,7 @@ services:
cache_from:
- type=registry,ref=us-east1-docker.pkg.dev/firezone-staging/cache/client:main
args:
# TODO: Fix after #4516 lands
PACKAGE: firezone-linux-client
image: ${CLIENT_IMAGE:-us-east1-docker.pkg.dev/firezone-staging/firezone/dev/client}:${CLIENT_TAG:-main}
cap_add:

View File

@@ -97,7 +97,7 @@ product documentation, organized as follows:
and deployed to your infrastructure.
- [rust/relay](../rust/relay): Relay - STUN/TURN server to facilitate
holepunching.
- [rust/linux-client](../rust/linux-client): Linux CLI client.
- [rust/headless-client](../rust/headless-client): Cross-platform CLI client.
- [rust/gui-client](../rust/gui-client): Cross-platform GUI client.
- [swift/](../swift/apple): macOS / iOS clients.
- [kotlin/](../kotlin/android): Android / ChromeOS clients.

46
rust/Cargo.lock generated
View File

@@ -1848,27 +1848,6 @@ dependencies = [
"url",
]
[[package]]
name = "firezone-client-tunnel"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"connlib-client-shared",
"connlib-shared",
"dirs",
"firezone-cli-utils",
"humantime",
"nix 0.28.0",
"resolv-conf",
"secrecy",
"serde",
"serde_json",
"tokio",
"tracing",
"url",
]
[[package]]
name = "firezone-gateway"
version = "1.0.0"
@@ -1915,7 +1894,7 @@ dependencies = [
"connlib-shared",
"crash-handler",
"dirs",
"firezone-client-tunnel",
"firezone-headless-client",
"futures",
"git-version",
"hex",
@@ -1954,12 +1933,33 @@ dependencies = [
"zip",
]
[[package]]
name = "firezone-headless-client"
version = "1.0.0"
dependencies = [
"anyhow",
"clap",
"connlib-client-shared",
"connlib-shared",
"dirs",
"firezone-cli-utils",
"humantime",
"nix 0.28.0",
"resolv-conf",
"secrecy",
"serde",
"serde_json",
"tokio",
"tracing",
"url",
]
[[package]]
name = "firezone-linux-client"
version = "1.0.0"
dependencies = [
"anyhow",
"firezone-client-tunnel",
"firezone-headless-client",
"tokio",
]

View File

@@ -1,6 +1,5 @@
[workspace]
members = [
"client-tunnel",
"connlib/clients/android",
"connlib/clients/apple",
"connlib/clients/shared",
@@ -8,8 +7,9 @@ members = [
"connlib/tunnel",
"connlib/snownet",
"gateway",
"linux-client",
"firezone-cli-utils",
"headless-client",
"linux-client",
"snownet-tests",
"phoenix-channel",
"relay",
@@ -39,9 +39,8 @@ rtnetlink = { version = "0.14.1", default-features = false, features = ["tokio_s
connlib-client-android = { path = "connlib/clients/android"}
connlib-client-apple = { path = "connlib/clients/apple"}
connlib-client-shared = { path = "connlib/clients/shared"}
firezone-client-tunnel = { path = "client-tunnel" }
firezone-gateway = { path = "gateway"}
firezone-linux-client = { path = "linux-client"}
firezone-headless-client = { path = "headless-client"}
firezone-gui-client = { path = "gui-client/src-tauri"}
firezone-cli-utils = { path = "firezone-cli-utils"}
snownet = { path = "connlib/snownet"}

View File

@@ -1,10 +0,0 @@
# firezone-client-tunnel
A privileged tunnel process that can communicate with the Linux GUI Client (and eventually Windows)
## Files
- `/etc/dev.firezone.client/token` - The service account token, provided by the human administrator. Must be owned by root and have 600 permissions (r/w by owner, nobody else can read) If present, the tunnel will ignore any GUI Client and run as a headless Client. If absent, the tunnel will wait for commands from a GUI Client
- `/usr/bin/firezone-client-tunnel` - The tunnel binary. This must run as root so it can modify the system's DNS settings. If DNS is not needed, it only needs CAP_NET_ADMIN.
- `/usr/lib/systemd/system/firezone-client-tunnel.service` - A systemd service unit, installed by the deb package.
- `/var/lib/dev.firezone.client/config/firezone-id` - The device ID, unique across an organization. The tunnel will generate this if it's not present.

View File

@@ -4,7 +4,7 @@ services:
build:
target: test
volumes:
- ./rust/target/x86_64-unknown-linux-musl/debug/firezone-linux-client:/bin/firezone-linux-client
- ./rust/target/x86_64-unknown-linux-musl/debug/firezone-headless-client:/bin/firezone-headless-client
gateway:
build:

View File

@@ -1,3 +1,5 @@
(TODO: Change "client-tunnel" to "headless-client")
# Process split
This is meant for Linux, but it will be similar on Windows.

View File

@@ -20,7 +20,7 @@ clap = { version = "4.5", features = ["derive", "env"] }
connlib-client-shared = { workspace = true }
connlib-shared = { workspace = true }
crash-handler = "0.6.1"
firezone-client-tunnel = { path = "../../client-tunnel" }
firezone-headless-client = { path = "../../headless-client" }
git-version = "0.3.9"
hex = "0.4.3"
# Same crate Hickory uses

View File

@@ -1,4 +1,4 @@
#[tokio::main]
async fn main() -> anyhow::Result<()> {
firezone_client_tunnel::run().await
firezone_headless_client::run().await
}

View File

@@ -1,7 +1,9 @@
[package]
name = "firezone-client-tunnel"
version = "0.1.0"
name = "firezone-headless-client"
# mark:automatic-version
version = "1.0.0"
edition = "2021"
authors = ["Firezone, Inc."]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -0,0 +1,65 @@
# headless-client
This crate acts as the CLI / headless Client, and the privileged tunnel service for the GUI Client, for both Linux and Windows.
It is built as:
- `linux-client` to act as the Linux headless Client
- `firezone-headless-client` to act as the Linux tunnel service, Windows headless Client, or Windows tunnel service
In general, the brand name should be part of the file name, but the OS name should not be.
## Running
To run the headless Client:
1. Generate a new Service account token from the "Actors -> Service Accounts"
section of the admin portal and save it in your secrets manager. The Firezone
Linux client requires a service account at this time.
1. Ensure `/etc/dev.firezone.client/token` is only readable by root (i.e. `chmod 400`)
1. Ensure `/etc/dev.firezone.client/token` contains the Service account token. The Client needs this before it can start
1. Set `FIREZONE_ID` to a unique string to identify this client in the portal,
e.g. `export FIREZONE_ID=$(uuidgen)`. The client requires this variable at
startup.
1. Set `LOG_DIR` to a suitable directory for writing logs
```
export LOG_DIR=/tmp/firezone-logs
mkdir $LOG_DIR
```
1. Now, you can start the client with:
```
./firezone-headless-client
```
If you're running as an unprivileged user, you'll need the `CAP_NET_ADMIN`
capability to open `/dev/net/tun`. You can add this to the client binary with:
```
sudo setcap 'cap_net_admin+eip' /path/to/firezone-headless-client
```
## Building
Assuming you have Rust installed, you can build the headless Client with:
```
cargo build --release -p firezone-headless-client
```
The binary will be in `target/release/firezone-headless-client`
The release on Github are built with musl. To build this way, use:
```bash
rustup target add x86_64-unknown-linux-musl
sudo apt-get install musl-tools
cargo build --release -p headless-client --target x86_64-unknown-linux-musl
```
## Files
- `/etc/dev.firezone.client/token` - The service account token, provided by the human administrator. Must be owned by root and have 600 permissions (r/w by owner, nobody else can read) If present, the tunnel will ignore any GUI Client and run as a headless Client. If absent, the tunnel will wait for commands from a GUI Client
- `/usr/bin/firezone-headless-client` - The tunnel binary. This must run as root so it can modify the system's DNS settings. If DNS is not needed, it only needs CAP_NET_ADMIN.
- `/usr/lib/systemd/system/firezone-headless-client.service` - A systemd service unit, installed by the deb package.
- `/var/lib/dev.firezone.client/config/firezone-id` - The device ID, unique across an organization. The tunnel will generate this if it's not present.

View File

@@ -0,0 +1,4 @@
#[tokio::main]
async fn main() -> anyhow::Result<()> {
firezone_headless_client::run().await
}

View File

@@ -3,13 +3,14 @@ name = "firezone-linux-client"
# mark:automatic-version
version = "1.0.0"
edition = "2021"
authors = ["Firezone, Inc."]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = { version = "1.0" }
firezone-client-tunnel = { workspace = true }
tokio = { version = "1.36", default-features = false, features = ["rt", "macros"] }
firezone-headless-client = { path = "../headless-client" }
tokio = { version = "1.36.0", features = ["macros", "signal"] }
[lints]
workspace = true

View File

@@ -1,53 +1 @@
# linux-client
This crate houses the Firezone linux client.
## Building
Assuming you have Rust installed, you can build the Linux client from a Linux
host with:
```
cargo build --release --bin firezone-linux-client
```
You should then find a binary in `target/release/firezone-linux-client`.
The releases on Github are built with musl. To build this way, use:
```bash
rustup target add x86_64-unknown-linux-musl
sudo apt-get install musl-tools
cargo build --release --bin firezone-linux-client --target x86_64-unknown-linux-musl
```
## Running
To run the Linux client:
1. Generate a new Service account token from the "Actors -> Service Accounts"
section of the admin portal and save it in your secrets manager. The Firezone
Linux client requires a service account at this time.
1. Ensure the `FIREZONE_TOKEN=<service_account_token>` environment variable is
set securely in your client's shell environment. The client requires this
variable at startup.
1. Set `FIREZONE_ID` to a unique string to identify this client in the portal,
e.g. `export FIREZONE_ID=$(uuidgen)`. The client requires this variable at
startup.
1. Set `LOG_DIR` to a suitable directory for writing logs
```
export LOG_DIR=/tmp/firezone-logs
mkdir $LOG_DIR
```
1. Now, you can start the client with:
```
./firezone-linux-client
```
If you're running as an unprivileged user, you'll need the `CAP_NET_ADMIN`
capability to open `/dev/net/tun`. You can add this to the client binary with:
```
sudo setcap 'cap_net_admin+eip' /path/to/firezone-linux-client
```
This is a stub to fix a build issue in CI. Remove it once PR #4516 is merged into main.

View File

@@ -1,4 +1,4 @@
#[tokio::main]
async fn main() -> anyhow::Result<()> {
firezone_client_tunnel::run().await
firezone_headless_client::run().await
}

View File

@@ -63,9 +63,9 @@
};
in
{
packages.firezone-linux-client = naersk.buildPackage {
packages.firezone-headless-client = naersk.buildPackage {
name = "foo";
src = ../../rust/linux-client;
src = ../../rust/headless-client;
};
devShells.default = mkShellWithRustVersion [

View File

@@ -5,7 +5,7 @@ set -euo pipefail
BINARY_NAME=firezone-linux-client
docker compose exec client cat firezone-linux-client >"$BINARY_NAME"
docker compose exec client cat firezone-linux-client > "$BINARY_NAME"
chmod u+x "$BINARY_NAME"
sudo mv "$BINARY_NAME" "/usr/bin/$BINARY_NAME"
# TODO: Check whether this is redundant with the systemd service file