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
Add Secrets Database #1309
Conversation
* provide Init functions to initialize a DB with a particular type * add methods to assert a DB is a particular type which can be used in constructors of storage modules which require a particular type
require --secretsdir flag
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.
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) |
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.
better to print the path
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.
err := os.MkdirAll(fnb.BaseConfig.secretsdir, 0700) | ||
fnb.MustNot(err).Str("dir", fnb.BaseConfig.secretsdir).Msg("could not create secrets db dir") |
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.
If the directory already exists, would running the second time still work?
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.
It will - we do the same for the existing database
Line 437 in 27802a0
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") |
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.
Why not crashing? shouldn't secret encryption key always exist?
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.
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)
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.
OK, better to add a TODO for reminding us to remove it in next spork or something
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.
will add key derivation suggestions there
cmd/consensus/main.go
Outdated
var flowClient *client.Client | ||
if insecureAccessAPI { | ||
flowClient, err = common.InsecureFlowClient(accessAddress) | ||
if err != nil { | ||
return nil, err |
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.
not sure if these change have anything to do with Secrets database
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.
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
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.
func NewDKGKeys(collector module.CacheMetrics, db *badger.DB) *DKGKeys { | ||
func NewDKGKeys(collector module.CacheMetrics, db *badger.DB) (*DKGKeys, error) { | ||
|
||
err := operation.EnsureSecretDB(db) |
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.
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.
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.
The database will fail to open if the encryption key isn't correct. Going to add a test case that validates this.
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.
Added a test here: aab5d8e
Codecov Report
@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
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.
Nice work 💯
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.
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") |
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.
will add key derivation suggestions there
bors merge |
This PR creates a separate database for confidential data. It implements part of the Identity-Agnostic Database Structure proposal.
Changes
systemd
files