1

I want to build a Docker image (tarball) in my GitLab CI pipeline using kaniko, then scan it with trivy and push it to an AWS ECR using kaniko.

  • Step 1: kaniko build (tarball)
  • Step 2: trivy scan
  • Step 3: kaniko push (to AWS ECR!)

Unfortunately I can't find a way to push an existing tarball image with kaniko without rebuilding it.

I also tried crane for the push, but can't get a login due to the non-existent credHelper.

I don't actually want to do big installations, nor do I want to create a custom image for this.

Is this possible? What would be potential solutions?

Stefan
  • 1,253
  • 2
  • 12
  • 36

1 Answers1

1

Coincidentally, I did exactly this a while ago. Here is how I did it:

docker:build:
  stage: build
  image:
    name: Kaniko image
    entrypoint: [""]
  script:
    - mkdir tar_images
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context ${CI_PROJECT_DIR} --no-push --destination $CI_REGISTRY/<image_name>:<image_tag> --tarPath tar_images/$file_name.tar
  artifacts:
    paths:
      - tar_images
    when: on_success
  # scan all built images
  # currently bug with grype as docker registry is not public!
docker:scan:
  stage: scan
  image:
    name: trivy
    entrypoint: [""]
  script:
    - mkdir scan_result
    - cd tar_images
    - |
      for tar_image in *.tar; 
      do
        [ -e "$tar_image" ] || continue;
        file_name=${tar_image%.*};
        echo $file_name;
        if [ "$vulnerability_scanner" = "trivy" ]; then
          trivy image --timeout 15m --offline-scan --input $tar_image -f json -o ../scan_result/$file_name.json --severity CRITICAL;
         fi
      done
  artifacts:
    paths:
      - scan_result
    expire_in: 1 month

# push all images without detected security issues
docker:push:
  stage: push
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  rules:
    - if: $UPDATE
  script:
    - cd tar_images
    - |
      for tar_image in *.tar; 
      do 
        file_name=${tar_image%.*};
        vulnerabilities=`awk  -F '[:,]' '/"Vulnerabilities"/ {gsub("[[:blank:]]+", "", $2); print $2}' ../scan_result/$file_name.json`; # find vulnerabilities in json file
        if ! [ -z "$vulnerabilities" ]; then # if vulnerabilities found in image
          echo "There are security issues with the image $img.Dockerfile. Image is not pushed to registry!";
        else # push image
            crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY;
            crane push $tar_image $CI_REGISTRY_IMAGE/<image_name>:<image_tag>;
        fi
      done

What happens here is that in the first job the images are built using kaniko. They are stored as tar files and made accessible to the next job via artifacts. In the next job they are scanned using trivy and the scan results are stored as artifacts. Then the scan reports are analyzed and if no vulnerabilities had been detected the image is pushed using crane.

The code above probably does not work out of the box as I copied it out of a bigger yaml file.

Moritz
  • 307
  • 1
  • 4
  • 10
  • 1
    Hi, thanks for your input. You are pushing it to the GitLab repository - thats the part I've already solved as well. But I want to push it to ECR. Without the credential Helper (which is not part of crane) I am struggling on the crane auth login part. The rest of the pipeline is clear. – Stefan Jan 27 '23 at 16:16
  • 1
    then leave out step 1 and 2 in your question. It has nothing to do with your actual question – Moritz Jan 30 '23 at 10:53