From 6266e5a4875f5718c2041edc11f384390e72167b Mon Sep 17 00:00:00 2001 From: mreiger Date: Fri, 25 Jun 2021 17:52:21 +0200 Subject: [PATCH 01/10] Initial work on adding splunk output --- fluent-bit.conf | 15 +++++++++++++ kind/konnectivity-agent.yaml | 2 +- .../kube-apiserver_konnectivity_patch.yaml | 2 +- main.go | 22 +++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/fluent-bit.conf b/fluent-bit.conf index 73f3140..98a88be 100644 --- a/fluent-bit.conf +++ b/fluent-bit.conf @@ -25,3 +25,18 @@ tls.crt_file ${TLS_CRT_FILE} tls.key_file ${TLS_KEY_FILE} tls.vhost ${TLS_VHOST} + +[OUTPUT] + Name splunk + Match * + Host ${SPLUNK_HOST} + Port ${SPLUNK_PORT} + Splunk_Token ${SPLUNK_HEC_TOKEN} + TLS On + TLS.Verify On + TLS.CA_FILE ${SPLUNK_CA_FILE} + Retry_Limit False + +# Unused so far: +# SPLUNK_INDEX +# CLUSTER_NAME diff --git a/kind/konnectivity-agent.yaml b/kind/konnectivity-agent.yaml index 795d49b..b11def9 100644 --- a/kind/konnectivity-agent.yaml +++ b/kind/konnectivity-agent.yaml @@ -34,7 +34,7 @@ spec: - --service-account-token-path=/var/run/secrets/tokens/konnectivity-agent-token command: - /proxy-agent - image: k8s.gcr.io/kas-network-proxy/proxy-agent:v0.0.12 + image: k8s.gcr.io/kas-network-proxy/proxy-agent:v0.0.15 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 diff --git a/kind/kustomize-konnectivity/kube-apiserver_konnectivity_patch.yaml b/kind/kustomize-konnectivity/kube-apiserver_konnectivity_patch.yaml index 8aca722..6145bad 100644 --- a/kind/kustomize-konnectivity/kube-apiserver_konnectivity_patch.yaml +++ b/kind/kustomize-konnectivity/kube-apiserver_konnectivity_patch.yaml @@ -20,7 +20,7 @@ - --delete-existing-uds-file=true command: - /proxy-server - image: k8s.gcr.io/kas-network-proxy/proxy-server:v0.0.12 + image: k8s.gcr.io/kas-network-proxy/proxy-server:v0.0.15 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 diff --git a/main.go b/main.go index 0a28683..8497841 100644 --- a/main.go +++ b/main.go @@ -90,6 +90,12 @@ type Opts struct { LogLevel string FluentLogLevel string KonnectivityUDSSocket string + SplunkHost string + SplunkPort string + SplunkCaFile string + SplunkHECToken string + SplunkIndex string + ClusterName string } var cmd = &cobra.Command{ @@ -134,6 +140,12 @@ func init() { cmd.Flags().StringP("log-level", "L", "info", "sets the application log level") cmd.Flags().StringP("fluent-log-level", "O", "info", "sets the log level for the fluent-bit command") cmd.Flags().StringP("konnectivity-uds-socket", "u", "", "If set, try and connect through this konnectivity UDS socket. Expected method is http-connect.") + cmd.Flags().String("splunk-host", "", "Splunk HEC endpoint to which the audit data should also be sent, in addition to the cluster audittailer") + cmd.Flags().String("splunk-port", "8080", "Port on which to contact the splunk HEC endpoint") + cmd.Flags().String("splunk-ca-file", "/etc/splunk/splunk_ca.crt", "The absolute path to the CA file for checking the splunk HEC endpoint certificate") + cmd.Flags().String("splunk-hec-token", "", "The token to pass to the splunk HEC endpoint") + cmd.Flags().String("splunk-index", "", "The index that should receive the log data in splunk") + cmd.Flags().String("cluster-name", "", "The cluster name to pass on to the splunk HEC endpoint") err = viper.BindPFlags(cmd.Flags()) if err != nil { @@ -158,6 +170,12 @@ func initOpts() (*Opts, error) { LogLevel: viper.GetString("log-level"), FluentLogLevel: viper.GetString("fluent-log-level"), KonnectivityUDSSocket: viper.GetString("konnectivity-uds-socket"), + SplunkHost: viper.GetString("splunk-host"), + SplunkPort: viper.GetString("splunk-port"), + SplunkCaFile: viper.GetString("splunk-ca-file"), + SplunkHECToken: viper.GetString("splunk-hec-token"), + SplunkIndex: viper.GetString("splunk-index"), + ClusterName: viper.GetString("cluster-name"), } validate := validator.New() @@ -440,6 +458,10 @@ func runForwarder(fluentTargetIP, servicePort string, opts *Opts) { "TLS_KEY_FILE="+path.Join(opts.TLSBaseDir, opts.TLSKeyFile), "TLS_VHOST="+opts.TLSVhost, "LOG_LEVEL="+fluentLogLevel.String(), + "SPLUNK_HOST="+opts.SplunkHost, + "SPLUNK_PORT="+opts.SplunkPort, + "SPLUNK_HEC_TOKEN="+opts.SplunkHECToken, + "SPLUNK_CA_FILE="+opts.SplunkCaFile, ) logger.Debugw("Executing:", "Command", strings.Join(cmd.Args, " "), ", Environment:", strings.Join(cmd.Env, ", ")) From efe73e110fed41b66299a8704e0d339714102e8e Mon Sep 17 00:00:00 2001 From: mreiger Date: Fri, 25 Jun 2021 19:01:03 +0200 Subject: [PATCH 02/10] Just include additional config files for extra outputs instead of passing static options through the controller --- fluent-bit.conf | 18 +++------------ .../kube-apiserver_patch.yaml | 2 +- main.go | 22 ------------------- 3 files changed, 4 insertions(+), 38 deletions(-) diff --git a/fluent-bit.conf b/fluent-bit.conf index 98a88be..90386e7 100644 --- a/fluent-bit.conf +++ b/fluent-bit.conf @@ -6,6 +6,7 @@ Name tail Path ${AUDIT_LOG_PATH} DB /audit.db + Tag audit Parser audit Read_from_Head On Buffer_Chunk_Size 2MB @@ -14,7 +15,7 @@ [OUTPUT] Name forward - Match * + Match audit Host ${AUDIT_TAILER_HOST} Port ${AUDIT_TAILER_PORT} Require_ack_response True @@ -26,17 +27,4 @@ tls.key_file ${TLS_KEY_FILE} tls.vhost ${TLS_VHOST} -[OUTPUT] - Name splunk - Match * - Host ${SPLUNK_HOST} - Port ${SPLUNK_PORT} - Splunk_Token ${SPLUNK_HEC_TOKEN} - TLS On - TLS.Verify On - TLS.CA_FILE ${SPLUNK_CA_FILE} - Retry_Limit False - -# Unused so far: -# SPLUNK_INDEX -# CLUSTER_NAME +@INCLUDE /fluent-bit/add/*.conf diff --git a/kind/kustomize-auditforwarder/kube-apiserver_patch.yaml b/kind/kustomize-auditforwarder/kube-apiserver_patch.yaml index f564f1a..634023f 100644 --- a/kind/kustomize-auditforwarder/kube-apiserver_patch.yaml +++ b/kind/kustomize-auditforwarder/kube-apiserver_patch.yaml @@ -1,7 +1,7 @@ - op: add path: /spec/containers/1 value: - image: ghcr.io/metal-stack/audit-forwarder:pr-rework-proxy + image: ghcr.io/metal-stack/audit-forwarder:pr-add-splunk imagePullPolicy: Always name: audit-forwarder env: diff --git a/main.go b/main.go index 8497841..0a28683 100644 --- a/main.go +++ b/main.go @@ -90,12 +90,6 @@ type Opts struct { LogLevel string FluentLogLevel string KonnectivityUDSSocket string - SplunkHost string - SplunkPort string - SplunkCaFile string - SplunkHECToken string - SplunkIndex string - ClusterName string } var cmd = &cobra.Command{ @@ -140,12 +134,6 @@ func init() { cmd.Flags().StringP("log-level", "L", "info", "sets the application log level") cmd.Flags().StringP("fluent-log-level", "O", "info", "sets the log level for the fluent-bit command") cmd.Flags().StringP("konnectivity-uds-socket", "u", "", "If set, try and connect through this konnectivity UDS socket. Expected method is http-connect.") - cmd.Flags().String("splunk-host", "", "Splunk HEC endpoint to which the audit data should also be sent, in addition to the cluster audittailer") - cmd.Flags().String("splunk-port", "8080", "Port on which to contact the splunk HEC endpoint") - cmd.Flags().String("splunk-ca-file", "/etc/splunk/splunk_ca.crt", "The absolute path to the CA file for checking the splunk HEC endpoint certificate") - cmd.Flags().String("splunk-hec-token", "", "The token to pass to the splunk HEC endpoint") - cmd.Flags().String("splunk-index", "", "The index that should receive the log data in splunk") - cmd.Flags().String("cluster-name", "", "The cluster name to pass on to the splunk HEC endpoint") err = viper.BindPFlags(cmd.Flags()) if err != nil { @@ -170,12 +158,6 @@ func initOpts() (*Opts, error) { LogLevel: viper.GetString("log-level"), FluentLogLevel: viper.GetString("fluent-log-level"), KonnectivityUDSSocket: viper.GetString("konnectivity-uds-socket"), - SplunkHost: viper.GetString("splunk-host"), - SplunkPort: viper.GetString("splunk-port"), - SplunkCaFile: viper.GetString("splunk-ca-file"), - SplunkHECToken: viper.GetString("splunk-hec-token"), - SplunkIndex: viper.GetString("splunk-index"), - ClusterName: viper.GetString("cluster-name"), } validate := validator.New() @@ -458,10 +440,6 @@ func runForwarder(fluentTargetIP, servicePort string, opts *Opts) { "TLS_KEY_FILE="+path.Join(opts.TLSBaseDir, opts.TLSKeyFile), "TLS_VHOST="+opts.TLSVhost, "LOG_LEVEL="+fluentLogLevel.String(), - "SPLUNK_HOST="+opts.SplunkHost, - "SPLUNK_PORT="+opts.SplunkPort, - "SPLUNK_HEC_TOKEN="+opts.SplunkHECToken, - "SPLUNK_CA_FILE="+opts.SplunkCaFile, ) logger.Debugw("Executing:", "Command", strings.Join(cmd.Args, " "), ", Environment:", strings.Join(cmd.Env, ", ")) From af1a890cc77ad23ebc080d4d568cade9b3804c3c Mon Sep 17 00:00:00 2001 From: mreiger Date: Fri, 25 Jun 2021 19:34:38 +0200 Subject: [PATCH 03/10] Try and work aroud a bug in fluent-bit that absolute paths for include files can not have wildcards --- fluent-bit.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fluent-bit.conf b/fluent-bit.conf index 90386e7..b53dce6 100644 --- a/fluent-bit.conf +++ b/fluent-bit.conf @@ -27,4 +27,4 @@ tls.key_file ${TLS_KEY_FILE} tls.vhost ${TLS_VHOST} -@INCLUDE /fluent-bit/add/*.conf +@INCLUDE add/*.conf From fe9f9d400ffe35bbde72eb8125cff0fe8aea0681 Mon Sep 17 00:00:00 2001 From: mreiger Date: Fri, 25 Jun 2021 19:58:38 +0200 Subject: [PATCH 04/10] Make include directive not fail --- Dockerfile | 4 +++- fluent-bit.conf | 2 +- null.conf | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 null.conf diff --git a/Dockerfile b/Dockerfile index dffff98..baa2e35 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,8 @@ RUN make bin/audit-forwarder FROM fluent/fluent-bit:1.7.3-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ -COPY *.conf /fluent-bit/etc/ +COPY fluent-bit.conf /fluent-bit/etc/ +COPY parsers.conf /fluent-bit/etc/ +COPY null.conf /fluent-bit/add/ CMD ["/fluent-bit/bin/audit-forwarder"] \ No newline at end of file diff --git a/fluent-bit.conf b/fluent-bit.conf index b53dce6..90386e7 100644 --- a/fluent-bit.conf +++ b/fluent-bit.conf @@ -27,4 +27,4 @@ tls.key_file ${TLS_KEY_FILE} tls.vhost ${TLS_VHOST} -@INCLUDE add/*.conf +@INCLUDE /fluent-bit/add/*.conf diff --git a/null.conf b/null.conf new file mode 100644 index 0000000..5271636 --- /dev/null +++ b/null.conf @@ -0,0 +1 @@ +# An empty fluent-bit config file so that the @INCLUDE directive in fluent-bit.conf does not fail. \ No newline at end of file From c64bc187d15d13e891c492d6c15dda44ccae20e1 Mon Sep 17 00:00:00 2001 From: mreiger Date: Fri, 25 Jun 2021 20:05:11 +0200 Subject: [PATCH 05/10] One more try to fix include --- Dockerfile | 2 +- fluent-bit.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index baa2e35..2644678 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,6 @@ FROM fluent/fluent-bit:1.7.3-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ COPY fluent-bit.conf /fluent-bit/etc/ COPY parsers.conf /fluent-bit/etc/ -COPY null.conf /fluent-bit/add/ +COPY null.conf /fluent-bit/etc/add/ CMD ["/fluent-bit/bin/audit-forwarder"] \ No newline at end of file diff --git a/fluent-bit.conf b/fluent-bit.conf index 90386e7..b53dce6 100644 --- a/fluent-bit.conf +++ b/fluent-bit.conf @@ -27,4 +27,4 @@ tls.key_file ${TLS_KEY_FILE} tls.vhost ${TLS_VHOST} -@INCLUDE /fluent-bit/add/*.conf +@INCLUDE add/*.conf From df23e1d2b356389b2df8617ab901228988cc777b Mon Sep 17 00:00:00 2001 From: mreiger Date: Thu, 1 Jul 2021 19:00:04 +0200 Subject: [PATCH 06/10] Update fluent-bit version --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2644678..c154111 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ COPY .git Makefile go.* *.go /work/ COPY pkg/ /work/pkg/ RUN make bin/audit-forwarder -FROM fluent/fluent-bit:1.7.3-debug +FROM fluent/fluent-bit:1.7.9-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ COPY fluent-bit.conf /fluent-bit/etc/ From 68734566aa4f366752e60f1c536d098e6b93d110 Mon Sep 17 00:00:00 2001 From: mreiger Date: Thu, 1 Jul 2021 19:14:58 +0200 Subject: [PATCH 07/10] Revert fluentd version to troubleshoot sending to splunk --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c154111..2644678 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ COPY .git Makefile go.* *.go /work/ COPY pkg/ /work/pkg/ RUN make bin/audit-forwarder -FROM fluent/fluent-bit:1.7.9-debug +FROM fluent/fluent-bit:1.7.3-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ COPY fluent-bit.conf /fluent-bit/etc/ From 785f6b7a75bea724f21ea44c025970b516029f7a Mon Sep 17 00:00:00 2001 From: mreiger Date: Thu, 1 Jul 2021 19:25:32 +0200 Subject: [PATCH 08/10] Try and find the fluent-bit versio that broke splunk --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2644678..13b3324 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ COPY .git Makefile go.* *.go /work/ COPY pkg/ /work/pkg/ RUN make bin/audit-forwarder -FROM fluent/fluent-bit:1.7.3-debug +FROM fluent/fluent-bit:1.7.5-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ COPY fluent-bit.conf /fluent-bit/etc/ From 5a490dfbba01bd06d4f2aaabcb755806982dcfdd Mon Sep 17 00:00:00 2001 From: mreiger Date: Thu, 1 Jul 2021 19:57:18 +0200 Subject: [PATCH 09/10] Keep fluent-bit version at the last know good version for splunk raw output --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 13b3324..ca176fd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,9 @@ COPY .git Makefile go.* *.go /work/ COPY pkg/ /work/pkg/ RUN make bin/audit-forwarder -FROM fluent/fluent-bit:1.7.5-debug +# Need to keep fluent-bit version below 1.7.5 for now, +# due to bug https://github.com/fluent/fluent-bit/issues/3699 +FROM fluent/fluent-bit:1.7.4-debug COPY --from=builder /work/bin/audit-forwarder /fluent-bit/bin/ COPY fluent-bit.conf /fluent-bit/etc/ From 41f40404f4bf6bad6cd6e6486487883c3f4940a6 Mon Sep 17 00:00:00 2001 From: mreiger Date: Thu, 1 Jul 2021 20:10:09 +0200 Subject: [PATCH 10/10] Add files to test splunk forwarding with kind --- kind/audit/add/splunk.conf | 36 +++++++++++++++++++ .../kube-apiserver_patch.yaml | 32 +++++++++++++++++ .../kustomization.yaml | 7 ++++ kind/make-audit-forwarder-splunk | 31 ++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 kind/audit/add/splunk.conf create mode 100644 kind/kustomize-auditforwarder-splunk/kube-apiserver_patch.yaml create mode 100644 kind/kustomize-auditforwarder-splunk/kustomization.yaml create mode 100755 kind/make-audit-forwarder-splunk diff --git a/kind/audit/add/splunk.conf b/kind/audit/add/splunk.conf new file mode 100644 index 0000000..4bd0d79 --- /dev/null +++ b/kind/audit/add/splunk.conf @@ -0,0 +1,36 @@ + +[FILTER] + Name rewrite_tag + Match audit + Rule $kind Event tosplunk true + +[FILTER] + Name nest + Match tosplunk + Operation nest + Wildcard * + Nest_under event + +[FILTER] + Name record_modifier + Match tosplunk + Record host cluster-name + Record sourcetype kube:apiserver:auditlog + Record source apiserver-pod-name + Record index REPLACE_WITH_SPLUNK_INDEX + +[OUTPUT] + Name splunk + Match tosplunk + Host REPLACE_WITH_SPLUNK_HEC_ENDPOINT + Port REPLACE_WITH_PORT + Splunk_Token REPLACE_WITH_SPLUNK_HEC_TOKEN + TLS On + TLS.Verify On + Retry_Limit False + Splunk_Send_Raw On + +[OUTPUT] + Name stdout + Match tosplunk + Format json_lines diff --git a/kind/kustomize-auditforwarder-splunk/kube-apiserver_patch.yaml b/kind/kustomize-auditforwarder-splunk/kube-apiserver_patch.yaml new file mode 100644 index 0000000..99fbd8f --- /dev/null +++ b/kind/kustomize-auditforwarder-splunk/kube-apiserver_patch.yaml @@ -0,0 +1,32 @@ +- op: add + path: /spec/containers/1 + value: + image: ghcr.io/metal-stack/audit-forwarder:pr-add-splunk + imagePullPolicy: Always + name: audit-forwarder + env: + - name: AUDIT_KUBECFG + value: "/kube.config" + - name: AUDIT_LOG_LEVEL + value: "info" + volumeMounts: + - mountPath: /auditlog + name: auditlog + - mountPath: /kube.config + name: kubeconfig + - mountPath: /fluent-bit/etc/add + name: add-config +- op: add + path: /spec/volumes/0 + value: + hostPath: + path: /etc/kubernetes/audit/kube.config + type: File + name: kubeconfig +- op: add + path: /spec/volumes/0 + value: + hostPath: + path: /etc/kubernetes/audit/add + type: Directory + name: add-config \ No newline at end of file diff --git a/kind/kustomize-auditforwarder-splunk/kustomization.yaml b/kind/kustomize-auditforwarder-splunk/kustomization.yaml new file mode 100644 index 0000000..29e5372 --- /dev/null +++ b/kind/kustomize-auditforwarder-splunk/kustomization.yaml @@ -0,0 +1,7 @@ +resources: +- kube-apiserver.yaml +patches: +- path: kube-apiserver_patch.yaml + target: + kind: Pod + name: kube-apiserver diff --git a/kind/make-audit-forwarder-splunk b/kind/make-audit-forwarder-splunk new file mode 100755 index 0000000..fcb4a19 --- /dev/null +++ b/kind/make-audit-forwarder-splunk @@ -0,0 +1,31 @@ +#!/bin/sh + +# First check if a forwarder has already been applied and get the kube-apiserver manifest if it isn't. +if grep forwarder kind-etc-kubernetes/manifests/kube-apiserver.yaml >/dev/null; then + echo "Forwarder config already applied." + if [ ! -f kustomize-auditforwarder-splunk/kube-apiserver.yaml ]; then + echo "No saved kube-apiserver manifest exists, exiting." + exit + else + if grep forwarder kustomize-auditforwarder-splunk/kube-apiserver.yaml >/dev/null; then + echo "Saved config contains forwarder too, can not patch. Exiting." + exit + fi + fi +else + echo "Getting kube-apiserver manifest." + cp kind-etc-kubernetes/manifests/kube-apiserver.yaml kustomize-auditforwarder-splunk/ +fi + +# Patch the generated kind kubeconfig with the apiserver URL valid from within the cluster. + +echo "Generating the in-cluster kubeconfig:" + +# Get the IP and port from the apiserver manifest: +line=`grep kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint kustomize-auditforwarder-splunk/kube-apiserver.yaml` +apiserver=${line##*kubeadm.kubernetes.io\/kube-apiserver.advertise-address.endpoint:?} + +sed "s+https://.*$+https://$apiserver+" kube.config >kind-etc-kubernetes/audit/kube.config + +echo "Patching and applying the kube-apiserver manifest:" +kustomize build kustomize-auditforwarder-splunk >kind-etc-kubernetes/manifests/kube-apiserver.yaml