Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
76a08af
fix(controller): time out fleet API TLS handshakes
ilackarms Nov 9, 2026
3e30920
fix(controller): time out fleet API requests
ilackarms Nov 9, 2026
16833ad
fix(controller): close fleet connections whose peer stopped answering
ilackarms Nov 9, 2026
d67560c
fix(controller): limit requests and streams per fleet connection
ilackarms Nov 9, 2026
f5228c2
fix(controller): cap fleet message sizes, with a small cap for enroll…
ilackarms Nov 9, 2026
99fedcb
fix(controller): limit enrollment requests per client and in total
ilackarms Nov 9, 2026
72de9e2
fix(controller): cap fleet connections in total and per client address
ilackarms Nov 9, 2026
b93f68c
fix(controller): one Connect stream per device, with a message rate l…
ilackarms Nov 9, 2026
cc2f8d7
fix(helm): keep device addresses visible to the controller
ilackarms Nov 9, 2026
5e0cbd8
fix(controller): close idle fleet connections, and evict idle ones at…
ilackarms Nov 9, 2026
41b9a93
fix(controller): apply the small message cap to callers without a dev…
ilackarms Nov 9, 2026
381faef
fix(controller): end the Connect response when the device's side ends
ilackarms Nov 9, 2026
d38e52d
fix(controller): keep Connect budgets per device and limit how often …
ilackarms Nov 9, 2026
e8d114b
fix(controller): count IPv6 clients by /64 and bound the enrollment p…
ilackarms Nov 9, 2026
5124d45
fix(controller): let CompleteEnrollment wait for a slot instead of fa…
ilackarms Nov 9, 2026
88c58cb
fix(controller): warn when fleet limits refuse clients, at most once …
ilackarms Nov 9, 2026
a6e7f80
feat(controller): configure the deployment-dependent fleet limits
ilackarms Nov 9, 2026
c4e28cf
fix(helm): leave the external traffic policy at the Kubernetes default
ilackarms Nov 9, 2026
ed4e95b
fix(controller): release a device enrollment's reservation when its r…
ilackarms Nov 9, 2026
97a37d9
docs(controller): describe tcp_keepalive as the idle time before probes
ilackarms Nov 9, 2026
b59e746
fix(controller): keep a connection busy only while Connect is open
ilackarms Nov 9, 2026
fd5bd37
fix(controller): check the per-address cap before evicting at the tot…
ilackarms Nov 9, 2026
4c4ab7d
fix(controller): count a connection's requests under the registry lock
ilackarms Nov 9, 2026
7210a6b
fix(controller): time out identity provider requests
ilackarms Nov 9, 2026
c8955fb
test(controller): cover fleet limits on the production connection path
ilackarms Nov 9, 2026
a84bb31
docs(deploy): note that devices behind one address share an enrollmen…
ilackarms Nov 9, 2026
4b8a4f2
docs(config): describe maxMessageBytes as a two-way limit; schema rej…
ilackarms Nov 9, 2026
7fd2ceb
test(controller): keep the first-request deadline out of the idle-clo…
ilackarms Nov 9, 2026
95a3688
fix(controller): free a Connect stream's connection when its session …
ilackarms Nov 9, 2026
0d8fade
fix(controller): never let a Connect session wait on a device that st…
ilackarms Nov 9, 2026
54bf011
refactor(controller): require the fleet limits when building the flee…
ilackarms Nov 9, 2026
7e77782
test(controller): check that every fleetLimits setting reaches the fl…
ilackarms Nov 10, 2026
e661541
fix(controller): say what a throttled warning's count covers
ilackarms Nov 10, 2026
a5342e3
docs(controller): correct two comments and explain the enrollment che…
ilackarms Nov 10, 2026
f5f2757
docs(config): describe the burst settings as bursts, not concurrency
ilackarms Nov 10, 2026
56a31be
fix(controller): stop re-arming a busy connection's idle timer on eve…
ilackarms Nov 10, 2026
2c23e26
test(controller): lower only the limits each fleet test exercises
ilackarms Nov 10, 2026
8a170a9
refactor(controller): build the fleet listener with every limit in on…
ilackarms Nov 10, 2026
72f3efe
test(controller): fail when a fleet RPC has no limit class
ilackarms Nov 10, 2026
ba24b92
fix(controller): select the rustls provider before the fleet TLS list…
ilackarms Nov 10, 2026
d915119
fix(controller): limit the streams a client can make the fleet listen…
ilackarms Nov 11, 2026
03bd372
refactor(controller): keep one per-connection stream limit
ilackarms Nov 11, 2026
381f8c9
refactor(controller): make the fleet service wrapper private
ilackarms Nov 11, 2026
3f4a88d
refactor(controller): make token-bucket refill and take methods of Bu…
ilackarms Nov 11, 2026
bbed8a9
refactor(controller): embed the fleet limits configuration in FleetLi…
ilackarms Nov 11, 2026
df701e1
fix(controller): slow a device over its message budget instead of clo…
ilackarms Nov 11, 2026
0bbe4d9
fix(controller): check fleet connection deadlines on writes too
ilackarms Nov 12, 2026
025ac7a
fix(controller): only device requests keep a fleet connection busy
ilackarms Nov 12, 2026
523222e
test(controller): run the fleet limit tests against the real fleet ha…
ilackarms Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ base64 = "0.23"
bytes = "1"
clap = { version = "4", features = ["derive"] }
futures-core = "0.3"
http-body = "1"
http-body-util = "0.1"
humantime-serde = "1"
hostname = "0.4"
Expand Down Expand Up @@ -67,6 +68,7 @@ tokio-stream = "0.1"
tonic = { version = "0.14", features = ["transport", "tls-aws-lc"] }
tonic-prost = "0.14"
tonic-prost-build = "0.14"
tower-layer = "0.3"
tracing = "0.1"
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
Expand Down
2 changes: 2 additions & 0 deletions crates/controller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ axum-server = { version = "0.8", features = ["tls-rustls-no-provider"] }
base64.workspace = true
clap.workspace = true
futures-core.workspace = true
http-body.workspace = true
jsonwebtoken.workspace = true
mime_guess = "2"
notify.workspace = true
Expand All @@ -35,6 +36,7 @@ sqlx = { workspace = true, features = ["postgres", "tls-rustls-aws-lc-rs"] }
tokio.workspace = true
tokio-stream.workspace = true
tonic.workspace = true
tower-layer.workspace = true
tracing.workspace = true
time.workspace = true
url.workspace = true
Expand Down
23 changes: 12 additions & 11 deletions crates/controller/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use crate::{
daemon_config::{self, DaemonConfigStore},
database::Database,
device_ca::DeviceCertificateIssuer,
fleet_limits::FleetLimits,
gateway_jwt::{self, GatewayJwtIssuer},
management::{self, Settings, State},
oidc::OidcProvider,
service::FleetAgentService,
};
use agentdesktop_core::config::ControllerConfig;
use agentdesktop_proto::fleet::fleet_agent_server::FleetAgentServer;
use agentdesktop_usage::UsageIngest;
use anyhow::Context;
use tonic::{
service::Routes,
transport::{Certificate, Identity, Server, ServerTlsConfig},
transport::{Certificate, Identity, ServerTlsConfig},
};

