Hardening GitLab CI/CD: Secrets Detection, SAST & ECR Integration


DevOps is growing and changing every day, which also means new security risks can appear. Even if your cloud platform is well-protected, your CI/CD pipeline can still be a target. If the pipeline isn’t secure, attackers could find a way in or simple mistakes might go unnoticed and end up in production. That’s why it’s important to secure the entire process, not just the cloud.
Objectives
Sensitive information scanning using gitleaks
Static Application Security Testing (SAST)
ECR Integration
Requirement
Gitlab Account
AWS Account
Docker
AWS EC2 with gitlab-runner (How I Turned My EC2 into an AWS GitLab Runner)
The first we need to do is to
Fork and clone this repo https://gitlab.com/devsecops-projects2/sast-project.git
cd into sast-project folder and create a file .gitlab-ci.yml
inside the .gitlab-ci.yml define stages
stages:
- cache
- test
- build
- deploy
- upload_reports
- deploy-test
- deploy-prod
Install dependencies and Create Cache
create_cache:
image: node:18-bullseye
timeout: 2h
stage: cache
script:
- yarn install
cache:
key:
files:
- yarn.lock
paths:
- node_modules/
- yarn.lock
- .yarn
policy: pull-push
- Scan for Secrets using gitleaks
gitleaks:
stage: test
image:
name: zricethezav/gitleaks
entrypoint: [""]
script:
- gitleaks detect --verbose --source .
allow_failure: true
- Scan for vulnerabilities using njsscan
njsscan:
stage: test
image: python
before_script:
- pip3 install --upgrade njsscan
script:
- njsscan --exit-warning .
allow_failure: true
- One security scan is not enough. One security scan tool might be good in one area and not in another area. We will be using another tool called semgrep
semgrep:
stage: test
image: returntocorp/semgrep
variables:
SEMGREP_RULES: p/javascript
script:
- semgrep ci
allow_failure: true
When you run the pipeline. your pipeline is supposed to look like this
When you click on gitleaks you will see this result
You can see that it failed because it detected alot of secrets
- If you click on njsscan
It detected a lot of vulnerabilities
- When you click on semgrep
You will see the summary of the scan. The job failed because there are alot of security vulnerability on the code.
Docker and ECR Integration
To Create a repository in ecr
- Login to you aws console
Click on Search
Type ECR
Select Elastic Container Registry
- Click on Create
- Type the name (juice-shop)
- Scroll down and click on create
The ecr repository should look like this
Next is to generate access and secret keys in aws. if you dont know how to do that you can check out my previous post Mastering IAM in AWS: Creating Users and Roles Step-by-Step. Then create variables in gitlab settings. Create variables with this names
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_ACCOUNT_ID
You can check out my post on how to create variables https://devsecops-blog.hashnode.dev/how-to-securely-store-and-use-variables-in-gitlab-pipelines
Define the following variables at the top of your page
variables:
IMAGE_NAME: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/juice-shop
IMAGE_TAG: $CI_COMMIT_SHA
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_ACCOUNT_ID: $AWS_ACCOUNT_ID
AWS_DEFAULT_REGION: us-east-1
Putting everything together
variables:
IMAGE_NAME: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/juice-shop
IMAGE_TAG: $CI_COMMIT_SHA
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_ACCOUNT_ID: $AWS_ACCOUNT_ID
AWS_DEFAULT_REGION: us-east-1
stages:
- cache
- test
- build
create_cache:
image: node:18-bullseye
timeout: 2h
stage: cache
script:
- yarn install
cache:
key:
files:
- yarn.lock
paths:
- node_modules/
- yarn.lock
- .yarn
policy: pull-push
gitleaks:
stage: test
image:
name: zricethezav/gitleaks
entrypoint: [""]
script:
- gitleaks detect --verbose --source .
allow_failure: true
njsscan:
stage: test
image: python
before_script:
- pip3 install --upgrade njsscan
script:
- njsscan --exit-warning .
allow_failure: true
semgrep:
stage: test
image: returntocorp/semgrep
variables:
SEMGREP_RULES: p/javascript
script:
- semgrep ci
allow_failure: true
build_image_and_push:
stage: build
needs: ["create_cache", "gitleaks", "njsscan", "semgrep"]
before_script:
- aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
# - echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
script:
- docker build -t $IMAGE_NAME:$IMAGE_TAG -t $IMAGE_NAME:latest .
- docker push $IMAGE_NAME:$IMAGE_TAG .
- docker push $IMAGE_NAME:latest
tags:
- ec2
- shell
If your pipeline run successfully you should have something like this
Subscribe to my newsletter
Read articles from Oshaba Samson directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Oshaba Samson
Oshaba Samson
I am a software developer with 5 years + experience. I have working on web apps ecommerce, e-learning, hrm web applications and many others