diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index a533f1fbbf0..df9242fe031 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -189,6 +189,7 @@ https://github.com/elastic/beats/compare/v6.2.3...master[Check the HEAD diff] Linux kernel not supporting auditing (CONFIG_AUDIT=n). {pull}7012[7012] - Added XXH64 hash option for file integrity checks. {pull}7311[7311] - Added the `show auditd-rules` and `show auditd-status` commands to show kernel rules and status. {pull}7114[7114] +- Add kubernetes specs for auditbeat file integrity monitoring {pull}7642[7642] *Filebeat* diff --git a/deploy/kubernetes/Makefile b/deploy/kubernetes/Makefile index 10732ea4575..722cac158d1 100644 --- a/deploy/kubernetes/Makefile +++ b/deploy/kubernetes/Makefile @@ -1,4 +1,4 @@ -ALL=filebeat metricbeat +ALL=filebeat metricbeat auditbeat BEAT_VERSION=$(shell head -n 1 ../../libbeat/docs/version.asciidoc | cut -c 17- ) .PHONY: all $(ALL) diff --git a/deploy/kubernetes/auditbeat-kubernetes.yaml b/deploy/kubernetes/auditbeat-kubernetes.yaml new file mode 100644 index 00000000000..90a7ae4a675 --- /dev/null +++ b/deploy/kubernetes/auditbeat-kubernetes.yaml @@ -0,0 +1,185 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: auditbeat-config + namespace: kube-system + labels: + k8s-app: auditbeat +data: + auditbeat.yml: |- + auditbeat.config.modules: + # Mounted `auditbeat-daemonset-modules` configmap: + path: ${path.config}/modules.d/*.yml + # Reload module configs as they change: + reload.enabled: false + + processors: + - add_cloud_metadata: + + cloud.id: ${ELASTIC_CLOUD_ID} + cloud.auth: ${ELASTIC_CLOUD_AUTH} + + output.elasticsearch: + hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}'] + username: ${ELASTICSEARCH_USERNAME} + password: ${ELASTICSEARCH_PASSWORD} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: auditbeat-daemonset-modules + namespace: kube-system + labels: + k8s-app: auditbeat +data: + system.yml: |- + - module: file_integrity + paths: + - /hostfs/bin + - /hostfs/usr/bin + - /hostfs/sbin + - /hostfs/usr/sbin + - /hostfs/etc + exclude_files: + - '(?i)\.sw[nop]$' + - '~$' + - '/\.git($|/)' + scan_at_start: true + scan_rate_per_sec: 50 MiB + max_file_size: 100 MiB + hash_types: [sha1] + recursive: true +--- +# Deploy a auditbeat instance per node for node metrics retrieval +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: auditbeat + namespace: kube-system + labels: + k8s-app: auditbeat +spec: + template: + metadata: + labels: + k8s-app: auditbeat + spec: + serviceAccountName: auditbeat + terminationGracePeriodSeconds: 30 + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + containers: + - name: auditbeat + image: docker.elastic.co/beats/auditbeat:7.0.0-alpha1 + args: [ + "-c", "/etc/auditbeat.yml" + ] + env: + - name: ELASTICSEARCH_HOST + value: elasticsearch + - name: ELASTICSEARCH_PORT + value: "9200" + - name: ELASTICSEARCH_USERNAME + value: elastic + - name: ELASTICSEARCH_PASSWORD + value: changeme + - name: ELASTIC_CLOUD_ID + value: + - name: ELASTIC_CLOUD_AUTH + value: + securityContext: + runAsUser: 0 + resources: + limits: + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + volumeMounts: + - name: config + mountPath: /etc/auditbeat.yml + readOnly: true + subPath: auditbeat.yml + - name: modules + mountPath: /usr/share/auditbeat/modules.d + readOnly: true + - name: bin + mountPath: /hostfs/bin + readOnly: true + - name: sbin + mountPath: /hostfs/sbin + readOnly: true + - name: usrbin + mountPath: /hostfs/usr/bin + readOnly: true + - name: usrsbin + mountPath: /hostfs/usr/sbin + readOnly: true + - name: etc + mountPath: /hostfs/etc + readOnly: true + volumes: + - name: bin + hostPath: + path: /bin + - name: usrbin + hostPath: + path: /usr/bin + - name: sbin + hostPath: + path: /sbin + - name: usrsbin + hostPath: + path: /usr/sbin + - name: etc + hostPath: + path: /etc + - name: config + configMap: + defaultMode: 0600 + name: auditbeat-config + - name: modules + configMap: + defaultMode: 0600 + name: auditbeat-daemonset-modules + - name: data + hostPath: + path: /var/lib/auditbeat-data + type: DirectoryOrCreate +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: auditbeat +subjects: +- kind: ServiceAccount + name: auditbeat + namespace: kube-system +roleRef: + kind: ClusterRole + name: auditbeat + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: auditbeat + labels: + k8s-app: auditbeat +rules: +- apiGroups: [""] + resources: + - nodes + - namespaces + - pods + verbs: ["get", "list", "watch"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: auditbeat + namespace: kube-system + labels: + k8s-app: auditbeat +--- diff --git a/deploy/kubernetes/auditbeat/README.md b/deploy/kubernetes/auditbeat/README.md new file mode 100644 index 00000000000..a0bc0316f49 --- /dev/null +++ b/deploy/kubernetes/auditbeat/README.md @@ -0,0 +1,31 @@ +# Auditbeat + +## Ship audit information from Kubernetes to Elasticsearch + +### Kubernetes DaemonSet + +By deploying auditbeat as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) +we ensure we get a running auditbeat daemon on each node of the cluster. + +Everything is deployed under `kube-system` namespace, you can change that by +updating YAML manifests under this folder. + +### Settings + +We use official [Beats Docker images](https://github.com/elastic/beats-docker), +as they allow external files configuration, a [ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) +is used for kubernetes specific settings. Check [auditbeat-configmap.yaml](auditbeat-configmap.yaml) +for details. + +Also, [auditbeat-daemonset.yaml](auditbeat-daemonset.yaml) uses a set of environment +variables to configure Elasticsearch output: + +Variable | Default | Description +-------- | ------- | ----------- +ELASTICSEARCH_HOST | elasticsearch | Elasticsearch host +ELASTICSEARCH_PORT | 9200 | Elasticsearch port +ELASTICSEARCH_USERNAME | elastic | Elasticsearch username for HTTP auth +ELASTICSEARCH_PASSWORD | changeme | Elasticsearch password + +If there is an existing `elasticsearch` service in the kubernetes cluster these +defaults will use it. diff --git a/deploy/kubernetes/auditbeat/auditbeat-daemonset-configmap.yaml b/deploy/kubernetes/auditbeat/auditbeat-daemonset-configmap.yaml new file mode 100644 index 00000000000..d5589df00bf --- /dev/null +++ b/deploy/kubernetes/auditbeat/auditbeat-daemonset-configmap.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: auditbeat-config + namespace: kube-system + labels: + k8s-app: auditbeat +data: + auditbeat.yml: |- + auditbeat.config.modules: + # Mounted `auditbeat-daemonset-modules` configmap: + path: ${path.config}/modules.d/*.yml + # Reload module configs as they change: + reload.enabled: false + + processors: + - add_cloud_metadata: + + cloud.id: ${ELASTIC_CLOUD_ID} + cloud.auth: ${ELASTIC_CLOUD_AUTH} + + output.elasticsearch: + hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}'] + username: ${ELASTICSEARCH_USERNAME} + password: ${ELASTICSEARCH_PASSWORD} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: auditbeat-daemonset-modules + namespace: kube-system + labels: + k8s-app: auditbeat +data: + system.yml: |- + - module: file_integrity + paths: + - /hostfs/bin + - /hostfs/usr/bin + - /hostfs/sbin + - /hostfs/usr/sbin + - /hostfs/etc + exclude_files: + - '(?i)\.sw[nop]$' + - '~$' + - '/\.git($|/)' + scan_at_start: true + scan_rate_per_sec: 50 MiB + max_file_size: 100 MiB + hash_types: [sha1] + recursive: true diff --git a/deploy/kubernetes/auditbeat/auditbeat-daemonset.yaml b/deploy/kubernetes/auditbeat/auditbeat-daemonset.yaml new file mode 100644 index 00000000000..2a3f19aac69 --- /dev/null +++ b/deploy/kubernetes/auditbeat/auditbeat-daemonset.yaml @@ -0,0 +1,96 @@ +# Deploy a auditbeat instance per node for node metrics retrieval +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: auditbeat + namespace: kube-system + labels: + k8s-app: auditbeat +spec: + template: + metadata: + labels: + k8s-app: auditbeat + spec: + serviceAccountName: auditbeat + terminationGracePeriodSeconds: 30 + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + containers: + - name: auditbeat + image: docker.elastic.co/beats/auditbeat:%VERSION% + args: [ + "-c", "/etc/auditbeat.yml" + ] + env: + - name: ELASTICSEARCH_HOST + value: elasticsearch + - name: ELASTICSEARCH_PORT + value: "9200" + - name: ELASTICSEARCH_USERNAME + value: elastic + - name: ELASTICSEARCH_PASSWORD + value: changeme + - name: ELASTIC_CLOUD_ID + value: + - name: ELASTIC_CLOUD_AUTH + value: + securityContext: + runAsUser: 0 + resources: + limits: + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + volumeMounts: + - name: config + mountPath: /etc/auditbeat.yml + readOnly: true + subPath: auditbeat.yml + - name: modules + mountPath: /usr/share/auditbeat/modules.d + readOnly: true + - name: bin + mountPath: /hostfs/bin + readOnly: true + - name: sbin + mountPath: /hostfs/sbin + readOnly: true + - name: usrbin + mountPath: /hostfs/usr/bin + readOnly: true + - name: usrsbin + mountPath: /hostfs/usr/sbin + readOnly: true + - name: etc + mountPath: /hostfs/etc + readOnly: true + volumes: + - name: bin + hostPath: + path: /bin + - name: usrbin + hostPath: + path: /usr/bin + - name: sbin + hostPath: + path: /sbin + - name: usrsbin + hostPath: + path: /usr/sbin + - name: etc + hostPath: + path: /etc + - name: config + configMap: + defaultMode: 0600 + name: auditbeat-config + - name: modules + configMap: + defaultMode: 0600 + name: auditbeat-daemonset-modules + - name: data + hostPath: + path: /var/lib/auditbeat-data + type: DirectoryOrCreate diff --git a/deploy/kubernetes/auditbeat/auditbeat-role-binding.yaml b/deploy/kubernetes/auditbeat/auditbeat-role-binding.yaml new file mode 100644 index 00000000000..dec98a5f1e5 --- /dev/null +++ b/deploy/kubernetes/auditbeat/auditbeat-role-binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: auditbeat +subjects: +- kind: ServiceAccount + name: auditbeat + namespace: kube-system +roleRef: + kind: ClusterRole + name: auditbeat + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/kubernetes/auditbeat/auditbeat-role.yaml b/deploy/kubernetes/auditbeat/auditbeat-role.yaml new file mode 100644 index 00000000000..ae6d32f4149 --- /dev/null +++ b/deploy/kubernetes/auditbeat/auditbeat-role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: auditbeat + labels: + k8s-app: auditbeat +rules: +- apiGroups: [""] + resources: + - nodes + - namespaces + - pods + verbs: ["get", "list", "watch"] diff --git a/deploy/kubernetes/auditbeat/auditbeat-service-account.yaml b/deploy/kubernetes/auditbeat/auditbeat-service-account.yaml new file mode 100644 index 00000000000..641f4ddd1eb --- /dev/null +++ b/deploy/kubernetes/auditbeat/auditbeat-service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: auditbeat + namespace: kube-system + labels: + k8s-app: auditbeat