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

[manager/state] Add fernet as an option for raft encryption #2535

Merged
merged 4 commits into from
Mar 21, 2018

Conversation

cyli
Copy link
Contributor

@cyli cyli commented Mar 1, 2018

This PR does the following:

  1. vendors https://github.com/fernet/fernet-go
  2. adds a fernet encrypter and decrypter to raft encryption
  3. sets it so that if FIPS is enabled, fernet is the only raft encryption/decryption mechanism. otherwise, swarm uses XSalsa20/Poly1305 from secretbox, but can decrypt both.

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.

@cyli cyli force-pushed the fernet-encryption branch 2 times, most recently from e81dd14 to 541bc19 Compare March 2, 2018 00:23
@cyli cyli changed the title WIP: Add fernet as an option for raft encryption WIP: [manager/state] Add fernet as an option for raft encryption Mar 2, 2018
@codecov
Copy link

codecov bot commented Mar 2, 2018

Codecov Report

Merging #2535 into master will increase coverage by 0.06%.
The diff coverage is 92.3%.

@@            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

@cyli cyli mentioned this pull request Mar 8, 2018
2 tasks
@marcusmartins marcusmartins requested review from aaronlehmann and removed request for aaronlehmann March 8, 2018 05:02
Copy link
Collaborator

@aaronlehmann aaronlehmann left a comment

Choose a reason for hiding this comment

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

Looks great.

@cyli
Copy link
Contributor Author

cyli commented Mar 8, 2018

@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.

@cyli cyli changed the title WIP: [manager/state] Add fernet as an option for raft encryption [manager/state] Add fernet as an option for raft encryption Mar 19, 2018
@cyli
Copy link
Contributor Author

cyli commented Mar 19, 2018

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

@dperny
Copy link
Collaborator

dperny commented Mar 19, 2018

I would be fine with removing the envvar in a different PR. I'm reviewing in depth now.

@cyli
Copy link
Contributor Author

cyli commented Mar 19, 2018

@dperny Thanks so much!

Copy link
Collaborator

@dperny dperny left a 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.

}

// MultiDecrypter is a decrypter that will attempts to decrypt with multiple decrypters
type MultiDecrypter map[api.MaybeEncryptedRecord_Algorithm][]Decrypter
Copy link
Collaborator

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?

Copy link
Collaborator

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Collaborator

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?

Copy link
Contributor Author

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

return frnt
}

// Algorithm returns the type of algorithm this is (NACL Secretbox using XSalsa20 and Poly1305)
Copy link
Collaborator

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.

Copy link
Contributor Author

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) != ""
Copy link
Contributor

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?

Copy link
Contributor Author

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 :|

Algorithm() api.MaybeEncryptedRecord_Algorithm
}

// MultiDecrypter is a decrypter that will attempts to decrypt with multiple decrypters
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: attempts -> attempt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, thanks!

@cyli cyli force-pushed the fernet-encryption branch 2 times, most recently from be33611 to 37667b9 Compare March 20, 2018 17:09
@dperny
Copy link
Collaborator

dperny commented Mar 20, 2018

LGTM!

cyli and others added 4 commits March 21, 2018 10:38
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>
@dperny dperny merged commit 3336081 into moby:master Mar 21, 2018
@cyli
Copy link
Contributor Author

cyli commented Mar 21, 2018

Thanks @dperny!

@cyli cyli deleted the fernet-encryption branch March 21, 2018 18:52
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.

4 participants