OpenSearch/x-pack/qa/smoke-test-plugins-ssl/build.gradle

143 lines
5.7 KiB
Groovy
Raw Normal View History

import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.MavenFilteringHack
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
import org.elasticsearch.gradle.test.NodeInfo
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.KeyManager
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.nio.charset.StandardCharsets
import java.security.KeyStore
import java.security.SecureRandom
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile "org.elasticsearch.plugin:x-pack-core:${version}"
}
String outputDir = "${buildDir}/generated-resources/${project.name}"
security: ssl by default on the transport layer This commit adds the necessary changes to make SSL work on the transport layer by default. A large portion of the SSL configuration/settings was re-worked with this change. Some notable highlights include support for PEM cert/keys, reloadable SSL configuration, separate HTTP ssl configuration, and separate LDAP configuration. The following is a list of specific items addressed: * `SSLSettings` renamed to `SSLConfiguration` * `KeyConfig` and `TrustConfig` abstractions created. These hide the details of how `KeyManager[]` and `TrustManager[]` are loaded. These are also responsible for settings validation (ie keystore password is not null) * Configuration fallback is changed. Previously any setting would fallback to the "global" value (`xpack.security.ssl.*`). Now a keystore path, key path, ca paths, or truststore path must be specified otherwise the configuration for that key/trust will fallback to the global configuration. In other words if you want to change part of a keystore or truststore in a profile you need to supply all the information. This could be considered breaking if a user relied on the old fallback * JDK trusted certificates (`cacerts`) are trusted by default (breaking change). This can be disabled via a setting. * We now monitor the SSL files for changes and enable dynamic reloading of the configuration. This will make it easier for users when they are getting set up with certificates so they do not need to restart every time. This can be disabled via a setting * LDAP realms can now have their own SSL configurations * HTTP can now have its own SSL configuration * SSL is enabled by default on the transport layer only. Hostname verification is enabled as well. On startup if no global SSL settings are present and SSL is configured to be used, we auto generate one based on the default CA that is shipped. This process includes a best effort attempt to generate the subject alternative names. * `xpack.security.ssl.hostname_verification` is deprecated in favor of `xpack.security.ssl.hostname_verification.enabled` * added Bouncy Castle info to NOTICE * consolidated NOTICE and LICENSE files Closes elastic/elasticsearch#14 Closes elastic/elasticsearch#34 Closes elastic/elasticsearch#1483 Closes elastic/elasticsearch#1933 Addresses security portion of elastic/elasticsearch#673 Original commit: elastic/x-pack-elasticsearch@7c359db90bbea93110f3824ede82c09eafcd2f79
2016-04-12 09:19:07 -04:00
task copyXPackPluginProps(type: Copy) {
from project(xpackModule('core')).file('src/main/plugin-metadata')
from project(xpackModule('core')).tasks.pluginProperties
security: ssl by default on the transport layer This commit adds the necessary changes to make SSL work on the transport layer by default. A large portion of the SSL configuration/settings was re-worked with this change. Some notable highlights include support for PEM cert/keys, reloadable SSL configuration, separate HTTP ssl configuration, and separate LDAP configuration. The following is a list of specific items addressed: * `SSLSettings` renamed to `SSLConfiguration` * `KeyConfig` and `TrustConfig` abstractions created. These hide the details of how `KeyManager[]` and `TrustManager[]` are loaded. These are also responsible for settings validation (ie keystore password is not null) * Configuration fallback is changed. Previously any setting would fallback to the "global" value (`xpack.security.ssl.*`). Now a keystore path, key path, ca paths, or truststore path must be specified otherwise the configuration for that key/trust will fallback to the global configuration. In other words if you want to change part of a keystore or truststore in a profile you need to supply all the information. This could be considered breaking if a user relied on the old fallback * JDK trusted certificates (`cacerts`) are trusted by default (breaking change). This can be disabled via a setting. * We now monitor the SSL files for changes and enable dynamic reloading of the configuration. This will make it easier for users when they are getting set up with certificates so they do not need to restart every time. This can be disabled via a setting * LDAP realms can now have their own SSL configurations * HTTP can now have its own SSL configuration * SSL is enabled by default on the transport layer only. Hostname verification is enabled as well. On startup if no global SSL settings are present and SSL is configured to be used, we auto generate one based on the default CA that is shipped. This process includes a best effort attempt to generate the subject alternative names. * `xpack.security.ssl.hostname_verification` is deprecated in favor of `xpack.security.ssl.hostname_verification.enabled` * added Bouncy Castle info to NOTICE * consolidated NOTICE and LICENSE files Closes elastic/elasticsearch#14 Closes elastic/elasticsearch#34 Closes elastic/elasticsearch#1483 Closes elastic/elasticsearch#1933 Addresses security portion of elastic/elasticsearch#673 Original commit: elastic/x-pack-elasticsearch@7c359db90bbea93110f3824ede82c09eafcd2f79
2016-04-12 09:19:07 -04:00
into outputDir
}
project.sourceSets.test.output.dir(outputDir, builtBy: copyXPackPluginProps)
// location of generated keystores and certificates
File keystoreDir = new File(project.buildDir, 'keystore')
File nodeKeystore = file("$keystoreDir/testnode.jks")
File nodeKey = file("$keystoreDir/testnode.pem")
File nodeCert = file("$keystoreDir/testnode.crt")
File clientKeyStore = file("$keystoreDir/testclient.jks")
File clientKey = file("$keystoreDir/testclient.pem")
File clientCert = file("$keystoreDir/testclient.crt")
// Add keystores to test classpath: it expects it there
task copyKeyCerts(type: Copy) {
from('./') {
include '*.crt', '*.pem', '*.jks'
}
into keystoreDir
}
// Add keystores to test classpath: it expects it there
sourceSets.test.resources.srcDir(keystoreDir)
processTestResources.dependsOn(copyKeyCerts)
integTestCluster.dependsOn(copyKeyCerts)
ext.pluginsCount = 0
project(':plugins').getChildProjects().each { pluginName, pluginProject ->
// need to get a non-decorated project object, so must re-lookup the project by path
integTestCluster.plugin(pluginProject.path)
pluginsCount += 1
}
integTestCluster {
setting 'xpack.monitoring.collection.interval', '1s'
setting 'xpack.monitoring.exporters._http.type', 'http'
setting 'xpack.monitoring.exporters._http.enabled', 'false'
setting 'xpack.ssl.certificate_authorities', 'testnode.crt'
setting 'xpack.monitoring.exporters._http.auth.username', 'monitoring_agent'
setting 'xpack.monitoring.exporters._http.auth.password', 'x-pack-test-password'
setting 'xpack.monitoring.exporters._http.ssl.verification_mode', 'full'
setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.enabled', 'true'
setting 'xpack.security.http.ssl.enabled', 'true'
setting 'xpack.security.http.ssl.key', 'testnode.pem'
setting 'xpack.security.http.ssl.certificate', 'testnode.crt'
keystoreSetting 'xpack.security.http.ssl.secure_key_passphrase', 'testnode'
setting 'xpack.ilm.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
// copy keystores, keys and certificates into config/
extraConfigFile nodeKeystore.name, nodeKeystore
extraConfigFile nodeKey.name, nodeKey
extraConfigFile nodeCert.name, nodeCert
extraConfigFile clientKeyStore.name, clientKeyStore
extraConfigFile clientKey.name, clientKey
extraConfigFile clientCert.name, clientCert
setupCommand 'setupTestUser',
'bin/elasticsearch-users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser'
setupCommand 'setupMonitoringUser',
'bin/elasticsearch-users', 'useradd', 'monitoring_agent', '-p', 'x-pack-test-password', '-r', 'remote_monitoring_agent'
waitCondition = { NodeInfo node, AntBuilder ant ->
File tmpFile = new File(node.cwd, 'wait.success')
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(clientKeyStore.newInputStream(), 'testclient'.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// We don't need a KeyManager as there won't be client auth required so pass an empty array
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(new KeyManager[0], tmf.getTrustManagers(), new SecureRandom());
for (int i = 0; i < 10; i++) {
// we use custom wait logic here for HTTPS
HttpsURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpsURLConnection) new URL("https://${node.httpUri()}/_cluster/health?wait_for_nodes=${numNodes}&wait_for_status=yellow").openConnection();
httpURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
httpURLConnection.setRequestProperty("Authorization", "Basic " +
Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)));
httpURLConnection.setRequestMethod("GET");
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == 200) {
tmpFile.withWriter StandardCharsets.UTF_8.name(), {
it.write(httpURLConnection.getInputStream().getText(StandardCharsets.UTF_8.name()))
}
}
} catch (IOException e) {
if (i == 9) {
logger.error("final attempt of calling cluster health failed", e)
} else {
logger.debug("failed to call cluster health", e)
}
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
// did not start, so wait a bit before trying again
Thread.sleep(500L);
}
return tmpFile.exists()
}
}
ext.expansions = [
'expected.plugins.count': pluginsCount
]
processTestResources {
from(sourceSets.test.resources.srcDirs) {
include '**/*.yml'
inputs.properties(expansions)
MavenFilteringHack.filter(it, expansions)
}
}