diff --git a/bitnami/elasticsearch/9.4/debian-12/Dockerfile b/bitnami/elasticsearch/9.4/debian-12/Dockerfile index d39c9137900a..c34800202616 100644 --- a/bitnami/elasticsearch/9.4/debian-12/Dockerfile +++ b/bitnami/elasticsearch/9.4/debian-12/Dockerfile @@ -9,13 +9,13 @@ ARG JAVA_EXTRA_SECURITY_DIR="/bitnami/java/extra-security" ARG TARGETARCH LABEL org.opencontainers.image.base.name="docker.io/bitnami/minideb:bookworm" \ - org.opencontainers.image.created="2026-06-10T11:47:17Z" \ + org.opencontainers.image.created="2026-06-30T19:26:53Z" \ org.opencontainers.image.description="Application packaged by Broadcom, Inc." \ org.opencontainers.image.documentation="https://github.com/bitnami/containers/tree/main/bitnami/elasticsearch/README.md" \ org.opencontainers.image.source="https://github.com/bitnami/containers/tree/main/bitnami/elasticsearch" \ org.opencontainers.image.title="elasticsearch" \ org.opencontainers.image.vendor="Broadcom, Inc." \ - org.opencontainers.image.version="9.4.2" + org.opencontainers.image.version="9.4.3" ENV HOME="/" \ OS_ARCH="${TARGETARCH:-amd64}" \ @@ -31,9 +31,9 @@ RUN --mount=type=secret,id=downloads_url,env=SECRET_DOWNLOADS_URL \ DOWNLOADS_URL=${SECRET_DOWNLOADS_URL:-${DOWNLOADS_URL}} ; \ mkdir -p /tmp/bitnami/pkg/cache/ ; cd /tmp/bitnami/pkg/cache/ || exit 1 ; \ COMPONENTS=( \ - "yq-4.53.3-0-linux-${OS_ARCH}-debian-12" \ + "yq-4.53.3-1-linux-${OS_ARCH}-debian-12" \ "java-21.0.11-11-2-linux-${OS_ARCH}-debian-12" \ - "elasticsearch-9.4.2-0-linux-${OS_ARCH}-debian-12" \ + "elasticsearch-9.4.3-0-linux-${OS_ARCH}-debian-12" \ ) ; \ for COMPONENT in "${COMPONENTS[@]}"; do \ if [ ! -f "${COMPONENT}.tar.gz" ]; then \ @@ -52,7 +52,7 @@ RUN find / -perm /6000 -type f -exec chmod a-s {} \; || true COPY rootfs / RUN /opt/bitnami/scripts/elasticsearch/postunpack.sh RUN /opt/bitnami/scripts/java/postunpack.sh -ENV APP_VERSION="9.4.2" \ +ENV APP_VERSION="9.4.3" \ BITNAMI_APP_NAME="elasticsearch" \ IMAGE_REVISION="0" \ JAVA_HOME="/opt/bitnami/java" \ diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-amd64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-amd64-debian-12.tar.gz.sha256 deleted file mode 100644 index 7e34041709e4..000000000000 --- a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-amd64-debian-12.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -1dd1d0db400000b4068bbe9eae23d5de0d5f146a8163b4ac2a608a4b0366f0c7 elasticsearch-9.4.2-0-linux-amd64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-arm64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-arm64-debian-12.tar.gz.sha256 deleted file mode 100644 index 5b3b62ee6145..000000000000 --- a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.2-0-linux-arm64-debian-12.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -88c13474de397d7822b9d2b9f42f2df51dc2a630ac6cc6b625f392ed3efa6ba3 elasticsearch-9.4.2-0-linux-arm64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-amd64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-amd64-debian-12.tar.gz.sha256 new file mode 100644 index 000000000000..d869f30f860c --- /dev/null +++ b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-amd64-debian-12.tar.gz.sha256 @@ -0,0 +1 @@ +79869ffd9c562dac8ed2c1370ac0279d5c33b313c36ffe3b13c8d867e26c23e4 elasticsearch-9.4.3-0-linux-amd64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-arm64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-arm64-debian-12.tar.gz.sha256 new file mode 100644 index 000000000000..9349926306a0 --- /dev/null +++ b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/elasticsearch-9.4.3-0-linux-arm64-debian-12.tar.gz.sha256 @@ -0,0 +1 @@ +8f06b961e99709d4bacd1515fe81f1195a9b99aa847d82bfe7b18ba2fdfefdb1 elasticsearch-9.4.3-0-linux-arm64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-amd64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-amd64-debian-12.tar.gz.sha256 deleted file mode 100644 index a0ded5d5d96e..000000000000 --- a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-amd64-debian-12.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -b22e39e895f9766d224a014325ed2b2ff7a5fcd865b2c285a938e5ca1d2d24db yq-4.53.3-0-linux-amd64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-arm64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-arm64-debian-12.tar.gz.sha256 deleted file mode 100644 index 2cca1a6ca36f..000000000000 --- a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-0-linux-arm64-debian-12.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -15c9b67b3b357eb8df309a1e328cf2af5a49b8ea360ffbef243cf3d4bde9ba65 yq-4.53.3-0-linux-arm64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-amd64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-amd64-debian-12.tar.gz.sha256 new file mode 100644 index 000000000000..075a7512681f --- /dev/null +++ b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-amd64-debian-12.tar.gz.sha256 @@ -0,0 +1 @@ +adcab17624d76cc523c54bc603664d08341c8817175615ce8bb226d4e527cdec yq-4.53.3-1-linux-amd64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-arm64-debian-12.tar.gz.sha256 b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-arm64-debian-12.tar.gz.sha256 new file mode 100644 index 000000000000..90ec18816415 --- /dev/null +++ b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/checksums/yq-4.53.3-1-linux-arm64-debian-12.tar.gz.sha256 @@ -0,0 +1 @@ +2613880712b56432dbcecb92a563967a7546b4cc4cac2766b5fa419a231d4f66 yq-4.53.3-1-linux-arm64-debian-12.tar.gz diff --git a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/scripts/libpersistence.sh b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/scripts/libpersistence.sh index 18445e7d27fa..833ee5ab1d65 100644 --- a/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/scripts/libpersistence.sh +++ b/bitnami/elasticsearch/9.4/debian-12/prebuildfs/opt/bitnami/scripts/libpersistence.sh @@ -39,7 +39,7 @@ persist_app() { fi pushd "$install_dir" >/dev/null || exit local file_to_persist_relative file_to_persist_destination file_to_persist_destination_folder - local -r tmp_file="/tmp/perms.acl" + local -r acl_file="$(mktemp "${TMPDIR:-/tmp}"/acl.XXXXXXXXXX)" for file_to_persist in "${files_to_persist[@]}"; do if [[ ! -f "$file_to_persist" && ! -d "$file_to_persist" ]]; then error "Cannot persist '${file_to_persist}' because it does not exist" @@ -50,22 +50,22 @@ persist_app() { file_to_persist_destination_folder="$(dirname "$file_to_persist_destination")" # Get original permissions for existing files, which will be applied later # Exclude the root directory with 'sed', to avoid issues when copying the entirety of it to a volume - getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$tmp_file" + getfacl -R "$file_to_persist_relative" | sed -E '/# file: (\..+|[^.])/,$!d' > "$acl_file" # Copy directories to the volume ensure_dir_exists "$file_to_persist_destination_folder" cp -Lr --preserve=links "$file_to_persist_relative" "$file_to_persist_destination_folder" # Restore permissions pushd "$persist_dir" >/dev/null || exit if am_i_root; then - setfacl --restore="$tmp_file" + setfacl --restore="$acl_file" else # When running as non-root, don't change ownership - setfacl --restore=<(grep -E -v '^# (owner|group):' "$tmp_file") + setfacl --restore=<(grep -E -v '^# (owner|group):' "$acl_file") fi popd >/dev/null || exit done popd >/dev/null || exit - rm -f "$tmp_file" + rm -f "$acl_file" # Install the persisted files into the installation directory, via symlinks restore_persisted_app "$@" } diff --git a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch-env.sh b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch-env.sh index 21fe6dd6ac97..9cd1069642fc 100644 --- a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch-env.sh +++ b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch-env.sh @@ -81,6 +81,7 @@ elasticsearch_env_vars=( ELASTICSEARCH_HTTP_TLS_CA_CERT_LOCATION ELASTICSEARCH_ENABLE_FIPS_MODE ELASTICSEARCH_FIPS_REQUIRED_PROVIDERS + ES_KEYSTORE_PASSPHRASE_FILE ELASTICSEARCH_PASSWD_HASH_ALGORITHM ELASTICSEARCH_KEYS ES_JAVA_HOME @@ -257,6 +258,7 @@ export ELASTICSEARCH_HTTP_TLS_CA_CERT_LOCATION="${ELASTICSEARCH_HTTP_TLS_CA_CERT export DB_HTTP_TLS_CA_CERT_LOCATION="$ELASTICSEARCH_HTTP_TLS_CA_CERT_LOCATION" export ELASTICSEARCH_ENABLE_FIPS_MODE="${ELASTICSEARCH_ENABLE_FIPS_MODE:-false}" export ELASTICSEARCH_FIPS_REQUIRED_PROVIDERS="${ELASTICSEARCH_FIPS_REQUIRED_PROVIDERS:-}" +export ES_KEYSTORE_PASSPHRASE_FILE="${ES_KEYSTORE_PASSPHRASE_FILE:-}" export ELASTICSEARCH_PASSWD_HASH_ALGORITHM="${ELASTICSEARCH_PASSWD_HASH_ALGORITHM:-}" export ELASTICSEARCH_KEYS="${ELASTICSEARCH_KEYS:-}" export JAVA_HOME="${BITNAMI_ROOT_DIR}/java" diff --git a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch/run.sh b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch/run.sh index b5f0c22bf507..9cd6c71b8cc4 100755 --- a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch/run.sh +++ b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/elasticsearch/run.sh @@ -25,7 +25,19 @@ ARGS+=("$@") info "** Starting Elasticsearch **" if am_i_root; then - exec_as_user "$DB_DAEMON_USER" "$EXEC" "${ARGS[@]}" + _exec_elasticsearch() { exec_as_user "$DB_DAEMON_USER" "$EXEC" "${ARGS[@]}"; } else - exec "$EXEC" "${ARGS[@]}" + _exec_elasticsearch() { exec "$EXEC" "${ARGS[@]}"; } +fi + +# In FIPS restricted mode ES 9.x reads the keystore password from stdin +# (Terminal.readSecret()). ES_KEYSTORE_PASSPHRASE is auto-populated from +# ES_KEYSTORE_PASSPHRASE_FILE by the Bitnami framework; supplying it via +# a here-string avoids an interactive TTY. +if [[ "${ELASTICSEARCH_ENABLE_FIPS_MODE:-false}" == "true" ]] && \ + [[ "${JAVA_TOOL_OPTIONS:-}" == *"java.security.restricted"* ]] && \ + [[ -n "${ES_KEYSTORE_PASSPHRASE:-}" ]]; then + _exec_elasticsearch <<< "${ES_KEYSTORE_PASSPHRASE}" +else + _exec_elasticsearch fi diff --git a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/libelasticsearch.sh b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/libelasticsearch.sh index 3bf77eca900f..7ca40b712c12 100644 --- a/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/libelasticsearch.sh +++ b/bitnami/elasticsearch/9.4/debian-12/rootfs/opt/bitnami/scripts/libelasticsearch.sh @@ -122,6 +122,33 @@ elasticsearch_set_keys() { fi } +######################## +# Ensure a FIPS-compliant password-protected keystore exists. +# Called during initialization when FIPS mode is enabled and +# ES_KEYSTORE_PASSPHRASE is set, even if no secure settings +# are being added (which would otherwise leave no keystore for the +# server to decrypt, causing bootstrap() to run with empty password). +# Globals: +# ELASTICSEARCH_ENABLE_FIPS_MODE, ES_KEYSTORE_PASSPHRASE, DB_CONF_DIR +# Arguments: +# None +# Returns: +# None +######################### +elasticsearch_ensure_fips_keystore() { + [[ "${ELASTICSEARCH_ENABLE_FIPS_MODE:-false}" == "true" ]] || return 0 + # Only enforce a password-protected keystore in restricted mode. + # BC FIPS (restricted) requires a minimum 112-bit passphrase for PBKDF2; relaxed mode does not. + [[ "${JAVA_TOOL_OPTIONS:-}" == *"java.security.restricted"* ]] || return 0 + is_empty_value "${ES_KEYSTORE_PASSPHRASE:-}" && return 0 + [[ -f "${DB_CONF_DIR}/elasticsearch.keystore" ]] && return 0 + + info "Creating FIPS-compliant password-protected Elasticsearch keystore..." + printf "%s\n%s\n" "$ES_KEYSTORE_PASSPHRASE" "$ES_KEYSTORE_PASSPHRASE" | elasticsearch-keystore create -p + am_i_root && configure_permissions_ownership "${DB_CONF_DIR}/elasticsearch.keystore" \ + --file-mode "640" --user "$DB_DAEMON_USER" --group "$DB_DAEMON_GROUP" +} + ######################## # Set Elasticsearch keystore values # Globals: @@ -136,9 +163,38 @@ elasticsearch_set_key_value() { local value="${2:?missing value}" debug "Storing key: ${key}" - elasticsearch-keystore add --stdin --force "$key" <<<"$value" - am_i_root && chown "$DB_DAEMON_USER:$DB_DAEMON_GROUP" "${DB_CONF_DIR}/elasticsearch.keystore" + # Keystore password (required in FIPS restricted mode). + # BC FIPS requires a minimum 112-bit (>=14 char) passphrase for all PBKDF2 + # key derivation operations used by elasticsearch-keystore internally. + # ES_KEYSTORE_PASSPHRASE is auto-populated from ES_KEYSTORE_PASSPHRASE_FILE + # by the Bitnami framework when the _FILE variant is declared in env.jsonnet. + local ks_pass="${ES_KEYSTORE_PASSPHRASE:-}" + + # Create keystore if it doesn't exist yet. In FIPS restricted mode the + # keystore must be password-protected; delegate to elasticsearch_ensure_fips_keystore + # which handles that case. If not created above (non-FIPS or no passphrase), + # fall back to an unprotected keystore. + if [[ ! -f "${DB_CONF_DIR}/elasticsearch.keystore" ]]; then + elasticsearch_ensure_fips_keystore + if [[ ! -f "${DB_CONF_DIR}/elasticsearch.keystore" ]]; then + elasticsearch-keystore create + am_i_root && configure_permissions_ownership "${DB_CONF_DIR}/elasticsearch.keystore" \ + --file-mode "640" --user "$DB_DAEMON_USER" --group "$DB_DAEMON_GROUP" + fi + fi + + # Add the key value. When the keystore is password-protected, the CLI reads + # the keystore password from stdin first (Terminal.readSecret), then the + # value. Pipe both so no interactive prompt is needed. + if [[ -n "$ks_pass" ]]; then + printf "%s\n%s\n" "$ks_pass" "$value" | elasticsearch-keystore add --stdin --force "$key" + else + elasticsearch-keystore add --stdin --force "$key" <<<"$value" + fi + + am_i_root && configure_permissions_ownership "${DB_CONF_DIR}/elasticsearch.keystore" \ + --file-mode "640" --user "$DB_DAEMON_USER" --group "$DB_DAEMON_GROUP" # Avoid exit code of previous commands to affect the result of this function true } @@ -719,6 +775,48 @@ elasticsearch_initialize() { replace_in_file "${DB_CONF_DIR}/jvm.options" "(^.*logs[/]gc.log.*$)" "# \1" fi elasticsearch_set_heap_size + # Write BC FIPS JVM options only when FIPS mode is enabled AND Java is in restricted mode. + # Restricted mode is signalled by JAVA_TOOL_OPTIONS containing "java.security.restricted", + # which the chart sets via common.fips.config when fips.java=restricted. + # Relaxed mode (fips.java=relaxed) uses the non-FIPS BouncyCastle provider and does not + # need the BC FIPS module path. + if is_boolean_yes "${ELASTICSEARCH_ENABLE_FIPS_MODE:-false}" && \ + [[ "${JAVA_TOOL_OPTIONS:-}" == *"java.security.restricted"* ]]; then + info "Writing BC FIPS JVM options to ${DB_CONF_DIR}/jvm.options.d/bc-fips.options..." + # BC FIPS JARs are placed into ${BITNAMI_ROOT_DIR}/elasticsearch/lib/ at container start by the + # prepare-bcfips-lib initContainer (see charts-private extra-init-vals7.yaml). This makes + # them named modules (org.bouncycastle.fips.core etc.) in the ES server layer, which is + # required for the es.entitlements.policy.server patch to work. + # The patch grants manage_threads to org.bouncycastle.fips.core so DisposalDaemon can + # call Thread.setDaemon() without triggering NotEntitledException. + # --module-path is NOT written here; BC FIPS is already in lib/ (server layer) via the + # initContainer, and JAVA_TOOL_OPTIONS provides it for CLI tools and the boot layer. + # The version is detected at runtime from the installed JAR filename so the patch + # never goes stale on upgrades. We avoid calling elasticsearch_get_version() here + # because at this point the BC FIPS JARs are already in lib/ (server layer via the + # prepare-bcfips-lib initContainer), and running the elasticsearch binary without + # the entitlement patch would trigger DisposalDaemon. → NotEntitledException + # before the version string is ever printed (chicken-and-egg problem). + local es_version + es_version="$(ls "${DB_BASE_DIR}/lib/elasticsearch-"*.jar 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1)" + if [[ -z "$es_version" ]]; then + warn "Could not detect Elasticsearch version from lib/; skipping entitlement patch" + return + fi + local bc_fips_entitlement_patch + bc_fips_entitlement_patch="$(printf 'versions:\n - %s\npolicy:\n org.bouncycastle.fips.core:\n - manage_threads\n' "${es_version}" | base64 -w 0)" + + cat > "${DB_CONF_DIR}/jvm.options.d/bc-fips.options" <