From dfd885aa68d5cde546e9fbfe6c6f3a3edb184c27 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Fri, 17 May 2024 14:08:32 +0200 Subject: [PATCH] SCANDOCKER-7 Stage the image to repox instead of Docker Hub --- .cirrus.yml | 42 +++++++++++++++------------- .cirrus/wss-unified-agent.config | 1 - .github/workflows/release.yml | 47 ++++++++++++++++++++------------ 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 5a6f652..a6c096a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,14 +4,16 @@ env: CIRRUS_VAULT_AUTH_PATH: jwt-cirrusci CIRRUS_VAULT_ROLE: cirrusci-${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME} - DOCKER_USERNAME: VAULT[development/kv/data/docker/sonardockerrw data.username] - DOCKER_PASSWORD: VAULT[development/kv/data/docker/sonardockerrw data.access_token_rwd] + ARTIFACTORY_DEPLOY_USERNAME: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-docker-release username] + ARTIFACTORY_DEPLOY_PASSWORD: VAULT[development/artifactory/token/${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME}-docker-release access_token] - # Mend scan global configuration + # Mend scan global configuration MEND_API_KEY: VAULT[development/kv/data/mend data.apikey] # Staging image configuration - STAGING_IMAGE_NAME: sonarsource/sonarqube + DOCKER_REPOX_BUILDS_REGISTRY: repox-sonarsource-docker-builds.jfrog.io + DOCKER_IMAGE: "sonarsource/sonar-scanner-cli" + STAGING_IMAGE_TAG: "${DOCKER_REPOX_BUILDS_REGISTRY}/${DOCKER_IMAGE}:${CI_BUILD_NUMBER}" vm_instance_template: &VM_TEMPLATE experimental: true # see https://github.com/cirruslabs/cirrus-ci-docs/issues/1051 @@ -31,30 +33,32 @@ build_task: ec2_instance: <<: *VM_TEMPLATE login_script: - - docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD + - docker login "${DOCKER_REPOX_BUILDS_REGISTRY}" -u "${ARTIFACTORY_DEPLOY_USERNAME}" --password-stdin <<<"${ARTIFACTORY_DEPLOY_PASSWORD}" build_script: - - echo "Build and push the ${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER} image" - - docker build --tag "${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER}" --push . + - echo "Build and push the ${STAGING_IMAGE_TAG} image" + - docker build --tag "${STAGING_IMAGE_TAG}" --push . -private_scan_task: +# Scan the current image built and pushed to Artifactory +mend_task: # run only on default and long-term branches only_if: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_TAG == "" && ($CIRRUS_BRANCH == $CIRRUS_DEFAULT_BRANCH || $CIRRUS_BRANCH =~ "branch-.*") ec2_instance: <<: *VM_TEMPLATE login_script: - - docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD + - docker login "${DOCKER_REPOX_BUILDS_REGISTRY}" -u "${ARTIFACTORY_DEPLOY_USERNAME}" --password-stdin <<<"${ARTIFACTORY_DEPLOY_PASSWORD}" setup_script: - apt-get remove -y unattended-upgrades - apt-get update && apt-get install -y --no-install-recommends openjdk-17-jre - curl -sSL https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar -o wss-unified-agent.jar - - echo "docker.includes=.*${STAGING_IMAGE_NAME}.*" >> .cirrus/wss-unified-agent.config + - echo "docker.includes=.*${DOCKER_IMAGE}.*" >> .cirrus/wss-unified-agent.config scan_script: - - echo "Scan the ${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER} image" - - docker pull "${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER}" - - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY + - echo "Scan the ${STAGING_IMAGE_TAG} image" + - docker pull "${STAGING_IMAGE_TAG}" + - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY -project ${DOCKER_IMAGE}:${CIRRUS_BRANCH} depends_on: build -public_scan_task: +# Scan the latest image published on Docker Hub +latest_mend_task: only_if: $CIRRUS_CRON == 'nightly-mend-scan' env: PUBLIC_IMAGE_NAME: sonarsource/sonar-scanner-cli @@ -65,11 +69,11 @@ public_scan_task: - apt-get remove -y unattended-upgrades - apt-get update && apt-get install -y --no-install-recommends openjdk-17-jre - curl -sSL https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar -o wss-unified-agent.jar - - echo "docker.includes=.*${TAG}.*" >> .cirrus/wss-unified-agent.config + - echo "docker.includes=.*${PUBLIC_IMAGE_NAME}.*" >> .cirrus/wss-unified-agent.config scan_script: - echo "Scan the ${PUBLIC_IMAGE_NAME}:${TAG} image" - docker pull "${PUBLIC_IMAGE_NAME}:${TAG}" - - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY + - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY -project ${PUBLIC_IMAGE_NAME}:${TAG} test_docker_builder: <<: *ONLY_SONARSOURCE_QA @@ -77,13 +81,13 @@ test_docker_builder: - git submodule init - git submodule update login_script: - - docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD + - docker login "${DOCKER_REPOX_BUILDS_REGISTRY}" -u "${ARTIFACTORY_DEPLOY_USERNAME}" --password-stdin <<<"${ARTIFACTORY_DEPLOY_PASSWORD}" test_script: - apt-get update && apt-get install -qy bats - echo "Checking out the sonar-scanning-examples repository" - git clone https://github.com/SonarSource/sonar-scanning-examples.git target_repository - - echo "Test the ${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER} image" - - TEST_IMAGE="${STAGING_IMAGE_NAME}:scanner-${CI_BUILD_NUMBER}" bats --tap test + - echo "Test the ${STAGING_IMAGE_TAG} image" + - TEST_IMAGE="${STAGING_IMAGE_TAG}" bats --tap test depends_on: build sonar_scan_task: diff --git a/.cirrus/wss-unified-agent.config b/.cirrus/wss-unified-agent.config index f8a6670..5851ddb 100644 --- a/.cirrus/wss-unified-agent.config +++ b/.cirrus/wss-unified-agent.config @@ -1,5 +1,4 @@ excludes=**/opt/sonar-scanner/**/* -docker.projectNameFormat=repositoryNameAndTag docker.scanImages=true wss.url=https://saas-eu.whitesourcesoftware.com/agent productName=Scanner/CliDocker diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 85ec7cf..ea434fb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,7 @@ jobs: development/kv/data/sign passphrase | gpg_passphrase; development/kv/data/docker/sonardockerrw access_token_rwd | docker_access_token; development/kv/data/docker/sonardockerrw username | docker_username; + development/artifactory/token/{REPO_OWNER_NAME_DASH}-docker-release username | repox_username; development/artifactory/token/{REPO_OWNER_NAME_DASH}-docker-release access_token | repox_access_token; development/kv/data/slack webhook | slack_webhook; - name: Get the version @@ -48,38 +49,50 @@ jobs: path: target_repository - name: Pull staged image run: | - docker login --username ${{ fromJSON(steps.secrets.outputs.vault).docker_username }} --password-stdin <<< "${{ fromJSON(steps.secrets.outputs.vault).docker_access_token }}" - docker pull "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "sonarsource/sonar-scanner-cli:latest" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:latest" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }}" - docker tag "sonarsource/sonarqube:scanner-${{ steps.get_version.outputs.buildnumber }}" "repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }}" + docker login repox-sonarsource-docker-builds.jfrog.io --username ${{ fromJSON(steps.secrets.outputs.vault).repox_username }} --password-stdin <<< "${{ fromJSON(steps.secrets.outputs.vault).repox_access_token }}" + docker pull "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.buildnumber }}" - name: Generate CycloneDX SBOM uses: SonarSource/gh-action_sbom@v1 with: - image: "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }}" + image: "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.buildnumber }}" filename: "sonar-scanner-cli-docker-${{ steps.get_version.outputs.full_image_tag }}-bom.json" upload-artifact: true upload-release-assets: true env: GPG_PRIVATE_KEY_PASSPHRASE: ${{ fromJSON(steps.secrets.outputs.vault).gpg_passphrase }} GPG_PRIVATE_KEY_BASE64: ${{ fromJSON(steps.secrets.outputs.vault).gpg_key }} - - name: Push image to Docker Hub and Repox releases + - name: Promote the staged build + env: + ARTIFACTORY_URL: https://repox.jfrog.io/repox run: | + source_repo_key=sonarsource-docker-builds + target_repo_key=sonarsource-docker-releases + docker_image=sonarsource/sonar-scanner-cli + buildnumber=${{ steps.get_version.outputs.buildnumber }} + full_image_tag=${{ github.event.release.tag_name }} + DATA_JSON="{ \"targetRepo\": \"${target_repo_key}\", \"dockerRepository\": \"${docker_image}\", \"tag\": \"${buildnumber}\", \"targetTag\": \"${full_image_tag}\", \"copy\": true }" + HTTP_CODE=$(curl -s -o /dev/null -w %{http_code} -H "Content-Type: application/json" -H "Authorization: Bearer ${{ fromJSON(steps.secrets.outputs.vault).repox_access_token }}" -X POST "$ARTIFACTORY_URL/api/docker/$source_repo_key/v2/promote" --data "$DATA_JSON") + if [ "$HTTP_CODE" != "200" ]; then + echo "Cannot promote ${docker_image}#${full_image_tag}: ($HTTP_CODE)" + exit 1 + else + echo "${docker_image}#${full_image_tag} promoted to ${target_repo_key}" + fi + - name: Push image to Docker Hub + run: | + buildnumber=${{ steps.get_version.outputs.buildnumber }} + + docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:latest" + docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }}" + docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }}" + docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }}" + docker login --username ${{ fromJSON(steps.secrets.outputs.vault).docker_username }} --password-stdin <<< "${{ fromJSON(steps.secrets.outputs.vault).docker_access_token }}" + docker push sonarsource/sonar-scanner-cli:latest docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }} docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }} docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }} - docker login repox-sonarsource-docker-releases.jfrog.io --username vault-SonarSource-sonar-scanner-cli-docker-docker-release --password-stdin <<< "${{ fromJSON(steps.secrets.outputs.vault).repox_access_token }}" - docker push repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:latest - docker push repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }} - docker push repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }} - docker push repox-sonarsource-docker-releases.jfrog.io/sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }} - name: Notify success on Slack uses: Ilshidur/action-slack@2.1.0 env: