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

Access SSL contexts using names instead of Settings #30953

Merged
merged 39 commits into from
Jul 13, 2018

Conversation

tvernum
Copy link
Contributor

@tvernum tvernum commented May 30, 2018

Historically we have loaded SSL objects (such as SSLContext,
SSLIOSessionStrategy) by passing in the SSL settings, constructing a
new SSL configuration from those settings and then looking for a
cached object that matches those settings.

The primary issue with this approach is that it requires a fully
configured Settings object to be available any time the SSL context
needs to be loaded. If the Settings include SecureSettings (such as
passwords for keys or keystores) then this is not true, and the cached
SSL object cannot be loaded at runtime.

This commit introduces an alternative approach of naming every cached
ssl configuration, so that it is possible to load the SSL context for
a named configuration (such as "xpack.http.ssl"). This means that the
calling code does not need to have ongoing access to the secure
settings that were used to load the configuration.

Resolves: #30344

tvernum added 10 commits May 7, 2018 16:36
Historically we have loaded SSL objects (such as SSLContext,
SSLIOSessionStrategy) by passing in the SSL settings, constructing a
new SSL configuration from those settings and then looking for a
cached object that matches those settings.

The primary issue with this approach is that it requires a fully
configured Settings object to be available any time the SSL context
needs to be loaded. If the Settings include SecureSettings (such as
passwords for keys or keystores) then this is not true, and the cached
SSL object cannot be loaded at runtime.

This commit introduces an alternative approach of naming every cached
ssl configuration, so that it is possible to load the SSL context for
a named configuration (such as "xpack.http.ssl"). This means that the
calling code does not need to have ongoing access to the secure
settings that were used to load the configuration.
@tvernum tvernum added WIP :Security/TLS SSL/TLS, Certificates labels May 30, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@tvernum
Copy link
Contributor Author

tvernum commented May 30, 2018

This is mostly done, but I need to do another pass over it before reviews

@jaymode
Copy link
Member

jaymode commented Jun 13, 2018

This is mostly done, but I need to do another pass over it before reviews

@tvernum how are we looking? Should we go ahead with reviews?

@tvernum
Copy link
Contributor Author

tvernum commented Jun 15, 2018

@jaymode It's ready for review now.
I had 1 last test I wanted to write, and that got caught up in various changes to master (broken builds, unused imports, etc).

@tvernum tvernum added the review label Jun 15, 2018
@tvernum
Copy link
Contributor Author

tvernum commented Jun 22, 2018

I'm going to need to think through a couple more issues on this one.
It fails on dynamic settings for monitoring, and I don't have a clear solution in my head yet.

As it stands, the SSLService configures each context name to have a fixed configuration, so updating monitoring SSL settings dynamically has no affect.
I can fix that, but then we run back into the original problem that triggered this.

What I think I need is to be able to apply an update to a named configuration (probably by getting the config, merging the new settings into it, and then putting that config back)

contextName = contextName.substring(0, contextName.length() - 1);
}
final SSLConfiguration configuration = sslConfigurations.get(contextName);
if (configuration == null && logger.isTraceEnabled()) {
Copy link
Member

Choose a reason for hiding this comment

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

derp isTraceEnabled means the warn log message only gets logged when trace is enabled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤦‍♂️

*/
@Deprecated
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 handle this as part of this change or do you want it to be separate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm planning on tackling it, it's just still being used in a few places & will require some more work.

storeSslConfiguration(key, configuration);
sslContextHolders.computeIfAbsent(configuration, this::createSslContext);
}
});

// transport is special because we want to use a auto-generated key when there isn't one
Copy link
Member

Choose a reason for hiding this comment

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

can you do me a favor and delete this comment? It is a left over from me that is no longer relevant

profileSettings.forEach((profileSetting) ->
sslConfigurations.computeIfAbsent(new SSLConfiguration(profileSetting, transportSSLConfiguration), this::createSslContext));
return Collections.unmodifiableMap(sslConfigurations);
this.sslConfigurations.put("_transport", transportSSLConfiguration);
Copy link
Member

Choose a reason for hiding this comment

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

the use of _ as our prefix to avoid collisions or to make something special concerns me. In the IpFilter we use .http for HTTP to avoid collisions since it is much harder to create a setting/name that would result in that as the key. Maybe we should use . instead of _ 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.

