Skip to content
Draft
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
64 changes: 14 additions & 50 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
################################################################################
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for your commit messages please break lines at 75 characters

# Base image for all builds

FROM public.ecr.aws/amazonlinux/amazonlinux:2 AS builder-base
RUN yum group install -y "Development Tools"
FROM public.ecr.aws/amazonlinux/amazonlinux:2023 AS builder-base
RUN dnf group install -y "Development Tools"
RUN useradd builder


################################################################################
# Statically linked, more recent version of bash

FROM builder-base AS builder-static
RUN yum install -y glibc-static
RUN dnf install -y glibc-static

ARG musl_version=1.2.5
ARG bash_version=5.1.16
ARG bash_version=5.2.15

WORKDIR /opt/build
COPY ./sdk-fetch ./
Expand Down Expand Up @@ -47,66 +47,30 @@ RUN CC=""/usr/local/musl/bin/musl-gcc CFLAGS="-Os -DHAVE_DLOPEN=0" \
--enable-static-link \
--without-bash-malloc \
|| { cat config.log; exit 1; }

# Build bash library first, then remove conflicting strtoimax object to avoid duplicate symbols with musl
RUN make lib/sh/libsh.a && \
ar d lib/sh/libsh.a lib/sh/strtoimax.o && \
ranlib lib/sh/libsh.a
RUN make -j`nproc`
RUN cp bash /opt/bash
RUN mkdir -p /usr/share/licenses/bash && \
cp -p COPYING /usr/share/licenses/bash


################################################################################
# Rebuild of Amazon Linux 2's systemd v219 with downstream patches

FROM builder-base AS builder-systemd
RUN yum install -y yum-utils rpm-build
RUN yum-builddep -y systemd

USER builder
WORKDIR /home/builder
RUN yumdownloader --source systemd
RUN rpm -Uv systemd-219-*.src.rpm

WORKDIR /home/builder/rpmbuild/SOURCES
COPY systemd-patches/*.patch ./

WORKDIR /home/builder/rpmbuild/SPECS
# Recreate the spec file from three parts: everything up until the last upstream
# patch, downstream patches, everything else.
RUN last_patch=$(awk '/^Patch[0-9]+/ { line = NR } END { print line }' systemd.spec); \
head -n${last_patch} systemd.spec >systemd.mod.spec; \
{ \
echo ;\
echo '# Bottlerocket Patches'; \
echo 'Patch9500: 9500-cgroup-util-extract-cgroup-hierarchy-base-path-into-.patch'; \
echo 'Patch9501: 9501-cgroup-util-accept-cgroup-hierarchy-base-as-option.patch'; \
echo 'Patch9502: 9502-core-move-initialization-of-.slice-and-init.scope-in.patch'; \
echo 'Patch9503: 9503-core-drop-.slice-from-shipped-units.patch'; \
echo 'Patch9504: 9504-core-skip-restart-when-a-JOB_STOP-job-is-pending.patch'; \
echo ; \
} >>systemd.mod.spec; \
tail -n+$((last_patch + 1)) systemd.spec >>systemd.mod.spec; \
mv systemd.mod.spec systemd.spec
RUN rpmbuild --bb systemd.spec


################################################################################
# Actual admin container image

FROM public.ecr.aws/amazonlinux/amazonlinux:2
FROM public.ecr.aws/amazonlinux/amazonlinux:2023

ARG IMAGE_VERSION
# Make the container image version a mandatory build argument
RUN test -n "$IMAGE_VERSION"
LABEL "org.opencontainers.image.version"="$IMAGE_VERSION"

# Install the custom systemd build in the same transaction as all original
# packages to save space. For example, openssh-server pulls in systemd. This
# dependency is best satisfied by the downstream build. Reinstalling it later
# would result in also carrying around the original systemd in the final image
# where it would remain forever hidden and unused in a lower layer.
RUN --mount=type=bind,from=builder-systemd,source=/home/builder/rpmbuild/RPMS,target=/tmp/systemd-rpms \
yum update -y \
&& yum install -y \
/tmp/systemd-rpms/*/systemd-{219,libs}*.rpm \
RUN dnf update -y \
&& dnf install -y \
crypto-policies-scripts \
ec2-instance-connect \
jq \
openssh-server \
Expand All @@ -115,7 +79,7 @@ RUN --mount=type=bind,from=builder-systemd,source=/home/builder/rpmbuild/RPMS,ta
shadow-utils \
sudo \
util-linux \
&& yum clean all
&& dnf clean all

# Delete SELinux config file to prevent relabeling with contexts provided by the container's image
RUN rm -rf /etc/selinux/config
Expand Down
4 changes: 2 additions & 2 deletions hashes/bash
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# https://ftp.gnu.org/gnu/bash/bash-5.1.16.tar.gz
SHA512 (bash-5.1.16.tar.gz) = a32a343b6dde9a18eb6217602655f72c4098b0d90f04cf4e686fb21b81fc4ef26ade30f7226929fbb7c207cde34617dbad2c44f6103161d1141122bb31dc6c80
# https://ftp.gnu.org/gnu/bash/bash-5.2.15.tar.gz
SHA512 (bash-5.2.15.tar.gz) = 08a67f6da4af7a75ff2b2d5a9eb8fc46d8c6e9ae80ccaf73b51736d6609916861b1f3fced938ce3ea16d014edb324e1a3d8e03f4917f68dc56ffb665316f26c7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, you are missing a newline

4 changes: 2 additions & 2 deletions motd
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
╱┄┄╲ This container provides access to the Bottlerocket host
│▗▖│ filesystems (see /.bottlerocket/rootfs) and contains common
╱│ │╲ tools for inspection and troubleshooting. It is based on
│╰╮╭╯│ Amazon Linux 2, and most things are in the same places you
╹╹ would find them on an AL2 host.
│╰╮╭╯│ Amazon Linux 2023, and most things are in the same places you
╹╹ would find them on an AL2023 host.

To permit more intrusive troubleshooting, including actions that mutate the
running state of the Bottlerocket host, we provide a tool called "sheltie"
Expand Down
57 changes: 30 additions & 27 deletions start_admin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ declare -r SSH_HOST_KEY_DIR="${PERSISTENT_STORAGE_BASE_DIR}/etc/ssh"
declare -r USER_DATA="${PERSISTENT_STORAGE_BASE_DIR}/user-data"
declare -r HOST_CERTS="/.bottlerocket/certs"

#shellcheck disable=SC2155 # If not set then we'll treat it as 0
declare -r FIPS_MODE_FLAG=$(cat '/proc/sys/crypto/fips_enabled' 2>/dev/null || echo 0)

if [ ! -s "${USER_DATA}" ]; then
log "Admin host-container user-data is empty, going to sleep forever"
exec sleep infinity
Expand Down Expand Up @@ -45,6 +48,16 @@ link_host_certs() {
update-ca-trust
}

# Update crypto policies to FIPS if FIPS is enabled
if [[ ${FIPS_MODE_FLAG} -eq 1 ]]; then
update-crypto-policies --set FIPS 2>/dev/null
if [[ "$(cat '/etc/crypto-policies/config')" != "FIPS" ]]; then
log "Failed to validate FIPS configuration"
exit 1
fi
fi


get_user_data_keys() {
# Extract the keys from user-data json
local raw_keys
Expand Down Expand Up @@ -207,7 +220,13 @@ fi

# Generate the server keys
mkdir -p "${SSH_HOST_KEY_DIR}"
for key_alg in rsa ecdsa ed25519; do
# Skip ED25519 in FIPS mode as it's not allowed
key_algorithms=(rsa ecdsa)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the default size of the RSA key? It must be >= 2048 bits. And for ECDSA, make sure you use FIPS curve.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like for RSA its 3072 bits (changed from 2048 in OpenSSH 8.2). ECSDA defaults to P-256 which is a FIPS curve. Of course if we wanted to be extra sure we could set these explicitly to avoid changes in behavior.

if [[ "${FIPS_MODE_FLAG}" -ne 1 ]]; then
key_algorithms+=(ed25519)
fi

for key_alg in "${key_algorithms[@]}"; do
# If both of the keys exist, don't overwrite them
if [[ -s "${SSH_HOST_KEY_DIR}/ssh_host_${key_alg}_key" ]] \
&& [[ -s "${SSH_HOST_KEY_DIR}/ssh_host_${key_alg}_key.pub" ]]; then
Expand All @@ -228,6 +247,15 @@ for key_alg in rsa ecdsa ed25519; do
fi
done

readonly host_cgroup="/.bottlerocket/rootfs/sys/fs/cgroup"

cgroup_fstype=$(findmnt -n -o FSTYPE "${host_cgroup}" || true)
if [[ "${cgroup_fstype}" == tmpfs ]]; then
# Host uses cgroup v1, so use cgroup v1 in container too
ln -sf "${host_cgroup}" /sys/fs/cgroup
log "cgroup v1 enabled in admin container to match host"
fi

install_proxy_profile

enable_systemd_services
Expand All @@ -236,32 +264,7 @@ enable_systemd_services

systemd_options=()

# cgroup v2 compatibility crimes: systemd 219 in the admin container only
# supports cgroup v1.
if [[ $(findmnt -n -o FSTYPE /sys/fs/cgroup) = cgroup2 ]]; then
# Mount an extra cgroup v1 hierarchy for use by systemd in the admin
# container. Vanilla systemd is hard-wired to look for it at /sys/fs/cgroup
# but that path is already taken by the host's proper cgroup hierarchy.
# Mounting a cgroup v1 hierarchy here might confuse the host and the systemd
# documentation advises against manually interfering with anything in that
# path. Therefore, mount the extra hierarchy elsewhere and tell systemd in
# the admin container where to look. Requirements:
#
# 1. The base must be a mount point.
# 2. The base must contain another mounted cgroup file system named "systemd".
#
# In either case there is no need to populate the file systems with any
# actual cgroup controllers, since the host is expected to manage processes.
readonly cgroup_base=/.bottlerocket/admin-container-cgroup
mkdir -p "${cgroup_base}"
mount -t tmpfs -o nosuid,nodev,noexec tmpfs "${cgroup_base}"
mkdir -p "${cgroup_base}"/systemd
mount -o remount,ro "${cgroup_base}"
mount -t cgroup -o none,name=systemd cgroup "${cgroup_base}"/systemd
systemd_options+=( --cgroup-base "${cgroup_base}" )
fi

# Persuade systemd that it's OK to run as a user manager.
export XDG_RUNTIME_DIR="/run/user/${UID}"
mkdir -p /run/systemd/system "${XDG_RUNTIME_DIR}"
exec /usr/lib/systemd/systemd "${systemd_options[@]}" --user --unit=admin.target
exec /usr/lib/systemd/systemd "${systemd_options[@]}" --user --unit=admin.target
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing a new line at the end of this file.