diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2a60dbb..e815fd8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -33,13 +33,10 @@ jobs: kv-gitlab-ci/data/node/build/cosign password | COSIGN_PASSWORD ; kv-gitlab-ci/data/node/build/cosign private_key | COSIGN_PRIVATE_KEY ; - - name: Build image - run: make build - - - name: Push image + - name: Build and push image run: | echo ${DOCKERHUB_PASSWORD} | docker login -u ${DOCKERHUB_USER} --password-stdin - make push + make build - name: Sign image id: sign @@ -55,7 +52,7 @@ jobs: syft -o spdx-json ${IMAGE_NAME} > ${SBOM_SPDX} cosign attach sbom --sbom ${SBOM_SPDX} ${IMAGE_DIGEST} cosign sign --yes --key env://COSIGN_PRIVATE_KEY "${IMAGE_URI}.sbom" - cosign sign --yes --key env://COSIGN_PRIVATE_KEY ${IMAGE_DIGEST} + cosign sign --recursive --yes --key env://COSIGN_PRIVATE_KEY ${IMAGE_DIGEST} echo "sbom=${SBOM_SPDX}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e5eb9cd..f562543 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,15 @@ permissions: jobs: build: name: Build - runs-on: self-hosted-amd64-1cpu + runs-on: ${{ matrix.RUNNER }} + strategy: + fail-fast: false + matrix: + include: + - PLATFORM: amd64 + RUNNER: self-hosted-amd64-1cpu + - PLATFORM: aarch64 + RUNNER: self-hosted-arm64-1cpu outputs: helm_args: ${{ steps.compute_helm_args.outputs.helm_args }} steps: @@ -31,15 +39,15 @@ jobs: - name: Build run: | IMAGE="wallarm/sidecar-controller" - make build TAG=${GITHUB_SHA} IMAGE=${IMAGE} + make build TAG=${GITHUB_SHA} IMAGE=${IMAGE} PLATFORMS=linux/${{ matrix.PLATFORM }} BUILDX_ARGS=--load mkdir artifacts - docker save -o artifacts/docker-image.tar ${IMAGE}:${GITHUB_SHA} + docker save -o artifacts/docker-image-${{ matrix.PLATFORM }}.tar ${IMAGE}:${GITHUB_SHA} - name: Save artifact uses: actions/upload-artifact@v3 with: name: docker-artifact - path: artifacts/docker-image.tar + path: artifacts/docker-image-${{ matrix.PLATFORM }}.tar retention-days: 1 - name: Compute Helm arguments @@ -51,7 +59,7 @@ jobs: test: name: Test needs: build - uses: wallarm/sidecar/.github/workflows/test.yaml@main + uses: wallarm/sidecar/.github/workflows/test.yaml@DE-11 # TODO: fix, tmp, no dynamic resolving here secrets: VAULT_URL: ${{ secrets.VAULT_URL }} VAULT_ROLE: ${{ secrets.VAULT_ROLE }} diff --git a/.github/workflows/helm_publish.yaml b/.github/workflows/helm_publish.yaml index d79957e..c47e323 100644 --- a/.github/workflows/helm_publish.yaml +++ b/.github/workflows/helm_publish.yaml @@ -4,6 +4,7 @@ on: push: tags: - 'helm-chart-[0-9]+.[0-9]+.[0-9]+' + - 'helm-chart-[0-9]+.[0-9]+.[0-9]+-rc*' permissions: contents: read @@ -14,6 +15,7 @@ jobs: runs-on: self-hosted-amd64-1cpu outputs: chart_version: ${{ steps.get_versions.outputs.chart_version }} + release_type: ${{ steps.check_release.outputs.type }} steps: - name: Import secrets uses: hashicorp/vault-action@130d1f5f4fe645bb6c83e4225c04d64cfb62de6e # v2.5.0 @@ -30,6 +32,16 @@ jobs: - name: Checkout uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - name: Check release type + id: check_release + run: | + TYPE="production" + if [[ ${GITHUB_REF#refs/*/} =~ "rc" ]]; then + TYPE="release-candidate" + fi + echo -e "Type: ${TYPE}" + echo "type=${TYPE}" >> $GITHUB_OUTPUT + - name: Get versions id: get_versions run: | @@ -52,6 +64,7 @@ jobs: update_version: name: Update package version + if: needs.release.outputs.release_type == 'production' runs-on: self-hosted-amd64-1cpu needs: release steps: diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b43eb11..cb5d23e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -119,9 +119,9 @@ jobs: test: name: Integration test + runs-on: ${{ matrix.RUNNER }} if: ${{ inputs.run_test }} needs: check - runs-on: self-hosted-amd64-1cpu strategy: matrix: kubeVersion: @@ -132,6 +132,11 @@ jobs: - 1.23.13 - 1.24.7 - 1.25.3 + PLATFORM: [ amd64 ] + RUNNER: [ self-hosted-amd64-1cpu ] + include: + - { kubeVersion: 1.19.16, PLATFORM: aarch64, RUNNER: self-hosted-arm64-1cpu } + - { kubeVersion: 1.25.3, PLATFORM: aarch64, RUNNER: self-hosted-arm64-1cpu } steps: - name: Import secrets uses: hashicorp/vault-action@130d1f5f4fe645bb6c83e4225c04d64cfb62de6e # v2.5.0 @@ -169,7 +174,7 @@ jobs: - name: Load image if: ${{ inputs.load_artifact }} - run: kind load image-archive artifacts/docker-image.tar + run: kind load image-archive artifacts/docker-image-${{ matrix.PLATFORM }}.tar - name: Install Helm chart run: | @@ -234,7 +239,7 @@ jobs: - name: Load image if: ${{ inputs.load_artifact }} - run: kind load image-archive artifacts/docker-image.tar + run: kind load image-archive artifacts/docker-image-amd64.tar - name: Run test env: diff --git a/.github/workflows/update_versions.yaml b/.github/workflows/update_versions.yaml index af05733..38c7143 100644 --- a/.github/workflows/update_versions.yaml +++ b/.github/workflows/update_versions.yaml @@ -85,13 +85,7 @@ jobs: export TAG="${{ inputs.upstream_tag }}" export VERSION=$(echo "${TAG}" | cut -d "-" -f 1) yq e -i '.appVersion = env(VERSION)' helm/Chart.yaml - yq e -i \ - '(.postanalytics.init.image.tag = env(TAG)) | - (.postanalytics.cron.image.tag = env(TAG)) | - (.postanalytics.tarantool.image.tag = env(TAG)) | - (.postanalytics.heartbeat.image.tag = env(TAG)) | - (.postanalytics.antibot.image.tag = env(TAG)) | - (.postanalytics.appstructure.image.tag = env(TAG))' helm/values.yaml + yq e -i '.helper.image.tag = env(TAG)' helm/values.yaml echo "next-version=${VERSION}" >> $GITHUB_OUTPUT - name: Update sidecar version diff --git a/.github/workflows/upstream_update.yaml b/.github/workflows/upstream_update.yaml index a6bbcef..a7ef7df 100644 --- a/.github/workflows/upstream_update.yaml +++ b/.github/workflows/upstream_update.yaml @@ -55,11 +55,7 @@ jobs: if [ ${{ github.event.client_payload.upstream_update }} = true ]; then UPSTREAM_TAG=${{ github.event.client_payload.upstream_tag }} HELM_ARGS+="\ - --set postanalytics.init.image.tag=${UPSTREAM_TAG} \ - --set postanalytics.cron.image.tag=${UPSTREAM_TAG} \ - --set postanalytics.tarantool.image.tag=${UPSTREAM_TAG} \ - --set postanalytics.heartbeat.image.tag=${UPSTREAM_TAG} \ - --set postanalytics.appstructure.image.tag=${UPSTREAM_TAG}" + --set helper.image.tag=${UPSTREAM_TAG}" echo "HELM_ARGS: ${HELM_ARGS}" fi diff --git a/Dockerfile b/Dockerfile index 553568a..547bc96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,15 @@ -FROM golang:1.21.1-alpine3.18 as builder +ARG ALPINE_VERSION +FROM golang:1.21.1-alpine${ALPINE_VERSION} as builder + +MAINTAINER Wallarm Support Team + +LABEL org.opencontainers.image.title="Docker official image for Wallarm Node. API security platform agent" +LABEL org.opencontainers.image.title="Kubernetes Sidecar schema of Wallarm API Security deployment" +LABEL org.opencontainers.image.documentation="https://docs.wallarm.com/installation/kubernetes/sidecar-proxy/deployment/" +LABEL org.opencontainers.image.source="https://github.com/wallarm/sidecar" +LABEL org.opencontainers.image.vendor="Wallarm" +LABEL org.opencontainers.image.revision="${COMMIT_SHA}" +LABEL com.wallarm.sidecar-controller.versions.alpine="${ALPINE_VERSION}" RUN apk add --no-cache \ bash \ @@ -10,15 +21,16 @@ WORKDIR /build COPY cmd/ go.mod go.sum ./ RUN go mod download +ARG TARGETARCH ARG CGO_ENABLED=0 ARG GOOS=linux -ARG GOARCH=amd64 +ARG GOARCH=$TARGETARCH RUN go test -v . && \ go build -a -ldflags="-s -w" \ -o sidecar-controller . && \ upx -9 sidecar-controller -FROM alpine:3.18 +FROM alpine:${ALPINE_VERSION} ARG UID=65222 ARG GID=65222 diff --git a/Makefile b/Makefile index 57a69bb..67d13f6 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,23 @@ # https://makefiletutorial.com/ -include env.ini + +ifndef CI + PLATFORMS?=linux/amd64 + BUILDX_ARGS?=--load +else + PLATFORMS?=linux/amd64,linux/aarch64 + BUILDX_ARGS?=--push +endif + .EXPORT_ALL_VARIABLES: DOCKERFILE := ./Dockerfile TAG ?= $(shell cat TAG) IMAGE ?= wallarm/sidecar-controller CONTROLLER_IMAGE = $(IMAGE):$(TAG) - -### For embedding into the chart -### -SIDECAR_IMAGE := wallarm/sidecar:4.8.0-1 -TARANTOOL_IMAGE := wallarm/ingress-tarantool:4.8.1-1 -RUBY_IMAGE := wallarm/ingress-ruby:4.8.1-1 -PYTHON_IMAGE := wallarm/ingress-python:4.8.1-1 +COMMIT_SHA ?= git-$(shell git rev-parse --short HEAD) +ALPINE_VERSION = 3.18 ### Contribution routines ### @@ -68,13 +72,7 @@ clean-all: ### Helm routines ### HELMARGS := --set "config.wallarm.api.token=$(WALLARM_API_TOKEN)" \ - --set "config.wallarm.api.host=$(WALLARM_API_HOST)" \ - --set "config.sidecar.image.fullname=$(SIDECAR_IMAGE)" \ - --set "postanalytics.init.image.fullname=$(RUBY_IMAGE)" \ - --set "postanalytics.cron.image.fullname=$(RUBY_IMAGE)" \ - --set "postanalytics.tarantool.image.fullname=$(TARANTOOL_IMAGE)" \ - --set "postanalytics.appstructure.image.fullname=$(PYTHON_IMAGE)" \ - --set "postanalytics.antibot.image.fullname=$(PYTHON_IMAGE)" + --set "config.wallarm.api.host=$(WALLARM_API_HOST)" helm-template: @$(HELM) template wallarm-sidecar ./helm -f ./helm/values.dev.yaml $(HELMARGS) --debug @@ -108,8 +106,23 @@ test: fmt vet ### Build ### -build: - @docker build -t $(CONTROLLER_IMAGE) . --force-rm --no-cache --progress=plain + +setup_buildx: + docker buildx rm multi-arch || true + docker buildx create \ + --name multi-arch \ + --platform linux/amd64,linux/arm64 \ + --driver docker-container \ + --use + +build: setup_buildx + @docker buildx build \ + --file Dockerfile \ + --platform=$(PLATFORMS) \ + --build-arg ALPINE_VERSION="$(ALPINE_VERSION)" \ + --build-arg COMMIT_SHA="$(COMMIT_SHA)" \ + --force-rm --no-cache --progress=plain \ + --tag $(CONTROLLER_IMAGE) $(BUILDX_ARGS) . push rmi: @docker $@ $(CONTROLLER_IMAGE) diff --git a/TAG b/TAG index 8c9698a..aaf8be7 100644 --- a/TAG +++ b/TAG @@ -1 +1 @@ -1.3.4 \ No newline at end of file +1.3.5 \ No newline at end of file diff --git a/files/template.yaml.tpl b/files/template.yaml.tpl index f8bd27c..e29eed7 100644 --- a/files/template.yaml.tpl +++ b/files/template.yaml.tpl @@ -28,7 +28,6 @@ volumes: env: {{ if ne (getAnnotation .ObjectMeta (withAP "sidecar-injection-schema") .Config.injectionStrategy.schema) "split" -}} {{ template "wallarmApiVariables" . }} - {{ template "wallarmCronVariables" . }} {{ template "wallarmVersion" . }} {{- end }} {{ if (isSet .ObjectMeta.Annotations (withAP "wallarm-application")) -}} @@ -67,6 +66,8 @@ volumes: value: "{{ getAnnotation .ObjectMeta (withAP `wallarm-upstream-connect-attempts`) .Config.wallarm.upstream.connectAttempts }}" - name: WALLARM_UPSTREAM_RECONNECT_INTERVAL value: "{{ getAnnotation .ObjectMeta (withAP `wallarm-upstream-reconnect-interval`) .Config.wallarm.upstream.reconnectInterval }}" + - name: WALLARM_APIFW_ENABLE + value: "{{ getAnnotation .ObjectMeta (withAP `api-firewall-enabled`) .Config.wallarm.apiFirewallMode }}" - name: NGINX_LISTEN_PORT value: "{{ getAnnotation .ObjectMeta (withAP `nginx-listen-port`) .Config.nginx.listenPort }}" - name: NGINX_PROXY_PASS_PORT @@ -152,11 +153,11 @@ volumes: {{ toYaml .Config.sidecar.containers.proxy.readinessProbe | indent 4 }} {{ end }} volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm - - mountPath: /var/lib/wallarm-acl + - mountPath: /opt/wallarm/var/lib/wallarm-acl name: wallarm-acl - - mountPath: /var/lib/nginx/wallarm/ + - mountPath: /opt/wallarm/var/lib/nginx/wallarm/ name: wallarm-cache {{- if and .Profile (index .Profile "sidecar") -}} {{- with .Profile.sidecar.volumeMounts }} @@ -179,17 +180,16 @@ volumes: - name: sidecar-helper image: {{ template "image" . }} imagePullPolicy: {{ .Config.sidecar.image.pullPolicy }} - command: ["supervisord", "-c", "/etc/supervisor/supervisord.helper.conf"] + command: ["/usr/local/run-helper.sh"] env: {{ template "wallarmApiVariables" . }} - {{ template "wallarmCronVariables" . }} {{ template "wallarmVersion" . }} - name: NGINX_STATUS_PORT value: "{{ getAnnotation .ObjectMeta (withAP `nginx-status-port`) .Config.nginx.statusPort }}" volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm - - mountPath: /var/lib/wallarm-acl + - mountPath: /opt/wallarm/var/lib/wallarm-acl name: wallarm-acl securityContext: {{ toYaml .Config.sidecar.securityContext | indent 4 }} @@ -208,9 +208,9 @@ volumes: - name: WALLARM_FALLBACK value: "{{ getAnnotation .ObjectMeta (withAP `wallarm-fallback`) .Config.wallarm.fallback }}" volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm - - mountPath: /var/lib/wallarm-acl + - mountPath: /opt/wallarm/var/lib/wallarm-acl name: wallarm-acl securityContext: {{ toYaml .Config.sidecar.securityContext | indent 4 }} @@ -231,7 +231,7 @@ volumes: value: "{{ template `applicationPort` . }}" - name: NGINX_PORT value: "{{ getAnnotation .ObjectMeta (withAP "nginx-listen-port") .Config.nginx.listenPort }}" - command: ["iptables"] + command: ["iptables-legacy"] args: ["-t", "nat", "-A", "PREROUTING", "-p", "tcp", "-d", "$(POD_IP)", "--dport", "$(APP_PORT)", "-j", "REDIRECT", "--to-ports", "$(NGINX_PORT)"] securityContext: {{ toYaml .Config.sidecar.initContainers.iptables.securityContext | indent 4 }} @@ -283,37 +283,6 @@ volumes: value: "{{ .Config.component.version }}" {{- end }} -{{- define "wallarmCronVariables" }} - - name: WALLARM_CRON_EXPORT_ENV_SCHEDULE - value: "{{ .Config.wallarm.cron.exportEnvironment.schedule }}" - - name: WALLARM_CRON_EXPORT_ENV_TIMEOUT - value: "{{ .Config.wallarm.cron.exportEnvironment.timeout }}" - - name: WALLARM_CRON_EXPORT_ENV_COMMAND - value: "{{ .Config.wallarm.cron.exportEnvironment.command }}" - - name: WALLARM_CRON_EXPORT_METRICS_SCHEDULE - value: "{{ .Config.wallarm.cron.exportMetrics.schedule }}" - - name: WALLARM_CRON_EXPORT_METRICS_TIMEOUT - value: "{{ .Config.wallarm.cron.exportMetrics.timeout }}" - - name: WALLARM_CRON_EXPORT_METRICS_COMMAND - value: "{{ .Config.wallarm.cron.exportMetrics.command }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_SCHEDULE - value: "{{ .Config.wallarm.cron.syncIpLists.schedule }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_TIMEOUT - value: "{{ .Config.wallarm.cron.syncIpLists.timeout }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_COMMAND - value: "{{ .Config.wallarm.cron.syncIpLists.command }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_SOURCE_SCHEDULE - value: "{{ .Config.wallarm.cron.syncIpListsSource.schedule }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_SOURCE_TIMEOUT - value: "{{ .Config.wallarm.cron.syncIpListsSource.timeout }}" - - name: WALLARM_CRON_SYNC_IP_LISTS_SOURCE_COMMAND - value: "{{ .Config.wallarm.cron.syncIpListsSource.command }}" - - name: WALLARM_CRON_SYNC_NODE_SCHEDULE - value: "{{ .Config.wallarm.cron.syncNode.schedule }}" - - name: WALLARM_CRON_SYNC_NODE_COMMAND - value: "{{ .Config.wallarm.cron.syncNode.command }}" -{{- end }} - {{- define "helperContainer.resources" }} {{- if or (isSet .ObjectMeta.Annotations (withAP "helper-cpu")) (isSet .ObjectMeta.Annotations (withAP "helper-memory")) (isSet .ObjectMeta.Annotations (withAP "helper-cpu-limit")) (isSet .ObjectMeta.Annotations (withAP "helper-memory-limit")) }} {{- if or (isSet .ObjectMeta.Annotations (withAP "helper-cpu")) (isSet .ObjectMeta.Annotations (withAP "helper-memory")) }} diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 0c5c770..28fe494 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: wallarm-sidecar -version: 4.8.1 -appVersion: 4.8.0-1 +version: 4.10.2 +appVersion: 4.10.2-1 description: Sidecar controller for Kubernetes. Injects sidecar proxy based on NGINX with Wallarm module and helper services. home: https://github.com/wallarm/sidecar icon: https://static.wallarm.com/wallarm-logo.svg @@ -21,12 +21,8 @@ kubeVersion: ">=1.19.16-0" annotations: artifacthub.io/images: | - name: sidecar - image: wallarm/sidecar:4.8.0-1 + image: wallarm/sidecar:4.10.2-1 - name: sidecar-controller - image: wallarm/sidecar-controller:1.3.4 - - name: ingress-ruby - image: wallarm/ingress-ruby:4.8.1-1 - - name: ingress-python - image: wallarm/ingress-python:4.8.1-1 - - name: ingress-tarantool - image: wallarm/ingress-tarantool:4.8.1-1 + image: wallarm/sidecar-controller:1.3.5 + - name: node-helpers + image: wallarm/node-helpers:4.10.2-2 diff --git a/helm/templates/postanalytics-configmap.yaml b/helm/templates/postanalytics-configmap.yaml index f62be7d..f453f66 100644 --- a/helm/templates/postanalytics-configmap.yaml +++ b/helm/templates/postanalytics-configmap.yaml @@ -15,15 +15,103 @@ metadata: {{- . | toYaml | nindent 4 }} {{- end }} data: - crontab: |- - ### Post-analytics service crontab - ### - {{- range $k, $v := .Values.postanalytics.cron.config }} - {{- $timeout := " " }} - {{- if (index $v "timeout" | default dict) }} - {{- $timeout = printf " timeout %s " $v.timeout }} - {{- end }} - # {{ $k }} - {{ $v.schedule }}{{ $timeout }}{{ $v.command }} - {{- end }} -{{- end }} \ No newline at end of file + supervisord.conf: |- + [supervisord] + nodaemon=true + loglevel={{ .Values.postanalytics.supervisord.logLevel }} + logfile=/dev/stdout + logfile_maxbytes=0 + pidfile=/opt/wallarm/run/supervisor/pid + + {{- with .Values.postanalytics.supervisord.commands }} + # export-attacks + [program:export-attacks] + command=/opt/wallarm/usr/share/wallarm-common/export-attacks -r -l STDOUT -L {{ .exportAttacks.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # export-counters + [program:export-counters] + command=/opt/wallarm/usr/share/wallarm-common/export-counters -l STDOUT -L {{ .exportCounters.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # export-environment + [program:export-environment] + command=/opt/wallarm/usr/share/wallarm-common/export-environment -w -l STDOUT -L {{ .exportEnvironment.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # brute-detect + [program:brute-detect] + command=/opt/wallarm/usr/share/wallarm-common/brute-detect -w -l STDOUT -L {{ .bruteDetect.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # sync-markers + [program:sync-markers] + command=/opt/wallarm/usr/share/wallarm-common/sync-markers -w -l STDOUT -L {{ .syncMarkers.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # weak-jwt-detect + [program:weak-jwt-detect] + command=/opt/wallarm/usr/share/wallarm-common/weak-jwt-detect -l STDOUT -L {{ .weakJwtDetect.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # sync-node + [program:sync-node] + command=/opt/wallarm/usr/share/wallarm-common/syncnode -f -p -r 120 -l STDOUT -L {{ .syncNode.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # export-blocked-stats + [program:export-blocked-stats] + command=/opt/wallarm/usr/share/wallarm-common/export-blocked-stats -l STDOUT -L {{ .exportBlockedStat.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + + # detect-cred-stuffing + [program:detect-cred-stuffing] + command=/opt/wallarm/usr/share/wallarm-common/detect-cred-stuffing -l STDOUT -L {{ .detectCredStuffing.logLevel }} + autorestart=true + startretries=4294967295 + stdout_logfile_maxbytes=0 + stdout_logfile=/dev/stdout + stderr_logfile_maxbytes=0 + stderr_logfile=/dev/stdout + {{- end }} +{{- end }} diff --git a/helm/templates/postanalytics-deployment.yaml b/helm/templates/postanalytics-deployment.yaml index 33ea2f2..4b6bf06 100644 --- a/helm/templates/postanalytics-deployment.yaml +++ b/helm/templates/postanalytics-deployment.yaml @@ -26,7 +26,7 @@ spec: template: metadata: annotations: - checksum/config: {{ .Values.postanalytics.cron.config | toJson | sha256sum }} + checksum/config: {{ index (include (print .Template.BasePath "/postanalytics-configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }} checksum/secret: {{ .Values.config.wallarm.api | toJson | sha256sum }} {{- include "wallarm-sidecar.annotations" . | nindent 8 }} {{- with .Values.postanalytics.extraAnnotations }} @@ -64,14 +64,9 @@ spec: {{- end }} initContainers: - name: init - image: {{ include "wallarm-sidecar.image" .Values.postanalytics.init.image }} - imagePullPolicy: "{{ .Values.postanalytics.init.image.pullPolicy }}" - command: - - sh - - -c - - > - /opt/wallarm/ruby/usr/share/wallarm-common/register-node --force --batch --no-export-env {{- if eq .Values.config.wallarm.fallback "on" }} || true {{- end }}; - /opt/wallarm/ruby/usr/share/wallarm-common/export-environment -l STDOUT || true + image: {{ include "wallarm-sidecar.image" .Values.helper.image }} + imagePullPolicy: "{{ .Values.helper.image.pullPolicy }}" + args: [ "register"{{- if eq .Values.config.wallarm.fallback "on" }}, "fallback"{{- end }} ] env: {{- include "wallarm-sidecar.credentials" . | nindent 10 }} {{- include "wallarm-sidecar.version" . | nindent 10 }} @@ -102,9 +97,9 @@ spec: resources: {{ . | toYaml | nindent 12 }} {{- end }} volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm - - mountPath: /var/lib/wallarm-acl + - mountPath: /opt/wallarm/var/lib/wallarm-acl name: wallarm-acl {{- with .Values.postanalytics.init.extraVolumeMounts }} {{- . | toYaml | nindent 10 }} @@ -113,28 +108,27 @@ spec: {{- . | toYaml | nindent 8 }} {{- end }} containers: - - name: cron - image: {{ include "wallarm-sidecar.image" .Values.postanalytics.cron.image }} - imagePullPolicy: "{{ .Values.postanalytics.cron.image.pullPolicy }}" - command: ["/bin/dumb-init", "--"] - args: ["/bin/supercronic", "-json", "/opt/cron/crontab"] + - name: supervisord + image: {{ include "wallarm-sidecar.image" .Values.helper.image }} + imagePullPolicy: "{{ .Values.helper.image.pullPolicy }}" + args: ["supervisord"] env: {{- include "wallarm-sidecar.credentials" . | nindent 10 }} {{- include "wallarm-sidecar.version" . | nindent 10 }} - {{- with .Values.postanalytics.cron.extraEnvs }} + {{- with .Values.postanalytics.supervisord.extraEnvs }} {{- . | toYaml | nindent 10 }} {{- end }} - {{- with .Values.postanalytics.cron.livenessProbe }} + {{- with .Values.postanalytics.supervisord.livenessProbe }} livenessProbe: {{ . | toYaml | nindent 12 }} {{- end }} - {{- with .Values.postanalytics.cron.readinessProbe }} + {{- with .Values.postanalytics.supervisord.readinessProbe }} readinessProbe: {{ . | toYaml | nindent 12 }} {{- end }} - {{- with .Values.postanalytics.cron.lifecycle }} + {{- with .Values.postanalytics.supervisord.lifecycle }} lifecycle: {{ . | toYaml | nindent 12 }} {{- end }} - {{- if .Values.postanalytics.cron.securityContext }} - securityContext: {{ .Values.postanalytics.cron.securityContext | toYaml | nindent 12 }} + {{- if .Values.postanalytics.supervisord.securityContext }} + securityContext: {{ .Values.postanalytics.supervisord.securityContext | toYaml | nindent 12 }} {{- else }} securityContext: privileged: false @@ -144,24 +138,25 @@ spec: drop: - ALL {{- end }} - {{- with .Values.postanalytics.cron.resources }} + {{- with .Values.postanalytics.supervisord.resources }} resources: {{ . | toYaml | nindent 12 }} {{- end }} volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm - - mountPath: /var/lib/wallarm-acl + - mountPath: /opt/wallarm/var/lib/wallarm-acl name: wallarm-acl - - mountPath: /opt/cron/crontab - name: wallarm-cron - subPath: crontab + - mountPath: /opt/supervisord/supervisord.conf + name: wallarm-supervisord + subPath: supervisord.conf readOnly: true - {{- with .Values.postanalytics.cron.extraVolumeMounts }} + {{- with .Values.postanalytics.supervisord.extraVolumeMounts }} {{- . | toYaml | nindent 10 }} {{- end }} - name: tarantool - image: {{ include "wallarm-sidecar.image" .Values.postanalytics.tarantool.image }} - imagePullPolicy: "{{ .Values.postanalytics.tarantool.image.pullPolicy }}" + image: {{ include "wallarm-sidecar.image" .Values.helper.image }} + imagePullPolicy: "{{ .Values.helper.image.pullPolicy }}" + args: ["tarantool"] env: {{- include "wallarm-sidecar.credentials" . | nindent 10 }} - name: SLAB_ALLOC_ARENA @@ -203,8 +198,9 @@ spec: {{- . | toYaml | nindent 10 }} {{- end }} - name: appstructure - image: {{ include "wallarm-sidecar.image" .Values.postanalytics.appstructure.image }} - imagePullPolicy: "{{ .Values.postanalytics.appstructure.image.pullPolicy }}" + image: {{ include "wallarm-sidecar.image" .Values.helper.image }} + imagePullPolicy: "{{ .Values.helper.image.pullPolicy }}" + args: ["appstructure"] env: {{- include "wallarm-sidecar.credentials" . | nindent 10 }} {{- with .Values.postanalytics.appstructure.extraEnvs }} @@ -234,15 +230,15 @@ spec: resources: {{ . | toYaml | nindent 12 }} {{- end }} volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm {{- with .Values.postanalytics.tarantool.extraVolumeMounts }} {{- . | toYaml | nindent 10 }} {{- end }} - name: antibot - image: {{ include "wallarm-sidecar.image" .Values.postanalytics.antibot.image }} - imagePullPolicy: "{{ .Values.postanalytics.antibot.image.pullPolicy }}" - command: ["/opt/wallarm/python/usr/bin/antibotapiextractor"] + image: {{ include "wallarm-sidecar.image" .Values.helper.image }} + imagePullPolicy: "{{ .Values.helper.image.pullPolicy }}" + args: ["antibot"] env: {{- include "wallarm-sidecar.credentials" . | nindent 10 }} {{- with .Values.postanalytics.antibot.extraEnvs }} @@ -272,7 +268,7 @@ spec: resources: {{ . | toYaml | nindent 12 }} {{- end }} volumeMounts: - - mountPath: /etc/wallarm + - mountPath: /opt/wallarm/etc/wallarm name: wallarm {{- with .Values.postanalytics.tarantool.extraVolumeMounts }} {{- . | toYaml | nindent 10 }} @@ -285,7 +281,7 @@ spec: emptyDir: {} - name: wallarm-acl emptyDir: {} - - name: wallarm-cron + - name: wallarm-supervisord configMap: name: {{ include "wallarm-sidecar.fullname" . }}-postanalytics {{- with .Values.postanalytics.extraVolumes }} diff --git a/helm/test/integration_test.py b/helm/test/integration_test.py index 5dc6ea5..c816ca3 100644 --- a/helm/test/integration_test.py +++ b/helm/test/integration_test.py @@ -9,11 +9,11 @@ logger = logging.getLogger(__name__) -ALLOWED_HTTP_PATH = '/get' +ALLOWED_HTTP_PATH = '/' FORBIDDEN_HTTP_PATH = '/?id=\'or+1=1--a-\'' SCRIPT_PATH = os.path.dirname(os.path.realpath(__file__)) PATCHES_PATH = f'{SCRIPT_PATH}/kustomize/patches' -WAIT_PODS_TIMEOUT = '120s' +WAIT_PODS_TIMEOUT = '180s' print('PATCHES_PATH: ${PATCHES_PATH}') patchList = [] @@ -23,11 +23,25 @@ class Helpers: @staticmethod - def subprocess_run(cmd: str) -> subprocess.CompletedProcess: + def get_container_logs(namespace: str): + describe_cmd = f'kubectl describe po -n {namespace} -l wallarm-sidecar=enabled' + describe = subprocess.run(shlex.split(describe_cmd), capture_output=True, text=True).stdout + logger.info(f'Describe pods in "{namespace}" namespace: \n\n{describe}') + logger.info(f'End of describe pod') + + logs_cmd = f'kubectl logs -n {namespace} -l wallarm-sidecar=enabled --all-containers --ignore-errors --since=1h' + logs = subprocess.run(shlex.split(logs_cmd), capture_output=True, text=True).stdout + logger.info(f'Logs from "{namespace}" namespace: \n\n{logs}') + logger.info(f'End of logs') + + @staticmethod + def subprocess_run(cmd: str, namespace=None) -> subprocess.CompletedProcess: logger.info(f'Command: {cmd}') completed_process = subprocess.run(shlex.split(cmd), capture_output=True, text=True) if completed_process.returncode != 0: logger.error(completed_process.stderr) + if namespace: + Helpers.get_container_logs(namespace) raise Exception(f'Command: {cmd} ' f'Exit code: {completed_process.returncode} ' f'Stderr: {completed_process.stderr}') @@ -52,7 +66,7 @@ def wait_pods(namespace: str) -> None: cmd = f'kubectl --namespace {namespace} ' \ f'wait --for=condition=Ready pods --all --timeout={WAIT_PODS_TIMEOUT}' logger.info('Wait for all Pods ready ...') - Helpers.subprocess_run(cmd) + Helpers.subprocess_run(cmd, namespace) @staticmethod def delete_namespace(namespace: str) -> None: @@ -93,11 +107,6 @@ def test_main_functionality(self, config, helpers, teardown_namespace): # Register teardown and setup resources for test teardown_namespace['namespace'] = namespace - # Skip tests with ip-tables if run on arm64 - if ("iptables_enabled" in config) and ("aarch64" in sysconfig.get_platform().split("-")[-1].lower()): - pytest.skip(f'Skip {config} test since aarch64') - return - helpers.setup_resources(config_path, namespace) # Need delay here to ensure that service is ready to send traffic to pods diff --git a/helm/test/kustomize/base/configmap.yaml b/helm/test/kustomize/base/configmap.yaml index 5b72a34..c0b1525 100644 --- a/helm/test/kustomize/base/configmap.yaml +++ b/helm/test/kustomize/base/configmap.yaml @@ -12,7 +12,7 @@ data: proxy_read_timeout 60s; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; - proxy_set_header Host $http_host; + #proxy_set_header Host $http_host; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; diff --git a/helm/test/kustomize/base/deployment.yaml b/helm/test/kustomize/base/deployment.yaml index 5943efd..e624cf2 100644 --- a/helm/test/kustomize/base/deployment.yaml +++ b/helm/test/kustomize/base/deployment.yaml @@ -14,19 +14,86 @@ spec: wallarm-sidecar: enabled spec: containers: - - name: application - image: kennethreitz/httpbin - imagePullPolicy: IfNotPresent + - name: nginx + image: nginx:stable-alpine ports: - name: http containerPort: 80 readinessProbe: httpGet: - path: /status/200 + path: / port: http scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 1 successThreshold: 1 - failureThreshold: 5 \ No newline at end of file + failureThreshold: 5 + volumeMounts: + - name: config + mountPath: /etc/nginx + readOnly: true + volumes: + - name: config + configMap: + name: workload + items: + - key: nginx.conf + path: nginx.conf +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: workload +data: + nginx.conf: | + user nginx; + worker_processes 3; + error_log /var/log/nginx/error.log; + events { + worker_connections 10240; + } + http { + log_format main '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" "$gzip_ratio"'; + access_log /var/log/nginx/access.log main; + server { + listen 80; + server_name _; + location / { + return 200; + } + # Location for API discovery test + location /api-discovery-test { + add_header Api-Discovery-Header "Hello, I am header!"; + return 200 '{"json_response": "Hello, I am json"}'; + default_type application/json; + } + # Location for Blocking Tor Source Type + location /blocking-by-tor-test { + add_header Block-by-Tor "Hello, I am header!"; + return 200 '{"json_response": "Hello, I am json"}'; + default_type application/json; + } + # Some mocks for test_api_abuse_prevention.py + location /.git { + if ($http_custom_id) { + return 400; + } + return 200; + } + location /admin { + if ($http_custom_id) { + return 401; + } + return 200; + } + location /api/v2 { + if ($http_custom_id) { + return 502; + } + return 200; + } + } + } diff --git a/helm/values.yaml b/helm/values.yaml index 5203fee..e708bed 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -76,6 +76,10 @@ config: ### https://docs.wallarm.com/admin-en/configure-parameters-en/#wallarm_unpack_response ### unpackResponse: "on" + ### Global setting to turn Wallarm API Firewall component on or off + ### https://wallarm.github.io/api-firewall/ + ### + apiFirewallMode: "on" ### Post-analytics node endpoint configuration ### upstream: @@ -87,26 +91,6 @@ config: ### https://docs.wallarm.com/admin-en/configure-parameters-en/#wallarm_upstream_reconnect_interval ### reconnectInterval: 15s - cron: - exportEnvironment: - schedule: "0 */1 * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-environment -l STDOUT" - timeout: 10m - exportMetrics: - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-metrics -l STDOUT" - timeout: 3h - syncIpLists: - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/sync-ip-lists -l STDOUT" - timeout: 3h - syncIpListsSource: - schedule: "*/5 * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/sync-ip-lists-source -l STDOUT" - timeout: 3h - syncNode: - schedule: "*/2 * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/syncnode -f -p -r 120 -l STDOUT -L DEBUG" ### Default Annotation prefix which is used in sidecar template to overwrite default values annotationPrefix: sidecar.wallarm.io ### Default sidecar injection strategy. Parameters in this section can be overwritten individually @@ -199,7 +183,7 @@ config: image: registry: docker.io image: wallarm/sidecar - tag: "4.8.0-1" + tag: "4.10.2-1" pullPolicy: IfNotPresent ### Shared security context for all (init and regular) containers in sidecar schema except `iptables` container. ### For `iptables` container it is described in `sidecar.initContainers.iptables.securityContext` value @@ -293,6 +277,8 @@ config: ### Security context for `iptables` container ### securityContext: + runAsNonRoot: false + runAsUser: 0 capabilities: add: - NET_ADMIN @@ -358,6 +344,13 @@ config: imagePullSecrets: [] # - name: secretName +helper: + image: + registry: "docker.io" + image: "wallarm/node-helpers" + tag: "4.10.2-2" + pullPolicy: IfNotPresent + ### Configuration for post-analytics module ### postanalytics: @@ -472,11 +465,6 @@ postanalytics: ### Container-specific options ### init: - image: - registry: docker.io - image: wallarm/ingress-ruby - tag: "4.8.1-1" - pullPolicy: IfNotPresent ### Additional environment variables to pass to the container ### extraEnvs: [] @@ -519,47 +507,30 @@ postanalytics: extraVolumeMounts: [] # - name: something # mountPath: /mnt/something - cron: - config: - ### Cron jobs configuration - ### - "export-attacks": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-attacks -l STDOUT" - timeout: 3h - "export-counters": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-counters -l STDOUT" - timeout: 11m - "export-environment": - schedule: "0 */1 * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-environment -l STDOUT" - timeout: 10m - "brute-detect": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/brute-detect -l STDOUT" - timeout: 6m - "sync-markers": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/sync-markers -l STDOUT" - timeout: 1h - "weak-jwt-detect": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/weak-jwt-detect -l STDOUT" - timeout: 10m - "sync-node": - schedule: "*/2 * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/syncnode -f -p -r 120 -l STDOUT -L DEBUG" - "export-blocked-stats": - schedule: "* * * * *" - command: "/opt/wallarm/ruby/usr/share/wallarm-common/export-blocked-stats -l STDOUT -L DEBUG" - timeout: 24h - - image: - registry: docker.io - image: wallarm/ingress-ruby - tag: "4.8.1-1" - pullPolicy: IfNotPresent + supervisord: + ### Per-script debug level + commands: + exportAttacks: + logLevel: INFO + exportCounters: + logLevel: ERROR + exportEnvironment: + logLevel: INFO + bruteDetect: + logLevel: INFO + syncMarkers: + logLevel: INFO + weakJwtDetect: + logLevel: INFO + syncNode: + logLevel: INFO + exportBlockedStat: + logLevel: INFO + detectCredStuffing: + logLevel: INFO + ### Supervisord log level (blather|trace|debug|info|warn|error|critical) + ### Ref: http://supervisord.org/logging.html + logLevel: warn ### Additional environment variables to pass to the container ### extraEnvs: [] @@ -607,12 +578,7 @@ postanalytics: ### The allocated memory size in GB for Tarantool in-memory storage. Detailed recommendations are provided ### here: https://docs.wallarm.com/admin-en/configuration-guides/allocate-resources-for-waf-node/ ### - arena: "0.5" - image: - registry: docker.io - image: wallarm/ingress-tarantool - tag: "4.8.1-1" - pullPolicy: IfNotPresent + arena: "2.0" ### Additional environment variables to pass to the container ### extraEnvs: [] @@ -664,11 +630,6 @@ postanalytics: # - name: something # mountPath: /mnt/something appstructure: - image: - registry: docker.io - image: wallarm/ingress-python - tag: "4.8.1-1" - pullPolicy: IfNotPresent ### Additional environment variables to pass to the container ### extraEnvs: [] @@ -712,11 +673,6 @@ postanalytics: # - name: something # mountPath: /mnt/something antibot: - image: - registry: docker.io - image: wallarm/ingress-python - tag: "4.8.1-1" - pullPolicy: IfNotPresent ### Additional environment variables to pass to the container ### extraEnvs: [] @@ -829,7 +785,7 @@ controller: image: registry: docker.io image: wallarm/sidecar-controller - tag: "1.3.4" + tag: "1.3.5" pullPolicy: IfNotPresent # -- Admission webhook configuration # @default -- *See below for details* diff --git a/kind/docker/manifests/init/pytest.yaml b/kind/docker/manifests/init/pytest.yaml index 89f8b66..7717e2b 100644 --- a/kind/docker/manifests/init/pytest.yaml +++ b/kind/docker/manifests/init/pytest.yaml @@ -68,7 +68,8 @@ data: pip install pip --upgrade && pip install -r helm/test/requirements.txt echo "Installing Kubectl ..." apk update && apk add curl - curl -LO -s "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + ARCH=$([ $(uname -m) = "x86_64" ] && echo amd64 || echo arm64) + curl -LO -s "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl" mv kubectl /usr/bin/kubectl && chmod +x /usr/bin/kubectl echo "Configuring kube context ..." SA="/var/run/secrets/kubernetes.io/serviceaccount"