Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REKDAT-164: Add workflows for security scans #292

Merged
merged 17 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions .github/workflows/scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Run security scans

on:
workflow_dispatch:
pull_request:

jobs:
sast-scanner:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
security-events: write
steps:
- name: checkout
uses: actions/checkout@v4

- name: configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_SCAN_ROLE }}
role-session-name: github-actions
aws-region: eu-west-1

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
with:
registries: ${{ secrets.TOOLS_REGISTRY }}

- name: setup docker buildx
uses: docker/setup-buildx-action@v3

- name: Build sast scanner
uses: docker/build-push-action@v6
with:
context: ./docker/sast-scanner-meta
file: ./docker/sast-scanner-meta/Dockerfile
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ env.REPOSITORY }}/sast-scanner-meta:latest
load: true
env:
DOCKER_BUILD_RECORD_UPLOAD: false
REPOSITORY: ${{ secrets.TOOLS_REPOSITORY }}


- name: Run sast scanner
run: |
docker run --rm -v "${{ github.workspace }}:/src" -e LEVEL=HIGH -e TARGET=APP -e FORMAT=sarif $REPOSITORY/sast-scanner-meta:latest
env:
REPOSITORY: ${{ secrets.TOOLS_REPOSITORY }}


- name: upload results to advanced security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep-app-report.sarif
category: semgrep

dependency-check:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
security-events: write
steps:
- name: checkout
uses: actions/checkout@v4

- name: configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_SCAN_ROLE }}
role-session-name: github-actions
aws-region: eu-west-1

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
with:
registries: ${{ secrets.TOOLS_REGISTRY }}


- name: Run dependency check
run: |
docker run --rm -v "${{ github.workspace }}:${{ github.workspace }}" -e SCAN_DIR=${{ github.workspace }} -e FORMAT=SARIF -e OUTDIR=${{ github.workspace }} $REGISTRY/$REPOSITORY/dependency-check:v1.0.0
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ secrets.TOOLS_REPOSITORY }}


- name: upload results to advanced security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: dependency-check-report.sarif
category: dependency-check


47 changes: 47 additions & 0 deletions cloudformation/github-actions-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ Parameters:
Type: String
Default: false
AllowedValues: [true, false]
CreateScanRole:
Description: Is the scan role required for this aws account
Type: String
Default: false
AllowedValues: [ true, false ]
ToolsRepositoryArn:
Description: Arn for tools repository (Optional)
Type: String


Conditions:
CreateOIDCProvider: !Equals
- !Ref OIDCProviderArn
- ""
ShouldCreateBuildRole: !Equals ['true', !Ref CreateBuildRole]
ShouldCreateScanRole: !Equals [ 'true', !Ref CreateScanRole ]


Resources:
Role:
Expand Down Expand Up @@ -126,6 +137,42 @@ Resources:
- "ecr:UploadLayerPart"
Resource: !Ref ECRRepositoryArn

ScanRole:
Type: AWS::IAM::Role
Condition: ShouldCreateScanRole
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !If
- CreateOIDCProvider
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: !Ref OIDCAudience
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
Policies:
- PolicyName: ecr-tools-login
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "ecr:GetAuthorizationToken"
Resource: "*"
- PolicyName: ecr-tools-pull
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "ecr:BatchGetImage"
- "ecr:GetDownloadUrlForLayer"
Resource: !Ref ToolsRepositoryArn


GithubOidc:
Type: AWS::IAM::OIDCProvider
Expand Down
8 changes: 8 additions & 0 deletions docker/sast-scanner-meta/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM 373155601093.dkr.ecr.eu-west-1.amazonaws.com/dvv/sast-scanner-meta:v1.0.0

COPY ./entrypoint.sh /app/
RUN ["chmod", "+x", "/app/entrypoint.sh"]

WORKDIR /src

ENTRYPOINT ["sh", "-c", "/app/entrypoint.sh ${LEVEL} ${TARGET} ${SRCDIR} ${IACDIR} ${OUTDIR} ${FORMAT} ${EXCLUDE_RULES}"]
138 changes: 138 additions & 0 deletions docker/sast-scanner-meta/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash

EXCLUSIONS="*.md,web/coverage,web/node,web/node_properties,application.properties"
EXCLUDES=""
IFS=',' read -ra ADDR <<< "$EXCLUSIONS"
for i in "${ADDR[@]}"; do
EXCLUDES+="--exclude $i "
done

echo "[*] using exclude for files ${EXCLUSIONS}"

RULE_EXCLUSIONS="--exclude-rule python.lang.compatibility.python37.python37-compatibility-importlib2 "
IFS=',' read -ra ADDR <<< "$EXCLUDE_RULES"
for i in "${ADDR[@]}"; do
RULE_EXCLUSIONS+="--exclude-rule $i "
done

echo "[*] using exclude for rules ${RULE_EXCLUSIONS}"

APP_RULES="--config /app/custom-rules --config "p/default" --config "p/ci" --config "p/java" --config "p/python" --config "p/docker" --config "p/typescript" --config "p/javascript" --config "p/kotlin" --config "p/r2c-security-audit" --config "p/eslint" --config "p/csharp""

IAC_RULES="--config /app/custom-rules --config "p/terraform" --config "p/kubernetes""

function summary {
function join_by { local IFS="$1"; shift; echo "$*"; }
sarif summary $2 | grep -v '^\s' | grep .
SUMMARIES=($(sarif summary $2 | grep -v '^\s' | grep . | tr -d " "))
SEVERITIES=()
SEVERITY_COUNTS=()
for summary in "${SUMMARIES[@]}"
do
SEVERITIES+=("$(echo $summary | cut -d':' -f1)")
SEVERITY_COUNTS+=("$(echo $summary | cut -d':' -f2)")
done
summary_file=$1
join_by , "${SEVERITIES[@]}" > $summary_file
join_by , "${SEVERITY_COUNTS[@]}" >> $summary_file

echo "[*] Summary report written to $1"
}

handle_output() {
if [ -f $OUTDIR/semgrep-app-report.sarif ]; then
sarif html $OUTDIR/semgrep-app-report.sarif --output $OUTDIR/semgrep-app-report-from-sarif.html
summary "$OUTDIR/semgrep-app-summary.csv" "$OUTDIR/semgrep-app-report.sarif"
echo "[*] HTML scan app results written"
fi

if [ -f $OUTDIR/semgrep-iac-report.sarif ]; then
sarif html $OUTDIR/semgrep-iac-report.sarif --output $OUTDIR/semgrep-app-report-from-sarif.html
summary "$OUTDIR/semgrep-iac-summary.csv" "$OUTDIR/semgrep-iac-report.sarif"

echo "[*] HTML scan iac results written"
fi

if [ -f $OUTDIR/semgrep-app-report.xml ]; then
mv $OUTDIR/semgrep-app-report.xml $OUTDIR/semgrep-app-junit-report.xml
echo "[*] XML scan app results written"

junit2html $OUTDIR/semgrep-app-junit-report.xml $OUTDIR/semgrep-app-report.html
echo "[*] HTML scan app results written"
fi

if [ -f $OUTDIR/semgrep-iac-report.xml ]; then
mv $OUTDIR/semgrep-iac-report.xml $OUTDIR/semgrep-iac-junit-report.xml
echo "[*] XML scan iac results written"

junit2html $OUTDIR/semgrep-iac-junit-report.xml $OUTDIR/semgrep-iac-report.html
echo "[*] HTML scan iac results written"
fi
}

# Handling severity levels
if [ $# -eq 0 ]
then
echo "[*] Default severity levels will be used."
SEMGREP_SEVERITY="--severity ERROR"
elif [ $1 = "LOW" ]
then
echo "[*] Custom LOW severity levels will be used."
SEMGREP_SEVERITY="--severity INFO"
elif [ $1 = "MEDIUM" ]
then
echo "[*] Custom MEDIUM severity levels will be used."
SEMGREP_SEVERITY="--severity WARNING"
elif [ $1 = "HIGH" ]
then
echo "[*] Custom HIGH severity levels will be used."
SEMGREP_SEVERITY="--severity ERROR"
elif [ $1 = "CRITICAL" ]
then
echo "[*] Custom CRITICAL severity levels will be used."
SEMGREP_SEVERITY="--severity ERROR"
elif [ $1 = "ALL" ]
then
echo "[*] Custom ALL severity levels will be used."
SEMGREP_SEVERITY=""
else
echo "[x] Invalid severity level. Default severity levels will be used."
SEMGREP_SEVERITY="--severity ERROR"
fi


run_semgrep() {
echo "[*] Running semgrep on $1 source in $2"
if [ $FORMAT = "sarif" ]
then
echo "[*] SARIF format will be used."
OUTPUT_ARGS="--sarif --sarif-output $OUTDIR/semgrep-$1-report.sarif"
else
echo "[*] JUNIT-XML format will be used."
OUTPUT_ARGS="--junit-xml --output $OUTDIR/semgrep-$1-report.xml"
fi
semgrep scan $3 --metrics=off $EXCLUDES $RULE_EXCLUSIONS $OUTPUT_ARGS $SEMGREP_SEVERITY --no-error $ARGS
}

if [ $2 = "APP" ]
then
run_semgrep "app" $SRCDIR "$APP_RULES"

handle_output
elif [ $2 = "IAC" ]
then
run_semgrep "iac" $IACDIR "$IAC_RULES"
handle_output
else
run_semgrep "app" $SRCDIR "$APP_RULES"
run_semgrep "iac" $IACDIR "$IAC_RULES"

handle_output
fi

if [[ "${BUCKET}" ]]; then
/copy_to_s3.sh
fi

echo "[*] All done!"
exit 0
Loading