HawkScan and GitHub Actions

With our HawkScan GitHub Action, it is a snap to add application scanning to your GitHub Actions workflow.

To integrate StackHawk into GitHub Actions workflows, simply:

  1. Secure your API key as a Secret in your GitHub repository
  2. Configure your workflow with a .github/workflows/hawkscan.yml file
  3. Configure HawkScan with a stackhawk.yml file

In this how-to, we will first describe the simple scenario of scanning a publicly available example app, example.com. Then we will walk through how to scan a service on the localhost address, in a Docker bridge network, and in a Docker Compose configuration.

Secure Your API Key

When you signed up on StackHawk, you created an API key. To keep it a secret, and out of your repository, copy it to a GitHub secret for your repository. On GitHub, find your repository, and click into the ⚙️Settings tab near the top right side of the screen. Then click Secrets near the bottom left . Add your StackHawk API key as a secret called HAWK_API_KEY.

Configure Your Workflow

At the base directory of your code repository, add a .github/workflows/hawkscan.yml file to configure GitHub Actions to run HawkScan. Your file should look like this.

.github/workflows/hawkscan.yml

name: HawkScan
on:
  push:
  pull_request:
jobs:
  hawkscan:
    name: HawkScan
    runs-on: ubuntu-latest
    steps:
      - name: Clone repo
        uses: actions/checkout@v2
      - name: Run HawkScan
        uses: stackhawk/hawkscan-action@v1.3.0
        with:
          apiKey: ${{ secrets.HAWK_API_KEY }}

This configuration tells GitHub Actions to run a single job which checks out your code, and then runs HawkScan as a Docker container. We pass the StackHawk API key to HawkScan from the GitHub secret, HAWK_API_KEY.

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 our Development 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 applicationId with your Application ID from StackHawk.

Run It

Check those two files into source control, and push them to GitHub. Head over to the GitHub Actions 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 is simple, but it assumes that you have an integration environment that is publicly accessible. Alternatively, you can run your app and scan it directly on the ephemeral GitHub build host. Here are three common ways of doing that.

Scanning a Service on Localhost

One way to test an app after building it is to launch it on the VM where the workflow is running, and scan it on the localhost address. You can launch the HawkScan container with the flag --network host to give it access to localhost, and set app.host in stackhawk.yml to http://localhost:8080.

For our example app, we will launch an Nginx container listening on port 8080. Then we will scan it at the localhost address with HawkScan. This method works with any app you wish to scan, containerized or not, as long as it is listening on the localhost address.

Here’s our modified GitHub workflow.

.github/workflows/hawkscan.yml

name: HawkScan
on:
  push:
  pull_request:
jobs:
  hawkscan:
    name: HawkScan
    runs-on: ubuntu-latest
    steps:
      - name: Clone repo
        uses: actions/checkout@v2
      - name: Run Nginx
        run: docker run --rm --detach --publish 8080:80 --name nginx_test nginx
      - name: Run HawkScan
        uses: stackhawk/hawkscan-action@v1.3.0
        with:
          apiKey: ${{ secrets.HAWK_API_KEY }}

☝️ Notice the new Run Nginx step which launches our app.

Finally, here’s our modified HawkScan configuration pointing to the localhost address.

stackhawk.yml

app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://localhost:8080
  env: Development

When you run this workflow, it will launch Nginx, scan it with HawkScan, and post the results to your StackHawk scan list.

Scanning a Service on a Docker Network

Another option is to run the test app in a container and scan it on a Docker bridge network using the --network <network-name> flag for docker run. With this approach it becomes easier to build complex arrangements of Docker containers, adding databases and other services that your app can address by name.

Building on the last example, we add a step to create a Docker bridge network called scan_net. Then we launch an Nginx container with the name nginx_test as our test app on that network. Then, we run HawkScan against nginx_test on the scan_net network.

.github/workflows/hawkscan.yml

name: HawkScan
on:
  push:
  pull_request:
jobs:
  hawkscan:
    name: HawkScan
    runs-on: ubuntu-latest
    steps:
      - name: Clone repo
        uses: actions/checkout@v2
      - name: Create Docker network
        run: docker network create scan_net
      - name: Run Nginx on Docker network
        run: docker run --rm --detach --network scan_net --name nginx_test nginx
      - name: Run HawkScan on Docker network
        uses: stackhawk/hawkscan-action@v1.3.0
        with:
          apiKey: ${{ secrets.HAWK_API_KEY }}
          network: scan_net

Finally, update the HawkScan configuration to point to your test app, http://nginx_test.

stackhawk.yml

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

Scanning a Service in Docker Compose

Docker Compose can be a useful tool for modeling complex test environments in your CI/CD pipeline. It provides a concise way to combine your app server with any other services it might require to create a useful environment for integration testing and of course DAST scanning.

In Docker Compose, you can publish the ports of the service you want to scan using the services.<service-name>.ports configuration. That service would then be accessible on the localhost address of your build VM, so your HawkScan Action configuration would look just like the one above, under Scanning a Service on Localhost.

Alternatively, you can specify a named bridge network in Docker Compose to run your services on. Then, rather than publishing the ports of services you want to scan, you could run HawkScan on the same network.

For example, say you have an test environment for your application defined as the Docker Compose configuration below. It contains your app server, myapp, and a Postgres database, db. In addition, it defines a Docker bridge network named mynetwork, with all the services attached to it.

# docker-compose.yml

version: "3.9"

services:
  myapp:
    image: myapp
    networks:
      mynetwork:

  db:
    image: postgres
    restart: always
    networks:
      mynetwork:

networks:
  mynetwork:
    name: mynetwork

To scan the above, say you have a HawkScan configuration file like the following.

# stackhawk.yml

app:
  applicationId: xxxxxxxx-XXXX-xxxx-XXXX-xxxxxxxxxxxx
  env: Development
  host: http://myapp

Here is how we could configure a GitHub Actions workflow to use the mynetwork network.

# .github/workflows/hawkscan.yml

name: HawkScan
on:
  push:

jobs:
  hawkscan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: docker-compose up -d
      - uses: stackhawk/hawkscan-action@v1.3.0
        with:
          apiKey: ${{ secrets.HAWK_API_KEY }}
          network: mynetwork

For more details on configuring the HawkScan Action, visit HawkScan Action in the GitHub Actions marketplace!