How to Create ‘Security Policy as Code’ to Automate Application Security Policies in the CI/CD Pipeline
DevOps and DevSecOps teams can now automatically deploy and update new applications securely using Kubernetes Custom Resource Definition (CRDs)
As DevOps teams integrate their toolchain to enable automated deployment of container-based applications, one aspect has always slowed down a modern cloud-native pipeline: security. And while automated vulnerability scanning is now standard practice, creating the security policies to protect application workloads in production has largely been a manual process. The use of Kubernetes custom resources to capture and declare an application security policy early in the pipeline now solves this problem.
In his recent post “A Security Vision for the New World of Changing Perimeters,” NeuVector CTO Gary Duan talks about how the security policy must be attached to workload no matter where it runs. In this way, applications that are accompanied by security manifests which define the allowed application behavior are protected regardless of what cloud they run in. This enables efficient, secure, and error free deployment of cloud-native applications.
In this post we’ll discuss how the NeuVector custom resource definition can be used by various teams to define security policies in the NeuVector container security platform. Developers, DevOps, DevSecOps, and Security teams can collaborate to automate security policies deployed to production. CRDs can also be used to enforce global security policies across multiple Kubernetes clusters.
NeuVector CRD Benefits
There are many direct as well as related benefits for declaring run-time security policies through CRDs. In addition to being able to automated security into the CI/CD and deployment pipeline, these include:
- Capture the entire application behavior, including network rules, protocols, processes, and file activities that are allowed – or ‘whitelisted’ – for the application.
- Only permit allowed network connections between services – enforced by application protocol (layer 7) inspection.
- Allow or prevent external or ingress connections as warranted.
- Set the “protection mode” of the application to either Monitor mode (alerting only) or Protect mode (blocking all suspicious activity).
- Support integration with Open Policy Agent (OPA) and other security policy management tools.
- Allow DevOps and security teams to define application policies at different hierarchies such as per-service rules defined by DevOps and global rules defined by centralized security teams.
- Is RBAC-enabled, enforcing the creation and updates of security policy as allowed natively by Kubernetes service accounts and roles.
- Enable versioning of security policies for each application revision.
- Is extensible, to support future expansion of security policy as code to admission control rules, DLP rules, response rules and other NeuVector enforcement policies.
NeuVector customer Sean McCormick has this to say about the value of security policy as code:
“Security continues to shift left, and our Platform teams are eager to manage security policy as code,” said Sean McCormick, VP of Engineering at Element. “Doing so enables us to automate security further upstream – simplifying and hardening policy enforcement. With its Security Policy as Code support, NeuVector gives us a more granular capacity to centrally manage our security policies without needing to configure them through a UI. This is a significant improvement for Element, allowing us to maintain policy consistency across all customer and development environments.”
The NeuVector Custom Resource Definition (CRD)
The NeuVector CRD will enable creation of NeuVector security rules with Kubernetes-native yaml files. These rules can capture and enforce allowed application behavior, such as:
- Network connections. These include any connections in or out of the container and can be Layer 7 rules based on application protocols or layer 3/4 based on IP address and/or port. These rules can enforce east-west application segmentation as well as ingress and egress rules.
- Container processes. Processes which are expected to be started by the application container are whitelisted so unauthorized processes can be detected.
- Container file activity. Allowed file and/or directories can be defined together with specific applications which are whitelisted to access or modify those file/directories.
In addition to the core run-time security rules above, other NeuVector security objects and states can be defined, such as:
- Groups. Logical groupings of containers or other objects can be created in NeuVector, and rules can be applied to these Groups. For example, a custom group can be defined as ‘namespace=demo’ or ‘address=google.com’ which would then allow these to be used as sources or targets in rules.
- Application (Container) Protection State. Each application (and all the containers/pods scaled up for it) be in a different protection state or either Discover, Monitor, or Protect. In Discover mode, NeuVector allows and learns all behavior. In Monitor, all activity no defined in the whitelist rules are logged and alerted, but allowed. In Protect mode, all unauthorized activity such as processes, file access and network connections are blocked.
We begin the process by creating the NeuVector CRD. In the sample below we create the CRD yaml which defines the ‘NVSecurityRule’ and ‘NVClusterSecurityRule.’ This defines both namespaced as well as cluster-wide operations as the scope.
apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: nvsecurityrules.neuvector.com spec: group: neuvector.com names: kind: NvSecurityRule listKind: NvSecurityRuleList plural: nvsecurityrules singular: nvsecurityrule scope: Namespaced version: v1 versions: - name: v1 served: true storage: true --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: nvclustersecurityrules.neuvector.com spec: group: neuvector.com names: kind: NvClusterSecurityRule listKind: NvClusterSecurityRuleList plural: nvclustersecurityrules singular: nvclustersecurityrule scope: Cluster version: v1 versions: - name: v1 served: true storage: true
$ kubectl create -f nvsecurityrule.yaml
After the CRD is created, any custom resource invoked using the kind as NvSecurityRule will be processed by the NeuVector custom resource definition. Custom resources can now be created to define security policies in NeuVector. Note that there are additional clusterroles and clusterolebindings that also need to be added, which can be found in the NeuVector docs.
It is important to note that the ability to deploy NeuVector security rules using CRDs is natively RBAC enabled in Kubernetes. This means that if a CRD declared security policies for workloads in namespace ‘demo,’ only serviceaccounts (users) with rights to deploy to that workspace will be allowed to deploy the CRD. The cluster wide CRD definition allows for deployment across namespaces for serviceaccounts with cluster admin rights. Unauthorized CRD deployments will be rejected.
In the example snippet below demo-security-v1.yaml, the nginx-pod containers in the demo namespace are allowed to connect to the node-pod containers also in the demo space, using only the protocol HTTP.
The yaml example above would go on to include all other network connections allowed for the demo namespace containers, including network connections using the redis protocol, as well as the allowed processes and file activity for each container. This should be deployed into NeuVector BEFORE the application workload is deployed, so that the security rules are already in place once the application workloads start to run. Deploying the security policy is simple, for example:
$ kubectl create -f demo-security-v1.yaml
When a custom resource such as the example above is created, NeuVector will interpret the security policies defined in the CRD (note: we are using the term CRD in place of custom resource) and execute the appropriate REST API calls to the NeuVector Controller to create the appropriate rules and make the required configurations in NeuVector.
Security Policy as Code Use Cases
1. Developers and DevOps Define the Application Security Policy
In order to ‘shift left’ security, developers can take the initial task of creating not only the application deployment manifest but the security manifest. The images are built and automated vulnerability scanning is completed and reviewed by DevOps. Once those steps are passed, DevOps can test both the deployment manifest and the security manifest and provide feedback to developers on the results.
The DevOps team can then deploy new apps together with the security policy for the apps into the production environment, ensuring that apps are secured as soon as they start running in production.
2. DevOps Uses NeuVector Behavioral Learning to Create CRD
To simplify the learning and creation of NeuVector formatted CRD yaml files, the DevOps teams can use NeuVector’s behavioral learning in a test environment to help create the security policy.
This workflow begins with the DevOps/QA team deploying the app, as in the bottom right of the diagram above. Once deployed, NeuVector will learn the entire application behavior and automatically create the network, process, and file access rules for them. These are easily exported in the NeuVector CRD yaml format for review with developers. The CRD can then be edited if needed, tested by DevOps, then deployed into production.
3. Security and Compliance Deploys Global Security Polices
Security policies are often required that are not specific to an application, or perhaps apply to a large superset of applications with similar characteristics. Security, compliance and operations teams will also have the need to define these policies across an entire cluster or even multiple clusters. These ‘global’ rules can also benefit from the NeuVector CRD.
These teams can use the NeuVector CRD to define global security policies which are not tied to application workloads, or apply to other logical groupings of workloads in a cluster. Examples of these security policies include:
- Global network ingress/egress rules.
- Forbidden processes across all containers.
- Allowed processes for monitoring or diagnostics across all cluster.
Global CRDs can be used in conjunction with application specific CRDs to ensure complete security protection in the target clusters.
4. Migrating Policies from Staging to Production Clusters
The NeuVector CRD can be used to migrate all security policies or a selected subset from a staging environment into production after testing is complete. This way, the production environment can always stay ‘locked down’ in a Monitor or Protect mode while new services are deployed or updated.
The NeuVector console provides configuration for a ‘New Services Mode’ which can be set to Discover, Monitor, or Protect. By setting this to Monitor or Protect, all new services must have the security rules in place before they are deployed and begin activity to avoid process, file and network security alerts from being generated when they activate.
Full Lifecycle Security Automation
When combined with NeuVector’s full lifecycle vulnerability scanning and ConfigMap-based deployment capabilities, the NeuVector CRD further enhances security automation during the entire CI/CD pipeline and into production environments. NeuVector leverages cloud-native capabilities in Kubernetes and the ecosystem such as configmaps, CRDs, admission controls, HELM charts, and Open Policy Agent to ensure that the entire toolchain from DevOps to Run-time can be deployed securely.