Skip to content

Commit d31e10a

Browse files
authored
Verify signatures on official plugins (#30800)
We sign our official plugins yet this is not well-advertised and not at all consumed during plugin installation. For plugins that are installed over the intertubes, verifying that the downloaded artifact is signed by our signing key would establish both integrity and validity of the downloaded artifact. The chain of trust here is simple: our installable artifacts (archive and package distributions) so that if a user trusts our packages via their signatures, and our plugin installer (which would be executing trusted code) verifies the downloaded plugin, then the user can trust the downloaded plugin too. This commit adds verification of official plugins downloaded during installation. We do not add verification for offline plugin installs; a user can download our signatures and verify the artifacts themselves. This commit also needs to solve a few interesting challenges. One of these is that we want the bouncy castle JARs on the classpath only for the plugin installer, but not for the runtime Elasticsearch. Additionally, we want these JARs to not be present for the JAR hell checks. To address this, we shift these JARs into a sub-directory of lib (lib/tools/plugin-cli) that is only loaded for the plugin installer, and in the plugin installer we filter any JARs in this directory from the JAR hell check.
1 parent adc2d40 commit d31e10a

File tree

17 files changed

+458
-59
lines changed

17 files changed

+458
-59
lines changed

distribution/archives/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ task createPluginsDir(type: EmptyDirTask) {
4949
CopySpec archiveFiles(CopySpec modulesFiles, String distributionType, boolean oss) {
5050
return copySpec {
5151
into("elasticsearch-${version}") {
52-
with libFiles
52+
into('lib') {
53+
with libFiles
54+
}
5355
into('config') {
5456
dirMode 0750
5557
fileMode 0660

distribution/build.gradle

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,13 +227,15 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
227227
* Common files in all distributions *
228228
*****************************************************************************/
229229
libFiles = copySpec {
230-
into 'lib'
230+
// delay by using closures, since they have not yet been configured, so no jar task exists yet
231231
from { project(':server').jar }
232232
from { project(':server').configurations.runtime }
233233
from { project(':libs:plugin-classloader').jar }
234-
// delay add tools using closures, since they have not yet been configured, so no jar task exists yet
235234
from { project(':distribution:tools:launchers').jar }
236-
from { project(':distribution:tools:plugin-cli').jar }
235+
into('tools/plugin-cli') {
236+
from { project(':distribution:tools:plugin-cli').jar }
237+
from { project(':distribution:tools:plugin-cli').configurations.runtime }
238+
}
237239
}
238240

239241
modulesFiles = { oss ->

distribution/packages/build.gradle

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,23 @@ Closure commonPackageConfig(String type, boolean oss) {
124124
include 'README.textile'
125125
fileMode 0644
126126
}
127+
into('lib') {
128+
with copySpec {
129+
with libFiles
130+
// we need to specify every intermediate directory so we iterate through the parents; duplicate calls with the same part are fine
131+
eachFile { FileCopyDetails fcp ->
132+
String[] segments = fcp.relativePath.segments
133+
for (int i = segments.length - 2; i > 0 && segments[i] != 'lib'; --i) {
134+
directory('/' + segments[0..i].join('/'), 0755)
135+
}
136+
fcp.mode = 0644
137+
}
138+
}
139+
}
127140
into('modules') {
128141
with copySpec {
129142
with modulesFiles(oss)
130-
// we need to specify every intermediate directory, but modules could have sub directories
131-
// and there might not be any files as direct children of intermediates (eg platform)
132-
// so we must iterate through the parents, but duplicate calls with the same path
133-
// are ok (they don't show up in the built packages)
143+
// we need to specify every intermediate directory so we iterate through the parents; duplicate calls with the same part are fine
134144
eachFile { FileCopyDetails fcp ->
135145
String[] segments = fcp.relativePath.segments
136146
for (int i = segments.length - 2; i > 0 && segments[i] != 'modules'; --i) {
@@ -251,8 +261,8 @@ ospackage {
251261
signingKeyId = project.hasProperty('signing.keyId') ? project.property('signing.keyId') : 'D88E42B4'
252262
signingKeyPassphrase = project.property('signing.password')
253263
signingKeyRingFile = project.hasProperty('signing.secretKeyRingFile') ?
254-
project.file(project.property('signing.secretKeyRingFile')) :
255-
new File(new File(System.getProperty('user.home'), '.gnupg'), 'secring.gpg')
264+
project.file(project.property('signing.secretKeyRingFile')) :
265+
new File(new File(System.getProperty('user.home'), '.gnupg'), 'secring.gpg')
256266
}
257267

258268
requires('coreutils')
@@ -263,7 +273,6 @@ ospackage {
263273
permissionGroup 'root'
264274

265275
into '/usr/share/elasticsearch'
266-
with libFiles
267276
with noticeFile
268277
}
269278

distribution/src/bin/elasticsearch-cli

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ do
1010
source "`dirname "$0"`"/$additional_source
1111
done
1212

13+
IFS=';' read -r -a additional_classpath_directories <<< "$ES_ADDITIONAL_CLASSPATH_DIRECTORIES"
14+
for additional_classpath_directory in "${additional_classpath_directories[@]}"
15+
do
16+
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/$additional_classpath_directory/*"
17+
done
18+
1319
exec \
1420
"$JAVA" \
1521
$ES_JAVA_OPTS \

distribution/src/bin/elasticsearch-cli.bat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ for /f "tokens=1*" %%a in ("%*") do (
1111
set arguments=%%b
1212
)
1313

14+
if defined ES_ADDITIONAL_CLASSPATH_DIRECTORIES (
15+
for %%a in ("%ES_ADDITIONAL_CLASSPATH_DIRECTORIES:;=","%") do (
16+
set ES_CLASSPATH=!ES_CLASSPATH!;!ES_HOME!/%%a/*
17+
)
18+
)
19+
1420
%JAVA% ^
1521
%ES_JAVA_OPTS% ^
1622
-Des.path.home="%ES_HOME%" ^
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/bin/bash
22

3-
"`dirname "$0"`"/elasticsearch-cli \
3+
ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/plugin-cli \
4+
"`dirname "$0"`"/elasticsearch-cli \
45
org.elasticsearch.plugins.PluginCli \
56
"$@"

distribution/src/bin/elasticsearch-plugin.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
setlocal enabledelayedexpansion
44
setlocal enableextensions
55

6+
set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/plugin-cli
67
call "%~dp0elasticsearch-cli.bat" ^
78
org.elasticsearch.plugins.PluginCli ^
89
%* ^

distribution/tools/plugin-cli/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,22 @@
1919

2020
apply plugin: 'elasticsearch.build'
2121

22+
archivesBaseName = 'elasticsearch-plugin-cli'
23+
2224
dependencies {
2325
compileOnly "org.elasticsearch:elasticsearch:${version}"
2426
compileOnly "org.elasticsearch:elasticsearch-cli:${version}"
27+
compile "org.bouncycastle:bcpg-jdk15on:1.59"
28+
compile "org.bouncycastle:bcprov-jdk15on:1.59"
2529
testCompile "org.elasticsearch.test:framework:${version}"
2630
testCompile 'com.google.jimfs:jimfs:1.1'
2731
testCompile 'com.google.guava:guava:18.0'
2832
}
2933

34+
dependencyLicenses {
35+
mapping from: /bc.*/, to: 'bouncycastle'
36+
}
37+
3038
test {
3139
// TODO: find a way to add permissions for the tests in this module
3240
systemProperty 'tests.security.manager', 'false'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ee93e5376bb6cf0a15c027b5f5e4393f2738e709
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2507204241ab450456bdb8e8c0a8f986e418bd99

0 commit comments

Comments
 (0)