Skip to content
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

Agent configuration encryption #398

Merged
merged 39 commits into from
May 24, 2022
Merged

Conversation

aleksmaus
Copy link
Member

@aleksmaus aleksmaus commented May 2, 2022

What does this PR do?

Implements the key material storage and the agent configuration and state encryption.
Providing the bulletproof key material storage across all the platforms is fairly difficult.
The open source nature of the project is making it even more easier to figure any obfuscation techniques that we could have used to make it difficult to reverse engineer the key protection algorithm.

Opening this PR draft to gather feedback. If we agree on the general approach there are still some TODO items to finalize this change

TODO

  1. Improve unit test coverage
  2. Retest the agent on all platforms (darwin, linux, windows)

Implementation details

Here is the approach that was taken on the different platforms at the moment:

Darwin (Mac OS)

The key material is stored in the System keychain. The value is stored as is without any additional transformations.
Screen Shot 2022-05-02 at 9 33 16 AM

Windows

The data is encrypted with DPAPI CryptProtectData with CRYPTPROTECT_LOCAL_MACHINE.
The additional entropy is derived from crypto/rand bytes stored in .seed file.
The data is stored as separate files where the name of the file is SHA256 hash of the key and the content of the file is encrypted with DPAPI data.
The security of entropy data relies on file system permissions. Only the Administrator should be able to access the file.

Screen Shot 2022-04-28 at 1 24 41 PM

Linux

The encryption key is derived from crypto/rand bytes that stored in the .seed file after PBKDF2 transformation.
The data is stored as separate files where the name of the file is SHA256 hash of the key and the content of the file is AES256-GSM encrypted.
The security if the key material largely relies on the files system permissions.
Screen Shot 2022-05-02 at 9 15 45 AM

Screen Shot 2022-05-02 at 9 14 08 AM

The Agent modifications

  1. In this POC the Agent creates the encryption key during enrollment. I would probably need the feedback from the agent team on all the possible use cases, maybe the key should be created in the different place
  2. The new EncryptedDiskStore was implemented as a drop-in replacement for the DiskStore. The EncryptedDiskStore uses already /internal/pkg/crypto Reader and Writer implementation, which uses PBKDF2 for key derivation with AES-GCM encryption. We can change this to whatever else we prefer. Let me know.
  3. The Agent configuration (fleet.yml) is encrypted with the ".enc" file extension (fleet.enc).

Screen Shot 2022-05-04 at 2 21 11 PM

  1. The Agent state state.yml is encrypted with the ".enc" file extension (state.enc):

Screen Shot 2022-05-04 at 2 21 28 PM

Why is it important?

Address the configuration encryption at rest requirement.
https://github.com/elastic/obs-dc-team/issues/535

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation

How to test this PR locally

Full regression testing of the agent, including enrollment, upgrade etc.

Related issues

@aleksmaus aleksmaus requested a review from scunningham May 2, 2022 14:00
@mergify
Copy link
Contributor

mergify bot commented May 2, 2022

This pull request does not have a backport label. Could you fix it @aleksmaus? 🙏
To fixup this pull request, you need to add the backport labels for the needed
branches, such as:

  • backport-v./d./d./d is the label to automatically backport to the 8./d branch. /d is the digit

NOTE: backport-skip has been added to this pull request.

@mergify mergify bot added the backport-skip label May 2, 2022
@elasticmachine
Copy link
Contributor

elasticmachine commented May 2, 2022

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview preview

Expand to view the summary

Build stats

  • Start Time: 2022-05-23T19:16:04.535+0000

  • Duration: 17 min 32 sec

Test stats 🧪

Test Results
Failed 0
Passed 5778
Skipped 23
Total 5801

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

  • /package : Generate the packages.

  • run integration tests : Run the Elastic Agent Integration tests.

  • run end-to-end tests : Generate the packages and run the E2E Tests.

  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

@jlind23 jlind23 added the Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team label May 2, 2022
@ph ph self-requested a review May 2, 2022 14:46
@jlind23 jlind23 requested review from a team and narph and removed request for a team May 2, 2022 15:21
@cmacknz cmacknz requested a review from leehinman May 2, 2022 15:54
@ph ph requested a review from blakerouse May 2, 2022 18:39
Copy link
Contributor

@leehinman leehinman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

One request, could we add meta data to the keys? Specifically date created would be really nice if we have to do any kind of key rotation.

