diff --git a/.azure-pipelines/docker-sonic-mgmt.yml b/.azure-pipelines/docker-sonic-mgmt.yml index 8d1676ad79..c34bf3b010 100644 --- a/.azure-pipelines/docker-sonic-mgmt.yml +++ b/.azure-pipelines/docker-sonic-mgmt.yml @@ -8,24 +8,25 @@ schedules: - cron: "0 8 * * *" branches: include: - - master + - 202511 always: true trigger: none pr: branches: include: - - master + - 202511 paths: include: - dockers/docker-sonic-mgmt + - .azure-pipelines/docker-sonic-mgmt.yml resources: repositories: - repository: sonic-mgmt type: github name: sonic-net/sonic-mgmt - ref: master + ref: 202511 endpoint: sonic-net parameters: @@ -57,9 +58,7 @@ stages: make NOBUSTER=1 NOBULLSEYE=1 SONIC_BUILD_JOBS=$(nproc) DEFAULT_CONTAINER_REGISTRY=publicmirror.azurecr.io ENABLE_DOCKER_BASE_PULL=y configure PLATFORM=generic DOCKER_BUILDKIT=0 make -f Makefile.work BLDENV=bookworm SONIC_BUILD_JOBS=$(nproc) DEFAULT_CONTAINER_REGISTRY=publicmirror.azurecr.io ENABLE_DOCKER_BASE_PULL=y target/docker-sonic-mgmt.gz - cp target -r $(Build.ArtifactStagingDirectory)/target - docker load -i target/docker-sonic-mgmt.gz - docker tag docker-sonic-mgmt $REGISTRY_SERVER/docker-sonic-mgmt:latest + cp -r target $(Build.ArtifactStagingDirectory)/target env: REGISTRY_SERVER: ${{ parameters.registry_url }} displayName: Build docker-sonic-mgmt.gz @@ -68,48 +67,108 @@ stages: artifact: 'docker-sonic-mgmt' displayName: "Archive docker image sonic-mgmt" - - job: validate_docker_image_and_upload + - bash: | + set -ex + docker load -i $(Build.ArtifactStagingDirectory)/target/docker-sonic-mgmt.gz + docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:202511-lastbuild + docker images + env: + REGISTRY_SERVER: ${{ parameters.registry_url }} + displayName: 'Load and tag docker-sonic-mgmt as 202511-lastbuild' + + - task: Docker@2 + displayName: 'Push docker-sonic-mgmt:202511-lastbuild to registry' + condition: succeeded() + inputs: + containerRegistry: ${{ parameters.registry_conn }} + repository: docker-sonic-mgmt + command: push + tags: 202511-lastbuild + +- stage: SecurityScan + dependsOn: Build + condition: and(succeeded(), in(dependencies.Build.result, 'Succeeded')) + jobs: + - job: trivy_scan + displayName: "[OPTIONAL] Trivy vulnerability scan (docker-sonic-mgmt)" pool: sonicso1ES-amd64 - timeoutInMinutes: 360 - dependsOn: Build + continueOnError: true + timeoutInMinutes: 60 steps: - - checkout: sonic-mgmt - clean: true - fetchDepth: 0 - displayName: 'Checkout sonic-mgmt' - - download: current artifact: 'docker-sonic-mgmt' displayName: "Download docker image sonic-mgmt" - - script: | set -ex - - docker load -i $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz - - cd ansible - sudo ./setup-management-network.sh -d - cd ../ - docker rm -f sonic-mgmt - - ./setup-container.sh -n sonic-mgmt -d /data -i docker-sonic-mgmt -v - - docker exec sonic-mgmt bash -c "echo 'Container is running' && ps aux" - displayName: 'Setup sonic-mgmt docker container and verify' + TRIVY_VERSION="0.70.0" + curl -fLO https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.deb + sudo apt install -y ./trivy_${TRIVY_VERSION}_Linux-64bit.deb + trivy --version + displayName: "Install Trivy" + - script: | + set -x + trivy image \ + --input $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz \ + --scanners vuln \ + --severity MEDIUM,HIGH,CRITICAL \ + --ignore-unfixed \ + --exit-code 1 \ + --format table \ + --no-progress \ + --timeout 30m \ + --output $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt + TRIVY_EXIT=$? + echo "" + echo "=== Trivy Scan Results (docker-sonic-mgmt) ===" + cat $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt + exit $TRIVY_EXIT + displayName: "Trivy scan docker-sonic-mgmt" + - publish: $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt + artifact: trivy-scan-results + displayName: "Publish Trivy scan results" + condition: always() + +- stage: Test + dependsOn: Build + condition: and(succeeded(), in(dependencies.Build.result, 'Succeeded')) + variables: + - group: SONiC-Elastictest + - name: BUILD_BRANCH + value: $(Build.SourceBranchName) + jobs: + - template: .azure-pipelines/pr_test_template.yml@sonic-mgmt + parameters: + CHECKOUT_SONIC_MGMT: true + OVERRIDE_PARAMS: + REPO_NAME: "sonic-mgmt" + SETUP_CONTAINER_PARAMS: "-i ${{ parameters.registry_url }}/docker-sonic-mgmt:202511-lastbuild" + +- stage: Publish + dependsOn: Test + condition: and(not(canceled()), in(dependencies.Test.result, 'Succeeded', 'SucceededWithIssues')) + jobs: + - job: PublishAsLatest + pool: sonicso1ES-amd64 + timeoutInMinutes: 60 + steps: + - download: current + artifact: 'docker-sonic-mgmt' + displayName: "Download docker-sonic-mgmt image" - bash: | set -ex - - docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:latest + docker load -i $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz + docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:202511 + docker images env: REGISTRY_SERVER: ${{ parameters.registry_url }} - displayName: 'Tag docker-sonic-mgmt' + displayName: 'Load and tag docker-sonic-mgmt as 202511' - task: Docker@2 - displayName: Upload image + displayName: 'Push docker-sonic-mgmt:202511 to registry' condition: succeeded() inputs: containerRegistry: ${{ parameters.registry_conn }} repository: docker-sonic-mgmt command: push - tags: latest + tags: 202511 diff --git a/dockers/docker-sonic-mgmt/0001-Fix-getattr-AttributeError-in-multi-thread-scenario.patch b/dockers/docker-sonic-mgmt/0001-Fix-getattr-AttributeError-in-multi-thread-scenario.patch index b7f49c4e88..1393259feb 100644 --- a/dockers/docker-sonic-mgmt/0001-Fix-getattr-AttributeError-in-multi-thread-scenario.patch +++ b/dockers/docker-sonic-mgmt/0001-Fix-getattr-AttributeError-in-multi-thread-scenario.patch @@ -1,10 +1,8 @@ -From e323263795a0af4c9c61992bd7a3347d8928db39 Mon Sep 17 00:00:00 2001 -From: Xin Wang -Date: Thu, 14 Sep 2023 16:52:54 +0800 -Subject: [PATCH] Fix getattr AttributeError in multi-thread scenario - -When multi-thread is used, the plugin loader may raise AttributeError -while getting "ActionModule" from an action plugin. +From 94dd505c5e54341414dcb3b02bd50acef302b4eb Mon Sep 17 00:00:00 2001 +From: Sai Kiran <110003254+opcoder0@users.noreply.github.com> +Date: Fri, 15 May 2026 14:40:48 +1000 +Subject: [PATCH] When multi-thread is used, the plugin loader may raise + AttributeError while getting "ActionModule" from an action plugin. The reason is that cache is used while loading module. Before a module is fully loaded, it is already put into the sys.modules cache. When another @@ -13,34 +11,35 @@ module from the sys.modules cache. Then while getting "ActionModule" attribute from this module, exception AttributeError could be raised. Signed-off-by: Xin Wang +Signed-off-by: Sai Kiran <110003254+opcoder0@users.noreply.github.com> --- - lib/ansible/plugins/loader.py | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) + lib/ansible/plugins/loader.py | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/ansible/plugins/loader.py b/lib/ansible/plugins/loader.py -index 74bdeb5719..251531b62e 100644 +index e12ec1b9ea..fe7dc25443 100644 --- a/lib/ansible/plugins/loader.py +++ b/lib/ansible/plugins/loader.py -@@ -801,15 +801,14 @@ class PluginLoader: - warnings.simplefilter("ignore", RuntimeWarning) - spec = importlib.util.spec_from_file_location(to_native(full_name), to_native(path)) +@@ -934,14 +934,15 @@ class PluginLoader: + spec = importlib.util.spec_from_file_location(to_native(python_module_name), to_native(path)) module = importlib.util.module_from_spec(spec) -- + - # mimic import machinery; make the module-being-loaded available in sys.modules during import - # and remove if there's a failure... -- sys.modules[full_name] = module -- +- sys.modules[python_module_name] = module + try: spec.loader.exec_module(module) + # mimic import machinery; make the module-being-loaded available in sys.modules during import + # and remove if there's a failure... -+ sys.modules[full_name] = module ++ sys.modules[python_module_name] = module except Exception: -- del sys.modules[full_name] -+ if full_name in sys.modules: -+ del sys.modules[full_name] +- del sys.modules[python_module_name] ++ if python_module_name in sys.modules: ++ del sys.modules[python_module_name] raise - + return module --- -2.25.1 +-- +2.54.0.windows.1 + diff --git a/dockers/docker-sonic-mgmt/Dockerfile.j2 b/dockers/docker-sonic-mgmt/Dockerfile.j2 index 53f8e099d3..9d9ad983f0 100755 --- a/dockers/docker-sonic-mgmt/Dockerfile.j2 +++ b/dockers/docker-sonic-mgmt/Dockerfile.j2 @@ -3,7 +3,9 @@ FROM {{ prefix }}ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y \ +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ apt-transport-https \ apt-utils \ bats \ @@ -39,7 +41,10 @@ RUN apt-get update && apt-get install -y \ sudo \ tcpdump \ telnet \ - vim + vim \ + && apt-get autoremove -y \ + && apt-get autoclean \ + && rm -rf /var/lib/apt/lists/* # Install uv - a fast Python package manager that replaces pip/venv/wheel. # This eliminates the need for python3-pip, python3-venv, and python3-wheel @@ -58,7 +63,7 @@ RUN sed -i 's|^PATH="|PATH="/opt/venv/bin:|' /etc/environment \ RUN uv pip install --no-cache \ aiohttp \ allure-pytest \ - ansible==11.10.0 \ + ansible==13.6.0 \ azure-storage-blob \ azure-kusto-data \ azure-kusto-ingest \ @@ -66,7 +71,7 @@ RUN uv pip install --no-cache \ celery[redis] \ cffi \ contextlib2 \ - cryptography \ + "cryptography>=48.0.1" \ ctypesgen \ debugpy \ dpkt \ @@ -89,14 +94,16 @@ RUN uv pip install --no-cache \ ncclient \ netaddr \ netmiko \ - opentelemetry-api==1.27.0 \ - opentelemetry-sdk==1.27.0 \ - opentelemetry-exporter-otlp==1.27.0 \ + opentelemetry-api==1.41.0 \ + opentelemetry-sdk==1.41.0 \ + opentelemetry-exporter-otlp==1.41.0 \ pandas \ paramiko \ passlib \ pexpect \ prettytable \ + "protobuf>=5.29.6,<6" \ + "pygnmi==0.8.15" \ psutil \ ptf==0.10.0 \ pyasn1 \ @@ -129,6 +136,7 @@ RUN uv pip install --no-cache \ tabulate \ textfsm \ thrift \ + kubernetes \ && wget https://github.com/nanomsg/nanomsg/archive/refs/tags/1.2.1.tar.gz \ && tar xvfz 1.2.1.tar.gz \ && cd nanomsg-1.2.1 \ @@ -154,6 +162,11 @@ RUN install -m 0755 -d /etc/apt/keyrings \ && apt-get install -y docker-ce-cli \ && curl -sL https://aka.ms/InstallAzureCLIDeb | bash +# Patch Azure CLI's bundled cryptography for CVE-2026-39892 and GHSA-537c-gmf6-5ccf (bundled OpenSSL) +RUN az_site_packages=$(/opt/az/bin/python -c "import site; print(site.getsitepackages()[0])") \ + && /opt/az/bin/python -m pip install --no-cache-dir --target "$az_site_packages" 'cryptography>=48.0.1' \ + && find "$az_site_packages" -name 'cryptography-4[0-7].*' -type d -exec rm -rf {} + 2>/dev/null; true + # Install dash-api RUN tmpdir=$(mktemp -d) \ && python_site_packages=$(python3 -c "import site; print(site.getsitepackages()[0])") \