Actually I have no idea why I'm naming this one in a special way. It should just be xpack.security.transport.ssl the only special one should be .global

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Scrap that, .global should just be xpack.ssl


@ESIntegTestCase.ClusterScope(scope = Scope.SUITE,
numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0, supportsDedicatedMasters = false)
public class HttpSslExporterIT extends MonitoringIntegTestCase {
Copy link
Member

Choose a reason for hiding this comment

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

this is a nit, but maybe HttpExporterSslIT so that if someone is looking for HttpExporter test classes, they easily find it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I originally named it HttpExporterSslIT but the combination of lower-case l followed up uppercase I offended my eyes, so I changed it. I'll switch it back.


@Override
protected Settings nodeSettings(int nodeOrdinal) {
if (keystore == null) {
Copy link
Member

Choose a reason for hiding this comment

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

@jkakavas is there something that should be done here for the FIPS work?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, thanks for catching this.

@tvernum can you please add the key and certificate files and use those instead of the keystore when setting up the MockWebServer ?
Using it for the truststore is fine, even in a FIPS-140 JVM so no additional requirements here. When I went through our tests, I opted for using the certificate for certificate_authorities instead of the JKS for truststore (when applicable and made sense ) mainly for consistency, but we don't have to .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh FIPS why do you want to make my life complicated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need to use the truststore (rather than certificate_authorities) because I need to test passwords, and PEM certs don't have passwords.

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!

@tvernum tvernum merged commit c662565 into elastic:master Jul 13, 2018
if (useGlobalSSL) {
connectionSettings = Settings.EMPTY;
sslConfiguration = sslService.getSSLConfiguration("_global");
Copy link
Member

Choose a reason for hiding this comment

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

_global -> xpack.ssl

tvernum added a commit that referenced this pull request Jul 20, 2018
These tests were creating a SSL service that was not aware of the
realm that they were trying to test.
This no longer works.
tvernum added a commit that referenced this pull request Jul 20, 2018
Historically we have loaded SSL objects (such as SSLContext,
SSLIOSessionStrategy) by passing in the SSL settings, constructing a
new SSL configuration from those settings and then looking for a
cached object that matches those settings.

The primary issue with this approach is that it requires a fully
configured Settings object to be available any time the SSL context
needs to be loaded. If the Settings include SecureSettings (such as
passwords for keys or keystores) then this is not true, and the cached
SSL object cannot be loaded at runtime.

This commit introduces an alternative approach of naming every cached
ssl configuration, so that it is possible to load the SSL context for
a named configuration (such as "xpack.http.ssl"). This means that the
calling code does not need to have ongoing access to the secure
settings that were used to load the configuration.

This change also allows monitoring exporters to use SSL passwords
from secure settings, however an exporter that uses a secure SSL setting
(e.g. truststore.secure_password) may not have its SSL settings updated
dynamically (this is prevented by a settings validator).
Exporters without secure settings can continue to be defined and updated
dynamically.

Backport of:
- c662565
- edbea73
- 6f2b7dc
martijnvg added a commit that referenced this pull request Jul 21, 2018
* es/6.x: (24 commits)
  Fix broken backport
  Switch full-cluster-restart to new style Requests (#32140)
  Fix multi level nested sort (#32204)
  MINOR: Remove unused `IndexDynamicSettings` (#32237) (#32248)
  [Tests] Remove QueryStringQueryBuilderTests#toQuery class assertions (#32236)
  Switch rolling restart to new style Requests (#32147)
  Enhance Parent circuit breaker error message (#32056)
  [ML] Use default request durability for .ml-state index (#32233)
  Enable testing in FIPS140 JVM (#31666) (#32231)
  Remove indices stats timeout from monitoring docs
  TESTS: Check for Netty resource leaks (#31861) (#32225)
  Rename ranking evaluation response section (#32166)
  Dependencies: Upgrade to joda time 2.10 (#32160)
  Backport SSL context names (#30953) to 6.x (#32223)
  Require Gradle 4.9  as minimum version (#32200)
  Detect old trial licenses and mimic behaviour (#32209)
  Painless: Simplify Naming in Lookup Package (#32177)
  add support for write index resolution when creating/updating documents (#31520)
  A replica can be promoted and started in one cluster state update (#32042)
  Rest test - allow for snapshots to take 0 milliseconds
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants