RapidScale Blog

CNAPP in practice: Unifying CSPM + CWPP + CI scanning with IaC drift control

Written by RapidScale | Sep 28, 2026, 1:00:00 PM

Cloud security has become increasingly complex, with organizations often managing fragmented tool stacks. This can easily create blind spots, increase operational overhead, and make it harder for your teams to maintain a consistent security posture.

Cloud-native application protection platforms (CNAPPs) unify cloud security capabilities in a single platform, offering visibility and protection from development to deployment. With CNAPP, you don’t need to run a separate cloud security posture management (CSPM) solution, a cloud workload protection platform (CWPP), and CI/CD security scanning tools, as it consolidates all these functions.

This post explores the core concepts of CNAPP and demonstrates how they work together using a practical example.

Understanding CNAPP

CNAPP integrates several security methodologies that are traditionally operated in silos.

Cloud security posture management (CSPM)

CSPM continuously checks for misconfigurations in your cloud infrastructure, e.g., whether your S3 buckets can be accessed publicly or your security groups allow unrestricted access to certain ports.

With CSPM, you gain the visibility you need into your cloud provider to see where attackers can exploit your services.

Cloud workload protection platform (CWPP)

CWPP protects workloads running in your cloud environment via, for example:

  • Image scanning for vulnerabilities
  • Runtime threat detection
  • Behavioral monitoring

CWPP helps you secure everything you deploy and ensures it stays secure during execution.

CI/CD security scanning

In CNAPP, shifting left is paramount. This means integrating all security checks into your pipelines, e.g., IaC, container security, and policy-as-code (PaC) scans, to catch issues before they reach your environments.

Drift detection and remediation

Infrastructure drift refers to a discrepancy between a desired and actual state.

When someone makes a manual change to your infrastructure outside of your infrastructure deployment process, they enable drift.

In some cases, you may introduce drift to fix a high-severity issue affecting customers, manually doing so to speed up resolution. But as soon as everything is up and running, you should include that change into your code to ensure the drift is resolved.

Unfortunately, engineers often forget to do this, which is why drift detection is so important. It easily detects discrepancies between your desired and actual infrastructure states. Once notified, you can restore the intended state.

Compliance framework mappings

To implement a proper CNAPP, you must map your security controls to recognized compliance frameworks, as this will provide both the required protection and audit evidence.

CIS Benchmarks

The Center for Internet Security (CIS) publishes benchmarks that can easily translate directly to CNAPP capabilities:

  • CIS AWS benchmarks: These map to CSPM rules. They also run automated checks against your AWS environment to ensure, e.g., that your S3 buckets block public access and MFA is enabled for your IAM users.
  • CIS Docker benchmarks: These map directly to CWPP runtime checks. They also ensure runtime protection is enabled by monitoring for violations of container user privileges, capability restrictions, and other issues.
  • CIS Kubernetes benchmarks: In addition to mapping to CWPP, these can also map to behavior monitoring. They help you integrate your container orchestration security with pod security standards, network policies, and API server configuration controls.

NIST 800-53 control mapping

NIST 800-53 provides a comprehensive security control catalog that also maps to CNAPP:

  • Access Control (AC) maps to IAM policy scanning in your IaC. These controls requiring you to implement least privilege access become Rego policies, which fail builds in your CI/CD pipelines containing overly permissive IAM policies.
  • System and Information Integrity (SI) map directly to container vulnerability scanning so that your CI/CD pipelines block containers with critical CVEs from being deployed.

Now that we’ve explored what CNAPP is and explored the CIS and NIST compliance frameworks, let’s take a look at an example setup of a unified CNAPP.

Example Setup for a Unified CNAPP

Let’s take a look at a practical CNAPP implementation. To do this, we’ll start by creating vulnerable IaC in Terraform, and then apply security controls at each layer.

Here’s the Terraform code that creates an EC2 instance and an overpermissive security group:

resource "aws_instance" "this" {

ami = "this_ami"

instance_type = "t2.micro"

} 

resource "aws_security_group" "this" {

name = "my-vulnerable-sg"

description = "Vulnerable SG"

ingress {

from_port = 22

to_port = 22

protocol = "tcp"

cidr_blocks = "0.0.0.0/0"

}

}

At a glance, we can see that there are two big issues:

  1. The AWS instance doesn’t have encryption enabled
  2. SSH is exposed to the internet via the security group

IaC vulnerability scanning

There are several tools for IaC vulnerability scanning. Checkov, an open-source static code analysis tool, performs software composition analysis (SCA) on images and package files.

Let’s run Checkov against this code and see what kind of security vulnerabilities we have:

terraform scan results:

Passed checks: 7, Failed checks: 6, Skipped checks: 0

We have six failed checks. Checkov offers explanations of all checks here, while its output includes fixes for any failed ones. The corrected code is as follows:

resource "aws_instance" "this" {

ami = "this_ami"

instance_type = "t2.micro"

monitoring = true

ebs_optimized = true

metadata_options {

http_endpoint = "enabled"

http_tokens = "required"

}

 

root_block_device {

encrypted = true

}

}

 

 

resource "aws_security_group" "this" {

name = "my-vulnerable-sg"

description = "Vulnerable SG"

 

ingress {

description = "Enable SSH"

from_port = 22

to_port = 22

protocol = "tcp"

cidr_blocks = "10.0.2.0/24"

}

}

After running another check, we can see that all the issues were fixed:

Passed checks: 13, Failed checks: 0, Skipped checks: 0

You can see other Checkov scan examples here.

Cloud misconfiguration scanning with Prowler

Prowler, which you can easily run with the CIS AWS Foundations benchmark, helps you scan your live AWS environment for misconfigurations. The following command will execute over 73 checks for different services in AWS:

prowler aws --compliance cis_2.0_aws

But let’s make it more specific:

prowler aws -c s3_bucket_default_encryption \

ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22

This will check only the EC2 service for security groups, and the S3 service to verify whether S3 buckets have default encryption enabled.

With Prowler, you can see all your security issues at a glance. It also saves detailed results in different formats:

 Prowler execution results

 

We can see that our AWS account failed a single EC2 check: a security group that has port 22 open.

What about container vulnerabilities? Let’s now take a look at how to scan for those

Container vulnerability scanning

Let’s build a simple Dockerfile that runs a Python application:

 FROM python:3.12 

RUN apt-get update && apt-get install -y curl wget

RUN pip install flask requests boto3

EXPOSE 8080

CMD ["python", "app.py"]

 
Now, run Trivy on the Dockerfile directly to check for any misconfigurations:

trivy config ./Dockerfile

This is the output we get from Trivy:

Dockerfile (dockerfile)

Tests: 27 (SUCCESSES: 24, FAILURES: 3, EXCEPTIONS: 0)

Failures: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 2, CRITICAL: 0)  

HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument

LOW: Add HEALTHCHECK instruction in your Dockerfile

HIGH: '--no-install-recommends' flag is missed:

As you can see, we have only three failures, and only two are high severity. Let’s build the image as it is, and then use Trivy to scan it for vulnerabilities:

trivy image your_image_id --severity HIGH,CRITICAL > trivy_result

The results for this example are as follows:

Total: 57 (HIGH: 53, CRITICAL: 4)

Our base image has over 57 High and Critical vulnerabilities. As a best practice, always scan the base images you plan to use before building your Dockerfiles.

A successful Trivy run that shows vulnerabilities (even critical ones) will always have an exit code of 0. So, to fail runs in a CI/CD pipeline when you get High or Critical issues, you could run your scan like this:

trivy image your_image_id --exit-code 1 --severity HIGH,CRITICAL

In a UNIX system, a 0 exit code means that your command has run successfully, while anything non-zero means there was an error.

Now that you’ve scanned your images for vulnerabilities, you need to make sure you’re not deploying containers that introduce issues in your Kubernetes clusters. This is where PaC comes in, helping you block deployments containing certain resources or resource parameters.

PaC isn’t limited to just Kubernetes. It can be used in IaC as well.

Implementing PaC for your Kubernetes manifests

Let’s look at a simple deployment for an Nginx application that uses the latest image tag, doesn’t define any resource requests or limits, and adds privileged capabilities:

apiVersion: apps/v1

kind: Deployment

metadata:

name: vulnerable-app

spec:

replicas: 2

selector:

matchLabels:

app: vulnerable-app

template:

metadata:

labels:

app: vulnerable-app

spec:

containers:

- name: vulnerable-app

image: nginx/nginx:latest

ports:

- containerPort: 8080

securityContext:

privileged: true

Now, we can create a Kyverno policy that blocks deployments and other Kubernetes resources that don’t have resource requests and limits:

 apiVersion: kyverno.io/v1

kind: ClusterPolicy

metadata:

name: require-resource-limits

annotations:

policies.kyverno.io/title: Require Limits

policies.kyverno.io/category: Limits

policies.kyverno.io/severity: high

spec:

background: true

rules:

- name: require-limits

match:

any:

- resources:

kinds:

- Pod

- Deployment

- StatefulSet

- DaemonSet

- Job

- CronJob

validate:

message: >-

Resource limits are required

pattern:

spec:

=(template):

spec:

containers:

- resources:

limits:

memory: "?*"

cpu: "?*"

Next, run the above policy against the Nginx deployment code:

kyverno apply policy.yaml --resource nginx-deployment.yaml

This is the command output, successfully showing us that there is a problem with the deployment:

policy require-resource-limits -> resource default/Deployment/vulnerable-app failed:

1 - require-limits validation error: Resource limitsare required. rule require-limits failed…

To fix the issue, add limits to the resources field:

resources:

limits:

memory: "256Mi"

cpu: "500m"

requests:

memory: "128Mi"

cpu: "250m"

Now, if we re-run Kyverno, the policy will pass:

pass: 1, fail: 0, warn: 0, error: 0, skip: 0

You will need to define separate policies for checking both the latest image tag and privileged capabilities.

Kyverno doesn’t have to run from your CLI; you can deploy all your policies in your Kubernetes cluster, and whenever someone tries to deploy a resource that violates any of these policies, the Admission Controller will deny their creation and explain why this is happening.

Alternatively, you can use Open Policy Agent (OPA), which uses the Rego language. OPA has a steeper learning curve than Kyverno, but can be used for both Kubernetes resources and IaC. Kyverno is also an option for IaC if you build your infrastructure by using Crossplane or Kubernetes operators.

Choosing between the two depends on your tech stack, but in either case, as a best practice in CNAPP, you should implement PaC for all your resources.

In addition to policy as code for Kubernetes, you can use Falco for runtime anomaly detection. By combining Falco with Prometheus, Grafana, and Alertmanager, you can build sophisticated alerts for runtime anomalies and be notified when issues occur.

The next step to implementing CNAPP is to integrate all these security checks into your CI/CD pipeline.

CI/CD pipeline integration

All of the above scans can be easily integrated into your CI/CD pipeline, regardless of whether it uses GitHub Actions, GitLab CI/CD, Jenkins, or another platform. Doing so creates a complete CNAPP implementation by covering all security pillars:

You can also implement drift detection for your IaC code by simply running plans on a schedule and alerting when any changes are detected. There are even dedicated platforms for more sophisticated drift detection, such as Spacelift, Terraform Cloud, Env0, and Scalr. These also offer out-of-the-box remediation workflows, state locking, and other dedicated IaC features.

A pipeline with integrated checks creates an automated and continuous security posture, which is central to CNAPP.

From fragmented tools to unified cloud security

CNAPP brings together traditionally disconnected security mechanisms into a single platform. By unifying CSPM, CWPP, CI/CD security scanning, and drift detection, you achieve consistent policy enforcement, clear visibility into potential vulnerabilities, and reduced overall operational complexity.

Building a unified approach with these solutions provides a solid foundation, but managing them at scale might require specialized tools and investment in maintenance, integrations, and alert correlation.

Ready to simplify your cloud security? RapidScale can help. We provide 24/7/365 managed cloud services, with solutions that include all CNAPP components.

Get back to building applications instead of wasting time on the complex aspects of cloud security.  Send a message to a RapidScale expert today.