DevSecOps with AWS CodePipeline and ECS

KUMAR KARAN
7 min readNov 15, 2023

--

CodePipline is a popular AWS Native CICD tool that we will use to build & deploy the application on the ECS. The blog covers the detailed steps and explanations to create a robust CICD pipeline with Code Build, CodeCommit, Code Deploy, and a few Security tools for the ECS.

Table Of Content

  • What is DevSecOps
  • Tools Used in DevSecOps Pipeline
  • AWS Code Pipeline
  • Configuration Steps
  • Conclusion

What is DevSecOps

DevSecOps incorporates security procedures into the DevOps workflow. The intention is to ensure that security is integrated into the software development lifecycle rather than being approached as an isolated component. This makes security issues easier to find and fix early on rather than as a late concern.

DevSecOps Pipeline Architecture Diagram

Tools Used in DevSecOps Pipeline

There is a wide variety of tools that can be used for DevSecOps and in this blog, we will cover the below-mentioned tools.

Below is the directory structure for the Implementation

SonarQube for SAST

SonarQube is a robust SAST (Static Application Security Testing) tool, that scans code for vulnerabilities. It identifies security issues, bugs, and code smells, offering detailed reports for informed remediation. SonarQube aids in maintaining code quality, ensuring more secure and reliable software development.

SonarQube Architecture

Installation Commands for SonarQube Server

# SonarQube Server:
# Pull the SonarQube Docker image from the official repository
docker pull sonarqube

# Run SonarQube as a container
docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube

Port 9000 must be opened to access the Sonarqube dashboard.

The default username and password is “admin” and needs to be changed post login.

Project Creation

Provide a name to the project(random) and click on the next to select “Choose the baseline for new code for this project”, we will choose “Use the Global Settings Options”.

once the project is created — it will ask for integration and we will select “Locally” as given below, as we do not have a code pipeline integration option.

create an access token for the project which we will need to use as authorization in the Sonar scanner.

Below are the buildspec-sast.yml to install the scanner and run the scan.

# buildspec.yml for SAST scan.

version: 0.2

phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- |
export SONAR_SCANNER_VERSION=5.0.1.3006
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS="-server"
- |
sonar-scanner \
-Dsonar.projectKey=AWS-CodePipeline-Project \
-Dsonar.sources=app.py \
-Dsonar.host.url=http://35.174.204.76:9000 \
-Dsonar.token=sqp_8b19297f74dd07de97d69b868662978510b79551
sleep 10
curl -s -u sqp_8b19297f74dd07de97d69b868662978510b79551: http://35.174.204.76:9000/api/qualitygates/project_status?projectKey=AWS-CodePipeline-Project > /tmp/result.json
cat /tmp/result.json
build:
commands:
- echo "post build completed"
- if [ $(jq -r '.projectStatus.status' /tmp/result.json) = ERROR ] ; then exit 1 ; fi

# - |
# sonar-scanner \
# -Dsonar.projectKey=AWS-CodePipeline-Project \
# -Dsonar.sources=main.py \
# -Dsonar.host.url=http://34.207.253.89:9000 \
# -Dsonar.token=sqp_8b19297f74dd07de97d69b868662978510b79551
# sleep 10
# curl -s -u sqp_8b19297f74dd07de97d69b868662978510b79551: http://34.207.253.89:9000/api/qualitygates/project_status?projectKey=AWS-CodePipeline-Project > /tmp/result.json
# cat /tmp/result.json
post_build:
commands:
- echo "post build completed"
# - if [ $(jq -r '.projectStatus.status' /tmp/result.json) = ERROR ] ; then CODEBUILD_BUILD_SUCCEEDING=0 ; fi
# - echo Code scan completed on `date`,Code is fine.
# - if [ "$CODEBUILD_BUILD_SUCCEEDING" -eq 0 ]; then echo "issues found in the code"; fi

Note: In the above code we have to edit the pre-build section with your Sonarqube token and its server's IP.

Hadolint for Linting Dockerfiles

Hadolint is a Dockerfile linter, that checks for errors and best practices in Dockerfile syntax and structure. It ensures adherence to industry standards and offers suggestions for improvement. Integrating it into development workflows enhances Dockerfile quality and maintains consistency. Analyzing Dockerfiles helps to catch potential issues early, promoting secure and efficient containerization. It’s a valuable tool for maintaining clean, standardized Dockerfiles in software development.

Below is the buildspec-hadolint.yml for scanning the Dockerfile and Building Docker Image.

Note: Below is the directory structure for the CodeCommit Repo

Thank you Subbaraju Penmetsa for your contribution to Hadolint Tool Implementation.

Below is the hadolint.yml file for the hadolint configuration.

# hadolint.yml

ignored:
- DL3013

trustedRegistries:
- docker.io

Below is the build spec file for the Dockerfile linting the dockerfile.

# buildspec file to scan the Dockerfile and building the Docker Image.

version: 0.2
run-as: root

phases:

install:
commands:
- echo Downloading the Hadolint tool...
- wget -O hadolint https://github.com/hadolint/hadolint/releases/download/v1.16.3/hadolint-Linux-x86_64
- cp hadolint /bin
- chmod +x /bin/hadolint
- /bin/hadolint --version

pre_build:
commands:
- echo Running Hadolint on the Dockerfile
- COMMIT_ID=$(aws codecommit get-branch --repository-name python-test-sonarqube-repo --branch-name main --region us-east-1 | jq -r '.branch.commitId')
- IMAGE_TAG=$(echo $COMMIT_ID | cut -c1-7)
build:
commands:
- echo Build started on `date`
- echo Validating the Dockerfile using Hadolint tool...
- /bin/hadolint --config hadolint.yml dockerfile
- echo Building Docker Image
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 088585194665.dkr.ecr.us-east-1.amazonaws.com
- docker build -t devsecops-ecr-repo .
- docker tag devsecops-ecr-repo:latest 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:latest
- docker tag devsecops-ecr-repo:latest 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:${IMAGE_TAG}
- docker push 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:latest
- docker push 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:${IMAGE_TAG}


post_build:
commands:
- echo Build completed on `date`

Note: Please provide the ECR Repo Full and CodeCommit full access to the Code Build Role.

Trivy for Scanning Docker Images

Trivy is a vulnerability scanner designed for containers and container images, swiftly detecting security issues within them. It examines container packages and dependencies, highlighting vulnerabilities and offering details to help mitigate risks.

# Buildspec file for Scanning Docker Image with Trivy.


version: 0.2

phases:
install:
commands:
- yum update -y && yum install wget -y
- wget https://github.com/aquasecurity/trivy/releases/download/v0.20.0/trivy_0.20.0_Linux-64bit.tar.gz
- tar zxvf trivy_0.20.0_Linux-64bit.tar.gz
- sudo mv trivy /usr/local/bin/
- trivy --version
- COMMIT_ID=$(aws codecommit get-branch --repository-name python-test-sonarqube-repo --branch-name main --region us-east-1 | jq -r '.branch.commitId')
- echo COMMIT_ID
- IMAGE_TAG=$(echo $COMMIT_ID | cut -c1-7)
- echo $IMAGE_TAG

build:
commands:
- echo Pulling the docker image for scanning
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 088585194665.dkr.ecr.us-east-1.amazonaws.com
- docker pull 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:latest

post_build:
commands:
- trivy --no-progress --exit-code 1 --severity CRITICAL 088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo:latest
- echo Trivy scan completed succesfully.
- |
IMAGE_DEFINITIONS_CONTENT=$(printf '[{"name": "nginx", "imageUri": "%s:%s"}]' "088585194665.dkr.ecr.us-east-1.amazonaws.com/devsecops-ecr-repo" "$IMAGE_TAG")
echo "$IMAGE_DEFINITIONS_CONTENT" > temp_file.json
IMAGE_DEFINITIONS=$(cat temp_file.json)
echo "$IMAGE_DEFINITIONS" > imagedefinitions.json
rm temp_file.json
artifacts:
files: imagedefinitions.json

Note: Based on the compliance we can modify the severity eg: — severity HIGH,CRITICAL

Now that we have our code build configured we can integrate the same in the code pipeline.

Note: Please provide the CodeCommit Full access to the Code Build Role.

Note: The [{“name”: “nginx”, “imageUri”: “%s:%s”}] represents the information about the container name and the image URI.

Please refer to the documentation for the imagedefinition file with the below link.

CodePipeline Configuration

Below are the steps to configure the Code Pipeline.

Configure the source as CodeCommit and select the repository and branch.

Select the Code Build project which will execute first and later we will add the other projects once the pipeline is created.

Skip the deploy stage as we will add this part later once the pipeline is created.

Create the pipeline with the above-mentioned configuration.

Now that we have a basic pipeline created we can edit the same to suit our implementation.

click on the edit pipeline and edit the build stage.

Below is the complete configuration for the SonarQube Scanning stage.

Below is the configuration for the Hadolint and DockerBuild stage.

Below is the configuration for the ECS deployment stage.

Below is the configuration for Code Deploy with ECS.

The pipeline execution is shown in the image below.

Now that we have configured all the steps below is the pipeline for the implementation, we can verify from the ECR and image task definition that our image is getting the Commit IDas a tag.

Below is the image from the task definition's latest revision.

Below is the image from the ECR.

Conclusion

Using AWS CodePipeline in conjunction with a DevSecOps approach ensures a comprehensive integration of security practices throughout the software development lifecycle. A proactive approach to security is promoted by utilizing tools such as Trivy, Hadolint, and SonarQube, which improve vulnerability scanning and code quality checks.In this blog we have configured a DevSecOps pipeline on the AWS to deploy the application on the AWS ECS.

--

--