4 minutes
Running OWASP Depedency Checker in AWS Codebuild
Recently people have been adding money to the buzzword jar (same idea as a swear jar), with “DevSecOps”.
In an attempt to add the “Sec” to “DevSecOps”, I took a look at the OWASP Dependency Checker.
I wanted to use AWS Codebuild to run a dependency check each time a developer opened a PR to the master
branch to check to see if they’re introducing any third party dependencies with known vulnerabilitites
The OWASP Dependency checker has a solid Jenkins Plugin that track vulnerabilities it finds over time, so wanted to see what could be done using the new AWS Codebuild Test Reports
When I open a PR to master, that triggers the OWASP build.
Here is my buildspec.yml
(note this is for a Javascript project)
---
version: 0.2
phases:
install:
commands:
- wget https://dl.bintray.com/jeremy-long/owasp/dependency-check-5.3.0-release.zip
- unzip dependency-check-*
- export PATH=dependency-check/bin:$PATH
- npm install
build:
commands:
- mkdir -p nvd # Will store nvd here
- |
dependency-check.sh \
--project my-project \
-s . \
-f JUNIT \
--disableNuspec \
--disableAssembly \
-d nvd \
--failOnCVSS $FAIL_ON_CVSS
# Caching the nvd database so each run doesn't download the
# entire nvd
cache:
paths:
- nvd/**/*
reports:
# ARN of the Codebuild Report created in Cloudformation
arn:aws:codebuild:us-east-1:111111111111:report-group/OwaspReportGroup-ABC123abc987:
files:
- dependency-check-junit.xml
file-format: JunitXml
Once the build runs, I get an entry in my report group, and can quickly see which dependencies have known vulnerabilities.
Since AWS Codebuild Reports are meant for test reports, even low risk vulnerabilities will cause the report to display as failed. I set the Codebuild project itself to only fail if the CVSS score was greater than 7 (See the $FAIL_ON_CVSS
variable)
I can see the Codebuild Report groups having value by showing dependency vulnerabilities over time to show trends in security posture.
What I wish were different
Publishing reports in buildspec.yml
To specify a report group inside the buildspec.yml
, I can either add an arbitrary name (which will create the repor group for you), or provide the full arn of a pre-existing report group.
I could do one or both of the following inside the buildspec.yml
reports:
my-new-report: # New report group gets created
files:
- dependency-check-junit.xml
file-format: JunitXml
arn:aws:codebuild:us-east-1:111111111111:report-group/owasp-dependency-checker:
files:
- dependency-check-junit.xml
file-format: JunitXml
However if I want to create my report group in Cloudformation using the AWS::CodeBuild::ReportGroup
, and not use the Name
property, I can’t pass the ARN (Which is the Return value when using the Ref intrinsic function) to my buildspec.yml
as an environment variable, because you can’t use a variable as a key.
I.e. I can’t pass an environment variable REPORT_ARN
to the Codebuild Project do this inside my buildspec.yml
reports:
'${REPORT_ARN}': # Can't do this
files:
- dependency-check-junit.xml
file-format: JunitXml
Codebuild Reports format
While the CodeBuild Reports are still in preview (as of this writing), and it’s purpose is to publish test results, the display of the OWASP dependency report isn’t fantastic.
In terms of failing your build if third party dependencies have critical vulnerabilities, this setup works fine.
From the Codebuild Reports section of the console, you can get a cursory level understand of what was found, but you’ll need to read the full report, which will get uploaded to S3 if you used the Cloudformation included.
Full Cloudformation for all resources:
---
AWSTemplateFormatVersion: "2010-09-09"
Description: >
Resources for Codebuild project to run OWASP dependecy checks
Parameters:
GithubRepo:
Type: String
Description: Github repo to use
Default: https://github.com/path-to-your/repo.git
FailOnCVSS:
Type: String
AllowedPattern: '[0-9]|10'
Description: >
If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified
Default: 7
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
GithubSourceCredential:
Type: AWS::CodeBuild::SourceCredential
Properties:
AuthType: PERSONAL_ACCESS_TOKEN
ServerType: GITHUB
# Uses my Personal Access token in Github, stored in AWS Secrets Manager
Token: '{{resolve:secretsmanager:github-access-token:SecretString:token}}'
CodebuildOwasp:
Type: AWS::CodeBuild::Project
DependsOn:
- GithubSourceCredential
Properties:
Artifacts:
Type: S3
Location: !Ref Bucket
Name: owasp
Packaging: ZIP
Cache:
Location: !Sub '${Bucket}/owasp.zip'
Type: S3
BadgeEnabled: true
Description: OWASP dependency check
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:2.0
Type: LINUX_CONTAINER
EnvironmentVariables:
- Name: FAIL_ON_CVSS
Value: !Ref FailOnCVSS
ServiceRole: !Ref CodebuildRole
Source:
BuildSpec: buildspec.yml
Type: GITHUB
Location: !Ref GithubRepo
ReportBuildStatus: true
Triggers:
Webhook: true
FilterGroups:
# When a pull request to master branch is created or updated
- - Type: EVENT
Pattern: PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED
- Type: BASE_REF
Pattern: ^refs/heads/master$
ExcludeMatchedPattern: false
OwaspReportGroup:
Type: AWS::CodeBuild::ReportGroup
Properties:
ExportConfig:
ExportConfigType: S3
S3Destination:
Bucket: !Ref Bucket
Packaging: ZIP
Type: TEST
CodebuildRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Principal:
Service:
- codebuild.amazonaws.com
Effect: Allow
Action:
- sts:AssumeRole
Policies:
- PolicyName: logs
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*'
- PolicyName: S3
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketAcl
- s3:GetBucketLocation
Resource:
- !Sub
- '${BucketArn}*'
- BucketArn: !GetAtt Bucket.Arn
- PolicyName: CodebuildReports
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Resource:
- !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*'