Skip to content

Commit ee98e85

Browse files
authored
Tighten up write permissions in Docker image (#73942)
Recursively remove write access from the bin, jdk, lib and modules directories, since this access is not required, and removing it makes it harder to exploit other issues in an ES distribution.
1 parent 1f1c8b0 commit ee98e85

File tree

5 files changed

+37
-22
lines changed

5 files changed

+37
-22
lines changed

distribution/docker/src/docker/Dockerfile

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,24 +230,26 @@ RUN tar -zxf /opt/elasticsearch.tar.gz --strip-components=1
230230
COPY ${config_dir}/elasticsearch.yml config/
231231
COPY ${config_dir}/log4j2.properties config/log4j2.docker.properties
232232
233-
# 1. Configure the distribution for Docker
234-
# 2. Ensure directories are created. Most already are, but make sure
235-
# 3. Apply correct permissions
236-
# 4. Move the distribution's default logging config aside
237-
# 5. Move the generated docker logging config so that it is the default
238-
# 6. Apply more correct permissions
239-
# 7. The JDK's directories' permissions don't allow `java` to be executed under a different
240-
# group to the default. Fix this.
241-
# 8. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
242-
# 9. Ensure all files are world-readable by default. It should be possible to
243-
# examine the contents of the image under any UID:GID
233+
# 1. Configure the distribution for Docker
234+
# 2. Ensure directories are created. Most already are, but make sure
235+
# 3. Apply correct permissions
236+
# 4. Move the distribution's default logging config aside
237+
# 5. Generate a docker logging config, to be used by default
238+
# 6. Apply more correct permissions
239+
# 7. The JDK's directories' permissions don't allow `java` to be executed under a different
240+
# group to the default. Fix this.
241+
# 8. Remove write permissions from all files under `lib`, `bin`, `jdk` and `modules`
242+
# 9. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
243+
# 10. Ensure all files are world-readable by default. It should be possible to
244+
# examine the contents of the image under any UID:GID
244245
RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elasticsearch-env && \\
245246
mkdir -p config/jvm.options.d data logs plugins && \\
246247
chmod 0775 config config/jvm.options.d data logs plugins && \\
247248
mv config/log4j2.properties config/log4j2.file.properties && \\
248249
mv config/log4j2.docker.properties config/log4j2.properties && \\
249250
chmod 0660 config/elasticsearch.yml config/log4j2*.properties && \\
250251
find ./jdk -type d -exec chmod 0755 {} + && \\
252+
chmod -R a-w lib bin jdk modules && \\
251253
find . -xdev -perm -4000 -exec chmod ug-s {} + && \\
252254
find . -type f -exec chmod o+r {} +
253255

qa/os/src/test/java/org/elasticsearch/packaging/test/DockerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void teardownTest() {
101101
* Checks that the Docker image can be run, and that it passes various checks.
102102
*/
103103
public void test010Install() {
104-
verifyContainerInstallation(installation, distribution());
104+
verifyContainerInstallation(installation);
105105
}
106106

107107
/**

qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ protected static void install() throws Exception {
221221
case DOCKER_UBI:
222222
case DOCKER_IRON_BANK:
223223
installation = Docker.runContainer(distribution);
224-
Docker.verifyContainerInstallation(installation, distribution);
224+
Docker.verifyContainerInstallation(installation);
225225
break;
226226
default:
227227
throw new IllegalStateException("Unknown Elasticsearch packaging type.");

qa/os/src/test/java/org/elasticsearch/packaging/util/Docker.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929

3030
import static java.nio.file.attribute.PosixFilePermissions.fromString;
3131
import static org.elasticsearch.packaging.util.DockerRun.getImageName;
32+
import static org.elasticsearch.packaging.util.FileMatcher.p555;
3233
import static org.elasticsearch.packaging.util.FileMatcher.p644;
3334
import static org.elasticsearch.packaging.util.FileMatcher.p664;
34-
import static org.elasticsearch.packaging.util.FileMatcher.p755;
3535
import static org.elasticsearch.packaging.util.FileMatcher.p770;
3636
import static org.elasticsearch.packaging.util.FileMatcher.p775;
3737
import static org.elasticsearch.packaging.util.FileUtils.getCurrentVersion;
@@ -443,9 +443,8 @@ public static void waitForPathToExist(Path path) throws InterruptedException {
443443
/**
444444
* Perform a variety of checks on an installation. If the current distribution is not OSS, additional checks are carried out.
445445
* @param installation the installation to verify
446-
* @param distribution the distribution to verify
447446
*/
448-
public static void verifyContainerInstallation(Installation installation, Distribution distribution) {
447+
public static void verifyContainerInstallation(Installation installation) {
449448
verifyOssInstallation(installation);
450449
verifyDefaultInstallation(installation);
451450
}
@@ -460,15 +459,13 @@ private static void verifyOssInstallation(Installation es) {
460459

461460
Stream.of(es.home, es.data, es.logs, es.config, es.plugins).forEach(dir -> assertPermissionsAndOwnership(dir, p775));
462461

463-
Stream.of(es.modules).forEach(dir -> assertPermissionsAndOwnership(dir, p755));
462+
Stream.of(es.bin, es.bundledJdk, es.lib, es.modules).forEach(dir -> assertPermissionsAndOwnership(dir, p555));
464463

465464
Stream.of("elasticsearch.yml", "jvm.options", "log4j2.properties")
466465
.forEach(configFile -> assertPermissionsAndOwnership(es.config(configFile), p664));
467466

468467
assertThat(dockerShell.run(es.bin("elasticsearch-keystore") + " list").stdout, containsString("keystore.seed"));
469468

470-
Stream.of(es.bin, es.lib).forEach(dir -> assertPermissionsAndOwnership(dir, p755));
471-
472469
Stream.of(
473470
"elasticsearch",
474471
"elasticsearch-cli",
@@ -477,7 +474,7 @@ private static void verifyOssInstallation(Installation es) {
477474
"elasticsearch-node",
478475
"elasticsearch-plugin",
479476
"elasticsearch-shard"
480-
).forEach(executable -> assertPermissionsAndOwnership(es.bin(executable), p755));
477+
).forEach(executable -> assertPermissionsAndOwnership(es.bin(executable), p555));
481478

482479
Stream.of("LICENSE.txt", "NOTICE.txt", "README.asciidoc").forEach(doc -> assertPermissionsAndOwnership(es.home.resolve(doc), p644));
483480

@@ -506,11 +503,18 @@ private static void verifyDefaultInstallation(Installation es) {
506503
"x-pack-env",
507504
"x-pack-security-env",
508505
"x-pack-watcher-env"
509-
).forEach(executable -> assertPermissionsAndOwnership(es.bin(executable), p755));
506+
).forEach(executable -> assertPermissionsAndOwnership(es.bin(executable), p555));
510507

511508
// at this time we only install the current version of archive distributions, but if that changes we'll need to pass
512509
// the version through here
513-
assertPermissionsAndOwnership(es.bin("elasticsearch-sql-cli-" + getCurrentVersion() + ".jar"), p755);
510+
assertPermissionsAndOwnership(es.bin("elasticsearch-sql-cli-" + getCurrentVersion() + ".jar"), p555);
511+
512+
final String architecture = getArchitecture();
513+
Stream.of("autodetect", "categorize", "controller", "data_frame_analyzer", "normalize", "pytorch_inference")
514+
.forEach(executableName -> {
515+
final Path executablePath = es.modules.resolve("x-pack-ml/platform/linux-" + architecture + "/bin/" + executableName);
516+
assertPermissionsAndOwnership(executablePath, p555);
517+
});
514518

515519
Stream.of("role_mapping.yml", "roles.yml", "users", "users_roles")
516520
.forEach(configFile -> assertPermissionsAndOwnership(es.config(configFile), p664));
@@ -619,4 +623,12 @@ public static Shell.Result getContainerLogs() {
619623
public static void restartContainer() {
620624
sh.run("docker restart " + containerId);
621625
}
626+
627+
private static String getArchitecture() {
628+
String architecture = System.getProperty("os.arch", "x86_64");
629+
if (architecture.equals("amd64")) {
630+
architecture = "x86_64";
631+
}
632+
return architecture;
633+
}
622634
}

qa/os/src/test/java/org/elasticsearch/packaging/util/FileMatcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public enum Fileness {
3737
Directory
3838
}
3939

40+
public static final Set<PosixFilePermission> p555 = fromString("r-xr-xr-x");
4041
public static final Set<PosixFilePermission> p775 = fromString("rwxrwxr-x");
4142
public static final Set<PosixFilePermission> p770 = fromString("rwxrwx---");
4243
public static final Set<PosixFilePermission> p755 = fromString("rwxr-xr-x");

0 commit comments

Comments
 (0)