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

Add Secrets Database #1309

Merged
merged 32 commits into from Sep 29, 2021
Merged

Add Secrets Database #1309

merged 32 commits into from Sep 29, 2021

Conversation

jordanschalm
Copy link
Member

@jordanschalm jordanschalm commented Sep 20, 2021

This PR creates a separate database for confidential data. It implements part of the Identity-Agnostic Database Structure proposal.

Changes

  • Add an additional database instance in the scaffold
    • ⚠️ Adds a new required flag to specify the location of this database
    • Adds optional encryption support for the new secrets database, using a new private bootstrap file specifying the encryption key, stored alongside the other keys
    • Updates localnet and integration tests to turn on encryption for the new database
  • Adds storage methods for initializing a database with a particular type (for the scaffold), and for ensuring that a database is marked as a particular type (for storage components to assert which database type they are being initialized against)
  • Adds the new flag to example systemd files

@jordanschalm jordanschalm changed the title Identity-Agnostic Database Structure Add Secrets Database Sep 22, 2021
@jordanschalm jordanschalm marked this pull request as ready for review September 22, 2021 21:34
@jordanschalm jordanschalm requested review from huitseeker and synzhu and removed request for vishalchangrani September 22, 2021 22:00
@jordanschalm jordanschalm removed the request for review from synzhu September 23, 2021 13:41
integration/testnet/network.go Outdated Show resolved Hide resolved
engine/testutil/nodes.go Outdated Show resolved Hide resolved
state/protocol/badger/mutator_test.go Outdated Show resolved Hide resolved
@jordanschalm jordanschalm requested review from vishalchangrani, synzhu and peterargue and removed request for AlexHentschel September 24, 2021 14:07
Copy link
Member

@zhangchiqing zhangchiqing left a comment

Choose a reason for hiding this comment

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

Nice work, just had one question and a few suggestions

