HawkScan and Concourse CI
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:
- Secure your API key as a secret credential.
- Build out your Concourse pipeline configuration.
- Configure HawkScan with a
stackhawk.yml
file.
Secure Your API Key
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"
Build Your Pipeline
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:
- Fetch the code repository, which contains a HawkScan configuration file,
stackhawk.yml
. - Fetch the HawkScan container image,
stackhawk/hawkscan
, for running tasks. - Run the HawkScan command,
shawk
, using thestackhawk.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
- name: hawkscan
type: docker-image
source:
repository: stackhawk/hawkscan
jobs:
- name: hawkscan-remote
plan:
- in_parallel:
- get: example-repo
trigger: true
- get: stackhawk
- 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
In this pipeline, we define two resources:
- example-repo, a GitHub repository which contains our HawkScan configuration. Typically, this would also contain the source code to be built, deployed, and tested.
- hawkscan - the StackHawk HawkScan Docker image.
We define a single job, hawkscan-remote, which fetches example-repo and hawkscan, and then executes the scan-remote task.
The scan-remote task sets two parameters,
API_KEY
andREPO_DIR
. The HawkScan container usesAPI_KEY
to authenticate to the StackHawk platform to submit scan results. It usesREPO_DIR
to set the working directory for running scans. Finally, the scan-remote task runs a small inline script which copies example-repo toREPO_DIR
, sets the working directory, and runs the scanner executable,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 ofhawkscan 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 ofhawkscan 4.0.0
).Configure HawkScan
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 ourDevelopment
environment API endpoint, http://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.
Run It
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
Head over to the Concourse CI console to watch your workflow run. When it is complete, check your account at StackHawk to review your scan details! —
Local Scanning
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.
Docker Compose
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.
Pipeline Configuration
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
.
HawkScan configuration
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!