fleetdm / fleet

Open-source platform for IT, security, and infrastructure teams. (Linux, macOS, Chrome, Windows, cloud, data center)
https://fleetdm.com
Other
3.16k stars 432 forks source link

Specify host identifier used by fleetd #14879

Closed ksatter closed 10 months ago

ksatter commented 1 year ago

Goal

User story
As an Endpoint Engineer,
I want Orbit (one component of the fleetd agent) to enroll using the same host identifier as osquery (another component of fleetd)
so that I don't see duplicate hosts enroll to Fleet.

Changes

Product

Context

QA

Risk assessment

Manual testing steps

First you will need to create a new local TUF repository.

# Use the PR's branch

git checkout 14879-fleetd-host-identifier

#
# You may need to modify the URLs depending on your host and VMs setup
#
# Note that Fleet Desktop is disabled (customer expecting this change doesn't use Fleet Desktop)
#

rm -rf test_tuf

SYSTEMS="macos windows linux" \
PKG_FLEET_URL=https://host.docker.internal:8080 \
PKG_TUF_URL=http://host.docker.internal:8081 \
DEB_FLEET_URL=https://host.docker.internal:8080 \
DEB_TUF_URL=http://host.docker.internal:8081 \
RPM_FLEET_URL=https://host.docker.internal:8080 \
RPM_TUF_URL=http://host.docker.internal:8081 \
MSI_FLEET_URL=https://host.docker.internal:8080 \
MSI_TUF_URL=http://host.docker.internal:8081 \
GENERATE_PKG=1 \
GENERATE_DEB=1 \
GENERATE_RPM=1 \
GENERATE_MSI=1 \
ENROLL_SECRET=uBtn8G3ONN9J2Ouib/t/yE0sa7w2iYNk \
INSECURE=1 \
./tools/tuf/test/main.sh

Testing scenarios for QA:

A. Test the new feature with two VMs that have the same hardware UUID and serial number. You can simulate this with the following steps:

  1. Installing a package that was generated with --host-identifier=instance, e.g. for macOS:
    ./build/fleetctl package --type=pkg --fleet-desktop --fleet-url=https://host.docker.internal:8080 --enroll-secret=uBtn8G3ONN9J2Ouib/t/yE0sa7w2iYNk --insecure --debug --update-roots=$(./build/fleetctl updates roots --path ./test_tuf) --update-interval=10s --disable-open-folder --update-url=http://host.docker.internal:8081 --host-identifier=instance
  2. Check that the host is enrolled in the Fleet UI.
  3. Uninstall the package.
  4. Install the same package again.
  5. You should now see two hosts with the same data in Fleet. (Because they now use instance as its identifier instead of the hardware UUID/serial)

B. Test generating packages without --host-identifier=instance (basically default behavior). Test both Fleet with MDM enabled and disabled.

C. Test packages generated without --host-identifier=instance against the latest released Fleet (4.41.1). Hosts should enroll without issues.

D. Test customers upgrading the flag on already installed fleetd instances. (Meaning they won't re-install the package and instead set the orbit flag manually or via config management like Chef.)

This should be tested on Linux and Windows. Not on macOS. Make sure to have Fleet Desktop disabled.

  1. Upgrade Fleet from fleet-v4.41.0 to this version (fleet-v4.42.0).
  2. Installing a package that was generated without --host-identifier with an old version of Orbit (e.g. latest released Orbit). You can do this by generating the TUF repository with main.sh on fleet-v4.41.1.
  3. Check that the host is enrolled in the Fleet UI. MySQL: select id, osquery_host_id, hostname, uuid, hardware_serial from fleet.hosts; osquery_host_id should match uuid.
  4. Publish this new version of orbit to your local TUF GOOS=linux GOARCH=amd64 go build -o orbit-linux ./orbit/cmd/orbit && ./tools/tuf/test/push_target.sh linux orbit orbit-linux 43). Orbit should auto-update.
  5. Stop the fleetd service: (e.g. on Linux sudo systemctl stop orbit)
  6. Delete the host in Fleet.
  7. Go to the orbit configuration and add the following flag to it: ORBIT_HOST_IDENTIFIER set to instance (on Linux it's /etc/defaults/orbit).
  8. Start service (on macOS sudo systemctl start orbit).
  9. Host should be enrolled again but with the osquery identifier as osquery_host_id: MySQL: select id, osquery_host_id, hostname, uuid, hardware_serial from fleet.hosts; osquery_host_id should match what osquery reports in instance_id when running the query select instance_id from osquery_info;.

For Windows:

E. Test enrolling vanilla osquery against Fleet.

--

Other things to take a look at:

Testing notes

Confirmation

  1. [ ] Engineer (@____): Added comment to user story confirming succesful completion of QA.
  2. [x] QA (@xpkoala ): Added comment to user story confirming succesful completion of QA.
noahtalerman commented 1 year ago

@zayhanlon and @ksatter heads up, this story will be air guitar'd during the next design sprint.

noahtalerman commented 1 year ago

Notes from internal call: https://docs.google.com/document/d/1o8446eiAk-z2Bm_GSz0mZdb7CPTF0eymv-CtIm_VVxU/edit#heading=h.8oggoi13xg7y

More info in customer thread in Slack (internal): https://fleetdm.slack.com/archives/C03AE5T2EQ0/p1698348948683799

ksatter commented 1 year ago

@noahtalerman It could be possible to manage this through Agent options, but it would require changes to the enrollment process. I thought of two potential scenarios for that:

  1. By default, fleetd gathers all of the values for different identifiers and passes them in the enroll request. When the request is received, Fleet checks config and uses the appropriate value
  2. Do a pre-enrollment check-in. Grab osquery and fleetd flags at this point, then send an enroll request with the appropriate data
noahtalerman commented 1 year ago

Option 1

Option 2

fleetd picks up whatever osquery has set as host-identifier. Or when you specify host-identifier is sets it for both fleetd and osquery.

Michael: This way, we could continue using the same workflow: give teams osquery flag file w/ host-identifier specified. If this won't work, fall back to option 1.

How? Fleetd starts osquery and runs this query to get host_identifier:

select value, instance_id from osquery_flags JOIN osquery_info where name = 'host_identifier';

Noah: If we can, I think the flagfile, if present, is the source of truth for osquery flags for the customer. The osquery flagfile overrides all osquery flags set remotely (agent_options.command_line_flags in Fleet YAML). We don't document this. Using Fleet YAML is best practice.

Noah: Can we make this work? Zach: Yes but using an osquery flagfile may be breaking the extensions loading because Fleet needs to be writing to a flagfile. Might be a reason to do option 1.

TODO Noah: Ask support if setting an osquery flagfile breaks managing extensions remotely.

Why? We're not certain that Orbit and osquery having the same host identifier will resolve the problem with receiving extensions.

noahtalerman commented 1 year ago

Future problem:

As an Endpoint Engineer, I want to be able to specify --tls_client_cert, --tls_client_key, and --watchdog_** flags via fleetctl package command or Fleet YAML so that I don't have to use an osquery flagfile.

UPDATE: The Fleet YAML already supports --fleet-tls-client-certificate, --fleet-certificate, and --watchdog_** flags.

The customer can use these instead of osquery flagfile.

The customer can set different values for these flags in each team in Fleet.

Are teams granular enough?

(2023-12-01)


Today, the customer is setting these flags in the osquery flagfile and updating them remotely via Chef.

My guess is that they can't use Fleet YAML to update these remotely because different hosts need different values for these flags. Targeting based on teams isn't sufficient (not granular enough) because the customer uses teams for a rollout use case (staging and production).

The likely solution to this problem is to allow different agent options based on label.

noahtalerman commented 12 months ago

@lucasmrod TODOs are in this Google doc: https://docs.google.com/document/d/187PA5ctmIFjD8-HLkAEYXjf0OOL61bvGhNnu-2VZa24/edit

noahtalerman commented 11 months ago
  • [ ] fleetd changes:
    • [ ] fleetd is forced to use the --host_identifier value set during fleetctl package no matter what value is set in an osquery flagfile.
    • [ ] fleetd is forced to use the --extensions-autoload value set by agent_options.extensions in Fleet YAML no matter what value is set in an osquery flagfile.

@lucasmrod here's how I summarized the fleetd changes based on discussion in this Google doc.

What do you think?

lucasmrod commented 11 months ago

fleetd is forced to use the --extensions-autoload value set by agent_options.extensions in Fleet YAML no matter what value is set in an osquery flagfile.

Should be something like:

fleetd is forced to use the --extensions-autoload value set by itself (orbit always sets this to /opt/orbit/extensions.autoload) no matter what value is set in an osquery flagfile or Fleet YAML.

lucasmrod commented 11 months ago

No migration needed for existing hosts. User will have to reinstall package to use this feature.

Once released users that are hitting these 2-hosts-as-1-bug will have to:

  1. Remove the hosts with the 2-hosts-as-1-bug from Fleet.
  2. Re-generate the package with the new fleetctl version (with fleetctl package --host_identifier=instance [...]) and re-install such package on the hosts.
noahtalerman commented 11 months ago

Remove the hosts with the 2-hosts-as-1-bug from Fleet.

@lucasmrod the customer has already deleted the Orbit enrolled host record in Fleet.

If I'm understanding correctly, they will have to delete the osquery enrolled host too?

If they want to, can they delete the osquery enrolled host after they install the new fleetd w/ --host-identifier flag? (step 2)

JoStableford commented 11 months ago

Related to a Slack conversation

lucasmrod commented 11 months ago

@noahtalerman Am changing the env var from HOST_IDENTIFIER to ORBIT_HOST_IDENTIFIER (all orbit variables have the ORBIT_ prefix).

lucasmrod commented 11 months ago

fleetd is forced to use the --host_identifier value set during fleetctl package no matter what value is set in an osquery flagfile.

Am also editing --host_identifier to --host-identifier.

lucasmrod commented 11 months ago

@xpkoala QA steps were added to the description.

fleet-release commented 10 months ago

Unified identifiers, No more duplicates in sight. Fleet's path becomes clear.