-
Notifications
You must be signed in to change notification settings - Fork 616
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
[manager/state] Add fernet as an option for raft encryption #2535
Conversation
e81dd14
to
541bc19
Compare
Codecov Report
@@ Coverage Diff @@
## master #2535 +/- ##
==========================================
+ Coverage 61.47% 61.53% +0.06%
==========================================
Files 133 134 +1
Lines 21765 21800 +35
==========================================
+ Hits 13379 13415 +36
Misses 6946 6946
+ Partials 1440 1439 -1 |
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.
Looks great.
@aaronlehmann Thanks for reviewing! I was thinking about actually removing the env var and propagating a FIPS boolean through the code, as per #2544. Unfortunately this means a large-ish change, but it also makes it easier to test mixed settings and run more tests in parallel. |
In the interests of avoiding conflicts, I'm ok with merging this and removing the go env var in a different PR, rather than the reverse. So if anyone else can have a look, that'd be awesome. :) cc @anshulpundir @nishanttotla @dperny |
I would be fine with removing the envvar in a different PR. I'm reviewing in depth now. |
@dperny Thanks so much! |
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.
Mostly looks good, but a couple of comments.
manager/encryption/encryption.go
Outdated
} | ||
|
||
// MultiDecrypter is a decrypter that will attempts to decrypt with multiple decrypters | ||
type MultiDecrypter map[api.MaybeEncryptedRecord_Algorithm][]Decrypter |
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.
I think newtyping maps and then defining methods on them is... a recipe for confusion later on. I was already confused on line 97 when I saw us iterating over what seemed to me to be an object.
Is there any advantage to newtyping a map over defining a struct with a map field?
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.
Also, I am unclear why we need a slice of Decrypter
s for each algorithm. It seems to me like mapping 1:1 algorithim->decrypter would be sufficient?
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.
I agree with @dperny here. Would prefer to have a struct with a map 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.
Also, I am unclear why we need a slice of Decrypters for each algorithm. It seems to me like mapping 1:1 algorithim->decrypter would be sufficient?
It's possible to have multiple keys per algorithm, if you have an old and new key. This is needed for instance when the encryption key is rotated, which happens when you go from unlocked (when the key was stored unencrypted in the TLS key header) to locked (when the key is encrypted in the TLS key header). Not everything may have finished porting over to use the new key, so some WALs will be encrypted with the old key, and some with the new. So 1 decrypter with the new key, 1 with the old, but same algorithm.
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.
That makes perfect sense. Could you add a comment to that effect?
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.
Done, and updated to a struct
manager/encryption/fernet.go
Outdated
return frnt | ||
} | ||
|
||
// Algorithm returns the type of algorithm this is (NACL Secretbox using XSalsa20 and Poly1305) |
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.
Comment seems to be a carryover from the non-fips algo.
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.
Yes, thanks for catching that!
|
||
// Enabled returns true when FIPS mode is enabled | ||
func Enabled() bool { | ||
return os.Getenv(EnvVar) != "" |
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.
@cyli is it sufficient to just check 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.
@nishanttotla The requirements were previously that the GOFIPS
environment variable is set to something at all, but the current plan is to remove this particular environment variable checking support from swarmkit, and just propagate a boolean through. The caller of node/node.go
will configure FIPS to be on or off - this should make it easier to test mixed environments in our integration tests.
It's just a big-ish change, so I was going to do it in a separate PR :|
manager/encryption/encryption.go
Outdated
Algorithm() api.MaybeEncryptedRecord_Algorithm | ||
} | ||
|
||
// MultiDecrypter is a decrypter that will attempts to decrypt with multiple decrypters |
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.
nit: attempts
-> attempt
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.
Fixed, thanks!
be33611
to
37667b9
Compare
LGTM! |
Signed-off-by: cyli <cyli@twistedmatrix.com>
Signed-off-by: cyli <cyli@twistedmatrix.com>
…round constructing one. Also make it a map instead of a list so that as available algorithms increase not every single algorithm needs to be tried to decrypt. Signed-off-by: Ying Li <ying.li@docker.com>
…eck it from the encryption package to determine the encryption defaults. Signed-off-by: Ying Li <ying.li@docker.com>
Thanks @dperny! |
This PR does the following:
Possibly we want to avoid using an environment variable, and just have FIPS be a configuration value when initializing the swarm. However, this would make it more annoying to pass the fips vs non-fips bool through all the layers to the key management facilities as well as raft encryption.
I don't see a use case for going from non-FIPS -> FIPS, because that means that it's possible you have some old data lying around that is not FIPS compliant. Hence if FIPS is set, only fernet can be used, so if you had previous non-FIPS raft data, you would not be able to decrypt it.
But I made it possible for the default decrypter to decrypt both NACL Secretbox and Fernet, because possibly someone would want to go from FIPS -> non-FIPS? cc @endophage
Also I am happy to split this into two PRs - the vendoring+ fernet encrypter/decrypter, and then the actual usage of the fernet encrypter/decrypter.