-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Refactored FIPS Checks into a Single Class (For Issue #34772) #36677
Conversation
Created a class FIPS Checks with a FIPS interface that allows you to perform a fips check per method, all checks are called at once,
Pinging @elastic/es-security |
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.
Hi @LuisAlvelaMendes !
Thanks once again for taking this up :) I did a first pass of your PR and I've left several comments and suggestions about how I think this could be further refactored. Let me know what you think.
Please also make sure that you have configured your git installation correctly to set your name in the commits ( https://help.github.com/articles/setting-your-username-in-git/ )
Finally also make sure that you read through or contribution guide and follow all the steps mentioned there. At the absolute minimum, ensure that precommit check is passing.
Let me know if you have any questions
/** | ||
* Context that is passed to every bootstrap check to make decisions on. | ||
*/ | ||
public class FIPSContext { |
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 don't think we actually need a FIPSContext
class since we only encapsulate the settings here ( as opposed to i.e. a BootstrapContext
that encapsulates settings and metadata. )
/** | ||
* Encapsulates a FIPS check. | ||
*/ | ||
public interface FIPSInterface { |
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'm not entirely sure it is required to have the FIPS checks implement an interface, but if we go down this path ,I think that conceptually it would make more sense to have a FIPScheck
interface that all the relevant checks ( settings, password hash etc. ) would then implement.
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 purpose would be to return an adequate FIPSCheckResult while also maintaining some consistency with how bootstrap checks were written .. I'm not quite sure what you mean by having the checks themselves implement it.
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 was thinking of an interface named FIPSCheck
that then the checks like FipsLicencingCheck
or FipsPasswordHashingAlgoCheck
would implement. But I do think we don't necessarily need this either, there is no mandate to simulate bootstrap checks implementation. Same with FIPSCheckResult
, it feels like an unnecessary abstraction. WDYT ?
|
||
public FIPSCheckResult keystoreCheck(FIPSContext context) { | ||
|
||
if (XPackSettings.FIPS_MODE_ENABLED.get(context.settings)) { |
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.
Depending on other changes/suggestions, we should probably conditionally apply the FipsChecks if FIPS_MODE_ENABLED already in Security.java
so that we don't have to check the settings value each time.
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.
Do you mean add an if clause like
if (XPackSettings.FIPS_MODE_ENABLED.get(context.settings)) {}
surrounding it? I'm not sure what impact that would have
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 meant that we can have the if clause once in Security.java
and call check()
on all the checks (or the one check()
if we decide to implement FipsChecks
in a simpler manner ) IF fips_mode
is set
return FIPSCheckResult.success(); | ||
} | ||
|
||
else { |
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.
we should probably consolidate the error messages from the results so that we don't only present the first (from a seemingly arbitrary check order) error that was encountered to the user
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.
How do you suggest we do it then?
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 was thinking something similar to how we use addValidationError
@@ -0,0 +1,76 @@ | |||
/* | |||
* Licensed to Elasticsearch under one or more contributor |
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.
Should be under Elastic License
@@ -0,0 +1,16 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
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.
please remove unrelated files from the PR
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
public class FIPS140JKSKeystoreBootstrapCheckTests extends ESTestCase { | ||
public class JKSKeystoreFIPSCheckTests extends ESTestCase { |
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 we have all checks in a single FipsChecks class, I think it would make more sense to refactor all the classes that test the old Bootstrap tests into a FipsChecksTests class and have methods that test all checks there
FIPS140LicenseBootstrapCheck.ALLOWED_LICENSE_OPERATION_MODES.contains(license.operationMode()) == false) { | ||
throw new IllegalStateException("FIPS mode cannot be used with a [" + license.operationMode() + | ||
|
||
License.OperationMode licenseOperationMode = FIPSChecksInstance.get().getLicenseOperationMode(); |
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.
we should still get the operation mode from LicenseService.getLicense(state.metaData())
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.
How, exactly? I thought we had established the license operations should be independant from any metadata.
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.
Apologies, I'm not sure when this was established. It can be that my comment in #34772 (comment) was misleading in that regard. I think we can safely use License license = LicenseService.getLicense(state.metaData());
here, do you see any issue with this ?
@@ -499,6 +498,10 @@ protected Clock getClock() { | |||
securityActionFilter.set(new SecurityActionFilter(authcService.get(), authzService, getLicenseState(), | |||
requestInterceptors, threadPool, securityContext.get(), destructiveOperations)); | |||
|
|||
FIPSContext context = new FIPSContext(settings); | |||
FIPSChecksInstance.set(new FIPSChecks(getLicenseState().getOperationMode())); |
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 do we need a FIPSChecksInstance
?
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.
So we can get that instance with those values from the instruction FIPSChecksInstance.get().check(context, env);
and call the checks
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 question was about why is it necessary to wrap the FIPSChecks
in a SetOnce
and not do
FIPSContext context = new FIPSContext(settings);
FIPSChecks checks = new FIPSChecks(getLicenseState().getOperationMode())
checks.check(context, env);
check Bootstraps check in the commented thing refactored tests and also calling FIPSChecks on Bootstrap instead BUILD Sucessfull, still have to correct metadata and tests Fips Checks Refactored Created a class FIPS Checks with a FIPS interface that allows you to perform a fips check per method, all checks are called at once, re-added deleted file
@LuisAlvelaMendes Thanks for the updates and apologies, I just noticed the new commits. I will take another look tomorrow, please feel free to ping me directly here every time there is a pending action on my side as otherwise your updates might get lost in the sea of Github notifications :) |
I thought I'd ping you and see how this is going and if you're still interested in seeing this PR through. If there's anything you'd want to discuss, feel free to add a comment here. e124f8a made me think that you had addressed some of the points we discussed above, hence my comment in #36677 (comment), but I then saw that this is the same as 7a4e6ff that you had committed earlier. |
@jkakavas Sorry, but due to some personal things I will not be able conclude this pull request. |
Closing this in favor of #47499 |
I have refactored all FIPS140 checks indicated in this issue: #34772
Into a single FIPSChecks class, I also tried to implement a custom FIPSContext and interface that operate much like Bootstrap contexts, except without worrying about sometimes not being enforced (as FIPS is always enforced) and without requiring any metadata.
I also modified the unit tests to fit the changes and tried to call this class and the check method (that runs all checks) in the appropriate place, as discussed: