diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1897bbd38e..ac7bc8c41e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,3 +11,4 @@ RELEASED_VERSIONS.unsupported @stackrox/collector-team # The RHTAP maintainers for ACS review all changes related to the RHTAP pipelines, such as new pipelines, # parameter changes or automated task updates. /.tekton/ @stackrox/rhtap-maintainers +/.konflux/ @stackrox/rhtap-maintainers diff --git a/.konflux/README.md b/.konflux/README.md new file mode 100644 index 0000000000..6d1f038f22 --- /dev/null +++ b/.konflux/README.md @@ -0,0 +1,3 @@ +# .konflux + +This is a directory with misc files needed for builds on Konflux. diff --git a/.konflux/scripts/subscription-manager-bro.sh b/.konflux/scripts/subscription-manager-bro.sh new file mode 100755 index 0000000000..2aba2f9675 --- /dev/null +++ b/.konflux/scripts/subscription-manager-bro.sh @@ -0,0 +1,316 @@ +#!/usr/bin/env bash + +# This script is for registering container with Red Hat subscription-manager during Konflux builds for getting access +# to RHEL RPMs during the build. +# The script was created as a workaround in absence of better options. +# TODO(ROX-20651): remove this script and switch to use content sets once available. + +set -euo pipefail + +SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")" +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" + +SECRET_NAME_IN_KONFLUX="subscription-manager-activation-key" +SECRET_KONFLUX_WORKSPACE_PATH="/workspace/${SECRET_NAME_IN_KONFLUX}" +SECRET_KEY="activation-key" +SECRET_LOCAL_PATH="${SCRIPT_DIR}/${SECRET_KEY}" +SECRET_INFO_URL='https://docs.engineering.redhat.com/pages/viewpage.action?pageId=407312060' + +RED_HAT_ORG_ID="11009103" +TARGETS_LIST_FILE="/tmp/subscription-manager-bro-targets" + +# These were figured experimentally with the help of self-test subcommand. +TARGET_BACKUP_PATHS=( + etc/pki/consumer + etc/pki/entitlement + etc/pki/product + etc/pki/product-default + etc/yum.repos.d + var/lib/rhsm + var/cache/ldconfig +) + +function main { + if [[ "$#" == "0" ]]; then + echo >&2 "Error: command is missing. See the usage below." + usage + exit 2 + fi + + local cmd="$1" + shift + + local fn + + case "$cmd" in + "help" | "--help" | "-h") + fn=usage + ;; + "smuggle") + fn=smuggle + ;; + "register") + fn=register + ;; + "cleanup") + fn=cleanup + ;; + "self-test") + fn=self_test + ;; + "diff") + fn=assert_diff + ;; + *) + echo >&2 "Error: unknown command '$1'; call '$SCRIPT_NAME help' to see the usage." + exit 2 + ;; + esac + + if [[ "$#" -gt "0" && "$cmd" != "diff" && "$cmd" != "register" ]]; then + echo >&2 "Error: too many arguments; call '$SCRIPT_NAME help' to see the usage." + exit 2 + fi + + "$fn" "$@" +} + +function usage { + local example_target_dir="/mnt" + + echo "Usage: $SCRIPT_NAME smuggle|register|cleanup|self-test" + echo + echo "This script enables access to RHEL RPMs during Konflux builds. The intended usage is as follows." + echo + + echo -n "1. Make sure there is a '$SECRET_NAME_IN_KONFLUX' secret in Konflux with key name '$SECRET_KEY' and " + echo "the actual activation key as a value." + echo " Find where to get the secret from ${SECRET_INFO_URL}" + + echo -n "2. In a Tekton pipeline step before the container build, copy the subscription manager activation " + echo "key secret to the source workspace. Use:" + echo " \$ /$SCRIPT_NAME smuggle" + echo -n " This expects the '$SECRET_NAME_IN_KONFLUX' secret to be mounted as a workspace with the same name " + echo "('$SECRET_KONFLUX_WORKSPACE_PATH')." + + echo "3. Arrange Dockerfile stages to have UBI (normal) as an installer and other RHEL/UBI (any) as a target." + echo " Make sure to match major versions: 8/8 is ok but 9/8 or 8/9 will result in errors." + echo " Copy the target contents to some directory, e.g. ${example_target_dir}, in the installer stage." + echo " See self-test Dockerfiles as examples." + + echo "4. In the installer stage, register the container with the subscription manager. Use:" + echo " \$ $SCRIPT_NAME register ${example_target_dir}" + echo -n " It is possible to provide multiple target directories as arguments if the script is used to prepare " + echo "multiple distinct stages." + + echo -n "5. Use 'dnf --installroot=${example_target_dir} ...' to install RHEL RPMs, enable RHEL modules, etc. " + echo "in the target contents." + + echo -n "6. In the same installer stage, deregister the container so that the end users can't use " + echo "our subscription on our behalf. Use:" + echo " \$ $SCRIPT_NAME cleanup" + echo " This step is mandatory because it cleans entitlements on the target in the right way." + + echo -n "7. Copy out ${example_target_dir} contents from the installer stage to a new 'scratch' stage. " + echo "That's your target container." + + echo + echo "When altering this script, use the 'self-test' command as a (regression) test tool:" + echo " \$ $SCRIPT_NAME self-test" + echo "For it to work, you need to put a valid activation key in ${SECRET_LOCAL_PATH} file." + echo "Find out where to get it from ${SECRET_INFO_URL}" +} + +function smuggle { + mkdir -p "$(dirname "${SECRET_LOCAL_PATH}")" + cp --verbose "${SECRET_KONFLUX_WORKSPACE_PATH}/${SECRET_KEY}" "${SECRET_LOCAL_PATH}" +} + +function register { + if [[ ! -s "${SECRET_LOCAL_PATH}" ]]; then + echo >&2 "Error: it does not look like the activation key is present in ${SECRET_LOCAL_PATH}" + exit 3 + fi + local secret + secret="$(cat "${SECRET_LOCAL_PATH}")" + + if [[ "$#" -lt 1 ]]; then + echo >&2 "Error: target path(s) must be provided for the 'register' command." + exit 2 + fi + + local target_dirs=("$@") + + check_targets_and_store_paths_for_cleanup "${target_dirs[@]}" + + # Besides just installing packages and making the desired updates to rpmdb, the use of subscription-manager with + # the subsequent installation introduces some side-effects that seem undesired. Backup and restore is how I suggest + # maintaining the original state of the target. + for target_dir in "${target_dirs[@]}"; do + echo "Backing up the original artifacts in $target_dir" + mkdir -p "${target_dir}/tmp/restore" + tar --create -vf "${target_dir}/tmp/restore/backup.tar" --files-from /dev/null + for item in "${TARGET_BACKUP_PATHS[@]}"; do + if [[ -e "${target_dir}/${item}" ]]; then + tar --append -vf "${target_dir}/tmp/restore/backup.tar" -C "${target_dir}" "${item}" + fi + done + done + + echo "Registering the installer container with the subscription manager" + subscription-manager register --org="$RED_HAT_ORG_ID" --activationkey="$secret" + + # It is suggested in the following articles that certain files can be linked to $target_dir/run/secrets, + # but I was not able to make it work, therefore doing it differently. + # https://www.neteye-blog.com/2022/07/how-to-use-a-hosts-redhat-subscription-to-run-containers-using-docker-instead-of-podman/ + # https://access.redhat.com/solutions/5870841 + for target_dir in "${target_dirs[@]}"; do + echo "Enabling entitled rpm repos in $target_dir" + mkdir -p "${target_dir}/etc/pki/entitlement" + ln --verbose -s /etc/pki/entitlement/*.pem "${target_dir}/etc/pki/entitlement" + ln --verbose --force -s /etc/yum.repos.d/redhat.repo "${target_dir}/etc/yum.repos.d/" + done + + echo "Looks like the registration succeeded. Don't forget to call '$SCRIPT_NAME cleanup' when done with rpms!" +} + +function check_targets_and_store_paths_for_cleanup { + local target_dirs=("$@") + + for target_dir in "${target_dirs[@]}"; do + if [[ ! -d "${target_dir}/etc" ]]; then + echo >&2 "Error: Looks like the target system is not placed at ${target_dir}" + exit 4 + fi + done + + if [[ -f "${TARGETS_LIST_FILE}" ]]; then + echo >&2 "Error: ${TARGETS_LIST_FILE} already exists. Are you trying to register again without doing a cleanup?" + exit 5 + fi + + printf "%s\n" "${target_dirs[@]}" > "${TARGETS_LIST_FILE}" +} + +function cleanup { + local -a target_dirs + readarray -t target_dirs < "${TARGETS_LIST_FILE}" + + for target_dir in "${target_dirs[@]}"; do + echo "Cleaning up entitlement artifacts in $target_dir" + + echo "Restoring original artifacts" + for item in "${TARGET_BACKUP_PATHS[@]}"; do + rm --verbose -rf "${target_dir:?}/${item}" + done + tar --extract -vf "${target_dir}/tmp/restore/backup.tar" -C "${target_dir}" + + echo "Removing original artifacts backups" + rm --verbose -rf "${target_dir:?}/tmp/restore" + done + + # It should be good to unregister this installer container so that it's not left hanging in some Red Hat database. + echo "Unregistering the installer container" + subscription-manager unregister + + rm --verbose "${TARGETS_LIST_FILE}" + + echo "Cleanup complete." +} + +function self_test { + local command="podman" + + local targets=( + "registry.access.redhat.com/ubi8/ubi-micro:latest" + "registry.access.redhat.com/ubi8/ubi-minimal:latest" + "registry.access.redhat.com/ubi8/ubi:latest" + "registry.redhat.io/rhel8/toolbox:latest" + + "registry.access.redhat.com/ubi9/ubi-micro:latest" + "registry.access.redhat.com/ubi9/ubi-minimal:latest" + "registry.access.redhat.com/ubi9/ubi:latest" + "registry.redhat.io/rhel9/toolbox:latest" + ) + + for target in "${targets[@]}"; do + [[ $target =~ /(ubi|rhel)([0-9]+)/ ]] + local major_version="${BASH_REMATCH[2]}" + + echo + echo + echo "Testing against ${target} with the installer major version ${major_version}" + echo + echo + + set -x + "${command}" build \ + -f "${SCRIPT_DIR}/bro.self-test.Dockerfile" \ + --build-arg TARGET_BASE="${target}" \ + --build-arg INSTALLER_MAJOR_VERSION="${major_version}" \ + "${SCRIPT_DIR}" + set +x + done + + "${command}" build -f "${SCRIPT_DIR}/bro.self-test-demo.Dockerfile" "${SCRIPT_DIR}" + "${command}" build -f "${SCRIPT_DIR}/bro.self-test-multiple-targets.Dockerfile" "${SCRIPT_DIR}" + echo "Self-tests passed." +} + +function assert_diff { + if [[ "$#" != "2" ]]; then + echo >&2 "Error: expecting two arguments: expected and actual paths" + exit 2 + fi + + local expected="$1" + local actual="$2" + + local failed_check_file + failed_check_file="$(mktemp)" + + echo "Comparing /etc" + if ! diff --brief --recursive --no-dereference --exclude='ld.so.cache' "$expected/etc" "$actual/etc"; then + echo 1 >> "$failed_check_file" + fi + + echo "Comparing /var" + local var_exclusions + var_exclusions="$(mktemp)" + { + # Before adding any exclusions here, make sure you check there's nothing sensitive in these files. + # If sensitive, they should be added to backup/restore (TARGET_BACKUP_PATHS) or cleanup. + echo '/var/lib: dnf' + echo '/var/lib/dnf/history\.sqlite' + echo '/var/lib/rpm(:|/)' + echo '/var/log: (dnf.*|hawkey)\.log' + echo '/var/log/(dnf.*|hawkey)\.log' + # /var/cache/dnf should be kept on Target, otherwise Konflux Enterprise Check fails not finding SBOM. + echo '/var/cache(: |/)dnf' + } >> "$var_exclusions" + + if { diff --brief --recursive --no-dereference "$expected/var" "$actual/var" || true; } \ + | grep -vEf "$var_exclusions" | { grep '.'; }; then + echo 2 >> "$failed_check_file" + fi + + local other_dirs_to_compare=(bin home lib lib64 media mnt opt root sbin srv tmp usr) + + for dir in "${other_dirs_to_compare[@]}"; do + echo "Comparing /$dir" + if ! diff --brief --recursive --no-dereference "$expected/$dir" "$actual/$dir"; then + echo 3 >> "$failed_check_file" + fi + done + + if [[ -s "$failed_check_file" ]]; then + echo >&2 "Error: differences detected" + exit 6 + fi + + echo "Diff check for $expected and $actual passed." +} + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + main "$@" +fi diff --git a/.tekton/collector-pull-request.yaml b/.tekton/collector-pull-request.yaml index 88d8213a5d..3fdb7f6253 100644 --- a/.tekton/collector-pull-request.yaml +++ b/.tekton/collector-pull-request.yaml @@ -61,6 +61,9 @@ spec: - name: git-auth secret: secretName: '{{ git_auth_secret }}' + - name: subscription-manager-activation-key + secret: + secretName: subscription-manager-activation-key # The pipeline regularly takes >1h to finish. timeouts: @@ -173,6 +176,7 @@ spec: workspaces: - name: workspace - name: git-auth + - name: subscription-manager-activation-key tasks: @@ -221,6 +225,21 @@ spec: - name: basic-auth workspace: git-auth + - name: prepare-rhel-rpm-subscriptions + runAfter: + - clone-repository + workspaces: + - name: source + workspace: workspace + - name: subscription-manager-activation-key + workspace: subscription-manager-activation-key + taskSpec: + steps: + # TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. + - name: smuggle-activation-key + image: registry.access.redhat.com/ubi8/ubi:latest + script: exec "$(workspaces.source.path)/source/.konflux/scripts/subscription-manager-bro.sh" smuggle + - name: prefetch-dependencies params: - name: input @@ -242,7 +261,6 @@ spec: - name: fetch-support-package runAfter: - - init - clone-repository taskSpec: steps: @@ -275,8 +293,9 @@ spec: - name: COMMIT_SHA value: $(tasks.clone-repository.results.commit) runAfter: - - prefetch-dependencies - fetch-support-package + - prefetch-dependencies + - prepare-rhel-rpm-subscriptions taskRef: params: - name: name diff --git a/.tekton/collector-push.yaml b/.tekton/collector-push.yaml index 290c342b15..32a7c2d32f 100644 --- a/.tekton/collector-push.yaml +++ b/.tekton/collector-push.yaml @@ -61,6 +61,9 @@ spec: - name: git-auth secret: secretName: '{{ git_auth_secret }}' + - name: subscription-manager-activation-key + secret: + secretName: subscription-manager-activation-key # The pipeline regularly takes >1h to finish. timeouts: @@ -173,6 +176,7 @@ spec: workspaces: - name: workspace - name: git-auth + - name: subscription-manager-activation-key tasks: @@ -221,6 +225,21 @@ spec: - name: basic-auth workspace: git-auth + - name: prepare-rhel-rpm-subscriptions + runAfter: + - clone-repository + workspaces: + - name: source + workspace: workspace + - name: subscription-manager-activation-key + workspace: subscription-manager-activation-key + taskSpec: + steps: + # TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. + - name: smuggle-activation-key + image: registry.access.redhat.com/ubi8/ubi:latest + script: exec "$(workspaces.source.path)/source/.konflux/scripts/subscription-manager-bro.sh" smuggle + - name: prefetch-dependencies params: - name: input @@ -242,7 +261,6 @@ spec: - name: fetch-support-package runAfter: - - init - clone-repository taskSpec: steps: @@ -275,8 +293,9 @@ spec: - name: COMMIT_SHA value: $(tasks.clone-repository.results.commit) runAfter: - - prefetch-dependencies - fetch-support-package + - prefetch-dependencies + - prepare-rhel-rpm-subscriptions taskRef: params: - name: name diff --git a/.tekton/collector-slim-pull-request.yaml b/.tekton/collector-slim-pull-request.yaml index 5f3ef569a2..5a73889df2 100644 --- a/.tekton/collector-slim-pull-request.yaml +++ b/.tekton/collector-slim-pull-request.yaml @@ -59,6 +59,9 @@ spec: - name: git-auth secret: secretName: '{{ git_auth_secret }}' + - name: subscription-manager-activation-key + secret: + secretName: subscription-manager-activation-key pipelineSpec: @@ -167,6 +170,7 @@ spec: workspaces: - name: workspace - name: git-auth + - name: subscription-manager-activation-key tasks: @@ -213,12 +217,27 @@ spec: - name: basic-auth workspace: git-auth + - name: prepare-rhel-rpm-subscriptions + runAfter: + - clone-repository + workspaces: + - name: source + workspace: workspace + - name: subscription-manager-activation-key + workspace: subscription-manager-activation-key + taskSpec: + steps: + # TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. + - name: smuggle-activation-key + image: registry.access.redhat.com/ubi8/ubi:latest + script: exec /workspace/source/source/.konflux/scripts/subscription-manager-bro.sh smuggle + - name: prefetch-dependencies params: - name: input value: $(params.prefetch-input) runAfter: - - clone-repository + - prepare-rhel-rpm-subscriptions taskRef: params: - name: name diff --git a/.tekton/collector-slim-push.yaml b/.tekton/collector-slim-push.yaml index e55d6207bc..f278bc3b35 100644 --- a/.tekton/collector-slim-push.yaml +++ b/.tekton/collector-slim-push.yaml @@ -59,6 +59,9 @@ spec: - name: git-auth secret: secretName: '{{ git_auth_secret }}' + - name: subscription-manager-activation-key + secret: + secretName: subscription-manager-activation-key pipelineSpec: @@ -167,6 +170,7 @@ spec: workspaces: - name: workspace - name: git-auth + - name: subscription-manager-activation-key tasks: @@ -213,12 +217,27 @@ spec: - name: basic-auth workspace: git-auth + - name: prepare-rhel-rpm-subscriptions + runAfter: + - clone-repository + workspaces: + - name: source + workspace: workspace + - name: subscription-manager-activation-key + workspace: subscription-manager-activation-key + taskSpec: + steps: + # TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. + - name: smuggle-activation-key + image: registry.access.redhat.com/ubi8/ubi:latest + script: exec /workspace/source/source/.konflux/scripts/subscription-manager-bro.sh smuggle + - name: prefetch-dependencies params: - name: input value: $(params.prefetch-input) runAfter: - - clone-repository + - prepare-rhel-rpm-subscriptions taskRef: params: - name: name diff --git a/collector/container/konflux-slim.Dockerfile b/collector/container/konflux-slim.Dockerfile index cf3409ac3f..fab84cadae 100644 --- a/collector/container/konflux-slim.Dockerfile +++ b/collector/container/konflux-slim.Dockerfile @@ -1,55 +1,48 @@ ARG BUILD_DIR=/build ARG CMAKE_BUILD_DIR=${BUILD_DIR}/cmake-build +# Builder # TODO(ROX-20312): we can't pin image tag or digest because currently there's no mechanism to auto-update that. -# TODO(ROX-20651): Use RHEL/ubi base image when entitlement is solved. -# RPMs requiring entitlement: bpftool, cmake-3.18.2-9.el8, elfutils-libelf-devel, tbb-devel, c-ares-devel, jq-devel -# FROM registry.access.redhat.com/ubi8/ubi:latest AS builder -FROM quay.io/centos/centos:stream8 AS builder +# TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. +FROM registry.access.redhat.com/ubi8/ubi:latest AS ubi-normal +FROM registry.access.redhat.com/ubi8/ubi:latest AS rpm-implanter-builder -COPY . . +COPY --from=ubi-normal / /mnt +COPY ./.konflux /tmp/.konflux # TODO(ROX-20234): use hermetic builds when installing/updating RPMs becomes hermetic. -RUN dnf upgrade -y --nobest \ - && dnf -y install --nobest \ - autoconf \ - automake \ - binutils-devel \ - bison \ - ca-certificates \ - clang-15.0.7 \ - cmake \ - cracklib-dicts \ - diffutils \ - elfutils-libelf-devel \ - file \ - flex \ - gcc \ - gcc-c++ \ - gdb \ - gettext \ - git \ - glibc-devel \ - libasan \ - libubsan \ - libcap-ng-devel \ - libcurl-devel \ - libtool \ - libuuid-devel \ +RUN /tmp/.konflux/scripts/subscription-manager-bro.sh register /mnt && \ + dnf -y --installroot=/mnt upgrade --nobest && \ + dnf -y --installroot=/mnt install --nobest \ make \ - openssh-server \ - openssl-devel \ - patchutils \ - passwd \ - pkgconfig \ - rsync \ - tar \ - unzip \ - valgrind \ wget \ - which \ + unzip \ + clang \ bpftool \ - && dnf clean all + cmake-3.18.2-9.el8 \ + gcc-c++ \ + openssl-devel \ + ncurses-devel \ + curl-devel \ + libuuid-devel \ + libcap-ng-devel \ + autoconf \ + libtool \ + git \ + elfutils-libelf-devel \ + tbb-devel \ + jq-devel \ + c-ares-devel && \ + /tmp/.konflux/scripts/subscription-manager-bro.sh cleanup && \ + dnf -y --installroot=/mnt clean all + +FROM scratch as builder + +COPY --from=rpm-implanter-builder /mnt / + +ARG SOURCES_DIR=/staging + +COPY . ${SOURCES_DIR} ARG BUILD_DIR ARG SRC_ROOT_DIR=${BUILD_DIR} @@ -66,17 +59,15 @@ ARG TRACE_SINSP_EVENTS=false WORKDIR ${BUILD_DIR} RUN mkdir kernel-modules \ - && cp -a /builder builder \ - && cp -a /collector collector \ - && cp -a /falcosecurity-libs falcosecurity-libs \ - && cp -a /builder/third_party third_party \ - && cp -a /kernel-modules/MODULE_VERSION kernel-modules/MODULE_VERSION \ - && cp -a /CMakeLists.txt CMakeLists.txt + && cp -a ${SOURCES_DIR}/builder builder \ + && ln -s builder/third_party third_party \ + && cp -a ${SOURCES_DIR}/collector collector \ + && cp -a ${SOURCES_DIR}/falcosecurity-libs falcosecurity-libs \ + && cp -a ${SOURCES_DIR}/kernel-modules/MODULE_VERSION kernel-modules/MODULE_VERSION \ + && cp -a ${SOURCES_DIR}/CMakeLists.txt CMakeLists.txt # WITH_RHEL_RPMS controls for dependency installation, ie if they were already installed as RPMs. -# Setting the value to empty will cause dependencies to be downloaded from repositories or accessed in submodules and compiled. -# TODO(ROX-20651): Set ENV WITH_RHEL_RPMS=true when RHEL RPMs can be installed to enable hermetic builds. -# ENV WITH_RHEL_RPMS=true +ENV WITH_RHEL_RPMS=true # Build with gperftools (DISABLE_PROFILING=OFF) only for supported # architectures, at the moment x86_64 only @@ -96,44 +87,68 @@ RUN ./builder/install/install-dependencies.sh && \ ctest -V --test-dir ${CMAKE_BUILD_DIR} && \ strip -v --strip-unneeded "${CMAKE_BUILD_DIR}/collector/collector" -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +# Application +FROM registry.access.redhat.com/ubi8/ubi-minimal:latest AS ubi-minimal +FROM ubi-normal AS rpm-implanter-app -ARG BUILD_DIR -ARG CMAKE_BUILD_DIR +COPY --from=ubi-minimal / /mnt +COPY ./.konflux /tmp/.konflux + +# TODO(ROX-20234): use hermetic builds when installing/updating RPMs becomes hermetic. +RUN /tmp/.konflux/scripts/subscription-manager-bro.sh register /mnt && \ + dnf -y --installroot=/mnt upgrade --nobest && \ + dnf -y --installroot=/mnt install --nobest \ + kmod \ + tbb \ + jq \ + c-ares && \ + /tmp/.konflux/scripts/subscription-manager-bro.sh cleanup && \ + # We can do usual cleanup while we're here: remove packages that would trigger violations. \ + dnf -y --installroot=/mnt clean all && \ + rpm --root=/mnt --verbose -e --nodeps $(rpm --root=/mnt -qa 'curl' '*rpm*' '*dnf*' '*libsolv*' '*hawkey*' 'yum*') && \ + rm -rf /mnt/var/cache/dnf /mnt/var/cache/yum + +FROM scratch + +COPY --from=rpm-implanter-app /mnt / # TODO(ROX-20236): configure injection of dynamic version value when it becomes possible. ARG COLLECTOR_VERSION=0.0.1-todo -ENV COLLECTOR_HOST_ROOT=/host +WORKDIR / LABEL \ com.redhat.component="rhacs-collector-slim-container" \ com.redhat.license_terms="https://www.redhat.com/agreements" \ description="This image supports runtime data collection in the StackRox Kubernetes Security Platform" \ + distribution-scope="public" \ io.k8s.description="This image supports runtime data collection in the StackRox Kubernetes Security Platform" \ io.k8s.display-name="collector-slim" \ io.openshift.tags="rhacs,collector,stackrox" \ maintainer="Red Hat, Inc." \ name="rhacs-collector-slim-rhel8" \ + # TODO(ROX-20236): release label is required by EC, figure what to put in the release version on rebuilds. + release="0" \ source-location="https://github.com/stackrox/collector" \ summary="Runtime data collection for the StackRox Kubernetes Security Platform" \ url="https://catalog.redhat.com/software/container-stacks/detail/60eefc88ee05ae7c5b8f041c" \ - version=${COLLECTOR_VERSION} + version=${COLLECTOR_VERSION} \ + vendor="Red Hat, Inc." -WORKDIR / +ARG BUILD_DIR +ARG CMAKE_BUILD_DIR -COPY collector/container/rhel/install.sh / -RUN ./install.sh && rm -f install.sh +ENV COLLECTOR_HOST_ROOT=/host -COPY collector/container/scripts/collector-wrapper.sh /usr/local/bin/ -COPY collector/container/scripts/bootstrap.sh / COPY kernel-modules/MODULE_VERSION /kernel-modules/MODULE_VERSION.txt COPY --from=builder ${CMAKE_BUILD_DIR}/collector/collector /usr/local/bin/ COPY --from=builder ${CMAKE_BUILD_DIR}/collector/self-checks /usr/local/bin/ +COPY --from=builder ${BUILD_DIR}/collector/container/scripts / -RUN echo '/usr/local/lib' > /etc/ld.so.conf.d/usrlocallib.conf && \ - ldconfig && \ - chmod 700 bootstrap.sh +RUN mv /collector-wrapper.sh /usr/local/bin/ && \ + chmod 700 bootstrap.sh && \ + echo '/usr/local/lib' > /etc/ld.so.conf.d/usrlocallib.conf && \ + ldconfig EXPOSE 8080 9090 diff --git a/collector/container/konflux.Dockerfile b/collector/container/konflux.Dockerfile index 93b43de21f..f8e1fcfd4e 100644 --- a/collector/container/konflux.Dockerfile +++ b/collector/container/konflux.Dockerfile @@ -1,55 +1,48 @@ ARG BUILD_DIR=/build ARG CMAKE_BUILD_DIR=${BUILD_DIR}/cmake-build +# Builder # TODO(ROX-20312): we can't pin image tag or digest because currently there's no mechanism to auto-update that. -# TODO(ROX-20651): Use RHEL/ubi base image when entitlement is solved. -# RPMs requiring entitlement: bpftool, cmake-3.18.2-9.el8, elfutils-libelf-devel, tbb-devel, c-ares-devel, jq-devel -# FROM registry.access.redhat.com/ubi8/ubi:latest AS builder -FROM quay.io/centos/centos:stream8 AS builder +# TODO(ROX-20651): use content sets instead of subscription manager for access to RHEL RPMs once available. +FROM registry.access.redhat.com/ubi8/ubi:latest AS ubi-normal +FROM registry.access.redhat.com/ubi8/ubi:latest AS rpm-implanter-builder -COPY . . +COPY --from=ubi-normal / /mnt +COPY ./.konflux /tmp/.konflux # TODO(ROX-20234): use hermetic builds when installing/updating RPMs becomes hermetic. -RUN dnf upgrade -y --nobest \ - && dnf -y install --nobest \ - autoconf \ - automake \ - binutils-devel \ - bison \ - ca-certificates \ - clang-15.0.7 \ - cmake \ - cracklib-dicts \ - diffutils \ - elfutils-libelf-devel \ - file \ - flex \ - gcc \ - gcc-c++ \ - gdb \ - gettext \ - git \ - glibc-devel \ - libasan \ - libubsan \ - libcap-ng-devel \ - libcurl-devel \ - libtool \ - libuuid-devel \ +RUN /tmp/.konflux/scripts/subscription-manager-bro.sh register /mnt && \ + dnf -y --installroot=/mnt upgrade --nobest && \ + dnf -y --installroot=/mnt install --nobest \ make \ - openssh-server \ - openssl-devel \ - patchutils \ - passwd \ - pkgconfig \ - rsync \ - tar \ - unzip \ - valgrind \ wget \ - which \ + unzip \ + clang \ bpftool \ - && dnf clean all + cmake-3.18.2-9.el8 \ + gcc-c++ \ + openssl-devel \ + ncurses-devel \ + curl-devel \ + libuuid-devel \ + libcap-ng-devel \ + autoconf \ + libtool \ + git \ + elfutils-libelf-devel \ + tbb-devel \ + jq-devel \ + c-ares-devel && \ + /tmp/.konflux/scripts/subscription-manager-bro.sh cleanup && \ + dnf -y --installroot=/mnt clean all + +FROM scratch as builder + +COPY --from=rpm-implanter-builder /mnt / + +ARG SOURCES_DIR=/staging + +COPY . ${SOURCES_DIR} ARG BUILD_DIR ARG SRC_ROOT_DIR=${BUILD_DIR} @@ -66,17 +59,15 @@ ARG TRACE_SINSP_EVENTS=false WORKDIR ${BUILD_DIR} RUN mkdir kernel-modules \ - && cp -a /builder builder \ - && cp -a /collector collector \ - && cp -a /falcosecurity-libs falcosecurity-libs \ - && cp -a /builder/third_party third_party \ - && cp -a /kernel-modules/MODULE_VERSION kernel-modules/MODULE_VERSION \ - && cp -a /CMakeLists.txt CMakeLists.txt + && cp -a ${SOURCES_DIR}/builder builder \ + && ln -s builder/third_party third_party \ + && cp -a ${SOURCES_DIR}/collector collector \ + && cp -a ${SOURCES_DIR}/falcosecurity-libs falcosecurity-libs \ + && cp -a ${SOURCES_DIR}/kernel-modules/MODULE_VERSION kernel-modules/MODULE_VERSION \ + && cp -a ${SOURCES_DIR}/CMakeLists.txt CMakeLists.txt # WITH_RHEL_RPMS controls for dependency installation, ie if they were already installed as RPMs. -# Setting the value to empty will cause dependencies to be downloaded from repositories or accessed in submodules and compiled. -# TODO(ROX-20651): Set ENV WITH_RHEL_RPMS=true when RHEL RPMs can be installed to enable hermetic builds. -# ENV WITH_RHEL_RPMS=true +ENV WITH_RHEL_RPMS=true # Build with gperftools (DISABLE_PROFILING=OFF) only for supported # architectures, at the moment x86_64 only @@ -134,45 +125,69 @@ RUN if [[ "$(ls -A /kernel-modules)" == "" ]]; then \ exit 1; \ fi -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +# Application +FROM registry.access.redhat.com/ubi8/ubi-minimal:latest AS ubi-minimal +FROM ubi-normal AS rpm-implanter-app -ARG BUILD_DIR -ARG CMAKE_BUILD_DIR +COPY --from=ubi-minimal / /mnt +COPY ./.konflux /tmp/.konflux + +# TODO(ROX-20234): use hermetic builds when installing/updating RPMs becomes hermetic. +RUN /tmp/.konflux/scripts/subscription-manager-bro.sh register /mnt && \ + dnf -y --installroot=/mnt upgrade --nobest && \ + dnf -y --installroot=/mnt install --nobest \ + kmod \ + tbb \ + jq \ + c-ares && \ + /tmp/.konflux/scripts/subscription-manager-bro.sh cleanup && \ + # We can do usual cleanup while we're here: remove packages that would trigger violations. \ + dnf -y --installroot=/mnt clean all && \ + rpm --root=/mnt --verbose -e --nodeps $(rpm --root=/mnt -qa 'curl' '*rpm*' '*dnf*' '*libsolv*' '*hawkey*' 'yum*') && \ + rm -rf /mnt/var/cache/dnf /mnt/var/cache/yum + +FROM scratch + +COPY --from=rpm-implanter-app /mnt / # TODO(ROX-20236): configure injection of dynamic version value when it becomes possible. ARG COLLECTOR_VERSION=0.0.1-todo -ENV COLLECTOR_HOST_ROOT=/host +WORKDIR / LABEL \ com.redhat.component="rhacs-collector-container" \ com.redhat.license_terms="https://www.redhat.com/agreements" \ description="This image supports runtime data collection in the StackRox Kubernetes Security Platform" \ + distribution-scope="public" \ io.k8s.description="This image supports runtime data collection in the StackRox Kubernetes Security Platform" \ io.k8s.display-name="collector" \ io.openshift.tags="rhacs,collector,stackrox" \ maintainer="Red Hat, Inc." \ name="rhacs-collector-rhel8" \ + # TODO(ROX-20236): release label is required by EC, figure what to put in the release version on rebuilds. + release="0" \ source-location="https://github.com/stackrox/collector" \ summary="Runtime data collection for the StackRox Kubernetes Security Platform" \ url="https://catalog.redhat.com/software/container-stacks/detail/60eefc88ee05ae7c5b8f041c" \ - version=${COLLECTOR_VERSION} + version=${COLLECTOR_VERSION} \ + vendor="Red Hat, Inc." -WORKDIR / +ARG BUILD_DIR +ARG CMAKE_BUILD_DIR -COPY collector/container/rhel/install.sh / -RUN ./install.sh && rm -f install.sh +ENV COLLECTOR_HOST_ROOT=/host -COPY collector/container/scripts/collector-wrapper.sh /usr/local/bin/ -COPY collector/container/scripts/bootstrap.sh / COPY --from=unpacker /kernel-modules /kernel-modules COPY kernel-modules/MODULE_VERSION /kernel-modules/MODULE_VERSION.txt COPY --from=builder ${CMAKE_BUILD_DIR}/collector/collector /usr/local/bin/ COPY --from=builder ${CMAKE_BUILD_DIR}/collector/self-checks /usr/local/bin/ +COPY --from=builder ${BUILD_DIR}/collector/container/scripts / -RUN echo '/usr/local/lib' > /etc/ld.so.conf.d/usrlocallib.conf && \ - ldconfig && \ - chmod 700 bootstrap.sh +RUN mv /collector-wrapper.sh /usr/local/bin/ && \ + chmod 700 bootstrap.sh && \ + echo '/usr/local/lib' > /etc/ld.so.conf.d/usrlocallib.conf && \ + ldconfig EXPOSE 8080 9090