Shift Security to the Left
Introduction
Cloud adaption has expanded since Amazon announced the EC2 in 2006. This adaption caused security challenges for legacy security. DevSecOps resolves these security challenges by integrating security in each stage of the Secure Development Life Cycle, or SDLC.
In this blog, we talked about DevSecOps and its importance in the DevOps world. We defined it as the integration of security practices and principles into DevOps. Now that we’ve defined it, we should learn how to do it. Today, we will talk more about the security testing types and their implementation.
Testing Types
There is no one magical application security testing that fits all the vulnerabilities. An approach incorporating many types provides comprehensive and in-depth security assessment. The strength of some tools can compensate for the drawbacks of other ones. The below image shows security testing tools that we can run in each stage of the SDLC.
Some major testing types are:
- Software Composition Analysis (SCA): SCA scans the code for open source libraries vulnerabilities. This test is done early in the pipeline during the code development. An example of SCA is OWASP Dependency-Check.
- SCA Advantages: Discover vulnerabilities in open source libraries.
- SCA Disadvantages: SCA can’t pinpoint vulnerabilities in proprietary code.
2. Static Application Security Testing (SAST): SAST scans the application’s source code for vulnerabilities. Like SCA, this SAST is done in the first stages of the pipeline. An example of a SAST tool is SonarQube.
SAST Advantages:
- Early discovery of the vulnerabilities in the source code.
- Allows for cheap and fast remediation.
- Provides root cause and remediations for the vulnerabilities. It is effective in detecting common weaknesses like SQL injection and cross-site scripting.
SAST Disadvantage:
- SAST can produce many false-positives if the tool is not tuned.
- Language-specific.
- SAST can’t discover run-time vulnerabilities.
3. Dynamic Application Security Testing (DAST): DAST is similar to penetration testing. This test analyses the application by running it to detect vulnerabilities. OWASP ZAP is an example of DAST testing tool.
DAST Advantages:
- Provide details about the exploitability of vulnerabilities.
DAST Disadvantages:
- Can’t specify the root cause of the vulnerability.
- Lacks the remediation capability and
- DAST can run only at a later stage of SDLC.
4. Interactive Application Security Testing (IAST): IAST assesses the application’s security based on runtime. This test is done during the running of the application either by unit test or manual testing. IAST hooks with the language compiler or interpreter at runtime. This method allows the IAST tool to watch the data as it passes through the applications. Contrast Assess is an example of the IAST tool.
IAST Advantages:
- High accuracy and low false positives.
IAST Disadvantages:
- Language-specific, and there are limited languages supported.
The below table compares the significant differences between SAST, DAST, and IAST.
Implementation
Now we will build a sample DevSecOps pipeline using Github Actions. Github Actions allows configuring jobs that can run in any stage of the pipeline. We only need a Github repository to run Github Action. You can create a free account here. This documentation provides a quick start for the Github Actions.
- Go to your repository on GitHub. You can fork a test repo like this hello world repo.
- Create a new file in the .github/workflows directory. Ex. pipeline.yml
In this pipeline, we will use different security types. We will use “DependencyCheck” as SCA, SonarCloud as SAST, and “OWASP ZAP” as DAST. Moreover, We will check for secrets in the source code using “Detect Secrets.” Also, we will scan the image before deploying it to the cloud.
3. Go to Github marketplace and search for the following Actions:
- Dependency Check
- Detect Secrets
- SonarCloud Scan
- Build and push Docker images
- Anchore
- Deploy to IBM Cloud Kubernetes Service
- OWASP ZAP full scan
4. Copy the YAML codes to the pipeline.yml. Update the settings to match the following snippets:
- Set the environment variables. Add the required secrets in the repository settings/secrets page. Change the “on, “IMAGE_NAME”, “PORT” settings.
name: DevSecOps Pipeline Example
on: [push]
env:
IBM_CLOUD_API_KEY: ${{ secrets.IBM_CLOUD_API_KEY }}
IBM_CLOUD_REGION: ${{ secrets.IBM_CLOUD_REGION }}
IBM_CLOUD_RESOURCE_GROUP: ${{ secrets.IBM_CLOUD_RESOURCE_GROUP }}
IKS_CLUSTER: ${{ secrets.IKS_CLUSTER }} # name or id of cluster
NAMESPACE: ${{ secrets.NAMESPACE }}
IP: ${{ secrets.IKS_CLUSTER_IP }}
IMAGE_NAME: node-hello-world
PORT: 30002
- Dependency Check:
jobs:
fetch-code:
runs-on: 'ubuntu-latest'
name: Fetch Latest Code
steps:
- uses: actions/checkout@master
with:
fetch-depth: 0
dependcy-check:
name: OWASP Dependency Check
runs-on: 'ubuntu-latest'
needs: fetch-code
steps:
- uses: sburris/dependency-check-action@master
with:
Project-Name: ${{ env.IMAGE_NAME }}
- Detect Secrets:
check-for-secrets:
name: Detect Secrets
runs-on: 'ubuntu-latest'
needs: fetch-code
steps:
- name: Run Yelp's detect-secrets
uses: RobertFischer/detect-secrets-action@v2.0.0
- name: Commit back .secrets.baseline (if it was missing)
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "build(detect-secrets): Commit the newly-generated .secrets.baseline file"
- SonarCloud Scan. Follow the instructions here to configure SonarCloud.
sonarcloud:
name: SonarCloud Scan
runs-on: ubuntu-latest
needs: fetch-code
steps:
- uses: actions/checkout@v2
with:
# Disabling shallow clone is recommended for improving relevancy of reporting
fetch-depth: 0
- name: SonarCloud Scan
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- Build and push Docker images. If you don’t have a docker account, click here to create a free one.
Build-publish-Image:
name: Build and Push Image
needs: [dependcy-check, check-for-secrets]
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- Anchore Container Scan
VA:
name: Anchore Container Scan
needs: Build-publish-Image
runs-on: ubuntu-latest
steps:
-
name: VA scan
uses: anchore/scan-action@v2
with:
image: "${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:latest"
fail-build: true
acs-report-enable: true
- name: upload Anchore scan SARIF report
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- Deploy to IBM Cloud Kubernetes Service. If you don’t have an account, click here to create a free one.
Deploy:
needs: Build-publish-Image
name: Deploy to IBM Cloud
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install IBM Cloud CLI
run: |
curl -fsSL https://clis.cloud.ibm.com/install/linux | sh
ibmcloud --version
ibmcloud config --check-version=false
ibmcloud plugin install -f kubernetes-service
ibmcloud plugin install -f container-registry# Authenticate with IBM Cloud CLI
- name: Authenticate with IBM Cloud CLI
run: |
ibmcloud login --apikey "${IBM_CLOUD_API_KEY}" -r "${IBM_CLOUD_REGION}" -g "${IBM_CLOUD_RESOURCE_GROUP}"
ibmcloud cr region-set "${IBM_CLOUD_REGION}"
ibmcloud cr login
# Deploy the Docker image to the IKS cluster
- name: Deploy to IKS
run: |
ibmcloud ks cluster config --cluster $IKS_CLUSTER
kubectl config current-context
kubectl apply -f deployment.yaml
- OWASP ZAP Full Scan
zap_scan:
needs: Deploy
runs-on: ubuntu-latest
name: OWASP ZAP-DAST
steps:
- name: ZAP Scan
uses: zaproxy/action-full-scan@v0.1.0
with:
target: 'http://${{ env.IP }}:${{ env.PORT }}/'
4. Commit a change to the repository and watch the pipeline.
5. For a list of VA alerts, check the code scanning alerts in the repository security tab.
6. ZAP Scan will create a git issue for any Vulnerability found.
Conclusion
This wraps our DevSecOps pipeline walkthrough. As we saw, end-to-end security integration is a doable task, even if it isn’t an easy one. Check out this LinkedIn course; it discusses some of the application security tools we discussed above. Also, check this Awesome DevSecOps Collection; it contains a range of related resources.
Jump in and get started with DevSecOps. Try to implement the above tools or any different ones that meet your requirements. Have fun securing your pipeline!