StackHawk Documentation StackHawk Logo HawkDocs

No results found

Try different keywords or check your spelling

Search documentation

Find guides, API references, and more

↑ ↓ ↵ esc

Concourse CI

ConcourseCI

HawkScan fits neatly into a Concourse CI pipeline, providing dynamic security scanning every time you commit code.

In this guide, we will describe a method to scan a publicly available example app. Then under Local Scanning, a method to run and test your app all within the Concourse CI build environment using Docker Compose.

Both approaches share the same high level steps:

  1. Secure your API key as a secret credential.
  2. Build out your Concourse pipeline configuration.
  3. Configure HawkScan with a stackhawk.yml file.

When you signed up on StackHawk, you created an API key. To keep it secret, add it to your credential management for use in your Concourse pipeline. Concourse supports many types of credential stores. For our examples, we use CredHub, and we store our key as hawk_api_key.

If you use CredHub, you can set your API key secret like so.

credhub set -n /concourse/main/hawk_api_key --type value --value "hawk.AAaaAAaaAAaaAAaaAAaa.BBbbBBbbBBbbBBbbBBbb"

Construct a ci/hawkscan-remote.yml file in your repository to configure a Concourse pipeline to run HawkScan. This pipeline will have a single job, hawkscan-remote, which will perform the following tasks:

  1. Fetch the code repository, which contains a HawkScan configuration file, stackhawk.yml.
  2. Install the hawk CLI with the hawk CLI install script.
  3. Run hawk scan using the stackhawk.yml configuration file found in your code repository.

Your file should look similar to this, substituting your own git repository for examplecorp/example:

ci/hawkscan-remote.yml
resources:
  - name: example-repo
    type: git
    source:
      uri: https://github.com/examplecorp/example.git
jobs:
  - name: hawkscan-remote
    plan:
      - get: example-repo
        trigger: true
      - task: scan-remote
        config:
          platform: linux
          image_resource:
            type: registry-image
            source:
              repository: buildpack-deps
              tag: jammy-curl
          inputs:
            - name: example-repo
          params:
            API_KEY: ((hawk_api_key))
            # Optional: pin a version (6.0.0 or later). Leave it unset to install the latest release.
            # HAWK_INSTALL_VERSION: "6.6.0"
          run:
            path: bash
            args:
              - -ec
              - |
                curl -fsSL https://download.stackhawk.com/hawk/install.sh | sh
                export PATH="$HOME/.hawk/bin:$PATH"
                cd example-repo
                hawk scan

In this pipeline, we define one resource, example-repo, a GitHub repository which contains our HawkScan configuration. Typically, this would also contain the source code to be built, deployed, and tested. We define a single job, hawkscan-remote, which fetches example-repo, and then executes the scan-remote task. The scan-remote task runs in the buildpack-deps:jammy-curl image, a small Ubuntu image that includes curl. The hawk binary needs glibc, so use a Debian- or Ubuntu-based image rather than Alpine. The task sets the API_KEY parameter, which the hawk CLI uses to authenticate to the StackHawk platform to submit scan results. Finally, the scan-remote task runs a small inline script which installs the latest HawkScan release, adds its install directory to the PATH (the install script doesn’t change the PATH itself), and runs hawk scan from the repository directory.

To run the scan in the HawkScan Docker image instead, use this pipeline. It fetches the stackhawk/hawkscan image as a resource and runs the scanner executable, shawk, inside it:

ci/hawkscan-remote.yml
resources:
  - name: example-repo
    type: git
    source:
      uri: https://github.com/examplecorp/example.git
  - name: hawkscan
    type: docker-image
    source:
      repository: stackhawk/hawkscan
jobs:
  - name: hawkscan-remote
    plan:
      - in_parallel:
          - get: example-repo
            trigger: true
          - get: hawkscan
      - task: scan-remote
        image: hawkscan
        config:
          platform: linux
          inputs:
            - name: example-repo
          params:
            API_KEY: ((hawk_api_key))
            REPO_DIR: /home/steve/example-repo
          run:
            path: bash
            args:
              - -exc
              - |
                cp -rp example-repo "${REPO_DIR}"
                cd "${REPO_DIR}"
                shawk

Pro Tip: The REPO_DIR variable tells HawkScan where to find your repository, and is set to the volume bind mount point, /zap (/steve as of hawkscan 4.0.0), by default. When you copy code directly into the container, this variable should be set to a directory under /home/zap (NOTE: /home/steve as of hawkscan 4.0.0).

At the base directory of your code repository, create a stackhawk.yml appropriate for scanning your application. For our example, we will create a minimal configuration pointing to our Development environment API endpoint, example.com.

stackhawk.yml
app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://example.com
  env: Development

Replace the value for app.applicationId with your Application ID from StackHawk, and set app.env to the environment name you prefer.

Check those two files into source control, and push them to GitHub. Set your pipeline up with the ci/hawkscan-remote.yml file, like so:

fly --target KAAKAW set-pipeline --pipeline hawkscan-remote --config ci/hawkscan-remote.yml

The previous example assumes that you have an integration environment that is publicly accessible. Alternatively, you can run your app and scan it directly on the ephemeral Concourse build container. A great way to do that is to assemble your application environment and HawkScan itself in a docker-compose file. This example uses the HawkScan Docker image, because the Docker Compose task image it runs in is based on Alpine Linux, where the hawk CLI can’t run.

For this run, we will simulate our app with a Nginx container named nginx_test, and run HawkScan against it on the bridge network, scan_net. We save this configuration at the base of our repository. Our configuration looks like this:

docker-compose.yml
version: "3"
services:
  # Fire up the app to test, nginx_test
  nginx_test:
    image: nginx
    networks:
      - scan_net
  # Fire up HawkScan and scan the test app (nginx_test)
  hawkscan:
    image: stackhawk/hawkscan
    environment:
      API_KEY: ${API_KEY}
    volumes:
      - type: bind
        source: .
        target: /hawk
    tty: true
    networks:
      - scan_net
    depends_on:
      - nginx_test
# Make a network on which to run the scan
networks:
  scan_net:

Note that the hawkscan service depends on nginx_test, to ensure the application is running before the scan begins.

Next, we set up the pipeline file, ci/hawkscan-local.yml. This time, we will run our job task in the karlkfi/concourse-dcind container, which has been tuned specifically for making it easy to run Docker Compose in a Concourse workflow.

ci/hawkscan-local.yml
resources:
  - name: example-repo
    type: git
    source:
      uri: https://github.com/examplecorp/example.git
  - name: docker-compose
    type: docker-image
    source:
      repository: karlkfi/concourse-dcind
jobs:
  - name: hawkscan-local
    plan:
      - in_parallel:
          - get: example-repo
            trigger: true
          - get: docker-compose
      - task: scan-local
        privileged: true
        image: docker-compose
        config:
          platform: linux
          inputs:
            - name: example-repo
          params:
            API_KEY: ((hawk_api_key))
          run:
            path: entrypoint.sh
            args:
              - bash
              - -ceux
              - |
                cd example-repo
                docker-compose up --abort-on-container-exit
                docker-compose down

We provide a single parameter, API_KEY, which is passed to the HawkScan container via Docker Compose. Finally, we run a short inline script that sets our working directory to the cloned repository, runs our docker-compose.yml script, and then cleans up after itself. Note the command docker-compose up. We add the --abort-on-container-exit flag to tell Docker Compose to tear down the composition if a container stops. That way, when HawkScan is finished, the other containers will stop too, and the script will move on to clean up with docker-compose down.

The HawkScan configuration looks almost the same as before, except that now our target host is nginx_test, the name of the application to be scanned in docker-compose.yml.

stackhawk.yml
app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://nginx_test
  env: Development

Give it a run and check out your results. This is a great way to build out arrangements of containers for integration testing directly within the Concourse build environment, adding databases, tiers, and other microservices as needed!

Your privacy settings

We use first and third party cookies to ensure that we give you the best experience on our website and in our products.