cmd/scaffold.go Outdated
func loadSecretsEncryptionKey(dir string, myID flow.Identifier) ([]byte, error) {
data, err := io.ReadFile(filepath.Join(dir, fmt.Sprintf(bootstrap.PathSecretsEncryptionKey, myID)))
if err != nil {
return nil, fmt.Errorf("could not read key: %w", err)
Copy link
Member

Choose a reason for hiding this comment

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

better to print the path

Copy link
Member Author

Choose a reason for hiding this comment

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

Comment on lines +477 to +478
err := os.MkdirAll(fnb.BaseConfig.secretsdir, 0700)
fnb.MustNot(err).Str("dir", fnb.BaseConfig.secretsdir).Msg("could not create secrets db dir")
Copy link
Member

Choose a reason for hiding this comment

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

If the directory already exists, would running the second time still work?

Copy link
Member Author

Choose a reason for hiding this comment

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

It will - we do the same for the existing database

err := os.MkdirAll(fnb.BaseConfig.datadir, 0700)

// attempt to read an encryption key for the secrets DB from the canonical path
encryptionKey, err := loadSecretsEncryptionKey(fnb.BootstrapDir, fnb.NodeID)
if errors.Is(err, os.ErrNotExist) {
fnb.Logger.Warn().Msg("starting with secrets database encryption disabled")
Copy link
Member

Choose a reason for hiding this comment

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

Why not crashing? shouldn't secret encryption key always exist?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because creating the encryption key requires an operator action (see #1340 and onflow/flow#641), the plan is to not make it a hard requirement initially (discussion here)

Copy link
Member

Choose a reason for hiding this comment

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

OK, better to add a TODO for reminding us to remove it in next spork or something

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

will add key derivation suggestions there

Comment on lines 722 to 726
var flowClient *client.Client
if insecureAccessAPI {
flowClient, err = common.InsecureFlowClient(accessAddress)
if err != nil {
return nil, err
Copy link
Member

Choose a reason for hiding this comment

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

not sure if these change have anything to do with Secrets database

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, this is duplicating the setup that is already implemented here: https://github.com/onflow/flow-go/pull/1309/files#diff-7d960671cc56ce82783f5366bad31f7108cf00270c1bb39b0e00fa57ca96334dR354-R383. Not sure how that happened, thanks for catching

Copy link
Member Author

Choose a reason for hiding this comment

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

func NewDKGKeys(collector module.CacheMetrics, db *badger.DB) *DKGKeys {
func NewDKGKeys(collector module.CacheMetrics, db *badger.DB) (*DKGKeys, error) {

err := operation.EnsureSecretDB(db)
Copy link
Member

Choose a reason for hiding this comment

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

Can't find my comment. Sorry if I asked this question again:

Can we let EnsureSecretDB check whether the encryption key is correct? Seems if the encryption key is incorrect, the db can still be initialized, and won't learn it's wrong until there is an query.

Copy link
Member Author

Choose a reason for hiding this comment

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

The database will fail to open if the encryption key isn't correct. Going to add a test case that validates this.

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 a test here: aab5d8e

@codecov-commenter
Copy link

codecov-commenter commented Sep 24, 2021

Codecov Report

Merging #1309 (3e174db) into master (28a6922) will decrease coverage by 1.01%.
The diff coverage is 38.77%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1309      +/-   ##
==========================================
- Coverage   56.25%   55.24%   -1.02%     
==========================================
  Files         500      506       +6     
  Lines       31162    31798     +636     
==========================================
+ Hits        17531    17567      +36     
- Misses      11262    11856     +594     
- Partials     2369     2375       +6     
Flag Coverage Δ
unittests 55.24% <38.77%> (-1.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
cmd/bootstrap/utils/key_generation.go 39.32% <0.00%> (-7.35%) ⬇️
cmd/node_builder.go 0.00% <0.00%> (ø)
storage/badger/operation/prefix.go 76.00% <ø> (ø)
cmd/scaffold.go 0.92% <13.51%> (ø)
storage/badger/init.go 42.85% <42.85%> (ø)
storage/badger/operation/init.go 84.61% <84.61%> (ø)
storage/badger/dkg_keys.go 100.00% <100.00%> (ø)
cmd/flags.go 0.00% <0.00%> (ø)
cmd/machine_account.go 0.00% <0.00%> (ø)
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 28a6922...3e174db. Read the comment docs.

storage/badger/operation/init_test.go Outdated Show resolved Hide resolved
Copy link
Member

@zhangchiqing zhangchiqing left a comment

Choose a reason for hiding this comment

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

Nice work 💯

Copy link
Contributor

@huitseeker huitseeker left a comment

Choose a reason for hiding this comment

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

LGTM, under heavy caveats that we discussed offline and that I'll re-state here for completeness:

  • since the DKG secrets can lead to consensus votes (in consensus v2),
  • those secrets being read by an out-of-process intruder on the node operator's machine can lead to a compromise of chain safety,
  • hence the DKG secrets DB being left unencrypted is unsafe (though perhaps just as bad as we deal with staking key persistence and custody)
  • so this should only be released in mainnet after a documentation PR that outlines all on-disk locations that the operator should secure with spectacular clarity,
  • this doc pr should let operators use infra / sre means to secure those storage locations using one of the myriad of solutions available (some FUSE-based overlay encryption, Docker, K8s, GCP secrets, etc ...)

// attempt to read an encryption key for the secrets DB from the canonical path
encryptionKey, err := loadSecretsEncryptionKey(fnb.BootstrapDir, fnb.NodeID)
if errors.Is(err, os.ErrNotExist) {
fnb.Logger.Warn().Msg("starting with secrets database encryption disabled")
Copy link
Contributor

Choose a reason for hiding this comment

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

will add key derivation suggestions there

@jordanschalm
Copy link
Member Author

bors merge

@bors
Copy link
Contributor

bors bot commented Sep 29, 2021

@bors bors bot merged commit 403772e into master Sep 29, 2021
@bors bors bot deleted the jordan/5856-secrets-db branch September 29, 2021 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants