Franziska Bühler
Posted on September 30, 2020
Let's start with the first Pixi-CRS Pipeline in the Cloud, namely on AWS: https://aws.amazon.com/console/.
This is the second blog post in the "Pixi-CRS goes to the Cloud" series. The intro blog post of this series can be found here.
This is how Pixi-CRS looks on Amazon Web Services:
In the image above, we see that the Pixi-CRS CI Pipeline on AWS was added as Developer Tools > CodeBuild > Build project.
Pixi-CRS Pipeline Code
The code behind the pipeline can be found here.
AWS pipeline code is written in buildspec.yml files in the root directory of the repository. It's pretty easy to create a new build project inside AWS. We just need to provide a "Project Name", a source repository, choose the option "Use a buildspec file" and enable logs.
Let's have a closer look at this buildspec.yml.
I will explain the different steps below. But I also give explanations in the comments in the provided yaml file.
# AWS buildspec.yml
#
version: 0.2
phases:
install:
runtime-versions:
docker: 19
build:
commands:
# We install testcafe. We don't run it in Docker, because volumes can not be mounted!
# They probably could be mounted in a docker-compose, but let's run testcafe another way...
- npm install -g testcafe
# Start the OWASP ModSecurity Core Rule Set and Pixi with its DB with docker-compose
# OWASP ModSecurity Core Rule Set Container (Apache Reverse Proxy)
# owasp/modsecurity-crs
# See https://coreruleset.org/
# ModSecurity Tuning:
# See https://www.netnea.com/cms/apache-tutorial-8_handling-false-positives-modsecurity-core-rule-set/
# We have to install a higher version of docker-compose manually
# so that --env-file is available
# Unfortunately -e does not work, even with a higer docker-compose version
- curl -L https://github.com/docker/compose/releases/download/1.26.2/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
- chmod +x ~/docker-compose
- mv ~/docker-compose /usr/local/bin/docker-compose
- docker-compose -v
- cat compose-aws.env
- docker-compose --env-file compose-aws.env up -d
# Application Tests with Testcafe
# skip-js-errors because of: Uncaught Error: Bootstrap tooltips require Tether
- testcafe "chrome:headless" testcafe/tests_localhost/test.js --skip-js-errors
# Application Tests with CRS with Testcafe
- testcafe "chrome:headless" testcafe/tests_localhost/testcrs.js --skip-js-errors
# WAF Tests with malicous request to test WAF itself
- testcafe "chrome:headless" testcafe/tests_localhost/testwaf.js --skip-js-errors
post_build:
commands:
# Fail if ModSecurity log is not empty
# Show ModSecurity logs of Testcafe Tests
- docker exec crs cat /var/log/apache2/error.log | grep ModSecurity | grep error | grep -vi "MyEvilWAFTest" | grep -v "949110" | grep -vi "980130" && echo "False Positive Found. Check Logs. Aborting!" && exit 1 || exit 0
# If not empty -> Repair your application OR
# -> ModSecurity Tuning:
# See https://www.netnea.com/cms/apache-tutorial-8_handling-false-positives-modsecurity-core-rule-set/ OR
# -> GitHub issue: https://github.com/SpiderLabs/owasp-modsecurity-crs
# Fail if ModSecurity log does not contain WAF Test String "MyEvilWAFTest"
# That means CRS is not working properly or test was aborted.
- docker exec crs cat /var/log/apache2/error.log | grep -q MyEvilWAFTest
# Show ModSecurity Full Logs:
- docker exec crs cat /var/log/apache2/error.log | grep ModSecurity | grep msg
If you want to read a full description of the CircleCI Pixi-CRS pipeline, you should have a look at this blog post.
Pipeline Steps
Installing Testcafe
This is the only pipeline that uses an installation of Testcafe. All other pipelines will use Testcafe in the testcafe/testcafe Docker container.
We use an installation of Testcafe because, at the time of this writing, I was not able to mount volumes into Docker containers on AWS, and Testcafe Docker uses volumes to mount the tests.
npm install -g testcafe
Installing docker-compose
Docker-compose is already available in the base image we use. However, we use a newer version of docker-compose because we want to use the argument --env-file.
Start Pixi and the CRS
We start Pixi and the CRS with one docker-compose up command. We provide an env-file that configures the listening port of the CRS container and the backend of the CRS container:
docker-compose --env-file compose-aws.env up -d
Testcafe tests
Now that the CRS and Pixi are running, we perform the Testcafe tests. First, we test Pixi directly, then we test Pixi through the CRS. We also test the CRS itself with a malicious string. We want to be sure that the WAF will block it.
For our tests, we call Pixi via http://localhost:8000 and the CRS via http://localhost because we installed testcafe and we now call the exposed Pixi and the CRS ports on localhost.
And this is how the Testcafe test output looks:
Check results
In the end, we check the results. We take a look at the ModSecurity log inside the CRS Docker container.
This is the important step that ensures that we did not get any false positives with our legitimate tests.
In addition, we ensure that our malicious test was logged.
Trigger
Because Pixi-CRS is a CI pipeline and we want to run our CodeBuild project after every push into the repository, we need to configure a trigger on push events.
This can be done in: Developer Tools > CodeBuild > Build projects > Pixi-CRS > Edit Source > Webhook. I want to trigger a build every time a code change is pushed to the Pixi-CRS GitHub repository.
I also see this webhook in GitHub then.
Things to mention
I didn't configure an AWS CodeDeploy or an AWS CodePipeline. These would be the next steps to deploy Pixi-CRS somewhere and also have Continuous Deployment. In this blog post, I only wanted to show the CI part. And I'm also aware that a lot more AWS options are available. But for this blog post, I wanted to keep it simple and concentrate on the Pixi-CRS CI part.
Next blog post
In the next blog post, we will get to know the Pixi-CRS pipeline on the Azure DevOps Pipeline.
Posted on September 30, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.