From c1165bc7c05a0ebc16f8107f428c6ae01bda54dc Mon Sep 17 00:00:00 2001 From: Philip Laine Date: Wed, 3 Feb 2021 08:50:24 +0100 Subject: [PATCH] Add falco to Kubernetes modules (#108) --- .github/workflows/check.yaml | 4 +- modules/kubernetes/README.md | 1 + modules/kubernetes/aks-core/README.md | 3 + modules/kubernetes/aks-core/modules.tf | 37 +++++++++++- modules/kubernetes/aks-core/variables.tf | 20 +++++++ modules/kubernetes/falco/README.md | 34 +++++++++++ modules/kubernetes/falco/main.tf | 59 +++++++++++++++++++ modules/kubernetes/falco/outputs.tf | 0 .../falco/templates/falco-values.yaml.tpl | 21 +++++++ .../templates/falcosidekick-values.yaml.tpl | 6 ++ modules/kubernetes/falco/variables.tf | 21 +++++++ validation/kubernetes/aks-core/main.tf | 4 ++ validation/kubernetes/falco/main.tf | 34 +++++++++++ 13 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 modules/kubernetes/falco/README.md create mode 100644 modules/kubernetes/falco/main.tf create mode 100644 modules/kubernetes/falco/outputs.tf create mode 100644 modules/kubernetes/falco/templates/falco-values.yaml.tpl create mode 100644 modules/kubernetes/falco/templates/falcosidekick-values.yaml.tpl create mode 100644 modules/kubernetes/falco/variables.tf create mode 100644 validation/kubernetes/falco/main.tf diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index e3b2fb8e8..6ee8423a0 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -9,11 +9,11 @@ jobs: - name: Setup TFLint uses: lablabs/setup-tflint@v1.0.2 with: - tflint_version: v0.20.3 + tflint_version: v0.23.1 - name: Install azurerm plugin run: | mkdir -p .tflint.d/plugins - wget https://github.com/terraform-linters/tflint-ruleset-azurerm/releases/download/v0.5.1/tflint-ruleset-azurerm_linux_amd64.zip + wget https://github.com/terraform-linters/tflint-ruleset-azurerm/releases/download/v0.7.0/tflint-ruleset-azurerm_linux_amd64.zip unzip tflint-ruleset-azurerm_linux_amd64.zip mv tflint-ruleset-azurerm .tflint.d/plugins/ - name: Run lint diff --git a/modules/kubernetes/README.md b/modules/kubernetes/README.md index 6f46c46aa..66d501d36 100644 --- a/modules/kubernetes/README.md +++ b/modules/kubernetes/README.md @@ -20,3 +20,4 @@ This directory contains all the Kubernetes Terraform modules. - [`datadog`](datadog/README.md) - [`external-secrtest`](external-secrets/README.md) - [`kyverno`](kyverno/README.md) +- [`falco`](falco/README.md) diff --git a/modules/kubernetes/aks-core/README.md b/modules/kubernetes/aks-core/README.md index 7d5c091b6..9a7c1d2ab 100644 --- a/modules/kubernetes/aks-core/README.md +++ b/modules/kubernetes/aks-core/README.md @@ -32,9 +32,12 @@ This module is used to create AKS clusters. | cert\_manager\_config | Cert Manager configuration |
object({
notification_email = string
dns_zone = string
})
| n/a | yes | | cert\_manager\_enabled | Should Cert Manager be enabled | `bool` | `true` | no | | csi\_secrets\_store\_provider\_azure\_enabled | Should csi-secrets-store-provider-azure be enabled | `bool` | `true` | no | +| datadog\_config | Datadog configuration |
object({
datadog_site = string
api_key = string
})
| n/a | yes | +| datadog\_enabled | Should Datadog be enabled | `bool` | `false` | no | | environment | The environment name to use for the deploy | `string` | n/a | yes | | external\_dns\_config | External DNS configuration |
object({
client_id = string
resource_id = string
})
| n/a | yes | | external\_dns\_enabled | Should External DNS be enabled | `bool` | `true` | no | +| falco\_enabled | Should Falco be enabled | `bool` | `false` | no | | fluxcd\_v1\_config | Configuration for fluxcd-v1 |
object({
flux_status_enabled = bool
azure_devops = object({
pat = string
org = string
proj = string
})
})
|
{
"azure_devops": {
"org": "",
"pat": "",
"proj": ""
},
"flux_status_enabled": false
}
| no | | fluxcd\_v1\_enabled | Should fluxcd-v1 be enabled | `bool` | `false` | no | | fluxcd\_v2\_config | Configuration for fluxcd-v2 |
object({
type = string
github = object({
owner = string
})
azure_devops = object({
pat = string
org = string
proj = string
})
})
| n/a | yes | diff --git a/modules/kubernetes/aks-core/modules.tf b/modules/kubernetes/aks-core/modules.tf index fa60f669d..55b14946a 100644 --- a/modules/kubernetes/aks-core/modules.tf +++ b/modules/kubernetes/aks-core/modules.tf @@ -1,5 +1,5 @@ locals { - excluded_namespaces = ["kube-system", "gatekeeper-system", "aad-pod-identity", "cert-manager", "ingress-nginx", "velero", "azdo-proxy", "flux-system", "external-dns", "kyverno", "csi-secrets-store-provider-azure"] + excluded_namespaces = ["kube-system", "gatekeeper-system", "aad-pod-identity", "cert-manager", "ingress-nginx", "velero", "azdo-proxy", "flux-system", "external-dns", "kyverno", "csi-secrets-store-provider-azure", "falco"] } # OPA Gatekeeper @@ -221,3 +221,38 @@ module "csi_secrets_store_provider_azure" { source = "../../kubernetes/csi-secrets-store-provider-azure" } + +# datadog +module "datadog" { + depends_on = [module.opa_gatekeeper] + + for_each = { + for s in ["datadog"] : + s => s + if var.datadog_enabled + } + + source = "../../kubernetes/datadog" + + location = var.location_short + environment = var.environment + datadog_site = var.datadog_config.datadog_site + api_key = var.datadog_config.api_key +} + +# falco +module "falco" { + depends_on = [module.opa_gatekeeper] + + for_each = { + for s in ["falco"] : + s => s + if var.falco_enabled + } + + source = "../../kubernetes/falco" + + environment = var.environment + datadog_site = var.datadog_config.datadog_site + datadog_api_key = var.datadog_config.api_key +} diff --git a/modules/kubernetes/aks-core/variables.tf b/modules/kubernetes/aks-core/variables.tf index 358a60c6f..95660b1eb 100644 --- a/modules/kubernetes/aks-core/variables.tf +++ b/modules/kubernetes/aks-core/variables.tf @@ -190,3 +190,23 @@ variable "csi_secrets_store_provider_azure_enabled" { type = bool default = true } + +variable "datadog_enabled" { + description = "Should Datadog be enabled" + type = bool + default = false +} + +variable "datadog_config" { + description = "Datadog configuration" + type = object({ + datadog_site = string + api_key = string + }) +} + +variable "falco_enabled" { + description = "Should Falco be enabled" + type = bool + default = false +} diff --git a/modules/kubernetes/falco/README.md b/modules/kubernetes/falco/README.md new file mode 100644 index 000000000..01810698e --- /dev/null +++ b/modules/kubernetes/falco/README.md @@ -0,0 +1,34 @@ +# Falco + +Adds [`Falco`](https://github.com/falcosecurity/falco) to a Kubernetes clusters. +The modules consists of two components, the main Falco driver and the sidekick which +exports events to Datadog. + +## Requirements + +| Name | Version | +|------|---------| +| terraform | 0.13.5 | +| helm | 1.3.2 | +| kubernetes | 1.13.3 | + +## Providers + +| Name | Version | +|------|---------| +| helm | 1.3.2 | +| kubernetes | 1.13.3 | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| datadog\_api\_key | Datadog api key used to authenticate | `string` | n/a | yes | +| datadog\_site | Datadog host to send events to | `string` | `"api.datadoghq.eu"` | no | +| environment | Variable to add to custom fields | `string` | n/a | yes | +| minimum\_priority | Minimum priority required before being exported | `string` | `"INFO"` | no | + +## Outputs + +No output. + diff --git a/modules/kubernetes/falco/main.tf b/modules/kubernetes/falco/main.tf new file mode 100644 index 000000000..b4136a1dc --- /dev/null +++ b/modules/kubernetes/falco/main.tf @@ -0,0 +1,59 @@ +/** + * # Falco + * + * Adds [`Falco`](https://github.com/falcosecurity/falco) to a Kubernetes clusters. + * The modules consists of two components, the main Falco driver and the sidekick which + * exports events to Datadog. + */ + +terraform { + required_version = "0.13.5" + + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "1.13.3" + } + helm = { + source = "hashicorp/helm" + version = "1.3.2" + } + } +} + +locals { + falco_values = templatefile("${path.module}/templates/falco-values.yaml.tpl", {}) + falcosidekick_values = templatefile("${path.module}/templates/falcosidekick-values.yaml.tpl", { + environment = var.environment + minimum_priority = var.minimum_priority + datadog_host = "https://${var.datadog_site}" + datadog_api_key = var.datadog_api_key + }) +} + +resource "kubernetes_namespace" "this" { + metadata { + labels = { + name = "falco" + } + name = "falco" + } +} + +resource "helm_release" "falco" { + repository = "https://falcosecurity.github.io/charts" + chart = "falco" + name = "falco" + namespace = kubernetes_namespace.this.metadata[0].name + version = "v1.7.2" + values = [local.falco_values] +} + +resource "helm_release" "falcosidekick" { + repository = "https://falcosecurity.github.io/charts" + chart = "falcosidekick" + name = "falcosidekick" + namespace = kubernetes_namespace.this.metadata[0].name + version = "v0.2.2" + values = [local.falcosidekick_values] +} diff --git a/modules/kubernetes/falco/outputs.tf b/modules/kubernetes/falco/outputs.tf new file mode 100644 index 000000000..e69de29bb diff --git a/modules/kubernetes/falco/templates/falco-values.yaml.tpl b/modules/kubernetes/falco/templates/falco-values.yaml.tpl new file mode 100644 index 000000000..7a7c5f441 --- /dev/null +++ b/modules/kubernetes/falco/templates/falco-values.yaml.tpl @@ -0,0 +1,21 @@ +auditLog: + enabled: false + +# Use EBPF instead of kernel module +ebpf: + enabled: true + +falco: + jsonOutput: true + jsonIncludeOutputProperty: true + httpOutput: + enabled: true + url: "http://falcosidekick:2801" + + # This should be further explored in the future but seems + # to be a bug right now with no fix so the solution is sadly + # to ignore all syscall errors. + # https://github.com/falcosecurity/falco/issues/1403 + syscallEventDrops: + actions: + - log diff --git a/modules/kubernetes/falco/templates/falcosidekick-values.yaml.tpl b/modules/kubernetes/falco/templates/falcosidekick-values.yaml.tpl new file mode 100644 index 000000000..993c02a30 --- /dev/null +++ b/modules/kubernetes/falco/templates/falcosidekick-values.yaml.tpl @@ -0,0 +1,6 @@ +config: + customfields: "source:falco,env:${environment}" + datadog: + host: "${datadog_host}" + apikey: "${datadog_api_key}" + minimumpriority: "${minimum_priority}" diff --git a/modules/kubernetes/falco/variables.tf b/modules/kubernetes/falco/variables.tf new file mode 100644 index 000000000..4b56eded7 --- /dev/null +++ b/modules/kubernetes/falco/variables.tf @@ -0,0 +1,21 @@ +variable "environment" { + description = "Variable to add to custom fields" + type = string +} + +variable "minimum_priority" { + description = "Minimum priority required before being exported" + type = string + default = "INFO" +} + +variable "datadog_site" { + description = "Datadog host to send events to" + type = string + default = "api.datadoghq.eu" +} + +variable "datadog_api_key" { + description = "Datadog api key used to authenticate" + type = string +} diff --git a/validation/kubernetes/aks-core/main.tf b/validation/kubernetes/aks-core/main.tf index b45008461..fe048e8b0 100644 --- a/validation/kubernetes/aks-core/main.tf +++ b/validation/kubernetes/aks-core/main.tf @@ -69,4 +69,8 @@ module "aks_core" { name = "name" } } + datadog_config = { + datadog_site = "" + api_key = "" + } } diff --git a/validation/kubernetes/falco/main.tf b/validation/kubernetes/falco/main.tf new file mode 100644 index 000000000..eae7294c1 --- /dev/null +++ b/validation/kubernetes/falco/main.tf @@ -0,0 +1,34 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "1.13.3" + } + helm = { + source = "hashicorp/helm" + version = "1.3.2" + } + } +} + +provider "kubernetes" { + load_config_file = "false" +} + +provider "helm" { + kubernetes { + load_config_file = "false" + } +} + +module "falco" { + source = "../../../modules/kubernetes/falco" + + providers = { + kubernetes = kubernetes + helm = helm + } + + environment = "dev" + datadog_api_key = "foobar" #tfsec:ignore:GEN003 +}