Skip to content

Commit 638082c

Browse files
committed
fix: fail the install when a fleet enrollment cannot add its include
ScheduleEnrollFleet only logged a NOTE when the installer was not allowed to change the configuration, and then enrolled anyway. The result is a host that generates a key pair, spends its one-time bootstrap token, registers with the fleet server and syncs - while nothing ever reads the configuration that comes back, because ScheduleWriteConfig never added the include that points at it. Managed on paper, unmanaged in practice, and the note lands in an MSI log that nobody reads on an unattended install. Fail instead, before the token is spent. The test is the same one ScheduleWriteConfig applies (CONF_CAN_CHANGE = 1), so the install fails exactly when the include would not have been written, and the error carries CONF_CAN_CHANGE_REASON so the log says which of the several reasons applied. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Michael Medin <michael@medin.name>
1 parent 3d94e51 commit 638082c

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

docs/docs/setup/installing.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,10 @@ A few things worth knowing:
341341
- **Enrollment is required to succeed.** If the fleet server cannot be reached, or rejects the token, the install fails
342342
with an error explaining what went wrong rather than leaving you with an agent that never joined the fleet. Bootstrap
343343
tokens are one-time and are burned on first use, so a rejected token means generating a new install command.
344+
- **The installer has to be allowed to write the configuration.** Enrollment is what adds the include that makes the
345+
host read what the fleet server sends it, so combining `FLEET_SERVER` with `ALLOW_CONFIGURATION=0` - or installing
346+
onto a configuration the installer cannot update - fails the install rather than enrolling a host that then ignores
347+
everything the fleet server tells it. The install log names the reason the configuration was held to be unchangeable.
344348
- **An already enrolled host keeps its identity.** If `agent-state.json` already exists (an upgrade, a repair, or a
345349
re-install over an existing installation) the enrollment is skipped and the existing identity is kept. Delete the file
346350
to enroll again.

installer_lib/installer_lib.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,13 +1158,23 @@ extern "C" UINT __stdcall ScheduleEnrollFleet(MSIHANDLE hInstall) {
11581158
}
11591159

11601160
// The include of the fleet-managed configuration is written by
1161-
// ScheduleWriteConfig, which only writes anything when the installer is
1162-
// allowed to change the configuration. Say so rather than leaving the
1163-
// operator with an enrolled host whose fleet configuration is never read.
1161+
// ScheduleWriteConfig, and only when it is allowed to change the
1162+
// configuration - the exact test repeated here, so we fail precisely when
1163+
// the include would not be written. Without it the host enrolls, reports
1164+
// in and syncs, but nothing ever reads what the fleet server sends back:
1165+
// managed on paper, unmanaged in practice. The enrollment that follows
1166+
// burns the bootstrap token, so this has to fail before the token is
1167+
// spent, not leave a note in a log nobody reads on an unattended install.
11641168
if (h.getMsiPropery(INT_CONF_CAN_CHANGE) != L"1") {
1165-
h.logMessage(
1166-
L"NOTE: configuration changes are not allowed, so the fleet configuration include cannot be added. Add it manually: [/includes] "
1167-
L"fleet=${shared-path}/fleet/fleet.ini");
1169+
std::wstring reason = boost::algorithm::trim_copy(h.getMsiPropery(INT_CONF_CAN_CHANGE_REASON));
1170+
if (reason.empty()) reason = L"the installer is not allowed to change the configuration";
1171+
h.errorMessage(
1172+
L"Refusing to enroll with a fleet server: the configuration cannot be changed (" + reason +
1173+
L"), so the include of the fleet-managed configuration ([/includes] fleet=${shared-path}/fleet/fleet.ini) cannot be added and this host "
1174+
L"would never read the configuration the fleet server sends it. Let the installer write the configuration (do not pass "
1175+
L"ALLOW_CONFIGURATION=0, or pass CONF_CAN_CHANGE=1), or install without FLEET_SERVER/FLEET_TOKEN and enroll afterwards with `nscp enroll` "
1176+
L"once the include is in place.");
1177+
return ERROR_INSTALL_FAILURE;
11681178
}
11691179

11701180
msi_helper::custom_action_data_w data;

0 commit comments

Comments
 (0)