Skip to content
Merged
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
128 changes: 65 additions & 63 deletions dockers/docker-ptf/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ FROM {{ prefix }}debian:bookworm
USER root
WORKDIR /root

LABEL maintainer="Pavel Shirshov"

COPY ["sources.list.{{ CONFIGURED_ARCH }}", "/etc/apt/sources.list"]
COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"]
COPY ["apt-retries-count", "/etc/apt/apt.conf.d"]
# Install certificates by disabling the peer verification
RUN apt -o Acquire::https::Verify-Peer=false update && \
apt -o Acquire::https::Verify-Peer=false install -y ca-certificates

## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive
Expand Down Expand Up @@ -51,7 +52,7 @@ RUN apt-get update \
{% if PTF_ENV_PY_VER == "mixed" %}
libboost-atomic1.71.0 \
{% else %}
libboost-atomic1.74.0 \
libboost-atomic1.81.0 \
flex \
bison \
tcpd \
Expand Down Expand Up @@ -102,19 +103,19 @@ RUN apt-get update \
quilt \
&& rm -rf /var/lib/apt/lists/*

# Install Go toolchain for building grpcurl and gnoic from source
# to ensure they use a patched Go stdlib (GO-2026-4337: crypto/tls)
# Install Go toolchain for building grpcurl and gnmic from source
# to ensure they use a patched Go stdlib (GO-2026-5039: net/textproto)
{% if CONFIGURED_ARCH == "armhf" %}
RUN GO_ARCH=armv6l \
&& GO_SHA256=7d4f0d266d871301e08ef4ac31c56e66048688893b2848392e5c600276351ee8 \
&& GO_SHA256=492d69badee59cae12e9a36282dfce94041bd4aac88fdddea575a7d99a2bd05d \
{% elif CONFIGURED_ARCH == "arm64" %}
RUN GO_ARCH=arm64 \
&& GO_SHA256=ec342e7389b7f489564ed5463c63b16cf8040023dabc7861256677165a8c0e2b \
&& GO_SHA256=c30bf9e156a54ea4e31fbbbf31a712b32734b58cc9a22426fa5ee632d0885124 \
{% else %}
RUN GO_ARCH=amd64 \
&& GO_SHA256=00859d7bd6defe8bf84d9db9e57b9a4467b2887c18cd93ae7460e713db774bc1 \
&& GO_SHA256=34f14304e856893f4ba30c2cacfe93906e9de7915c5f6aaaf3a81cdccd7ba30b \
{% endif %}
&& GO_VERSION=1.25.9 \
&& GO_VERSION=1.25.11 \
&& curl -L "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz \
&& echo "${GO_SHA256} /tmp/go.tar.gz" | sha256sum -c - \
&& tar -C /usr/local -xzf /tmp/go.tar.gz \
Expand Down Expand Up @@ -158,7 +159,10 @@ RUN set -eux \
&& ldconfig \
&& ln -sf /usr/local/bin/influxdb3 /usr/local/bin/influxd \
&& rm -f "influxdb3-core-${INFLUXDB_VERSION}_${INFLUXDB_ARCH}.tar.gz" \
&& rm -rf "/tmp/influxdb3-core-${INFLUXDB_VERSION}"
&& rm -rf "/tmp/influxdb3-core-${INFLUXDB_VERSION}" \
&& pip3 install --target /usr/local/lib/influxdb3-python/lib/python3.13/site-packages "pip>=26.1" \
&& NEWPIP=$(ls -d /usr/local/lib/influxdb3-python/lib/python3.13/site-packages/pip-*.dist-info | sort -V | tail -1) \
&& find /usr/local/lib/influxdb3-python/lib/python3.13/site-packages -maxdepth 1 -name 'pip-*.dist-info' ! -path "$NEWPIP" -exec rm -rf {} +
{% endif %}

{% if PTF_ENV_PY_VER == "py3" %}
Expand Down Expand Up @@ -209,7 +213,7 @@ RUN rm -rf /debs \
{% endif %}
&& git clone https://github.com/sflow/sflowtool \
&& cd sflowtool \
&& git checkout v6.04 \
&& git checkout v6.09 \
&& ./boot.sh \
&& ./configure \
&& make \
Expand All @@ -225,17 +229,17 @@ RUN rm -rf /debs \
&& make install \
&& cd .. \
&& rm -fr OpenBFDD \
&& wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \
&& tar xvfz 1.0.0.tar.gz \
&& cd nanomsg-1.0.0 \
&& wget https://github.com/nanomsg/nanomsg/archive/1.2.2.tar.gz \
&& tar xvfz 1.2.2.tar.gz \
&& cd nanomsg-1.2.2 \
&& mkdir -p build \
&& cd build \
&& cmake .. \
&& make install \
&& ldconfig \
&& cd ../.. \
&& rm -fr nanomsg-1.0.0 \
&& rm -f 1.0.0.tar.gz \
&& rm -fr nanomsg-1.2.2 \
&& rm -f 1.2.2.tar.gz \
{% if PTF_ENV_PY_VER == "mixed" %}
&& pip install cffi \
&& pip install nnpy \
Expand Down Expand Up @@ -274,7 +278,7 @@ COPY ["tacacs+", "/etc/default"]
# Workaround: Tornado installed outside of the
# virtualenv as the call to the process API
# Ansible -> Supervisor -> ExaBGP -> Process API
# causes the process API to have a restricted
# causes the process API to have a restricted
# environment without access to the virtualenv.
{% if PTF_ENV_PY_VER == "py3" %}
RUN pip3 install --break-system-packages "tornado>=6.5.5"
Expand All @@ -283,6 +287,9 @@ COPY ["tacacs+", "/etc/default"]

RUN python3 -m venv env-python3
# Activating a virtualenv. The virtualenv automatically works for RUN, ENV and CMD.
# Python 3 reproducible build hooks are not used after this point in docker-ptf.
# Once PATH is switched to the virtualenv, pip3 resolves to the venv binary
# instead of the host pip3 wrapper, so run_pip_command is bypassed.
ENV VIRTUAL_ENV=/root/env-python3
ARG BACKUP_OF_PATH="$PATH"
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
Expand All @@ -295,11 +302,11 @@ RUN pip3 install --upgrade pip
RUN python3 -m pip install --upgrade --ignore-installed pip
{% endif %}

# For py3 image the following offending packages below do not use the updated
# setuptools on Python 3.9. The packages downgrade setuptools
# For py3 image the following offending packages below do not use the updated
# setuptools on Python 3.9. The packages downgrade setuptools
# to 40.x causing further installations to fail
{% if PTF_ENV_PY_VER == "py3" %}
{% set offending_packages = ["supervisor", "ipython", "exabgp==4.2.25", "grpcio-tools", "pybrctl", "pyrasite", "scapy==2.5.0", "thrift"] %}
{% set offending_packages = ["supervisor", "ipython", "exabgp==4.2.25", "grpcio-tools", "pybrctl", "pyrasite", "scapy", "thrift"] %}
{{ install_offending_packages(offending_packages) }}
{% else %}
RUN pip3 install setuptools \
Expand All @@ -309,17 +316,15 @@ RUN pip3 install setuptools \
&& pip3 install grpcio-tools \
&& pip3 install pybrctl \
&& pip3 install pyrasite \
&& pip3 install scapy==2.5.0 \
&& pip3 install scapy \
&& pip3 install thrift
{% endif %}

# Install all python modules from pypi. python3-scapy is exception,
# Install all python modules from pypi. python3-scapy is exception,
# ptf debian package requires python3-scapy
RUN pip3 install Flask \
{% if PTF_ENV_PY_VER == "py3" %}
RUN pip3 install Flask \
&& pip3 install Werkzeug \
{% else %}
RUN pip3 install Flask \
{% endif %}
&& pip3 install Cython \
&& pip3 install cffi \
Expand All @@ -329,15 +334,12 @@ RUN pip3 install Flask \
&& pip3 install pysubnettree \
&& pip3 install paramiko \
&& pip3 install "tornado>=6.5.5" \
&& pip3 install Flask \
&& pip3 install exabgp \
&& pip3 install pyaml \
&& pip3 install pyro4 rpyc \
&& pip3 install unittest-xml-reporting \
&& pip3 install python-libpcap \
&& pip3 install enum34 \
&& pip3 install grpcio \
&& pip3 install six==1.16.0 \
&& pip3 install six \
&& pip3 install itsdangerous \
&& pip3 install retrying \
&& pip3 install jinja2
Expand All @@ -361,7 +363,8 @@ RUN set -e; \
{% endif %}

# Ensure setuptools >= 70.0.0 to address GHSA-cx63-2mw6-8hw5
RUN pip3 install "setuptools>=70.0.0"
# Upgrade lxml to address GHSA-vfmq-68hx-4jfw
RUN pip3 install "setuptools>=70.0.0" "lxml>=5.3.2"

## Adjust sshd settings
RUN mkdir /var/run/sshd \
Expand Down Expand Up @@ -412,50 +415,38 @@ RUN cd gnxi \
# Deactivating a virtualenv.
# ENV PATH="$BACKUP_OF_PATH"

# Build gnoic from source with patched Go and golang.org/x/* deps
# upgraded to latest to address current and future golang.org/x/* CVEs.
RUN git clone https://github.com/karimra/gnoic.git \
&& cd gnoic \
&& git checkout 27bc5a6 \
&& go get google.golang.org/grpc@v1.79.3 \
&& go get github.com/go-viper/mapstructure/v2@v2.4.0 \
&& go get github.com/go-jose/go-jose/v4@latest \
&& go get golang.org/x/crypto@latest golang.org/x/net@latest golang.org/x/text@latest golang.org/x/sys@latest golang.org/x/oauth2@latest \
&& go mod tidy \
&& go build -o /usr/local/bin/gnoic . \
&& cd .. \
&& rm -rf gnoic /root/go/pkg/mod /root/.cache/go-build

# Build gnmic from source with upgraded deps to address known CVEs
COPY gocloud-patches/ /tmp/gocloud-patches/
RUN GNMIC_VERSION=v0.43.0 \
&& git clone --depth 1 --branch "${GNMIC_VERSION}" https://github.com/openconfig/gnmic.git /tmp/gnmic \
# Build gnmic from source at a pinned upstream main commit. Picks up the
# dependency fixes merged after v0.45.0 (grpc 1.79.3, otel-sdk 1.43.0,
# go-git 5.19.0, prometheus 0.311.3, etc.) that address the CVEs which
# forced removal in #27059. The golang.org/x/* modules are additionally
# upgraded to latest to clear current/future golang.org/x/* CVEs (the
# pinned commit still locks older x/crypto, x/net, etc.). Temporary until
# the next tagged gnmic release ships.
RUN GNMIC_REV=653dc5dd4ddcd3bd4197317875a10c1ce8b06653 \
&& git clone https://github.com/openconfig/gnmic.git /tmp/gnmic \
&& cd /tmp/gnmic \
&& go get google.golang.org/grpc@v1.79.3 \
&& go get github.com/cloudflare/circl@v1.6.3 \
&& go get github.com/go-git/go-git/v5@latest \
&& go get github.com/nats-io/nats-server/v2@latest \
&& go get go.opentelemetry.io/otel/sdk@latest \
&& go get github.com/docker/docker@latest \
&& go get github.com/go-jose/go-jose/v4@latest \
&& go get github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream@latest github.com/aws/aws-sdk-go-v2/service/s3@latest github.com/aws/aws-sdk-go-v2/feature/s3/manager@latest \
&& git checkout "${GNMIC_REV}" \
&& go get golang.org/x/crypto@latest golang.org/x/net@latest golang.org/x/text@latest golang.org/x/sys@latest golang.org/x/oauth2@latest \
&& go get gocloud.dev@v0.25.1-0.20220408200107-09b10f7359f7 \
&& go mod tidy \
&& GOCLOUD_DIR="$(go list -m -f '{{ '{{' }}.Dir{{ '}}' }}' gocloud.dev)" \
&& chmod -R +w "$GOCLOUD_DIR" \
&& patch --forward -d "$GOCLOUD_DIR" -p1 < /tmp/gocloud-patches/0001-fix-aws-sdk-go-v2-pointer-api-changes.patch \
&& go build -o /usr/local/bin/gnmic . \
&& chmod +x /usr/local/bin/gnmic \
&& rm -rf /tmp/gnmic /tmp/gocloud-patches /root/go/pkg/mod /root/.cache/go-build
&& rm -rf /tmp/gnmic /root/go/pkg/mod /root/.cache/go-build

# Remove Go toolchain to reduce image size
RUN rm -rf /usr/local/go "$(go env GOPATH 2>/dev/null || echo $HOME/go)"
ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

{% if PTF_ENV_PY_VER == "py3" %}
# Install the python-saithrift into the virtual environment
RUN echo "/usr/lib/python3/dist-packages/saithrift-0.9-py3.11.egg" >> /root/env-python3/lib/python3.11/site-packages/easy-install.pth
# Register the python-saithrift egg on the virtualenv path. Use an
# executable .pth line that globs for the egg at every interpreter
# startup, so the path is resolved dynamically rather than pinned to a
# specific Python minor version. This keeps switch_sai_thrift importable
# even after test_update_saithrift_ptf swaps in a saithrift deb built for
# a different Python minor (e.g. py3.13 from a Trixie/OS13 DUT image).
# saithrift is thrift-generated pure Python, so the egg loads across py3.x.
RUN PYVER=$(python3 -c 'import sys; print("%d.%d" % sys.version_info[:2])') \
&& echo "import glob, sys; sys.path.extend(glob.glob('"'"'/usr/lib/python3/dist-packages/saithrift-0.9-py3.*.egg'"'"'))" \
>> "/root/env-python3/lib/python${PYVER}/site-packages/easy-install.pth"
{% endif %}

# {% if PTF_ENV_PY_VER == "py3" %}
Expand Down Expand Up @@ -490,6 +481,17 @@ RUN echo "/root/env-python3/lib/python3.11/site-packages" > /usr/lib/python3/dis

RUN echo "PYTHONPATH=/root/env-python3/lib/python3.11/site-packages" >> /etc/environment

# Final system-level security upgrade: ensure every Debian package is at its
# latest patched version. This must run AFTER all apt-get install / dpkg -i
# steps so nothing slips through.
# The build system pins package versions via /etc/apt/preferences.d/01-versions-deb.
# Remove the pin so apt-get upgrade can pull in the latest security patches.
RUN rm -f /etc/apt/preferences.d/01-versions-deb \
&& apt-get update \
&& apt-get upgrade -y \
&& apt-get dist-upgrade -y \
&& rm -rf /var/lib/apt/lists/*

COPY ["*.ini", "/etc/ptf/"]
EXPOSE 22 8009

Expand Down
Loading