Build/scan/push pipelines for container images in STO
You generally want to scan any container images you build and then push them to your production registry only if the scan did not detect any serious vulnerabilities.
The following workflows provide some examples of you can set up pipelines to automate security checks for your images.
Build/scan/push with Docker-in-Docker
This workflow is useful if you can use Docker-in-Docker and don't have a CI license. For a hands-on example of how to implement this, go to (STO license) Create a build-scan-push pipeline .
- 
Add a Docker-in-Docker background step to your pipeline. 
- 
Add a Run step to build a local copy of the container image. 
- 
Add a Security Tests step to scan the snapshot image and ingest the results. If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails. 
- 
Add a Run step that pushes the local image to your production container registry. 

Example build/scan/push pipeline using Docker-in-Docker
pipeline:
  projectIdentifier: jsmithstosandbox
  orgIdentifier: default
  identifier: buildscanpushwithdind
  name: build_scan_push_with_dind
  tags: {}
  stages:
    - stage:
        name: build
        identifier: build
        type: SecurityTests
        spec:
          cloneCodebase: false
          execution:
            steps:
              - step:
                  type: Background
                  name: DinD
                  identifier: Background
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    image: docker:dind
                    shell: Sh
                    privileged: true
                    entrypoint:
                      - dockerd
              - step:
                  type: Run
                  name: build_image
                  identifier: build_image
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    image: docker
                    shell: Sh
                    command: |-
                      # wait until the dind service is available
                      while ! docker ps ;do
                            echo "Docker not available yet"
                      done
                      echo "Docker service is ready"
                      # install git, clone the code repo, and cd to the local clone
                      apk add git
                      git --version
                      git clone https://github.com/<+stage.variables.GITHUB_USERNAME>/<+stage.variables.GITHUB_REPO>
                      cd <+stage.variables.GITHUB_REPO>
                      # build and tag the local image
                      docker login --username="<+stage.variables.DOCKERHUB_USERNAME>" --password="<+stage.variables.DOCKERHUB_PAT>" 
                      docker build -t <+stage.variables.DOCKER_IMAGE_LABEL> .
                      docker tag <+stage.variables.DOCKER_IMAGE_LABEL> <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>:bsp-<+pipeline.sequenceId>
                    privileged: true
              - step:
                  type: AquaTrivy
                  name: scan_image
                  identifier: scan_image
                  spec:
                    mode: orchestration
                    config: default
                    target:
                      name: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      type: container
                      variant: bsp-<+pipeline.sequenceId>
                    advanced:
                      log:
                        level: debug
                      fail_on_severity: none
                    privileged: true
                    image:
                      type: local_image
                      name: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      access_id: <+stage.variables.DOCKERHUB_USERNAME>
                      access_token: <+stage.variables.DOCKERHUB_PAT>
                      tag: bsp-<+pipeline.sequenceId>
              - step:
                  type: Run
                  name: push_image
                  identifier: push_image
                  spec:
                    connectorRef: CONTAINER_IMAGE_REGISTRY_CONNECTOR
                    image: docker
                    shell: Sh
                    command: |-
                      # if the image passed the scan,
                      # push it to the image registry
                      docker login --username="<+stage.variables.DOCKERHUB_USERNAME>" --password="<+stage.variables.DOCKERHUB_PAT>" 
                      docker push <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>:bsp-<+pipeline.sequenceId>
                    privileged: true
          sharedPaths:
            - /var/run
            - /var/lib/docker
          platform:
            os: Linux
            arch: Amd64
          runtime:
            type: Cloud
            spec: {}
          slsa_provenance:
            enabled: false
        variables:
          - name: DOCKERHUB_USERNAME
            type: String
            description: ""
            value: janesmith
          - name: DOCKERHUB_PAT
            type: Secret
            description: ""
            value: jsmith-dockerhub-pat
          - name: GITHUB_USERNAME
            type: String
            description: ""
            value: jane-smith
          - name: GITHUB_REPO
            type: String
            description: ""
            value: codebaseAlpha
          - name: GITHUB_PAT
            type: Secret
            description: ""
            value: jsmith-github-pat
          - name: DOCKER_IMAGE_LABEL
            type: String
            description: ""
            value: myalphaservice
        description: ""
Build/scan/push with CI and Docker-in-Docker
This workflow is useful if you can use Docker-in-Docker and have a CI license. For a hands-on example of how to implement this, go to Create a build-scan-push pipeline (STO and CI).
- 
Add a Docker-in-Docker background step to your pipeline. 
- 
Add a CI Build and Push step to build and push your image with a snapshot tag such as image:snapshot-donotuse-<+pipeline.executionId>.
- 
Add a Security Tests step to scan the snapshot image. If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails. 
- 
Add a second CI Build and Push step to build and push your image with a release tag such as image:<+pipeline.executionId>.

