Files
fleet/server/fleet/secrets.go
T
Juan Fernandez 89ec4f3abb Support custom (secret) variables in host name templates
Relates to #38806

Host name templates previously accepted only built-in $FLEET_VAR_*
variables and rejected custom $FLEET_SECRET_* (secret) variables. Allow
secret variables so admins can embed an org-wide custom value in an
Apple host's name.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [X] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
2026-07-15 14:29:02 -04:00

64 lines
2.8 KiB
Go

package fleet
import (
"errors"
"fmt"
"strings"
)
const ServerSecretPrefix = "FLEET_SECRET_"
// HostSecretPrefix is used for host-scoped secrets that are looked up by
// enrollment ID rather than by name. These are expanded at command delivery time.
//
// NOTE: This prefix is for Fleet-internal use only (e.g., injecting per-host
// recovery lock passwords into MDM commands). It is not user-configurable and
// should not be documented as a user-facing feature.
const HostSecretPrefix = "FLEET_HOST_SECRET_" //nolint:gosec // G101: this is a prefix constant, not a credential
// Host secret types
const (
// HostSecretRecoveryLockPassword is the host secret type for macOS recovery lock passwords.
// The password is stored encrypted in host_recovery_key_passwords and injected at delivery time.
HostSecretRecoveryLockPassword = "RECOVERY_LOCK_PASSWORD"
// HostSecretRecoveryLockPendingPassword is the host secret type for pending recovery lock passwords
// during password rotation. The pending password is stored encrypted in host_recovery_key_passwords
// (pending_encrypted_password column) and injected as the NewPassword during rotation.
HostSecretRecoveryLockPendingPassword = "RECOVERY_LOCK_PENDING_PASSWORD"
// HostSecretMDMUnlockToken is the host secret type for MDM unlock tokens.
// The token is stored in the nano_devices table and injected at delivery time for ClearPasscode commands sent to Apple MDM-enrolled hosts.
HostSecretMDMUnlockToken = "MDM_UNLOCK_TOKEN" // nolint:gosec // G101: this is a constant identifier, not a credential
// HostSecretPSSODeviceRegistrationToken is the host secret type for the Apple
// Platform SSO device registration token. The token is not stored: it is a
// Fleet-signed JWT minted on the fly for the requesting host at command
// delivery time, so it never appears in the database or on /mdm/commands.
HostSecretPSSODeviceRegistrationToken = "PSSO_DEVICE_REGISTRATION_TOKEN" // nolint:gosec // G101: this is a constant identifier, not a credential
)
type MissingSecretsError struct {
MissingSecrets []string
}
func (e MissingSecretsError) Error() string {
secretVars := make([]string, 0, len(e.MissingSecrets))
for _, secret := range e.MissingSecrets {
secretVars = append(secretVars, fmt.Sprintf("\"$%s%s\"", ServerSecretPrefix, secret))
}
plural := ""
if len(secretVars) > 1 {
plural = "s"
}
return fmt.Sprintf("Couldn't add. Secret variable%s %s missing from database", plural, strings.Join(secretVars, ", "))
}
// IsMissingSecretsError reports whether err is (or wraps) a MissingSecretsError,
// i.e. a reference to a secret variable that doesn't exist.
func IsMissingSecretsError(err error) bool {
var valErr MissingSecretsError
var ptrErr *MissingSecretsError
return errors.As(err, &valErr) || errors.As(err, &ptrErr)
}