Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public enum DockerBase {
"-wolfi",
"apk"
),

FIPS("docker.elastic.co/wolfi/chainguard-base-fips:sha256-feb7aeb1bbcb331afa089388f2fa1e81997fc24642ca4fa06b7e502ff599a4cf", "-fips", "apk"),
// spotless:on

// Based on WOLFI above, with more extras. We don't set a base image because
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.gradle.internal.distribution;

import org.elasticsearch.gradle.ElasticsearchDistributionType;

public class DockerFipsElasticsearchDistributionType implements ElasticsearchDistributionType {

DockerFipsElasticsearchDistributionType() {}

@Override
public String getName() {
return "dockerFips";
}

@Override
public boolean isDocker() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
import java.util.List;

public class InternalElasticsearchDistributionTypes {
public static ElasticsearchDistributionType DEB = new DebElasticsearchDistributionType();
public static ElasticsearchDistributionType RPM = new RpmElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER = new DockerElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_UBI = new DockerUbiElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_IRONBANK = new DockerIronBankElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_CLOUD_ESS = new DockerCloudEssElasticsearchDistributionType();
public static ElasticsearchDistributionType DOCKER_WOLFI = new DockerWolfiElasticsearchDistributionType();
public static final ElasticsearchDistributionType DEB = new DebElasticsearchDistributionType();
public static final ElasticsearchDistributionType RPM = new RpmElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER = new DockerElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER_UBI = new DockerUbiElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER_IRONBANK = new DockerIronBankElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER_CLOUD_ESS = new DockerCloudEssElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER_WOLFI = new DockerWolfiElasticsearchDistributionType();
public static final ElasticsearchDistributionType DOCKER_FIPS = new DockerFipsElasticsearchDistributionType();

public static List<ElasticsearchDistributionType> ALL_INTERNAL = List.of(
DEB,
Expand All @@ -29,6 +30,7 @@ public class InternalElasticsearchDistributionTypes {
DOCKER_UBI,
DOCKER_IRONBANK,
DOCKER_CLOUD_ESS,
DOCKER_WOLFI
DOCKER_WOLFI,
DOCKER_FIPS
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DEB;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_CLOUD_ESS;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_FIPS;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_IRONBANK;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_UBI;
import static org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes.DOCKER_WOLFI;
Expand Down Expand Up @@ -153,6 +154,7 @@ private static Map<ElasticsearchDistributionType, TaskProvider<?>> lifecycleTask
lifecyleTasks.put(DOCKER_IRONBANK, project.getTasks().register(taskPrefix + ".docker-ironbank"));
lifecyleTasks.put(DOCKER_CLOUD_ESS, project.getTasks().register(taskPrefix + ".docker-cloud-ess"));
lifecyleTasks.put(DOCKER_WOLFI, project.getTasks().register(taskPrefix + ".docker-wolfi"));
lifecyleTasks.put(DOCKER_FIPS, project.getTasks().register(taskPrefix + ".docker-fips"));
lifecyleTasks.put(ARCHIVE, project.getTasks().register(taskPrefix + ".archives"));
lifecyleTasks.put(DEB, project.getTasks().register(taskPrefix + ".packages"));
lifecyleTasks.put(RPM, lifecyleTasks.get(DEB));
Expand Down
68 changes: 56 additions & 12 deletions distribution/docker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.internal.DockerBase
import org.elasticsearch.gradle.internal.distribution.InternalElasticsearchDistributionTypes
import org.elasticsearch.gradle.internal.ExportElasticsearchBuildResourcesTask
import org.elasticsearch.gradle.internal.docker.DockerBuildTask
import org.elasticsearch.gradle.internal.docker.DockerSupportPlugin
import org.elasticsearch.gradle.internal.docker.DockerSupportService
Expand All @@ -17,6 +18,8 @@ apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.test.fixtures'
apply plugin: 'elasticsearch.internal-distribution-download'
apply plugin: 'elasticsearch.dra-artifacts'
apply plugin: 'elasticsearch.jdk-download'
apply plugin: 'elasticsearch.repositories'

String buildId = providers.systemProperty('build.id').getOrNull()
boolean useLocalArtifacts = buildId != null && buildId.isBlank() == false && useDra == false
Expand Down Expand Up @@ -93,6 +96,7 @@ configurations {
filebeat_x86_64
metricbeat_aarch64
metricbeat_x86_64
fips
}

String tiniArch = Architecture.current() == Architecture.AARCH64 ? 'arm64' : 'amd64'
Expand All @@ -109,6 +113,8 @@ dependencies {
filebeat_x86_64 "beats:filebeat:${VersionProperties.elasticsearch}:[email protected]"
metricbeat_aarch64 "beats:metricbeat:${VersionProperties.elasticsearch}:[email protected]"
metricbeat_x86_64 "beats:metricbeat:${VersionProperties.elasticsearch}:[email protected]"
fips "org.bouncycastle:bc-fips:1.0.2.5"
fips "org.bouncycastle:bctls-fips:1.0.19"
}

ext.expansions = { Architecture architecture, DockerBase base ->
Expand Down Expand Up @@ -286,6 +292,34 @@ void addBuildDockerContextTask(Architecture architecture, DockerBase base) {
filter TransformLog4jConfigFilter
}
}
if(base == DockerBase.FIPS) {

// If we're performing a release build, but `build.id` hasn't been set, we can
// infer that we're not at the Docker building stage of the build, and therefore
// we should skip the beats part of the build.
String buildId = providers.systemProperty('build.id').getOrNull()
boolean includeBeats = VersionProperties.isElasticsearchSnapshot() == true || buildId != null || useDra

if (includeBeats) {
from configurations.getByName("filebeat_${architecture.classifier}")
from configurations.getByName("metricbeat_${architecture.classifier}")
// For some reason, the artifact name can differ depending on what repository we used.
rename ~/((?:file|metric)beat)-.*\.tar\.gz$/, "\$1-${VersionProperties.elasticsearch}.tar.gz"
}

into("plugins") {
from configurations.allPlugins
}

into("fips") {
into("libs") {
from configurations.fips
}
into("resources") {
from tasks.named('fipsDockerResources')
}
}
}

Provider<DockerSupportService> serviceProvider = GradleUtils.getBuildService(
project.gradle.sharedServices,
Expand Down Expand Up @@ -431,7 +465,7 @@ void addBuildDockerImageTask(Architecture architecture, DockerBase base) {
}
}

void addBuildEssDockerImageTask(Architecture architecture) {
void addBuildCloudDockerImageTasks(Architecture architecture) {
DockerBase dockerBase = DockerBase.CLOUD_ESS
String arch = architecture == Architecture.AARCH64 ? '-aarch64' : ''
String contextDir = "${project.buildDir}/docker-context/elasticsearch${dockerBase.suffix}-${VersionProperties.elasticsearch}-docker-build-context${arch}"
Expand Down Expand Up @@ -463,10 +497,10 @@ void addBuildEssDockerImageTask(Architecture architecture) {
from(projectDir.resolve("src/docker/Dockerfile.ess")) {
expand(
[
base_image: "elasticsearch${baseSuffix}:${architecture.classifier}",
base_image : "elasticsearch${baseSuffix}:${architecture.classifier}",
docker_base: "${dockerBase.name().toLowerCase()}",
version: "${VersionProperties.elasticsearch}",
retry: ShellRetry
version : "${VersionProperties.elasticsearch}",
retry : ShellRetry
]
)
filter SquashNewlinesFilter
Expand Down Expand Up @@ -501,17 +535,24 @@ void addBuildEssDockerImageTask(Architecture architecture) {
}
}

// fips
TaskProvider<ExportElasticsearchBuildResourcesTask> fipsResourcesTask = tasks.register('fipsDockerResources', ExportElasticsearchBuildResourcesTask)
fipsResourcesTask.configure {
outputDir = project.layout.buildDirectory.dir('fips-docker-resources').get().asFile
copy 'fips_java.security'
copy 'fips_java.policy'
}

for (final Architecture architecture : Architecture.values()) {
for (final DockerBase base : DockerBase.values()) {
if (base == DockerBase.CLOUD_ESS) {
continue
addBuildCloudDockerImageTasks(architecture)
} else {
addBuildDockerContextTask(architecture, base)
addTransformDockerContextTask(architecture, base)
addBuildDockerImageTask(architecture, base)
}
addBuildDockerContextTask(architecture, base)
addTransformDockerContextTask(architecture, base)
addBuildDockerImageTask(architecture, base)
}

addBuildEssDockerImageTask(architecture)
}

def exportDockerImages = tasks.register("exportDockerImages")
Expand All @@ -535,14 +576,17 @@ subprojects { Project subProject ->
base = DockerBase.CLOUD_ESS
} else if (subProject.name.contains('wolfi-')) {
base = DockerBase.WOLFI
} else if (subProject.name.contains('fips-')) {
base = DockerBase.FIPS
}

final String arch = architecture == Architecture.AARCH64 ? '-aarch64' : ''
final String extension = base == DockerBase.UBI ? 'ubi.tar' :
(base == DockerBase.IRON_BANK ? 'ironbank.tar' :
(base == DockerBase.CLOUD_ESS ? 'cloud-ess.tar' :
(base == DockerBase.CLOUD_ESS ? 'cloud-ess.tar' :
(base == DockerBase.FIPS ? 'fips.tar' :
(base == DockerBase.WOLFI ? 'wolfi.tar' :
'docker.tar')))
'docker.tar'))))
final String artifactName = "elasticsearch${arch}${base.suffix}_test"

final String exportTaskName = taskName("export", architecture, base, 'DockerImage')
Expand Down
Empty file.
96 changes: 56 additions & 40 deletions distribution/docker/src/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ RUN chmod 0555 /bin/tini
<% } else { %>

# Install required packages to extract the Elasticsearch distribution
<% if (docker_base == 'default' || docker_base == 'cloud') { %>
<% 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") { %>
<% } else if (docker_base == "wolfi" || docker_base == "fips") { %>
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') { %>
<% if (docker_base != 'wolfi' && docker_base != 'fips' ) { %>
# `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,25 +117,46 @@ 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") { %>
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

# Add plugins infrastructure
RUN mkdir -p /opt/plugins/archive
RUN chmod -R 0555 /opt/plugins
<% if (docker_base == "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
<% } %>

################################################################################
Expand All @@ -157,7 +178,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") { %>
<% } else if (docker_base == "wolfi" || docker_base == "fips") { %>
RUN <%= retry.loop(package_manager,
"export DEBIAN_FRONTEND=noninteractive && \n" +
" ${package_manager} update && \n" +
Expand Down Expand Up @@ -201,28 +222,24 @@ RUN <%= retry.loop(
<% } %>


<% if (docker_base == "default" || docker_base == "cloud") { %>
<% if (docker_base == "default") { %>
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") { %>
<% } else if (docker_base == "wolfi" || docker_base == "fips") { %>
RUN groupadd -g 1000 elasticsearch && \
adduser -G elasticsearch -u 1000 elasticsearch -D --home /usr/share/elasticsearch elasticsearch && \
adduser elasticsearch root && \
chown -R 0:0 /usr/share/elasticsearch
<% } else { %>
RUN groupadd -g 1000 elasticsearch && \\
adduser -u 1000 -g 1000 -G 0 -d /usr/share/elasticsearch elasticsearch && \\
chown -R 0:0 /usr/share/elasticsearch
<% } %>

ENV ELASTIC_CONTAINER true

WORKDIR /usr/share/elasticsearch

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

Expand Down Expand Up @@ -251,12 +268,12 @@ RUN chmod g=u /etc/passwd && \\
chmod 0775 /usr/share/elasticsearch && \\
chown elasticsearch bin config config/jvm.options.d data logs plugins

<% if (docker_base == 'default' || docker_base == 'cloud') { %>
<% if (docker_base == 'default') { %>
# Update "cacerts" bundle to use Ubuntu's CA certificates (and make sure it
# 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') { %>
<% } else if (docker_base == 'wolfi' || docker_base == "fips") { %>
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 @@ -303,14 +320,7 @@ RUN mkdir /licenses && cp LICENSE.txt /licenses/LICENSE
COPY LICENSE /licenses/LICENSE.addendum
<% } %>

<% if (docker_base == "cloud") { %>
ENTRYPOINT ["/bin/tini", "--"]
CMD ["/app/elasticsearch.sh"]
# Generate a stub command that will be overwritten at runtime
RUN mkdir /app && \\
echo -e '#!/bin/bash\\nexec /usr/local/bin/docker-entrypoint.sh eswrapper' > /app/elasticsearch.sh && \\
chmod 0555 /app/elasticsearch.sh
<% } else if (docker_base == "wolfi") { %>
<% if (docker_base == "wolfi" || docker_base == "fips") { %>
# 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 @@ -330,6 +340,12 @@ USER 1000:0
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 == '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