---
title: "Spinnaker"
description: "Integrate StackHawk security testing into Spinnaker pipelines for automated API security scanning and vulnerability management."
url: https://docs.stackhawk.com/integrations/ci-cd/spinnaker/
---

# Spinnaker

![Spinnaker](https://docs.stackhawk.com/images/integrations/logos/spinnaker.svg)

This guide will show you how to run HawkScan in [Spinnaker](https://spinnaker.io/). We will build out a simple pipeline that deploys an API microservice, [miniapi](https://github.com/zconger/miniapi) to your Kubernetes cluster and runs HawkScan against it.

To work through this guide, you will need a StackHawk account. You can sign up for a free Developer account [here](https://auth.stackhawk.com/signup).

You will also need a Kubernetes cluster running Spinnaker. If you want an isolated test instance of Kubernetes and Spinnaker, try [Minnaker](https://github.com/armory/minnaker). It’s what we used for our own testing.

## Protect Your API Key

HawkScan will need your StackHawk [API key](https://app.stackhawk.com/settings/apikeys) to send results back to the platform. Use `kubectl` to store it as a Kubernetes secret.

```shell
kubectl create secret generic stackhawk-secrets \
  --from-literal=API_KEY='hawk.xXXxxXxxXXxxxXxxXxXx.xxxxXXxxXXXxxXXXXxXx'
```

## Create the development Namespace in Kubernetes

We will deploy our app to the `development` namespace. Create it now with the following command.

```shell
kubectl create namespace development
```

## Create a Git Repository

Create a GitHub repository to host your StackHawk configuration file. Normally this would be your application’s code repository. But for this guide, an otherwise empty repository is fine. For now, make this repository public so that the HawkScan pod can check it out without authentication. We won’t be storing any secret data in it.

Create a StackHawk configuration file, `stackhawk.yml`, at the root of your repository. Substitute your own StackHawk Application ID for `app.applicationId`. You can find your Application ID under [Applications](https://app.stackhawk.com/applications) in the StackHawk platform.

```yaml title="stackhawk.yml"
app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://miniapi.development:5000
  env: Development
```

Commit your changes and push them to GitHub.

---

## Build Your Pipeline

Create a new Application in Spinnaker called **miniapi**. Then create a new Pipeline for **miniapi** called **miniapi-pipeline**.

We will add two stages to **miniapi-pipeline**. The first will deploy the [containerized miniapi](https://hub.docker.com/r/zconger/miniapi) app to the `development` namespace. The second will scan **miniapi** in the `development` namespace with HawkScan using the `stackhawk.yml` configuration file from your Git repository.

### Stage 1: Deploy miniapi to Development

The first stage of your pipeline will launch a **miniapi** Deployment to the `development` namespace, and create a Service for it as well.

Add a new stage to **miniapi-pipeline** with the following configuration.

- Type: Deploy (Manifest)

- Stage Name:

- Deploy (Manifest) Configuration:

  - Basic Settings:

    - Account: spinnaker *(or whatever cluster you prefer)*
    - Override Namespace: True
    - Namespace: development

  - Manifest Configuration:

    - Manifest Source: Text
    - Manifest:
      ```yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: miniapi
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: miniapi
        template:
          metadata:
            labels:
              app: miniapi
          spec:
            containers:
              - image: 'zconger/miniapi:latest'
                name: primary
                ports:
                  - containerPort: 5000
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: miniapi
      spec:
        ports:
          - port: 5000
            protocol: TCP
            targetPort: 5000
        selector:
          app: miniapi
        type: LoadBalancer
      ```

### Stage 2: Scan miniapi with HawkScan

This stage runs HawkScan as a Kubernetes Job. A Job runs a container image, so it uses the HawkScan Docker image, `stackhawk/hawkscan`, rather than the [install script](https://docs.stackhawk.com/stackhawk-cli/#install-with-a-script) that the shell-based CI guides use.

Add a second stage with the following configuration.

- Type: Run Job (Manifest)

- Stage Name: HawkScan

- Deploy (Manifest) Configuration:

  - Basic Settings:
    - Account: spinnaker *(the same cluster as the first stage above)*

  - Manifest Configuration:

    - Manifest Source: Text
    - Manifest:
      ```yaml
      apiVersion: batch/v1
      kind: Job
      metadata:
        name: hawkscan
      spec:
        backoffLimit: 0
        template:
          spec:
            containers:
              - command:
                - /bin/bash
                - '-c'
                - |
                  git clone $REPO_URL $REPO_DIR
                  shawk
                env:
                  - name: API_KEY
                    valueFrom:
                      secretKeyRef:
                        key: API_KEY
                        name: stackhawk-secrets
                  - name: REPO_DIR
                    value: /home/steve/workdir
                  - name: REPO_URL
                    value: 'https://github.com/<YOUR-ORG>/<YOUR-REPO>.git'
                image: 'stackhawk/hawkscan:latest'
                name: hawkscan
            restartPolicy: Never
        ttlSecondsAfterFinished: 600
      ```

Set the `REPO_URL` environment variable in the Job manifest above to the HTTPS URL for the git repository that contains your `stackhawk.yml` configuration file.

> *Pro Tip: For this guide, our git repository is public, so no authentication is necessary. For a private repository, you can [inject an OAuth token](https://github.blog/2012-09-21-easier-builds-and-deployments-using-git-over-https-and-oauth/) into `REPO_URL` for authentication. In that case, `REPO_URL` should be stored as a Kubernetes secret.*

## Run That Pipeline!

Now start a manual pipeline execution in Spinnaker and watch your progress. If you check the console output from the HawkScan stage, the first message from the pod should be something like the following.

```shell
Cloning into '/home/steve/workdir'...
```

This indicates that the pod is working correctly and has cloned your Git repository. After a while you should see a summary of the scan results, like so.

```shell
StackHawk 🦅 HAWKSCAN - v0.8.30
* app id:              9e3a5594-0ec8-40f4-8ec7-48ef4442b767
* env:                 Development
* scan id:             fb1700b5-2c3e-4238-a8fe-d91a102ca371
* scan configs:        ['stackhawk.yml']
* app host:            http://miniapi.development:5000
* graphql:             False
Spider complete
Spider Crawled 3 URLs:
http://miniapi.development:5000
  http://miniapi.development:5000/robots.txt
  http://miniapi.development:5000/sitemap.xml
 Passive scanning progress 100%
Active Scan {'policy': 'c45e2369-6dd4-4b0f-bbd2-b9cc0c3cd228', 'target': 'http://miniapi.development:5000'} complete
Hawk Scanned 4 URLs:
  https://miniapi.development
  http://miniapi.development:5000
  http://miniapi.development:5000/robots.txt
  http://miniapi.development:5000/sitemap.xml
Uploading Logs Progress: 100%
Results for scan id fb1700b5-2c3e-4238-a8fe-d91a102ca371
Scan results for http://miniapi.development:5000
------------------------------------------------------------
Criticality: New/Triaged
   High: 0/0    Medium: 9/0    Low: 8/0 
------------------------------------------------------------
1) HTTP Only Site
   Risk: Medium 
   Cheatsheet: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.md
   Paths (1):
     [New] GET 
2) Content Security Policy (CSP) Header Not Set
   Risk: Medium 
   References: https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy
               https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
               http://www.w3.org/TR/CSP/
               http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html
               http://www.html5rocks.com/en/tutorials/security/content-security-policy/
               http://caniuse.com/#feat=contentsecuritypolicy
               http://content-security-policy.com/
   Paths (5):
     [New] GET 
     [New] GET /
     [New] GET /
     [New] GET /robots.txt
     [New] GET /sitemap.xml
3) X-Frame-Options Header Not Set
   Risk: Medium 
   References: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
   Paths (3):
     [New] GET 
     [New] GET /
     [New] GET /
4) Server Leaks Version Information via "Server" HTTP Response Header Field
   Risk: Low 
   References: http://httpd.apache.org/docs/current/mod/core.html#servertokens
               http://msdn.microsoft.com/en-us/library/ff648552.aspx#ht_urlscan_007
               https://learn.microsoft.com/en-us/archive/blogs/varunm/remove-unwanted-http-response-headers
               http://www.troyhunt.com/2012/02/shhh-dont-let-your-response-headers.html
   Paths (5):
     [New] GET 
     [New] GET /
     [New] GET /
     [New] GET /robots.txt
     [New] GET /sitemap.xml
5) X-Content-Type-Options Header Missing
   Risk: Low 
   References: http://msdn.microsoft.com/en-us/library/ie/gg622941%2528v%3Dvs.85%2529.aspx
               https://owasp.org/www-community/Security_Headers
   Paths (3):
     [New] GET 
     [New] GET /
     [New] GET /
View on StackHawk platform: https://app.stackhawk.com/scans/fb1700b5-2c3e-4238-a8fe-d91a102ca371
```

Finally, check your [scan results](https://app.stackhawk.com/scans) in the StackHawk app.

---

## Where to go from here

This guide should give you a sense for how you can incorporate HawkScan into your Spinnaker pipelines. There is much more you can do from here to increase the depth of the scan and change the behavior of your pipeline based on your scan results.

From here you should consider some of these options for your scan configuration.

- Make your code repository private and [use OAuth](https://github.blog/2012-09-21-easier-builds-and-deployments-using-git-over-https-and-oauth/) for authentication in your [HawkScan stage](#stage-2-scan-miniapi-with-hawkscan)
- [Authenticated Scanning](https://docs.stackhawk.com/hawkscan/authenticated-scanning/) to give the scanner deeper access to your app
- [OpenAPI Configuration](https://docs.stackhawk.com/hawkscan/configuration/openapi-configuration/) to discover more routes
- [GraphQL Configuration](https://docs.stackhawk.com/hawkscan/configuration/graphql-configuration/) to generate routes based on available operations
- A [failure threshold](https://docs.stackhawk.com/hawkscan/configuration/#hawk) to stop the pipeline if severe security issues are discovered.
- Additional stages to progress your deployment through to pre-production and production environments
