-
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
Remove duplicate ssl setup in sql/qa projects #57319
Remove duplicate ssl setup in sql/qa projects #57319
Conversation
Pinging @elastic/es-core-infra (:Core/Infra/Build) |
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.
One general comment is I wonder why we are still generating these files on the fly. In other projects (eg :x-pack:qa:smoke-test-plugins-ssl
) we have moved away from generating the ssl support files and instead check them in. What if we were to move them to a shared location in buildSrc and have a plugin that copies them into projects and does the configuration. That would also mean the sql projects here could support fips testing, which I believe is why we moved to static files in the first place.
cc @jkakavas
} | ||
} | ||
|
||
tasks.withType(org.elasticsearch.gradle.testclusters.TestClustersAware){ |
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.
Won't this aggressively realize all tasks? I think we need configureEach
?
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.
good catch. 👀 . Fixed
The reason is that the SQL client doesn't yet support to be configured with certificate/key material in PEM format and thus we can handle this in the same way we do in other qa projects. That's why we have this :
This is a step in the right direction IMHO, but we can always defer that to when we will be able to actually use the key/cert material in the SQL projects |
From what I can see there are two dynamic variables in this generation:
At least |
@jkakavas so I wonder is this dynamic in the creation of those files as described here: #57319 (comment) required or could we remove that so we can have those files generate once, checked in and reused in all environments (local devs, ci, etc)? |
No, we don't need to generate those dynamically. We can use catch-all SANs that would work for all
We have README files in most(wanted to say all but I noticed I didn't put one in We also have an issue open to clean these up and do deduplication: #41646 |
@jkakavas perfect. That should make things simpler and we can remove the overhead on every build run. I look into this. |
@elasticsearchmachine test this please |
1 similar comment
@elasticsearchmachine test this please |
4a77c93
to
86c96e6
Compare
86c96e6
to
63aea79
Compare
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 love this, it will help us untangle much of the setup in the security tests. I added some comments and questions on whether we can make this plugin slightly more generic so that it can handle other test use cases
File keyStoreDir = new File(project.getBuildDir(), "keystore"); | ||
TaskProvider<ExportElasticsearchBuildResourcesTask> exportKeyStore = project.getTasks() | ||
.register("copyTestCertificates", ExportElasticsearchBuildResourcesTask.class, (t) -> { | ||
t.copy("test/ssl/test-client.cert"); |
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.
nit: It doesn't really matter but can we rename the suffices to crt
instead ?
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.
done
t.copy("test/ssl/test-client.cert"); | ||
t.copy("test/ssl/test-client.jks"); | ||
t.copy("test/ssl/test-node.cert"); | ||
t.copy("test/ssl/test-node.jks"); |
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.
Can we also get the private keys into test/ssl/test-X.pem ? In general , given the applicability that this plugin has in so many projects in our security and core tests, I wonder if we can do a little more up front:
- Setup a CA key and certificate
- Generate test-node private key and certificate signed by that CA
- Generate test-client private key and certificate signed by that CA
- Make all the above available as PEM files ( x.crt and x.key ) and in JKS / PKCS12 keystores
- Copy all of them as extra config files
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.
@jkakavas I think we should be able to do that. Can you raise a separate issue for this? I'd like to keep this PR small and focussed.
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.
raised #57606
.getByName(TestClustersPlugin.EXTENSION_NAME); | ||
clusters.all(c -> { | ||
// ceremony to set up ssl | ||
c.setting("xpack.security.transport.ssl.keystore.path", "test-node.jks"); |
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.
Can I override/overwrite this in the build.gradle
file of a subproject where I use this new plugin ?
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.
yes, you can override them in the build script after applying the plugin
The certificates are generated using catch-all SAN in the following procedure: | ||
|
||
1. Generate the node's keystore: | ||
`keytool -genkey -alias test-node -keystore test-node.jks -keyalg RSA -keysize 2048 -validity 712 -dname CN="Elasticsearch Build Test Infrastructure" -keypass keypass -storepass keypass -ext san=dns:localhost,dns:localhost.localdomain,dns:localhost4,dns:localhost4.localdomain4,dns:localhost6,dns:localhost6.localdomain6,ip:127.0.0.1,ip:0:0:0:0:0:0:0:1` |
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 think we can go with something closer to 10 years here instead of 2. We don't gain anything by shorter lifetime. Maybe also add a note in the README with the date these certificates expire so that is more probable someone catches this and updates them before they expire and tests start failing?
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.
done
NamedDomainObjectContainer<ElasticsearchCluster> clusters = (NamedDomainObjectContainer<ElasticsearchCluster>) project | ||
.getExtensions() | ||
.getByName(TestClustersPlugin.EXTENSION_NAME); | ||
clusters.all(c -> { |
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.
Could we also have a conditional here that if we are inFipsJvm()
it would use key and certificate PEM files to set up TLS instead of keystores so that it can work even when the subproject that uses this plugin is running tests in fips mode ? i.e.
*.ssl.key
*.ssl.secure_key_passphrase
*.ssl.certificate
instead of
*.ssl.keystore.path
*.ssl.keystore.secure_password
and
*.ssl.certificate_authorities
instead of
*.ssl.keystore.path
or
*.ssl.truststore.path
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.
@jkakavas same as above. Would like to tackle this in a separate story
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 fine with that as long as we don't apply this plugin to any other subproject until we have the fips handling because it will start failing in CI. ( sql is fine because we mute the tests in fips eitherway )
- make them valid for 10 years - Add note to readme about date of expiration
NamedDomainObjectContainer<ElasticsearchCluster> clusters = (NamedDomainObjectContainer<ElasticsearchCluster>) project | ||
.getExtensions() | ||
.getByName(TestClustersPlugin.EXTENSION_NAME); | ||
clusters.all(c -> { |
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 fine with that as long as we don't apply this plugin to any other subproject until we have the fips handling because it will start failing in CI. ( sql is fine because we mute the tests in fips eitherway )
@elasticmachine test this please |
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.
Man this is about 1000% better. 👍
t.setOutputDir(keyStoreDir); | ||
}); | ||
|
||
project.getPlugins().withType(StandaloneRestTestPlugin.class).configureEach(restTestPlugin -> { |
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 does this compare to project.getPluginManager().withPlugin()
?
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.
getPluginManager() doesn't allow configuration by plugin type (class) which I usually prefer when coding. also depending on your environment it used to be better when doing safer when refactorings etc instead of relying on plugin ids. PluginManager
provides access to AppliedPlugin
which we do not need here.
|
||
project.getPlugins().withType(StandaloneRestTestPlugin.class).configureEach(restTestPlugin -> { | ||
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); | ||
SourceSet testSourceSet = sourceSets.getByName("test"); |
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 can use Util.getJavaTestSourceSet()
.
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.
done
testSourceSet.compiledBy(exportKeyStore); | ||
|
||
project.getTasks() | ||
.withType(org.elasticsearch.gradle.testclusters.TestClustersAware.class) |
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 we have to use the fully qualified name here? Can we add an import?
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.
done
|
||
// Tell the tests we're running with ssl enabled | ||
project.getTasks() | ||
.withType(RestIntegTestTask.class) |
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 instead configure all tasks of RestTestRunnerTask
type. There can be instances where we create these directly w/o creating a RestIntegTestTask
. Also, the latter will hopefully dissapear soon.
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.
Also, would we not want this for unit tests as well? Or is this very specific to integration tests?
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.
changed to use RestTestRunnerTask
. So far I don't think we have unit tests for this kind of testing. I don't see how this would look like tbh.
- Minor cleanup
* Remove duplicate ssl setup in sql/qa projects * Fix enforcement of task instances * Use static data for cert generation * Move ssl testing logic into a plugin * Document test cert creation
* Remove duplicate ssl setup in sql/qa projects * Fix enforcement of task instances * Use static data for cert generation * Move ssl testing logic into a plugin * Document test cert creation
* Remove duplicate ssl setup in sql/qa projects * Fix enforcement of task instances * Use static data for cert generation * Move ssl testing logic into a plugin * Document test cert creation
This is follow up on #57197 as we run ssl cert certification for each
with-ssl
subproject with identical parameters. This PR introduces anelasticsearch.test-with-ssl
plugin that configures projects to use pregenerated certificates for testing that are shipped with buildSrc.with-ssl
test projectsHere's a comparison of running
precommit
locally before(https://gradle-enterprise.elastic.co/s/lhoqf5yix5g24/performance/build) and after(https://gradle-enterprise.elastic.co/s/djogrpm6ci7fs/performance/build)