/// Runs fleet and management listeners with application-owned extensions.
Expand All @@ -25,6 +25,9 @@ pub async fn run(
database: Database,
extensions: management::Extensions,
) -> anyhow::Result<()> {
// Before any TLS configuration is built: the fleet listener's uses the
// process-wide rustls provider.
crate::install_rustls_provider();
// Fail before any network setup when the access mode has no provider.
management::auth(&config.admin_access, &extensions)?;
let tls = config.tls.files();
Expand Down Expand Up @@ -103,12 +106,14 @@ pub async fn run(
let device_certificate_issuer = DeviceCertificateIssuer::from_pem(ca_certificate, &ca_key)
.context("initialize device certificate issuer")?;
tracing::info!("device certificate issuance enabled");
let limits = FleetLimits::from_config(&config.fleet_limits);
let service = FleetAgentService::new(
Some(oidc),
database,
daemon_config,
gateway_jwt_issuer,
Some(device_certificate_issuer),
&limits,
)
.with_usage_collection(usage_ingest.is_some());

Expand All @@ -126,22 +131,18 @@ pub async fn run(
.identity(Identity::from_pem(certificate, key))
.client_ca_root(Certificate::from_pem(client_ca))
.client_auth_optional(true);
let mut server = Server::builder()
.accept_http1(true)
.tls_config(tls_config)?;

let fleet_listen = config.fleet_listen;
let fleet_listener = limits.listener(fleet_listen, Some(tls_config))?;

let admin_listen = config.admin_listen;
tracing::info!(listen = %fleet_listen, "fleet controller listening");
let fleet = async move {
let mut routes = Routes::from(gateway_jwt::routes(gateway_jwks))
.add_service(FleetAgentServer::new(service));
let mut routes = Routes::from(gateway_jwt::routes(gateway_jwks));
if let Some(usage_ingest) = usage_ingest {
routes = routes.add_service(usage_ingest);
}
server
.add_routes(routes)
.serve(fleet_listen)
fleet_listener
.serve(service, routes)
.await
.context("serve fleet gRPC API")
};
Expand Down
Loading
Loading