// Wrap into crypto writer, reusing already existing crypto writer, open to other suggestions
w, err := crypto.NewWriterWithDefaults(fd, d.key)
if err != nil {
fd.Close()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tmp file not removed in this case, is that expected?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

internal/pkg/agent/storage/encrypted_disk_store.go Outdated Show resolved Hide resolved
internal/pkg/agent/vault/aesgcm.go Show resolved Hide resolved
if _, err = rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := aesGCM.Seal(nonce, nonce, data, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the first nonce really supposed to be the dst?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this way the ciphertext is the concatenation of nonce + encrypted data, thats what is intent here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. might be worth a comment, on first read it looks a little odd.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented


func getSeed(path string) ([]byte, error) {
fp := filepath.Join(path, seedFile)
b, err := ioutil.ReadFile(fp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be a good idea to check permissions of seed file and complain if they are too permissive.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the root owner check. the agent will fail to run in .seed file is not root/root owned

$ sudo ./elastic-agent -e
Error: could not read overwrites: could not initialize config store: non-root file owner
For help, please see our troubleshooting guide at https://www.elastic.co/guide/en/fleet/8.3/fleet-troubleshooting.html

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nimarezainia, do we have plans to allow users to run the agent as non-root?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nimarezainia, do we have plans to allow users to run the agent as non-root?

Not at the moment.

internal/pkg/agent/vault/vault_linux.go Show resolved Hide resolved
@aleksmaus
Copy link
Member Author

nice

One request, could we add meta data to the keys? Specifically date created would be really nice if we have to do any kind of key rotation.

sure, can encode that into stored data.

@aleksmaus
Copy link
Member Author

nice
One request, could we add meta data to the keys? Specifically date created would be really nice if we have to do any kind of key rotation.

sure, can encode that into stored data.

done now, the value is encoded as JSON

// Secret is the structure that is JSON serialized and stored
type Secret struct {
	Value     []byte    `json:"v"` // binary value
	CreatedOn time.Time `json:"t"` // date/time the secret was created on
}

@amolnater-qasource
Copy link

Hi @jlind23
We have validated this PR on 8.3 BC2 Kibana cloud environment and had below observations:

  • Installed Windows, Linux and MAC agents with System integration and observed no issues with logs and data under Data Streams tab.
  • For enhanced testing we have validated the same with Endpoint Security integration and observed no issues there as well.

Further we have observed the files like:

  • fleet.enc at location Elastic/Agent for all the 3 OS's.
  • state.enc at Elastic/Agent/data/elastic-agent-8907dd/ for all the 3 OS's.
  • .seed file at location Elastic/Agent/data/elastic-agent-8907dd/vault for Windows and Linux agents.

We haven't observed vault folder for MAC agent. Could you please confirm if this is expected?

Build details:
VERSION: 8.3.0
BUILD: 53231
COMMIT: 25476b531ba9f32292bde85508d342aa5e1c29eb
Artifact Link: https://staging.elastic.co/8.3.0-fcd43da7/summary-8.3.0.html

NOTE:
Further we are in continuation of agent regression under P1 regression plan and will cover all the related agent scenarios.

Please let us know if we are missing anything here.
Thanks

@aleksmaus
Copy link
Member Author

We haven't observed vault folder for MAC agent. Could you please confirm if this is expected?

For Mac OS we use keychain, no vault folder is needed.

@amolnater-qasource
Copy link

Hi @aleksmaus
Thank you for the update. Could you please confirm we need to run any other test related to this PR on Agents?

Please let us know if we are missing anything here.
cc: @jlind23
Thanks

@aleksmaus
Copy link
Member Author

Hi @aleksmaus Thank you for the update. Could you please confirm we need to run any other test related to this PR on Agents?

Please let us know if we are missing anything here. cc: @jlind23 Thanks

Full regression testing of Elastic Agent would be necessary to make sure we didn't miss any code paths when transitioned to the encrypted storage.

@amolnater-qasource
Copy link

Hi @aleksmaus
Thanks for the feedback.
We are in continuation of agent tests under Fleet Team 8.3 BC2 Regression plan.
Further we have reported agent upgrade failure at #526

Thanks

@michalpristas
Copy link
Contributor

@amolnater-qasource have you tried standalone mode with this PR?

@amolnater-qasource
Copy link

Hi @michalpristas
Earlier we were having issues with standalone agent installation and reported at elastic/kibana#133276

However we had revalidated this issue on latest 8.3 BC2 and found this fixed.
Please let us know if any we need to validate this on any other build.

Thanks

@amolnater-qasource amolnater-qasource added the QA:Validated Validated by the QA Team label Jun 30, 2022
andrewvc added a commit to andrewvc/observability-docs that referenced this pull request Nov 15, 2022
Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.
andrewvc added a commit to elastic/observability-docs that referenced this pull request Nov 18, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
mergify bot pushed a commit to elastic/observability-docs that referenced this pull request Nov 18, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
(cherry picked from commit 7996f31)
andrewvc added a commit to elastic/observability-docs that referenced this pull request Nov 18, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
(cherry picked from commit 7996f31)

Co-authored-by: Andrew Cholakian <[email protected]>
mergify bot pushed a commit to elastic/observability-docs that referenced this pull request Nov 18, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
(cherry picked from commit 7996f31)
andrewvc added a commit to elastic/observability-docs that referenced this pull request Nov 18, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
(cherry picked from commit 7996f31)

Co-authored-by: Andrew Cholakian <[email protected]>
bmorelli25 pushed a commit to bmorelli25/ingest-docs that referenced this pull request Dec 19, 2022
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
bmorelli25 pushed a commit to bmorelli25/observability-docs that referenced this pull request Apr 11, 2023
* [agent] Add documentation for Agent encryption at rest

Based on elastic/elastic-agent#398
and a discussion with @cmacknz .

It's a somewhat common ask from synthetics users.

* Apply suggestions from code review

Thanks for the copy edits Dede!

Co-authored-by: DeDe Morton <[email protected]>

Co-authored-by: DeDe Morton <[email protected]>
@cmacknz cmacknz mentioned this pull request Apr 4, 2024
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-skip blocked QA:Needs Validation Needs validation by the QA Team QA:Validated Validated by the QA Team Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants