🡇 Content 🡇
From section 7.1 onwards, we will change the hostname in /etc/hostname
on the deploy instance and build instance to build-instance
and deploy-instance
to avoid confusion between these instances during practice!
🡅 Content 🡅
In this article, we will use SAST (Static Analyze Security Testing) tools to integrate into the CI/CD process to detect security vulnerabilities in your code.
You can choose tools that are suitable for your business. See the tools here:
Best Static Code Analysis Tools: User Reviews from August 2024 (g2.com).
Best Application Security Testing Reviews 2024 | Gartner Peer Insights
We will deploy the tools on the Build Instance.
You can refer to how to install CodeClimate CLI here: https://github.com/codeclimate/codeclimate
We pull the CodeClimate Docker image on the Build Instance:
docker pull codeclimate/codeclimate
Then we try running the CodeClimate CLI in the build directory in /home/gitlab-runner
where we previously ran CI/CD on this Build Instance.
su gitlab-runner
Navigate to your backend directory:
Then run the CodeClimate CLI as follows:
sudo docker run --interactive --tty --rm --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f html > ecommerce-backend.html
Explanation:
docker run
: This command creates and runs a Docker container from the specified image.-interactive --tty
(it
): These two options keep the interactive connection open and start a terminal inside the container, allowing you to interact with it.-rm
: This option automatically removes the container after it stops, saving resources and avoiding unnecessary storage of unused containers.-env CODECLIMATE_CODE="$PWD"
: Sets the CODECLIMATE_CODE
environment variable inside the container to the current directory ($PWD
).-volume "$PWD":/code
: This option mounts the current directory on the host machine (value $PWD
) into the /code
directory inside the container, allowing the container to access your source code for analysis.-volume /var/run/docker.sock:/var/run/docker.sock
: Mounts the Docker socket file from the host into the container. This allows the container to use the Docker CLI inside the container.-volume /tmp/cc:/tmp/cc
: Mounts the /tmp/cc
temporary directory from the host into the container to store temporary files during the analysis process.codeclimate/codeclimate
: This is the Docker image you are using to run the CodeClimate analysis tool.analyze -f html
: This is the command inside the container, instructing CodeClimate to analyze the source code and output the results in HTML format.> ecommerce-backend.html
: This redirects the output of the analysis command to the ecommerce-backend.html
file on the host.After the command runs, a ecommerce-backend.html
file will be generated in the backend folder.
When you open the file, it will be a static webpage displaying the detected issues in the code.
🡇 Content 🡇
If the terminal hangs during execution, it means your server does not have enough memory (no space left on device). In this case, there are several ways to resolve it:
df -h
to check the available memory.🡅 Content 🡅
If you want to view the HTML file, first copy it to /home/ubuntu/
:
sudo cp ecommerce-backend.html /home/ubuntu/
When you execute the command, you will see the HTML file appear in /home/ubuntu
:
Proceed to right-click → download:
After opening the file, here is the interface displaying all the issues in the source code:
First, in the backend project, create a new branch from the main branch for future reference:
Edit the file:
Enter the following line.
We create a new stage called test_source_code
to test after the source code has been built. After completing the script in test_source_code
, an HTML file will be generated, and it will be saved through the GitLab artifact with a retention period of one week. See more here: Job artifacts | GitLab.
We add when: manual
to the push_container
and deploy
stages to deploy manually by pressing the play button.
variables:
USER_PROJECT: "ecommerce"
PATH_PROJECT: "/home/${USER_PROJECT}/${CI_PROJECT_NAME}"
IMAGE_VERSION: "${CI_REGISTRY_USER}/${CI_PROJECT_NAME}-${USER_PROJECT}:${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}"
CODECLIMATE_FILE: "${CI_PROJECT_NAME}:${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}.html"
stages:
- build
- test_source_code
- push_container
- deploy
before_script:
- sudo mkdir -p $PATH_PROJECT
build:
stage: build
variables:
GIT_STRATEGY: clone
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker build -t $IMAGE_VERSION .
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner-build
only:
- tags
test_source_code:
stage: test_source_code
variables:
GIT_STRATEGY: none
script:
- sudo docker run --rm --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f html > $CODECLIMATE_FILE
tags:
- group-ecommerce-shell-runner-build
only:
- tags
artifacts:
paths:
- $CODECLIMATE_FILE
expire_in: 1 week
push_container:
stage: push_container
variables:
GIT_STRATEGY: none
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker push $IMAGE_VERSION
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner-build
when: manual
only:
- tags
deploy:
stage: deploy
variables:
GIT_STRATEGY: none
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker pull $IMAGE_VERSION
- sudo su ${USER_PROJECT} -c "
container_exists=\$(sudo docker ps -a -q -f name=${CI_PROJECT_NAME});
if [ ! -z \"\$container_exists\" ]; then
sudo docker rm -f ${CI_PROJECT_NAME};
fi;
sudo docker run --name ${CI_PROJECT_NAME} -dp ${BACKEND_PORT}:${BACKEND_PORT} ${IMAGE_VERSION}"
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner
when: manual
only:
- tags
After committing, we tag to trigger the pipeline.
The pipeline ran successfully.
We will check if there are any issues with the source code before proceeding with push_container
. Click on browse
.
An HTML file has been generated.
Click to go to the static web page provided by GitLab.
This is the HTML interface generated by CodeClimate.
When we are confident that the source code has no issues, we click the play button sequentially for push_container
and deploy
(after push_container
is completed, click deploy
).
Check that the backend is still running well.
We will deploy the frontend similarly.
variables:
USER_PROJECT: "ecommerce"
PATH_PROJECT: "/home/${USER_PROJECT}/${CI_PROJECT_NAME}"
IMAGE_VERSION: "${CI_REGISTRY_USER}/${CI_PROJECT_NAME}-${USER_PROJECT}:${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}"
CODECLIMATE_FILE: "${CI_PROJECT_NAME}:${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}.html"
stages:
- build
- test_source_code
- push_container
- deploy
before_script:
- sudo mkdir -p $PATH_PROJECT
build:
stage: build
variables:
GIT_STRATEGY: clone
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker build -t $IMAGE_VERSION .
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner-build
only:
- tags
test_source_code:
stage: test_source_code
variables:
GIT_STRATEGY: none
script:
- sudo docker run --rm --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f html > $CODECLIMATE_FILE
tags:
- group-ecommerce-shell-runner-build
only:
- tags
artifacts:
paths:
- $CODECLIMATE_FILE
expire_in: 1 week
push_container:
stage: push_container
variables:
GIT_STRATEGY: none
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker push $IMAGE_VERSION
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner-build
when: manual
only:
- tags
deploy:
stage: deploy
variables:
GIT_STRATEGY: none
before_script:
- sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PWD
script:
- sudo docker pull $IMAGE_VERSION
- sudo su ${USER_PROJECT} -c "
container_exists=\$(sudo docker ps -a -q -f name=${CI_PROJECT_NAME});
if [ ! -z \"\$container_exists\" ]; then
sudo docker rm -f ${CI_PROJECT_NAME};
fi;
sudo docker run --name ${CI_PROJECT_NAME} -dp ${FRONTEND_PORT}:80 ${IMAGE_VERSION}"
after_script:
- sudo docker logout
tags:
- group-ecommerce-shell-runner
when: manual
only:
- tags
The frontend is still running well.