Containers have changed the way we develop and deploy software. They allow us to take any technology stack and run it everywhere as a containerized application. We can, for instance, deploy a container in on-premises servers with no installation effort. Alternatively, we can run containers directly on scalable cloud services such as AWS Elastic Cloud Service (ECS) or Fargate without having to worry about infrastructure, operating systems, or hardware support. What is more, containers are a required stop on the way to orchestration platforms like Elastic Kubernetes Service (EKS).
Since containers run in an isolated environment, they may inspire a false sense of security. We might think that they are somehow immune to software vulnerabilities. But that is not the case at all. In fact, a recent study showed that more than half of the containers stored in Docker Hub, the largest container registry, have at least one critical vulnerability. Clearly, containers are not secure by default and need special security precautions.
While rolling a custom security solution is not recommended, it is still essential to understand how to protect containerized applications. In this article, we will look at the aspects of security from development to production.
Before Deploying Containers
Security should be baked in from the beginning of the development cycle, during deployment, and throughout the entire lifecycle of the application. Before deploying containers, there are some steps we can take to mitigate security risks:
- Code reviews: a teammate or a senior developer reviews commits and pull requests to ensure changes conform to the project’s quality standards and no evident security issues are introduced.
- Static analysis: these tests look for problematic patterns in the application. Static analysis tools scan the source code for structures known for introducing security vulnerabilities or making it harder for other developers to understand.
- Integration tests: these tests run the application in a specialized test environment. While security testing is not traditionally the primary objective here, some teams choose to use integration tests for exposing the application to purposely harmful data. This practice can show whether the application behaves in a reasonable way during an attack.
- Code audit: scanning the code and its dependencies for already-discovered vulnerabilities is a standard practice in software development. Some languages have security audit tooling built in. An example of this is Node.js, which has the npm audit command to check installed modules against a vulnerability database. Languages that don’t come with audit features have third-party packages that can perform this task.
To ensure the above tests always run, we should set up a Continuous Integration and Delivery (CI/CD) pipeline that checks the code after every change. A CI/CD pipeline executes a series of processes each time a commit is pushed to the repository. To avoid human error, you should use the pipeline to automatically run all the tests, pre-deployment jobs, and deployment jobs.
We’ll focus on AWS because it is responsible for the majority of the containers in the cloud. AWS offers two services for this: CodeCommit, a git code repository, and CodeBuild, a managed CI/CD platform.
While Deploying Containers
While deploying containers, you should perform two types of tests: Static Application Security Testing (SAST) and Dynamic Application Security Testing (DAST). SAST is used in the early stages to analyze the source code. Then, DAST solutions check for vulnerabilities after the container is deployed. This combination provides comprehensive application security coverage.
The deployment process installs the latest version of the container in production. This is your last opportunity to catch security issues before the container is exposed to the Internet. Security checks should be treated the same as any other application tests. They should run in the same CI/CD pipeline that performs the deployment, and stop the release if any issues arise.
The steps we can run at this stage to secure containers are:
- Environment tests: these tests check that your environment is working as expected, with tools such as Prowler, before deployment addresses the security risks. AWS’ shared responsibility model means that users are responsible for keeping the environment safe, managing the container security, and controlling network access.
- Secret scanning: these tests look for leaked credentials and other sensitive secrets in the container image.
- Container audit: this audit checks the complete container image, ensuring it has no insecure software and has the latest patches installed.
Container auditing is one of the most powerful features we can use to keep a containerized application safe before release. We have at our disposal several tools to automate this process:
- Clair: an open-source static vulnerability tool that works on Docker-compatible images. It scans the entire container image for signatures of known vulnerabilities.
- Docker Scan: the official Docker security container scanning tool for finding security issues on images. Docker Scan is only available as part of Docker Desktop.
- Docker Bench Security: a suite of security scripts that check for dozens of best practices on Docker-based deployments. Docker Bench is currently in beta.
- Elastic Container Registry (ECR) Image Scanning: a private image container registry with integrated security features. AWS provides a comprehensive list of security checks customized for their cloud environment.
So far, we’ve discussed static analysis tools. Dynamic testing solutions are different. The main contrast is that DAST doesn’t need to know how the application works. It doesn’t even need access to the code. DAST performs what is called black-box testing. It tries to break into the application by using a mixture of scanning and replaying standard attack techniques. Among other things, these techniques include SQL injections, buffer overflows, and cross-site request forgery. Dynamic testing is primarily aimed at examining the security of web applications.
Container tests should run after the containers are built but before the deployment stage in your CI/CD pipeline. For deployments, AWS gives us CodeDeploy to roll out containers into production.
After Deploying Containers
You can’t relax after the container is in production because even when deployed with the best-tuned CI/CD process, it will occasionally get configuration drift. As packages are superseded, and new vulnerabilities are found, new attack windows are opened every day. Critical security level issues must be addressed or mitigated immediately.
You can’t wait for the next application release. You must continually monitor containers to keep your application in check. Observability, monitoring, and awareness are critical for keeping your systems secure.
Container security requires specialized attention, and this is where security experts are most needed to ensure your environment is safe. For companies that can’t (or won’t) hire a full-time specialist team, the best answer is a managed, cloud-based service like Mission Cloud Managed Detection and Response (MDR).
Mission Cloud is an AWS Premier Consulting Partner that offers DevOps and security services for your containers. By subscribing to the MDR service, AWS customers can benefit from the advanced intrusion detection features. In addition, Mission Cloud security specialists will extend advice on best practices for the AWS cloud environment. The MDR service is powered by Alert Logic, a cloud-based, advanced alert and intrusion detection provider.
Container security can be challenging, and it requires a multi-layer approach. As a general rule, avoid rolling your own container security system. Instead, use existing battle-tested tools and employ security specialists. Catch security risks early, and monitor and audit production environments regularly.
Uplevel your container security today
Reach out to the container security experts at Mission for a free consultation.