Security Testing Orchestration Quickstart (Public Preview)

Updated 1 month ago by Michael Cretzman

This quickstart shows you how to use Harness Security Testing Orchestration (STO) to perform code and container security scanning on a CI Pipeline.

Currently Harness STO is in Public Preview. You will need some credentials from Harness to use STO (JSON Web Token, etc). Consequently, this quickstart isn't intended for you to set up STO without assistance from Harness. Once you have the necessary information from Harness, you can use this quickstart to set up STO in your Pipelines.

Objectives

You'll learn how to:

  1. Add STO Security steps to your Harness CI Pipelines.
  2. Configure Security steps for different security scanners: one for code scanning and one for container scanning.
  3. Run a CI Pipeline and scan its codebase and the container image built by the Pipeline.
  4. View the normalized and deduplicated security results in the Security dashboard.

Before You Begin

Make sure you have the following set up before you begin this quickstart:

  • Github account: this quickstart clones a codebase from a Github repo. You will need a Github account with a username and Personal Access Token (PAT) so Harness can connect to Github. The PAT scope is covered below.
  • Docker Hub account: the Pipeline pulls the Docker in Docker docker:dind image from Docker Hub. 
    • The CI Pipeline in this quickstart does not actually push the Docker image it builds to Docker Hub. You do not need a Docker Hub repo, just an account.
  • Kubernetes cluster for Harness Delegate and build infrastructure:
    • You'll need a Kubernetes cluster for Harness to use for the Harness Delegate and as a CI Pipeline build infrastructure. Ensure you have a cluster that meets the following requirements:
      • Number of pods: 3 (two pods for the Harness Delegate, the remaining pod for the build farm).
      • Machine type: 4vCPU.
      • Memory: 16GB RAM. The build farm and Delegate requirements are low but the remaining memory is for Kubernetes, the Docker container, and other default services.
      • Networking: outbound HTTPS for the Harness connection, and to connect to Docker Hub. Allow TCP port 22 for SSH.
      • Namespace: when you install the Harness Delegate, it will create the harness-delegate namespace. You'll use the same namespace for the build farm.
      • A Kubernetes service account with permission to create entities in the target namespace is required. The set of permissions should include list, get, create, and delete permissions. In general, the cluster-admin role or a namespace admin permission is enough. For more information, see User-Facing Roles from Kubernetes.

Google Kubernetes Engine (GKE) Autopilot is not supported at this time.

Review: Scanner Coverage

See Security Testing Orchestration in Supported Platforms and Technologies.

Step 1: Add the CI Pipeline using YAML

For this quickstart we'll add STO steps to a Harness CI Pipeline Stage. If you are new to Harness CI, you can try the CI Pipeline Quickstart. It will take you through setting up and running a CI Pipeline.

You don't need to create your own CI Pipeline. We will create one in this quickstart.

You can create a Harness Pipeline using the Visual Editor or YAML. For this quickstart, we'll give you the YAML for the Pipeline and then take you through updating it and then running it.

Let's get started!

Log into Harness.

If you do not already have a Harness Project, click Projects, and then click New Project.

Name the Project STO and click Save and Continue.

In Invite Collaborators, click Save and Continue.

In Which Harness module would you like to start using for this project, click Continuous Integration, and then Go to Module.

Your new Project appears.

Click Pipelines, and then Create a Pipeline.

In Name, enter Quickstart, and click Start.

Your new Pipeline appears. Now let's add the Pipeline settings using YAML.

Click YAML, and then in YAML editor, click Edit YAML.

Select all the YAML, delete it, and then paste the following YAML:

We use the Harness default Organization that is included in all accounts. If you use a different Org, simply update orgIdentifier: default with the other Org Id.
pipeline:
name: Quickstart
identifier: Quickstart
allowStageExecutions: false
projectIdentifier: STO
orgIdentifier: default
tags: {}
properties:
ci:
codebase:
connectorRef: GitHub
build: <+input>
stages:
- stage:
name: Docker Build and Scan
identifier: Docker_Build_and_Scan
type: CI
spec:
cloneCodebase: true
infrastructure:
type: KubernetesDirect
spec:
connectorRef: Quickstart
namespace: harness-qa-delegate
sharedPaths:
- /var/run
serviceDependencies:
- identifier: dind
name: dind
type: Service
spec:
connectorRef: Docker_Hub
image: docker:dind
privileged: true
entrypoint:
- dockerd-entrypoint.sh
execution:
steps:
- parallel:
- step:
type: Security
name: brakeman scan
identifier: brakeman_scan
spec:
connectorRef: account.harnessImage
privileged: true
settings:
policy_type: orchestratedScan
scan_type: repository
repository_project: nodegoat
repository_branch: <+codebase.branch>
product_name: brakeman
product_config_name: brakeman-default
fail_on_severity: HIGH
imagePullPolicy: Always
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Ignore
- step:
type: Security
name: owasp scan
identifier: owasp_scan
spec:
connectorRef: account.harnessImage
privileged: true
settings:
policy_type: orchestratedScan
scan_type: repository
repository_project: nodegoat
repository_branch: <+codebase.branch>
product_name: owasp
product_config_name: owasp 5.x
fail_on_severity: HIGH
imagePullPolicy: Always
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Ignore
- step:
type: Run
name: Build Image
identifier: Build_Docker_Image
spec:
connectorRef: Docker_Hub
image: docker:latest
command: docker build . -t nodegoat:local
privileged: true
- step:
type: Security
name: aqua-trivy scan
identifier: aqua_trivy_scan
spec:
connectorRef: account.harnessImage
privileged: true
settings:
product_name: aqua-trivy
product_config_name: aqua-trivy
policy_type: orchestratedScan
scan_type: container
container_type: local_image
container_domain: docker.io
container_project: nodegoat
container_tag: local
fail_on_severity: HIGH
imagePullPolicy: Always
failureStrategies: []
variables:
- name: sto_api_key
type: Secret
value: <+input>

Click Save. The Pipeline is updated. Click Visual to see the Pipeline in the visual editor.

Now that you have a starter CI Pipeline, we can update a few Connectors and you'll be reading to run your build and scans.

Step 2: Update the Codebase and Stage Overview

We need to update the Stage's Codebase to point to the public repo for NodeGoat at https://github.com/OWASP/NodeGoat. NodeGoat is provided by OWASP as an environment to learn how the OWASP Top 10 security risks can manifest in Node.js Web apps.

We'll add a Harness Connector to GitHub using your own credentials, which Harness will encrypt and store in the Harness Secret Manager by default. You can also add your own Secret Manager to Harness.

In your Stage, click Codebase.

In Edit Codebase Configuration, click in Connector.

In Create or Select an Existing Connector, click New Connector.

Enter the following settings.

  • Click GitHub Connector.
  • Name: GitHub.
  • URL Type: Repository.
  • Connection Type: HTTP.
  • GitHub Repository URL: https://github.com/OWASP/NodeGoat.git.
  • Username: Enter your GitHub username.
  • Personal Access Token: Create a secret in Harness for a GitHub PAT that has the following scopes:
    • repo
    • admin:repo_hook
    • user
  • Click Connect through Harness Platform.

When you're done, click Save and Continue. Harness will test the connection and credentials. Click Finish.

In Edit Codebase Configuration, click Save.

Now the codebase is ready.

Next, we will set up the build infrastructure for the CI Stage.

Step 3: Update the Infrastructure

You set up the Infrastructure for the Stage by adding a Kubernetes Cluster Connector to connector to your Kubernetes cluster. A Kubernetes Cluster Connector is a platform agnostic connection to any Kubernetes cluster.

You will also add a Harness Delegate to your cluster as part of this process. This simply involves logging into your cluster and applying a YAML file.

Click Infrastructure.

In Where do you want the builds to run?, click in Kubernetes Cluster.

In Create or Select an Existing Connector, click New Connector.

Enter the following settings.

  • Name: Quickstart.
  • Click Use the credentials of a specific Harness Delegate.

If you already have a Delegate set up in your Harness account, you can use the Specify master URL and credentials option.

This quickstart assumes you are new to Harness.

  • Click Install new Delegate.

If you already have a Delegate set up in your Harness account, you can use it.

This quickstart assumes you are new to Harness.

  • Click Kubernetes.
  • Delegate Name: sto.
  • Delegate Size: Small.
  • Download the YAML file.
  • In a Terminal, navigate to the location of the file.
  • In the same Terminal, log into your cluster and run the following:
    kubectl apply -f harness-delegate.yml

Once you apply the YAML file you will see an output like this:

% kubectl apply -f harness-delegate.yml
namespace/harness-delegate-ng created
clusterrolebinding.rbac.authorization.k8s.io/harness-delegate-ng-cluster-admin created
secret/sto-proxy created
statefulset.apps/sto created
service/delegate-service created

In the Harness Delegate setup, in Apply YAML and verify connection, you will see the Delegate register with Harness. This can take a few minutes.

If you encounter errors, ensure your cluster can connect outbound to app.harness.io. See Whitelist Harness Domains and IPs.

In Delegates Setup, select Connect only via Delegates with the following tags, select the new Delegate, and then click Save and Continue.

In Connection Test, click Finish.

In the Infrastructure Namespace setting, enter harness-qa-delegate or default or whatever namespace you want to use.

Now that you have the build infrastructure for the Stage set up, we can review the Execution.

Step 4: Update the Service Dependency

Harness STO uses Docker-in-Docker as a dependency. You simply need to update dind in Dependencies with a Connector to Docker Hub.

