Skip to content

[8.19] Address review feedback on fips docker image (#126330) #127640

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

Merged
merged 3 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/scripts/packaging-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# opensuse 15 has a missing dep for systemd

if which zypper > /dev/null ; then
sudo zypper install -y insserv-compat
sudo zypper install -y insserv-compat docker-buildx
fi

if [ -e /etc/sysctl.d/99-gce.conf ]; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,50 @@
* This class models the different Docker base images that are used to build Docker distributions of Elasticsearch.
*/
public enum DockerBase {
DEFAULT("ubuntu:20.04", "", "apt-get"),
DEFAULT("ubuntu:20.04", "", "apt-get", "Dockerfile"),

// "latest" here is intentional, since the image name specifies "8"
UBI("docker.elastic.co/ubi8/ubi-minimal:latest", "-ubi8", "microdnf"),
UBI("docker.elastic.co/ubi8/ubi-minimal:latest", "-ubi8", "microdnf", "Dockerfile"),

// The Iron Bank base image is UBI (albeit hardened), but we are required to parameterize the Docker build
IRON_BANK("${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG}", "-ironbank", "yum"),
IRON_BANK("${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG}", "-ironbank", "yum", "Dockerfile"),

// Chainguard based wolfi image with latest jdk
// This is usually updated via renovatebot
// spotless:off
WOLFI(
"docker.elastic.co/wolfi/chainguard-base:latest@sha256:1c7f5aa0e7997455b8500d095c7a90e617102d3941eb0757ac62cfea509e09b9",
"-wolfi",
"apk"
"apk",
"Dockerfile"
),
// spotless:on

// Based on WOLFI above, with more extras. We don't set a base image because
// we programmatically extend from the wolfi image.
CLOUD_ESS(null, "-cloud-ess", "apk"),
CLOUD_ESS(null, "-cloud-ess", "apk", "Dockerfile.ess"),

CLOUD_ESS_FIPS(
"docker.elastic.co/wolfi/chainguard-base-fips:sha256-ebfc3f1d7dba992231747a2e05ad1b859843e81b5e676ad342859d7cf9e425a7",
"-cloud-ess-fips",
"apk"
"apk",
"Dockerfile.ess-fips"
);

private final String image;
private final String suffix;
private final String packageManager;
private final String dockerfile;

DockerBase(String image, String suffix) {
this(image, suffix, "apt-get");
this(image, suffix, "apt-get", "dockerfile");
}

DockerBase(String image, String suffix, String packageManager) {
DockerBase(String image, String suffix, String packageManager, String dockerfile) {
this.image = image;
this.suffix = suffix;
this.packageManager = packageManager;
this.dockerfile = dockerfile;
}

public String getImage() {
Expand All @@ -65,4 +70,8 @@ public String getSuffix() {
public String getPackageManager() {
return packageManager;
}

public String getDockerfile() {
return dockerfile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ private void pullBaseImage(String baseImage) {
maybeConfigureDockerConfig(spec);
spec.executable("docker");
spec.args("pull");
spec.environment("DOCKER_BUILDKIT", "1");
spec.args(baseImage);
});

Expand Down Expand Up @@ -205,7 +206,7 @@ public void execute() {
maybeConfigureDockerConfig(spec);

spec.executable("docker");

spec.environment("DOCKER_BUILDKIT", "1");
if (isCrossPlatform) {
spec.args("buildx");
}
Expand Down
3 changes: 2 additions & 1 deletion distribution/docker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ ext.dockerBuildContext = { Architecture architecture, DockerBase base ->
from projectDir.resolve("src/docker/config")
}
}
from(projectDir.resolve("src/docker/Dockerfile")) {
from(projectDir.resolve("src/docker/${base.dockerfile}")) {
expand(varExpansions)
filter SquashNewlinesFilter
rename base.dockerfile, "Dockerfile"
}
}
}
Expand Down
64 changes: 8 additions & 56 deletions distribution/docker/src/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ RUN chmod 0555 /bin/tini
# Install required packages to extract the Elasticsearch distribution
<% if (docker_base == 'default') { %>
RUN <%= retry.loop(package_manager, "${package_manager} update && DEBIAN_FRONTEND=noninteractive ${package_manager} install -y curl ") %>
<% } else if (docker_base == "wolfi" || docker_base == 'cloud_ess_fips') { %>
<% } else if (docker_base == "wolfi") { %>
RUN <%= retry.loop(package_manager, "export DEBIAN_FRONTEND=noninteractive && ${package_manager} update && ${package_manager} update && ${package_manager} add --no-cache curl") %>
<% } else { %>
RUN <%= retry.loop(package_manager, "${package_manager} install -y findutils tar gzip") %>
<% } %>

<% if (docker_base != 'wolfi' && docker_base != 'cloud_ess_fips' ) { %>
<% if (docker_base != 'wolfi') { %>
# `tini` is a tiny but valid init for containers. This is used to cleanly
# control how ES and any child processes are shut down.
# For wolfi we pick it from the blessed wolfi package registry.
Expand Down Expand Up @@ -117,47 +117,6 @@ RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elas
chmod 0775 bin config config/jvm.options.d data logs plugins && \\
find config -type f -exec chmod 0664 {} +

<% if (docker_base == 'cloud_ess_fips') { %>
# Add plugins infrastructure
RUN mkdir -p /opt/plugins/archive
RUN chmod -R 0555 /opt/plugins

RUN mkdir -p /fips/libs
COPY fips/libs/*.jar /fips/libs/

COPY filebeat-${version}.tar.gz metricbeat-${version}.tar.gz /tmp/
RUN set -eux ; \\
for beat in filebeat metricbeat ; do \\
if [ ! -s /tmp/\$beat-${version}.tar.gz ]; then \\
echo "/tmp/\$beat-${version}.tar.gz is empty - cannot uncompress" 2>&1 ; \\
exit 1 ; \\
fi ; \\
if ! tar tf /tmp/\$beat-${version}.tar.gz >/dev/null; then \\
echo "/tmp/\$beat-${version}.tar.gz is corrupt - cannot uncompress" 2>&1 ; \\
exit 1 ; \\
fi ; \\
mkdir -p /opt/\$beat ; \\
tar xf /tmp/\$beat-${version}.tar.gz -C /opt/\$beat --strip-components=1 ; \\
done

COPY plugins/*.zip /opt/plugins/archive/

RUN chown 1000:1000 /opt/plugins/archive/*
RUN chmod 0444 /opt/plugins/archive/*

COPY fips/resources/fips_java.security /usr/share/elasticsearch/config/fips_java.security
COPY fips/resources/fips_java.policy /usr/share/elasticsearch/config/fips_java.policy

WORKDIR /usr/share/elasticsearch/config

## Add fips specific JVM options
RUN cat <<EOF > /usr/share/elasticsearch/config/jvm.options.d/fips.options
-Djavax.net.ssl.keyStoreType=BCFKS
-Dorg.bouncycastle.fips.approved_only=true
-Djava.security.properties=config/fips_java.security
-Djava.security.policy=config/fips_java.policy
EOF
<% } %>

################################################################################
# Build stage 2 (the actual Elasticsearch image):
Expand All @@ -178,7 +137,7 @@ RUN ${package_manager} update --setopt=tsflags=nodocs -y && \\
nc shadow-utils zip findutils unzip procps-ng && \\
${package_manager} clean all

<% } else if (docker_base == "wolfi" || docker_base == 'cloud_ess_fips') { %>
<% } else if (docker_base == "wolfi") { %>
RUN <%= retry.loop(package_manager,
"export DEBIAN_FRONTEND=noninteractive && \n" +
" ${package_manager} update && \n" +
Expand Down Expand Up @@ -227,7 +186,7 @@ RUN groupadd -g 1000 elasticsearch && \\
adduser --uid 1000 --gid 1000 --home /usr/share/elasticsearch elasticsearch && \\
adduser elasticsearch root && \\
chown -R 0:0 /usr/share/elasticsearch
<% } else if (docker_base == "wolfi" || docker_base == 'cloud_ess_fips') { %>
<% } else if (docker_base == "wolfi") { %>
RUN groupadd -g 1000 elasticsearch && \
adduser -G elasticsearch -u 1000 elasticsearch -D --home /usr/share/elasticsearch elasticsearch && \
adduser elasticsearch root && \
Expand All @@ -243,7 +202,7 @@ ENV ELASTIC_CONTAINER true
WORKDIR /usr/share/elasticsearch

COPY --from=builder --chown=0:0 /usr/share/elasticsearch /usr/share/elasticsearch
<% if (docker_base != "wolfi" && docker_base != 'cloud_ess_fips') { %>
<% if (docker_base != "wolfi") { %>
COPY --from=builder --chown=0:0 /bin/tini /bin/tini
<% } %>

Expand Down Expand Up @@ -277,7 +236,7 @@ RUN chmod g=u /etc/passwd && \\
# stays up-to-date with changes to Ubuntu's store)
COPY bin/docker-openjdk /etc/ca-certificates/update.d/docker-openjdk
RUN /etc/ca-certificates/update.d/docker-openjdk
<% } else if (docker_base == 'wolfi' || docker_base == 'cloud_ess_fips') { %>
<% } else if (docker_base == 'wolfi') { %>
RUN ln -sf /etc/ssl/certs/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts
<% } else { %>
RUN ln -sf /etc/pki/ca-trust/extracted/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts
Expand Down Expand Up @@ -324,7 +283,7 @@ RUN mkdir /licenses && cp LICENSE.txt /licenses/LICENSE
COPY LICENSE /licenses/LICENSE.addendum
<% } %>

<% if (docker_base == "wolfi" || docker_base == 'cloud_ess_fips') { %>
<% if (docker_base == "wolfi") { %>
# Our actual entrypoint is `tini`, a minimal but functional init program. It
# calls the entrypoint we provide, while correctly forwarding signals.
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/docker-entrypoint.sh"]
Expand All @@ -343,13 +302,6 @@ USER 1000:0
<% if (docker_base == 'iron_bank') { %>
HEALTHCHECK --interval=10s --timeout=5s --start-period=1m --retries=5 CMD curl -I -f --max-time 5 http://localhost:9200 || exit 1
<% } %>

<% if (docker_base == 'cloud_ess_fips') { %>
COPY --from=builder --chown=0:0 /opt /opt
ENV ES_PLUGIN_ARCHIVE_DIR /opt/plugins/archive
WORKDIR /usr/share/elasticsearch
COPY --from=builder --chown=0:0 /fips/libs/*.jar /usr/share/elasticsearch/lib/
<% } %>
################################################################################
# End of multi-stage Dockerfile
################################################################################
################################################################################
Loading