In the following tutorial you can learn how to implement container security as code. You probably have a CI/CD pipeline to automatically rebuild your container images. What if you could define your container security as code, push it into a Git repository to version control changes and then enforce your policy in your container orchestration tool like Docker or Kubernetes using Sysdig Secure? Terraform is an awesome tool to deploy and update your infrastructure using code. You might be using it already to automate your clusters deployment in cloud providers like AWS, Google Cloud, Azure or IBM. The good news is that now you can configure your container security as code with Terraform and Sysdig Secure.
Installing the Sysdig Secure Terraform provider
Installing the Sysdig Secure Terraform provider is really easy. Some pre-requirements that you need to have installed in your system are Terraform (>see here how) and Go (>1.9) to compile the provider code (the easiest is to install Go runtime using a package manager likeapt
or yum
).
Then:
- Go to our the Sysdig Secure Terraform provider repository and clone the code with
git clone https://github.com/draios/terraform-provider-sysdig.git
. - From the repository directory run
go build
. - Once built you will find a binary
terraform-provider-sysdig
, move it under$HOME/.terraform.d/plugins
(you might have to create that directory).
.tf
) or JSON (.tf.json
). If you are completely new to Terraform snyax might be a good idea to have a look at the syntax documentation.
How to implement #container #security as code with #Terraform and @sysdig Secure
Click to tweet
Quickstart your container security as code with Sysdig Secure Terraform provider
Let’s start getting our hands dirty and creating a basic Terraform configuration file for our container security policy configuration. First of all, you need to tell Terraform that we are going to use the Sysdig Secure provider and that all the following configuration will be handled by this module with:provider "sysdig" { }
Now Terraform will use the provider to handle all the resource definitions in the file. You need the Sysdig Secure API token so Terraform can execute all the required actions against the Sysdig Secure backend:
provider "sysdig" {
sysdig_secure_api_token = "<your_token>"
}
If you don’t want to save it in the file, Terraform will ask you to input it when executed interactively.
Now we are going to create some resources. The provider currently supports creating and updating:
- Security policies using the Falco language
- Notification channels for alerts and events forwarding into your SIEM or logging system
- Container security as code (as available on the UI)
Creating advanced container security policies using Falco rules
Falco is a behavioral activity monitoring tool built for containers, microservices and Cloud Native applications. It’s an open source project started by Sysdig but now hosted under the umbrella of the CNCF foundation. The commercial product Sysdig Secure is built on the foundations of Falco and you can leverage Falco filtering rules to create advanced Sysdig Secure policies. In Falco you can group your rules in different files. Actually we created default security profiles or rulesets for different services/applications like Nginx, HAproxy, Traefik, MongoDB, PostgreSQL, Redis, Elasticsearch, etcd or the different Kubernetes components like api-server or kubelet. You can find them in the Falco extras repository. In order to include the rules within these files you just need to instance a resource that includes the content of each file:resource "sysdig_secure_user_rules_file" "rules-traefik" {
content = "${file("${path.module}/rules-traefik.yaml")}"
}
You can instance rules from multiple files as long as you use a different resource name. Note that the path of the YAML file is relative to the same folder as your Terraform definition files.
Sending container security alerts to a SIEM or forwarding events to a logging system
Typically you want to aggregate security events from different sources in your SIEM or log them for auditing and compliance purposes. This is accomplished through notification channels in Sysdig Secure. To define a new notification channel we will create a new resource with the desired name and options. Options actually match the ones available within the Secure configuration GUI.resource "sysdig_secure_notification_channel" "sample-email" {
name = "Example Channel - Email"
enabled = true
type = "EMAIL"
recipients = "[email protected]"
notify_when_ok = false
notify_when_resolved = false
}
If you need to define notification channels that require OAuth authentication like Slack or PagerDuty, have a look at this little tool we built to automatically generate the resource definition from an existing channel created through the UI and configured using your browser.
Container security as code
Sysdig Secure allows you to create simple but very effective security policies using the UI. These define a behavior pattern and if the conditions are met, a security event is triggered. To respond to these events Sysdig can take multiple actions like isolating or killing the container, but also create a Sysdig capture with all the system activity for performing forensics and post-mortem analysis. Again, the options here match what’s available on Sysdig Secure UI, including name, description, severity, scope and then whitelists and blacklists for processes, container images, network activity, files activity or just system calls. We can also reference any rule created with Falco language. Here you can see a container security policy definition example including all possible options:resource "sysdig_secure_policy" "sample2" {
name = "Other example of Policy"
description = "this is other example of policy"
severity = 4
enabled = true
container_scope = true
host_scope = true
processes = {
default = "accept"
whitelist = ["mysql", "apache"]
blacklist = ["ssh"]
}
containers = {
default = "none"
whitelist = ["cassandra"]
blacklist = ["mongo"]
}
network = {
inbound = "accept"
outbound = "deny"
listening_ports {
default = "none"
tcp {
whitelist = [80, 443]
blacklist = [8080, 5000]
}
udp {
whitelist = [53, 4000]
blacklist = [3400, 543]
}
}
}
filesystem = {
read = {
whitelist = ["/home"]
blacklist = ["/etc"]
}
readwrite = {
whitelist = ["/home"]
blacklist = ["/tmp"]
}
other_paths = "none"
}
syscalls = {
default = "accept"
whitelist = ["accept", "close"]
blacklist = ["bind", "bpf"]
}
notification_channels = ["${sysdig_secure_notification_channel.sample-victorops.id}"]
falco_rule_name_regex = "Unexpected spawned process Traefik"
}
As you create your container security as code, multiple rules will have to be evaluated in a given priority order. This is just another resource that defines an ordered list rules referenced by their resource IDs:
resource "sysdig_secure_policies_priority" "priority" {
policies = [
"${sysdig_secure_policy.sample2.id}",
"${sysdig_secure_policy.sample.id}"]
}
A real example of a container security as code
Creating a security policy that alerts if someone executes an interactive shell inside any container in your production environment is definitely a good idea. This could be either an external attacker running a reverse shell in your container or someone within your organization that decided to play within the production environment, not a good practice in any case. In response to this security event we will fire an alert and we will trigger a system call capture to analyze what happened after spawning the shell. We are going to create a bunch of files here, we will place all within the same directory:demo_provider.tf
that indicates we are using the Sysdig Secure Terraform provider:
provider "sysdig" {
}
demo_notification_channels.tf
that includes the definition of our notification channels:
resource "sysdig_secure_notification_channel" "elastic-search" {
name = "ElasticSearch"
enabled = false
type = "WEBHOOK"
url = "http://ec2-44-444-44-444.compute-1.amazonaws.com:9200/sysdigsecure/event"
notify_when_ok = true
notify_when_resolved = true
}
demo_policies_priority.tf
that defines the evaluation order of our policy rules, just one this time:
resource "sysdig_secure_policies_priority" "priority" {
policies = [
"${sysdig_secure_policy.terminal-shell-in-container.id}"]
}
demo_policies.tf
contains the policy rules definition:
resource "sysdig_secure_policy" "terminal-shell-in-container" {
name = "Terminal shell in container"
description = "A shell was spawned by a program in a container with an attached terminal."
severity = 1
enabled = true
filter = "not kubernetes.namespace.name in ('ping', 'default')"
container_scope = true
host_scope = false
actions {
capture {
seconds_before_event = 10
seconds_after_event = 20
}
}
notification_channels = ["${sysdig_secure_notification_channel.webhook.id}", "${sysdig_secure_notification_channel.elastic-search.id}"]
falco_rule_name_regex = "Terminal shell in container"
}
If we had to upload our own Falco language rules, we would have a demo_user_rules.tf
file with:
resource "sysdig_secure_user_rules_file" "rules" {
content = "${file("${path.module}/rules.yaml")}"
}
Now, in order to apply the changes, from within this directory we just need to run terraform apply
and we are done! You can store all these files in Git and then let Jenkins or your favorite CI server to do the apply for you.