In the Stage Execution, in Dependencies, click dind.

Click in Container Registry, and then click New Connector.

Enter the following settings.

  • Click Docker Registry.
  • Name: Docker Hub.
  • Docker Registry URL: https://registry.hub.docker.com.
  • Provider Type: DockerHub.
  • Authentication: Anonymous.
  • Select the Delegate you added earlier.
  • Click Finish, and then in Create or Select an Existing Connector, click Apply Selected.

Back in Configure Service Dependency, in Image, enter docker:dind, and click Apply Changes.

Now Harness will pull in the Docker-in-Docker image at runtime.

Let's review all the STO and Build steps.

Step 5: Review the Security and Build Steps

Let's look at each STO step to see how they are configured to scan.

Brakeman Scan

Click the brakeman scan step.

Let's review the settings.

Setting

Example

Description

policy_type

orchestratedScan

Indicates that this is an orchestrated scan as opposed to a manual scan (manualUpload).

scan_type

repository

Indicates that this is a repo scan. A repo scan has certain requirements, which are provided in the repository_* settings.

repository_project

nodegoat

Name of the repo project.

repository_branch

<+codebase.branch>

This Harness expression resolves to the branch selected in the Codebase (the default branch).

product_name

brakeman

The name of the scan tool.

product_config_name

brakeman-default

The config to use with the tool.

fail_on_severity

HIGH

Minimum criteria for failing the step.

The fail_on_severity setting determines the minimum criteria for failing the step. For example, a HIGH vulnerability is found.

OWASP Scan

Click the owasp scan step.

Let's review the settings.

Setting

Example

Description

policy_type

orchestratedScan

Indicates that this is an orchestrated scan as opposed to a manual scan (manualUpload).

scan_type

repository

Indicates that this is a repo scan. A repo scan has certain requirements, which are provided in the repository_* settings.

repository_project

nodegoat

Name of the repo project.

repository_branch

<+codebase.branch>

This Harness expression resolves to the branch selected in the Codebase (the default branch).

product_name

owasp

The name of the scan tool.

product_config_name

owasp 5.x

The config to use with the tool.

fail_on_severity

HIGH

Minimum criteria for failing the step.

The fail_on_severity setting determines the minimum criteria for failing the step. For example, a HIGH vulnerability is found.

Build Image

Open the Build Image step.

The Build Image step simply builds the NodeGoat image in the Codebase using docker build . -t nodegoat:local in Command.

In the Build Image step, in Container Registry, simply select the same Docker Connector you set up in dind in Dependencies.

Aqua-Trivy Scan

Following the Build Image step, we can scan the container Harness created using Aqua Trivy.

Click the aqua-trivy scan step.

Let's review the settings.

Setting

Example

Description

product_name

aqua-trivy

The name of the scan tool.

product_config_name

aqua-trivy

The config to use with the tool.

policy_type

orchestratedScan

Indicates that this is an orchestrated scan as opposed to a manual scan (manualUpload).

scan_type

container

Indicates that this is a container scan. A container scan has certain requirements, which are provided in the container_* settings.

container_type

local_image

Scan a local image.

container_domain

docker.io

The default domain for the container.

container_project

nodegoat

Name of the container project.

container_tag

local

The tag on the container.

fail_on_severity

HIGH

Minimum criteria for failing the step.

The fail_on_severity setting determines the minimum criteria for failing the step. For example, a HIGH vulnerability is found.

Step 6: Run the Pipeline and View the Security Dashboard

Now that the Stage and its steps are completed and reviewed, you can run the Pipeline and see the scans.

Click Save, and then click Run.

Enter the following settings, and then click Run Pipeline.

  • Branch Name: master.
  • sto_api_key: enter the JSON Web Token (JWT) you obtained from Harness.

The Pipeline executes and fails as a result of the OWASP and Aqua Trivy scans.

Click a scan step to see the details of each scan.

Click the Security tab to see the dashboard.

The Security tab tells you what vulnerabilities you introduced and can fix (Only in current scan targets), as well as the vulnerabilities that existed prior to running the Pipeline (Common to anchor scan targets).

A few notes:

  • Severity: identifies what to work on first according to company policy.
  • Only in current scan targets: these are vulnerabilities we would introduce if we merged into the main code or infrastructure.
  • Common to anchor scan targets: these are vulnerabilities that existed in our anchor branch prior to running the Pipeline. These are vulnerabilities that someone has determined are either mitigated or cannot be remediated.

Congratulations

In this tutorial, you learned how to:

  1. Add STO Security steps to your Harness CI Pipelines.
  2. Configure Security steps for different security scanners: one for code scanning and one for container scanning.
  3. Run a CI Pipeline and scan its codebase and the container image built by the Pipeline.
  4. View the normalized and deduplicated security results in the Security dashboard.


Please Provide Feedback