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

[TEST] Reload secure settings transport IT #31180

Merged

Conversation

albertzaharovits
Copy link
Contributor

@albertzaharovits albertzaharovits commented Jun 7, 2018

Adds Integration Tests for the TransportNodesReloadSecureSettingsAction . Specifically, it tests:

  • SecureSettings are retrievable when plugins are notified
  • missing/invalid keystore is handled gracefully (no spurious reload calls)
  • reloadable plugins should fail independently (a throw during a plugin reload on any node will not interrupt the reload flow in any way - it will just return the exception in the response)

Previously there were tests only for the individual plugins implementing the reload handler, no tests for the "broadcast password - decrypt keystore - notify plugins - close keystore" logic.

One obstacle I struggled with was generating keystores programatically. They are test resources in the present implementation. The problem is that saving a generated keystores requires the Java SM permissions to change file permissions. This is not granted for the server codebase. In the real world the keystore is generated before the Security Manager is installed.

Relates: #29135
CC @elastic/es-security

@albertzaharovits albertzaharovits added >test Issues or PRs that are addressing/adding tests review :Core/Infra/Settings Settings infrastructure and APIs labels Jun 7, 2018
@albertzaharovits albertzaharovits self-assigned this Jun 7, 2018
@albertzaharovits albertzaharovits requested a review from jaymode June 7, 2018 15:59
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@@ -102,6 +104,8 @@ protected NodeRequest newNodeRequest(String nodeId, NodesReloadSecureSettingsReq
try {
p.reload(settingsWithKeystore);
} catch (final Exception e) {
logger.warn((Supplier<?>) () -> new ParameterizedMessage("Plugin [{}] threw [{}] on node [{}]",
p.getClass().getSimpleName(), e.getClass().getSimpleName(), clusterService.localNode().getName()), e);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

1/2 non test change

assert password.length == 0;
if (password.length != 0) {
throw new IllegalArgumentException("Keystore format does not accept non-empty passwords");
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

2/2 non test change
This password is no longer internal API, there are code paths where the user supplies its value.

@@ -102,6 +104,8 @@ protected NodeRequest newNodeRequest(String nodeId, NodesReloadSecureSettingsReq
try {
p.reload(settingsWithKeystore);
} catch (final Exception e) {
logger.warn((Supplier<?>) () -> new ParameterizedMessage("Plugin [{}] threw [{}] during reload",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

1/2 non test change

Copy link
Member

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 need the class name in the message since we also log the exception

Copy link
Member

@jaymode jaymode left a comment

Choose a reason for hiding this comment

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

I left some comments. Regarding not being able to write a keystore in tests, maybe someone from @elastic/es-core-infra could provide some thoughts about whether there is a better way than checking the files in as a resource.

@@ -102,6 +104,8 @@ protected NodeRequest newNodeRequest(String nodeId, NodesReloadSecureSettingsReq
try {
p.reload(settingsWithKeystore);
} catch (final Exception e) {
logger.warn((Supplier<?>) () -> new ParameterizedMessage("Plugin [{}] threw [{}] during reload",
Copy link
Member

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 need the class name in the message since we also log the exception


@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(MockReloadablePlugin.class, MisbehavingReloadablePlugin.class);
Copy link
Member

Choose a reason for hiding this comment

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

should we randomize the order? Sometimes the misbehaving goes first?

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! I was under the impression that the order here is not relevant when iterating oveer Plugin instances. But it is, and this is a good thing!


@Override
public List<Setting<?>> getSettings() {
return Arrays.asList(DUMMY_SECRET_SETTING);
Copy link
Member

Choose a reason for hiding this comment

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

Collections.singletonList


public static class MisbehavingReloadablePlugin extends CountingReloadablePlugin {

private volatile boolean sulky = false;
Copy link
Member

Choose a reason for hiding this comment

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

can we rename this to shouldThrow? Then just have a setter for the method? Also, let's make this non-volatile and the methods synchronized since we technically do a CAS in reload

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, I've been lax here.

@albertzaharovits
Copy link
Contributor Author

Thank you @jaymode .
I have addressed your comments. I will wait a little for suggestions, but probably start pulling someone's coat over slack.

Copy link
Member

@jaymode jaymode left a comment

Choose a reason for hiding this comment

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

LGTM pending discussion with the core-infra team regarding the updating of the keystore during the test

@albertzaharovits
Copy link
Contributor Author

@jaymode The matter did not piqued any interest.
I have found a workaround which does not require any permission changes.
The trick simply ignores the RuntimePermission("accessUserInformation"). This is possible because the access exception is thrown after the keystore has been written, as a matter of precaution against broken umask settings. This is not required in the test environment.
Also, the keystore contains only the seed value, which is alright in this case, as the setString is package-private.

Please take another short look, thanks!

Copy link
Member

@jaymode jaymode left a comment

Choose a reason for hiding this comment

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

Left one comment. Otherwise LGTM as long as CI is happy.

protected Collection<Class<? extends Plugin>> nodePlugins() {
final List<Class<? extends Plugin>> plugins = Arrays.asList(MockReloadablePlugin.class, MisbehavingReloadablePlugin.class);
// shuffle as reload is called in order
Collections.shuffle(plugins);
Copy link
Member

Choose a reason for hiding this comment

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

you need to use Collections.shuffle(plugins, random()) to fix the build failure

@albertzaharovits
Copy link
Contributor Author

albertzaharovits commented Jun 16, 2018

Appreciate the prompt review! Thank you, I will make sure CI runs several times before merging the feature branch!

@albertzaharovits albertzaharovits merged commit 80f6d9e into elastic:reload-secure-store-action Jun 16, 2018
@albertzaharovits albertzaharovits deleted the ReloadIT branch June 16, 2018 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Core/Infra/Settings Settings infrastructure and APIs >test Issues or PRs that are addressing/adding tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants