-
Notifications
You must be signed in to change notification settings - Fork 908
Warn users about file carving size limits #47376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
noahtalerman
wants to merge
9
commits into
main
Choose a base branch
from
noahtalerman-patch-84
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+38
−39
Draft
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
cf63e57
Update rest-api.md
noahtalerman 53d0afa
Create file-carving.md
noahtalerman 1d05837
Apply suggestion from @noahtalerman
noahtalerman 04f9768
Update file-carving.md
noahtalerman fc9a50d
Apply suggestion from @noahtalerman
noahtalerman 4e6a711
Apply suggestion from @noahtalerman
noahtalerman ad97563
Delete docs/Contributing/product-groups/orchestration/file-carving.md
noahtalerman 08178fc
Apply suggestion from @noahtalerman
noahtalerman 7003ef2
Update file-carving.md
noahtalerman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| # File carving | ||
|
|
||
| Fleet supports file carving which allows you to request files (and sets of files) and their full contents from hosts. | ||
|
|
||
| File carving data can be either stored in Fleet's database or to an external S3 bucket. For information on how to configure the latter, consult the [configuration docs](https://fleetdm.com/docs/deploying/configuration#s-3-file-carving-backend). | ||
|
|
||
| ## Setup | ||
|
|
||
| In your agent configuration, add the following [command line flags](https://fleetdm.com/docs/configuration/agent-configuration#options-and-command-line-flags) to enable carving: | ||
|
|
||
| ```yaml | ||
| command_line_flags: | ||
| disable_carver=false | ||
| carver_disable_function=false | ||
| carver_start_endpoint=/api/v1/osquery/carve/begin | ||
| carver_continue_endpoint=/api/v1/osquery/carve/block | ||
| carver_block_size=8000000 | ||
| ``` | ||
|
|
||
| For the (default) MySQL Backend, the configured `carver_block_size` must be less than the value of | ||
| `max_allowed_packet` in the MySQL connection, allowing for some overhead. The default for [MySQL 8](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_allowed_packet) it is 64MB. | ||
|
|
||
| For the S3-compatible backend, `carver_block_size` must be set to at least 5MiB (`5242880`) due to the | ||
| [constraints of S3's multipart | ||
| uploads](https://docs.aws.amazon.com/AmazonS3/latest/dev/qfacts.html). | ||
|
|
||
| Compression of the carve contents can be enabled with the `carver_compression` flag. When used, the carve results will be compressed with [Zstandard](https://facebook.github.io/zstd/) compression. | ||
|
|
||
| ## Create carves | ||
|
|
||
| File carves are initiated with live reports. Run live report using the `carves` table, providing `carve = 1` along with the desired path(s) as constraints. | ||
|
|
||
| For example, to extract the `/etc/hosts` file on a host with hostname `mac-workstation`: | ||
|
|
||
| ```sh | ||
| fleetctl query --hosts mac-workstation --query 'SELECT * FROM carves WHERE carve = 1 AND path = "/etc/hosts"' | ||
| ``` | ||
|
|
||
| The globbing syntax is also supported to carve entire directories or more: | ||
|
|
||
| ```sh | ||
| fleetctl query --hosts mac-workstation --query 'SELECT * FROM carves WHERE carve = 1 AND path LIKE "/etc/%%"' | ||
| ``` | ||
|
|
||
| ## Retrieve carves | ||
|
|
||
| List the non-expired (see below) carves with `fleetctl get carves`. Note that carves will not be available through this command until Fleet's agent (fleetd) checks in to the Fleet server with the first of the carve contents. This can take some time from initiation of the carve. | ||
|
|
||
| To also retrieve expired carves, use `fleetctl get carves --expired`. | ||
|
|
||
| Contents of carves are returned as .tar archives, and compressed if that option is configured. | ||
|
|
||
| To download the contents of a carve with ID 3, use | ||
|
|
||
| ```sh | ||
| fleetctl get carve --outfile carve.tar 3 | ||
| ``` | ||
|
|
||
| It can also be useful to pipe the results directly into the tar command for unarchiving: | ||
|
|
||
| ```sh | ||
| fleetctl get carve --stdout 3 | tar -x | ||
| ``` | ||
|
|
||
| ## Expiration | ||
|
|
||
| Carve contents remain available for 24 hours after the first data is provided from the Fleet's agent (fleetd). After this time, the carve contents are cleaned from the database and the carve is marked as "expired". | ||
|
|
||
| The same is not true if S3 is used as the storage backend. In that scenario, it is suggested to setup a [bucket lifecycle configuration](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html) to avoid retaining data in excess. Fleet, in an "eventual consistent" manner (i.e. by periodically performing comparisons), will keep the metadata relative to the files carves in sync with what it is actually available in the bucket. | ||
|
|
||
| ## Alternative carving backends | ||
|
|
||
| #### RustFS | ||
|
|
||
| Configure the following: | ||
| - `FLEET_S3_ENDPOINT_URL=rustfs_host:port` | ||
| - `FLEET_S3_BUCKET=bucket_name` | ||
| - `FLEET_S3_SECRET_ACCESS_KEY=your_secret_access_key` | ||
| - `FLEET_S3_ACCESS_KEY_ID=access_key_id` | ||
| - `FLEET_S3_FORCE_S3_PATH_STYLE=true` | ||
| - `FLEET_S3_REGION=localhost` or any non-empty string otherwise Fleet will attempt to derive the region. | ||
|
|
||
| If you're testing file carving locally with the docker-compose environment, the `--dev` flag on Fleet server will automatically point carves to the local RustFS container and write to the `carves-dev` bucket (created automatically) without needing to set additional configuration. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Check carve status | ||
|
|
||
| You can report on the status of carves through queries to the `carves` table. | ||
|
|
||
| The details provided by | ||
|
|
||
| ```sh | ||
| fleetctl query --labels 'All Hosts' --query 'SELECT * FROM carves' | ||
| ``` | ||
|
|
||
| can be helpful to debug carving problems. | ||
|
|
||
| ### Ensure `carver_block_size` is set appropriately | ||
|
|
||
| `carver_block_size` is an option that sets the size of each part of a file carve that Fleet's agent (fleetd) | ||
| sends to the Fleet server. | ||
|
|
||
| When using the MySQL backend (default), this value must be less than the `max_allowed_packet` | ||
| setting in MySQL. If it is too large, MySQL will reject the writes. | ||
|
|
||
| When using S3, the value must be at least 5MiB (5242880 bytes), as smaller multipart upload | ||
| sizes are rejected. Additionally, [S3 | ||
| limits](https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html) the maximum number of | ||
| parts to 10,000. | ||
|
|
||
| The value must be small enough that HTTP requests do not time out. | ||
|
|
||
| Start with a default of 2MiB for MySQL (2097152 bytes), and 5MiB for S3 (5242880 bytes). | ||
|
|
||
| <meta name="pageOrderInSection" value="2100"> | ||
|
|
||
| <meta name="articleTitle" value="File carving in Fleet"> | ||
| <meta name="authorFullName" value="Noah Talerman"> | ||
| <meta name="authorGitHubUsername" value="noahtalerman"> | ||
| <meta name="publishedOn" value="2026-06-10"> | ||
| <meta name="description" value="Learn how to TODO"> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rfairburn when you get the chance, can you please help me come up w/ a good warning here?
So
shackletonand other customers know the best practice max: https://fleetdm.slack.com/archives/C094ZAWGDHC/p1779392158155149cc @zayhanlon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case you refer to there were a couple of things that at first glance happened that didn't seem intentional
The net effect was a load both in bandwidth and db usage that came from an X * Y * Z * A situation where:
X = number of hosts
Y = number of paths requests
Z = number of files in the paths
A = avg file size of any individual file
Any one of these can be bigger in scope usually without there being a huge issue for example:
However, when all four of the dials end up being turned up (on accident in this case from the sounds of it), you suddenly end up with the db trying to write millions of new rows of metatada, while fleet is trying to populate 10s of terrabytes of data in the s3 carves bucket, while all hosts are both responding to the distributed query that does the
SELECTto trigger the carve and push all of this data over the carves endpoints.Another gotcha that did not occur in this specific case is the carves in question were only a one-off. There wasn't a scheduled query/automations=on situation, which can also compound.
The only nuance is that a particular carve select with multiple files would get combined into a single tar archive before being transferred, but we would still be subject to the 8GB size, block size of 256mb (row and s3 object per block), and the 4th-power load amplification if all factors get scaled at once.