Example build/scan/push pipeline using CI and Docker-in-Docker
pipeline:
  projectIdentifier: STO
  orgIdentifier: default
  tags: {}
  identifier: buildscanpushciexamplev2
  name: build-scan-push-ci-example-v2
  properties:
    ci:
      codebase:
        connectorRef: YOUR_CODE_REPO_CONNECTOR_ID
        repoName: codebasealpha
        build: <+input>
  stages:
    - stage:
        name: build
        identifier: build
        type: CI
        spec:
          cloneCodebase: true
          execution:
            steps:
              - step:
                  type: Background
                  name: DinD
                  identifier: Background
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    image: docker:dind
                    shell: Sh
                    privileged: true
                    entrypoint:
                      - dockerd
              - step:
                  type: BuildAndPushDockerRegistry
                  name: build_push_to_snapshot
                  identifier: build_push_to_snapshot
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    repo: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                    tags:
                      - <+stage.variables.SNAPSHOT_TAG>
              - step:
                  type: AquaTrivy
                  name: scan_snapshot
                  identifier: AquaTrivy_1
                  spec:
                    mode: orchestration
                    config: default
                    target:
                      name: +stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      type: container
                      variant: <+stage.variables.SNAPSHOT_TAG>
                    advanced:
                      log:
                        level: debug
                    privileged: true
                    image:
                      type: local_image
                      name: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      tag: <+stage.variables.SNAPSHOT_TAG>
              - step:
                  type: BuildAndPushDockerRegistry
                  name: build_push_to_prod
                  identifier: build_push_to_prod
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    repo: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                    tags:
                      - <+pipeline.sequenceId>
            "":
              type: BuildAndPushDockerRegistry
              name: build_and_push_prod
              identifier: build_and_push_prod
              spec:
                connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                repo: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                tags:
                  - <+stage.variables.SNAPSHOT_TAG>
          sharedPaths:
            - /var/run
            - /var/lib/docker
          slsa_provenance:
            enabled: false
          infrastructure:
            type: KubernetesDirect
            spec:
              connectorRef: YOUR_KUBERNETES_CLUSTER_CONNECTOR_ID
              namespace: YOUR_NAMESPACE
              automountServiceAccountToken: true
              nodeSelector: {}
              os: Linux
        variables:
          - name: DOCKERHUB_USERNAME
            type: String
            description: ""
            value: jsmith
          - name: DOCKERHUB_PAT
            type: Secret
            description: ""
            value: jsmithdockerhubpat
          - name: GITHUB_USERNAME
            type: String
            description: ""
            value: jane-smith
          - name: GITHUB_REPO
            type: String
            description: ""
            value: codebaseAlpha
          - name: GITHUB_PAT
            type: Secret
            description: ""
            value: account.janesmithgithubpatsto
          - name: DOCKER_IMAGE_LABEL
            type: String
            description: ""
            value: myalphaservice
          - name: SNAPSHOT_TAG
            type: String
            description: ""
            required: false
            value: scantest-donotuse
        description: ""
Build/scan/push with Kaniko
This workflow is useful if you don't have a CI license and want to use Kaniko (which doesn't require Privileged mode) instead of a Docker-in-Docker background step.
- 
In the Security stage overview, under Shared Paths, add a path on the stage volume where you can share the image TAR across steps. 
- 
Use a Run step to build a local copy of the container image. The step should also save the TAR of the image to the shared path on the stage volume. 
- 
Use a Run step to run a manual scan of the local image. 
- 
Add a Security Tests step to ingest your scan data. If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails. 
- 
Set up a Run step that uses kaniko to push the TAR file of the image to your production image registry. 

Build/scan/push with CI and skopeo
This workflow is useful if you have a CI license and want to use skopeo (which doesn't require Privileged mode) instead of a Docker-in-Docker background step.
- 
In the Security stage overview, under Shared Paths, add a path on the stage volume where you can share the image TAR across steps. 
- 
Use a CI Build and Push step to build and push your image with a snapshot tag such as image:snapshot-<+pipeline.executionId>.
- 
Use a Run step that uses skopeo to pull the image TAR to your shared path. 
- 
Use a Run step to scan the local image TAR. 
- 
Add a Security Tests step to ingest your scan data. If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails. 
- 
Add a Run step that uses skopeo to push the image TAR (with an official tag) from the shared path to the container image registry. 
