diff --git a/.github/workflows/ci-multi-server-tests.yml b/.github/workflows/ci-multi-server-tests.yml new file mode 100644 index 000000000000..164a4f167f54 --- /dev/null +++ b/.github/workflows/ci-multi-server-tests.yml @@ -0,0 +1,319 @@ +name: Multi-Server CI Tests + +on: + push: + branches-ignore: + - coverity_scan + - run-fuzzer** + - debug-fuzzer-** + pull_request: + paths: + - '.github/workflows/ci-multi-server-tests.yml' + - 'src/tests/multi-server/**' + workflow_dispatch: + +jobs: + pre-test: + runs-on: ubuntu-latest + outputs: + #selfhosted: 0 + selfhosted: ${{ (github.repository_owner == 'FreeRADIUS') && '1' || '0' }} + steps: + - run: echo "Pre-test job; checking if using self-hosted runners" + + # Job only runs on GitHub-hosted runners + run-multi-server-tests: + needs: pre-test + runs-on: ubuntu-24.04 + if: ${{ needs.pre-test.outputs.selfhosted != '1' }} + + env: + MULTI_SERVER_ENV_DOCKER_BUILD_OS: ubuntu24 + MULTI_SERVER_TEST_LOG: build/tests/multi-server/freeradius-multi-server-test-runtime-logs/multi-server-test.log + MULTI_SERVER_TEST_LISTENER_LOG: build/tests/multi-server/freeradius-multi-server-test-runtime-logs/multi-server-test-linelog-msg-output.log + + steps: + # Checkout, but defer pulling LFS objects until we've restored the cache + - uses: actions/checkout@v4 + with: + lfs: false + + - name: Package manager performance improvements + run: | + sudo sh -c 'echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02speedup' + echo 'man-db man-db/auto-update boolean false' | sudo debconf-set-selections + sudo dpkg-reconfigure man-db + sudo sed -i 's/^update_initramfs=.*/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf + + - name: NetworkRADIUS signing key + shell: bash + run: | + sudo install -d -o root -g root -m 0755 /etc/apt/keyrings + curl -s 'https://packages.inkbridgenetworks.com/pgp/packages.networkradius.com.asc' | sudo tee /etc/apt/keyrings/packages.networkradius.com.asc > /dev/null + + - name: Set up NetworkRADIUS extras repository + shell: bash + run: | + DIST=$(lsb_release -is | tr '[:upper:]' '[:lower:]') + RELEASE=$(lsb_release -cs) + sudo /bin/sh -c "echo \"deb [arch=amd64 signed-by=/etc/apt/keyrings/packages.networkradius.com.asc] http://packages.networkradius.com/extras/${DIST}/${RELEASE} ${RELEASE} main\" \ + > /etc/apt/sources.list.d/networkradius-extras.list" + sudo apt-get update + + # Remove pre-installed package which conflicts with dependency installation + - name: Remove package conflicts + run: | + sudo apt-get remove -y libhashkit2 + + # Installing build dependencies requires a ubuntu-24.04 runner + - name: Install build dependencies + run: | + sudo apt-get install -y --no-install-recommends build-essential devscripts equivs quilt + debian/rules debian/control + sudo mk-build-deps -irt"apt-get -y --no-install-recommends" debian/control + sudo mk-build-deps -irt"apt-get -y --no-install-recommends" scripts/ci/extra-packages.debian.control + + - name: Build Docker image for multi-server test environment + run: | + ./configure + make docker.${MULTI_SERVER_ENV_DOCKER_BUILD_OS}.build + + # List all images + docker images --all + + # Tag freeradius build image using using a non-OS specific name to be used with the multi-server docker compose environment. + docker tag freeradius4/${MULTI_SERVER_ENV_DOCKER_BUILD_OS}:latest freeradius-build:latest + + - name: Run multi-server tests + run: | + if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^freeradius-build:latest$"; then + echo "Error: freeradius-build:latest Docker image not found and required for multi-server test environment." + exit 1 + fi + + make -f src/tests/multi-server/all.mk + + - name: Verify test results + shell: bash + run: | + set -euo pipefail + + echo "${MULTI_SERVER_TEST_LOG}:" + cat "${MULTI_SERVER_TEST_LOG}" + + if grep -Eq "\(Failures:[^0-9]*[1-9][0-9]*\)" "${MULTI_SERVER_TEST_LOG}"; then + echo "TEST FAILED: Found > 0 failures in log" + + # Display the test's linelog message file + echo "${MULTI_SERVER_TEST_LISTENER_LOG}:" + cat "${MULTI_SERVER_TEST_LISTENER_LOG}" + exit 1 + fi + + # Verify that all of the expected linelog results were matched + # during the test(s). + # + # Checking to see that the value matches value in lines like: + # + # Matched: / (Failures: 0) + # + if awk ' + BEGIN { found=0; n1=0; n2=0; line="" } + index($0,"Matched:") { + orig=$0 + s=$0 + gsub(/[[:space:]]/, "", s) + sub(/^.*Matched:/, "", s) + sub(/\(.*/, "", s) + n = split(s, parts, "/") + if (n == 2) { + a = parts[1] + 0 + b = parts[2] + 0 + if (a > 0 && a == b) { found=1; n1=a; n2=b; line=orig } + } + } + END { + if (found) { printf "MATCH: %d / %d\nMatched line: %s\n", n1, n2, line; exit 0 } + exit 1 + } + ' "${MULTI_SERVER_TEST_LOG}" + then + : # PASS + else + echo "TEST FAILED: Detected issues with the test's linelog message logs" + # Display the test's linelog message file + echo "${MULTI_SERVER_TEST_LISTENER_LOG}:" + cat "${MULTI_SERVER_TEST_LISTENER_LOG}" + exit 1 + fi + + # Job only runs on self-hosted runners + run-multi-server-tests-selfhosted: + needs: pre-test + runs-on: self-hosted + if: ${{ needs.pre-test.outputs.selfhosted == '1' }} + + services: + dind: + image: docker:dind + options: --privileged + env: + DOCKER_TLS_CERTDIR: "" + # Bypass the squid proxy for internal registry access. + NO_PROXY: "*.networkradius.com,127.0.0.1" + # Mount the host's internal CA so dind trusts + # docker.internal.networkradius.com for image pulls. + # + # Share the runner's workspace with dind so that docker + # compose bind-mounts (radiusd.conf, env-setup.sh, listener + # dirs, etc.) resolve to real files inside the dind daemon. + # + # github.workspace is the HOST path to the workspace. + # The runner mounts it into the job container at a + # different path (/__w/...), so we use a fixed mount + # point (/workspace) that both containers agree on. + volumes: + - /usr/local/share/ca-certificates/networkradius.com.crt:/etc/docker/certs.d/docker.internal.networkradius.com/ca.crt:ro + - ${{ github.workspace }}:/workspace + + env: + MULTI_SERVER_ENV_DOCKER_BUILD_OS: ubuntu24 + MULTI_SERVER_TEST_LOG: build/tests/multi-server/freeradius-multi-server-test-runtime-logs/multi-server-test.log + MULTI_SERVER_TEST_LISTENER_LOG: build/tests/multi-server/freeradius-multi-server-test-runtime-logs/multi-server-test-linelog-msg-output.log + + container: + image: docker.internal.networkradius.com/self-hosted + # "privileged" is needed for Samba install + # "memory-swap -1" enables full use of host swap and may help + # with containers randomly quitting with "The operation was + # canceled" + options: >- + --privileged + --memory-swap -1 + env: + DOCKER_HOST: tcp://dind:2375 + NO_PROXY: dind + # Shared workspace — see dind volumes comment above. + volumes: + - ${{ github.workspace }}:/workspace + + defaults: + run: + working-directory: /workspace + + steps: + + - name: Install extra packages + run: | + apt-get update && apt-get install -y --no-install-recommends docker.io docker-buildx docker-compose-v2 python3-venv + + # Checkout, but defer pulling LFS objects until we've restored the cache + - uses: actions/checkout@v4 + with: + lfs: false + + # Authenticate to the internal registry via the dind daemon. + # The host Docker daemon is logged in via the runner's + # job-started hook, but dind is a separate daemon with no + # auth config. + - name: Login to internal Docker registry + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_REPO_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.DOCKER_REPO_PASSWORD }} + run: | + echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin https://docker.internal.networkradius.com/ + + - name: Build Docker image from source + run: | + make docker.${MULTI_SERVER_ENV_DOCKER_BUILD_OS}.build + docker tag freeradius4/${MULTI_SERVER_ENV_DOCKER_BUILD_OS}:latest freeradius-build:latest + docker images --all + + - name: Run multi-server tests + run: | + if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^freeradius-build:latest$"; then + echo "Error: freeradius-build:latest Docker image not found and required for multi-server test environment." + exit 1 + fi + + make -f src/tests/multi-server/all.mk + + - name: Verify test results + shell: bash + run: | + set -euo pipefail + + echo "${MULTI_SERVER_TEST_LOG}:" + cat "${MULTI_SERVER_TEST_LOG}" + + if grep -Eq "\(Failures:[^0-9]*[1-9][0-9]*\)" "${MULTI_SERVER_TEST_LOG}"; then + echo "TEST FAILED: Found > 0 failures in log" + + # Display the test's linelog message file + echo "${MULTI_SERVER_TEST_LISTENER_LOG}:" + cat "${MULTI_SERVER_TEST_LISTENER_LOG}" + exit 1 + fi + + # Verify that all of the expected linelog results were matched + # during the test(s). + # + # Checking to see that the value matches value in lines like: + # + # Matched: / (Failures: 0) + # + if awk ' + BEGIN { found=0; n1=0; n2=0; line="" } + index($0,"Matched:") { + orig=$0 + s=$0 + gsub(/[[:space:]]/, "", s) + sub(/^.*Matched:/, "", s) + sub(/\(.*/, "", s) + n = split(s, parts, "/") + if (n == 2) { + a = parts[1] + 0 + b = parts[2] + 0 + if (a > 0 && a == b) { found=1; n1=a; n2=b; line=orig } + } + } + END { + if (found) { printf "MATCH: %d / %d\nMatched line: %s\n", n1, n2, line; exit 0 } + exit 1 + } + ' "${MULTI_SERVER_TEST_LOG}" + then + : # PASS + else + echo "TEST FAILED: Detected issues with the test's linelog message logs" + # Display the test's linelog message file + echo "${MULTI_SERVER_TEST_LISTENER_LOG}:" + cat "${MULTI_SERVER_TEST_LISTENER_LOG}" + exit 1 + fi + + # + # If the CI has failed and the branch is multi-server-baseline-tests then we start a tmate + # session to provide interactive shell access to the session. + # + # The SSH rendezvous point will be emitted continuously in the job output, + # which will look something like: + # + # SSH: ssh VfuX8SrNuU5pGPMyZcz7TpJTa@sfo2.tmate.io + # + # For example: + # + # git push origin multi-server-baseline-tests --force + # + # Look at the job output in: https://github.com/FreeRADIUS/freeradius-server/actions + # + # ssh VfuX8SrNuU5pGPMyZcz7TpJTa@sfo2.tmate.io + # + # Access requires that you have the private key corresponding to the + # public key of the GitHub user that initiated the job. + # + - name: "Debug: Start tmate" + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true + if: ${{ github.ref == 'refs/heads/multi-server-baseline-tests' && failure() }} diff --git a/src/tests/all.mk b/src/tests/all.mk index c75eb39d44e2..8eedaeea21f9 100644 --- a/src/tests/all.mk +++ b/src/tests/all.mk @@ -102,6 +102,10 @@ endif $(BUILD_DIR)/tests: ${Q}mkdir -p $@ +.PHONY: test.multi-server.% +test.multi-server.%: + $(MAKE) -f src/tests/multi-server/all.mk $* + ###################################################################### # # Generic rules to set up the tests diff --git a/src/tests/multi-server/README.md b/src/tests/multi-server/README.md new file mode 100644 index 000000000000..379a60bc4339 --- /dev/null +++ b/src/tests/multi-server/README.md @@ -0,0 +1,83 @@ +If you are reading this, you are probably wondering how to run a multi-server test. Here's a quick overview. + +## Before You Begin +Running the multi-server tests requires the availability of a Docker image `freeradius-build:latest` to be available on the host running the tests. +```bash +% cd ${FREERADIUS-SERVER-LOCAL-REPO} +% make docker.ubuntu24.build +% docker tag freeradius-build:latest +``` + + +## Run Test With Makefile +### Run All Tests + +2. Run make target based on the test name. All testcase config files start with "test-*". +```bash +% cd ${FREERADIUS-SERVER-LOCAL-REPO} +% make -f src/tests/multi-server/all.mk +``` + +### Run Specific Tests (Example) +```bash +% cd ${FREERADIUS-SERVER-LOCAL-REPO} +% make -f src/tests/multi-server/all.mk test-5hs-autoaccept +``` +or +```bash +% cd ${FREERADIUS-SERVER-LOCAL-REPO} +% make -f src/tests/multi-server/all.mk test-1p-2hs-autoaccept +``` + +### Optional Debug Logs and Logging Verbosity Level +```bash +% cd ${FREERADIUS-SERVER-LOCAL-REPO} +% make -f src/tests/multi-server/all.mk test-5hs-autoaccept DEBUG=1 VERBOSE=4 +``` + +## Run Multi-Server Tests Manually Without Makefile (Optional) + +### Clone Multi-Server Test Framework Repo & Activate Python venv +```bash +git clone git@github.com:InkbridgeNetworks/freeradius-multi-server.git ${FREERADIUS-MULTI-SERVER-LOCAL-REPO} +cd ${FREERADIUS-MULTI-SERVER-LOCAL-REPO} +./configure +source .venv/bin/activate +``` + +### Render Jinja Templates + +In this example we render the Jinja templates used by the environment configuration used by the `test-5hs-autoaccept` test. +The Docker Compose `env-5hs-autoaccept.yml` file represents the `load-generator -> 5 homeserver` test environment used by the test. + +Render FreeRADIUS "homeserver" Virtual Server config: +```bash +% python3 src/config_builder.py \ + --vars-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \ + --aux-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/configs/freeradius/homeserver/radiusd.conf.j2" \ + --include-path "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/" + ``` + Render FreeRADIUS "load-generator" Virtual Server config: + ```bash + python3 src/config_builder.py \ + --vars-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \ + --aux-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/configs/freeradius/load-generator/radiusd.conf.j2" \ + --include-path "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/" +``` +Render Docker Compose environment: +```bash + python3 src/config_builder.py \ + --vars-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml" \ + --aux-file "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml.j2" \ + --include-path "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/" +``` + +### Run the test: +```bash +% DATA_PATH="${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/configs" \ + make test-framework -- -x -v \ + --compose "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml" \ + --test "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/src/tests/multi-server/test-5hs-autoaccept.yml" \ + --use-files \ + --listener-dir "${FREERADIUS-MULTI-SERVER-LOCAL-REPO_ABS_PATH}/build/tests/multi-server/freeradius-multi-server-test-runtime-logs/test-5hs-autoaccept" +``` diff --git a/src/tests/multi-server/all.mk b/src/tests/multi-server/all.mk new file mode 100644 index 000000000000..9a4ad500bb6a --- /dev/null +++ b/src/tests/multi-server/all.mk @@ -0,0 +1,282 @@ +# +# all.mk for multi-server tests +# +# Makefile arguments affecting test framework debug logs and verbosity: +# - DEBUG=1 to enable debug logs from multi-server test framework +# - VERBOSE= 1 for normal verbosity (default), up to 4 +# + +# Set required variables for Makefile +SHELL := /bin/bash + +FREERADIUS_SERVER_SRC_PATH_REL := ./ +FREERADIUS_SERVER_SRC_PATH_ABS := $(abspath $(FREERADIUS_SERVER_SRC_PATH_REL)) +FREERADIUS_SERVER_BUILD_DIR_PATH_ABS := $(FREERADIUS_SERVER_SRC_PATH_ABS)/build +FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS := $(FREERADIUS_SERVER_SRC_PATH_ABS)/src/tests/multi-server +FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS := $(FREERADIUS_SERVER_BUILD_DIR_PATH_ABS)/tests/multi-server +FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_REPO := https://github.com/InkbridgeNetworks/freeradius-multi-server.git +FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_BRANCH := logging-rework + +FREERADIUS_MULTI_SERVER_FRAMEWORK_LOG_DIR_ABS:= $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/logs +FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS := $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/logs + +MULTI_SERVER_TEST_COMBINED_LOG := $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/multi-server-tests-stdout-combined.log +MULTI_SERVER_TEST_LINELOG_COMBINED_LOG := $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/multi-server-tests-linelog-combined.log + +# Enable multi-server test framework debug logs +DEBUG ?= 0 +DEBUG_LEVEL_0 := "" +DEBUG_LEVEL_1 := -x +DEBUG_LEVEL_2 := -xx +DEBUG_ARG := $(DEBUG_LEVEL_$(DEBUG)) + +# Multi-server test verbosity level +VERBOSE ?= 1 +VERBOSE_LEVEL_0 := "" +VERBOSE_LEVEL_1 := -v +VERBOSE_LEVEL_2 := -vv +VERBOSE_LEVEL_3 := -vvv +VERBOSE_LEVEL_4 := -vvvv +VERBOSE_ARG := $(VERBOSE_LEVEL_$(VERBOSE)) + +# Default Multi-server tests (1st target of Makefile) +# We purposely do not run all make targets here to run the short +# tests by default. +multi-server: test-5hs-autoaccept test-1p-2hs-autoaccept combine-multi-server-test-linelog + +.PHONY: test.multi-server +test.multi-server: multi-server + +# Clean target to remove all .log and .txt.bak files in the runtime logs directory +.PHONY: clean.test.multi-server +clean.test.multi-server: + @echo "INFO: Removing all .log and .txt.bak files in $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)" + rm -f $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/*.log + rm -f $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/*.log.bak + rm -f $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/*.txt.bak + +# Allow standalone use: make -f src/tests/multi-server/all.mk clean +# Prerequisite-only rule merges safely with the top-level clean target +.PHONY: clean +clean: clean.test.multi-server + +# Hook into the top-level clean.test when included as a submakefile +clean.test: clean.test.multi-server + +# Additional multi-server tests for longer runs +multi-server-5min: test-5hs-autoaccept-5min test-1p-2hs-autoaccept-5min combine-multi-server-test-linelog + +.PHONY: env-5hs-autoaccept test-5hs-autoaccept test-5hs-autoaccept-5min env-1p-2hs-autoaccept test-1p-2hs-autoaccept test-1p-2hs-autoaccept-5min combine-multi-server-test-linelog + +env-5hs-autoaccept: + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + ENV_NAME=$@; \ + \ + echo "INFO: FREERADIUS_SERVER_SRC_PATH_REL=$(FREERADIUS_SERVER_SRC_PATH_REL)"; \ + echo "INFO: FREERADIUS_SERVER_SRC_PATH_ABS=$(FREERADIUS_SERVER_SRC_PATH_ABS)"; \ + echo "INFO: FREERADIUS_SERVER_BUILD_DIR_PATH_ABS=$(FREERADIUS_SERVER_BUILD_DIR_PATH_ABS)"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS=$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS=$(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)"; \ + \ + mkdir -p "$(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)"; \ + mkdir -p "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)"; \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS); \ + \ + if [ ! -d freeradius-multi-server/.git ]; then \ + ( git clone $(FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_REPO) freeradius-multi-server && cd freeradius-multi-server && git checkout $(FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_BRANCH) && cd freeradius-multi-server && git checkout $(FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_BRANCH) ); \ + else \ + #( cd freeradius-multi-server && git pull ); \ + #( cd freeradius-multi-server ); \ + ( cd freeradius-multi-server && git checkout $(FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_BRANCH) && git pull ); \ + fi; \ + \ + cd freeradius-multi-server; \ + $(MAKE) configure; \ + . .venv/bin/activate; \ + \ + echo "INFO: Currently in $$(pwd)"; \ + \ + MULTI_SERVER_ENV_VARS_FILE_PATH_ABS="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/jinja-vars/$$ENV_NAME.vars.yml"; \ + JINJA_RENDERING_SCOPE_PATH_ABS="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)"; \ + echo "INFO: MULTI_SERVER_ENV_VARS_FILE_PATH_ABS=$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS=$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)"; \ + echo "INFO: JINJA_RENDERING_SCOPE_PATH_ABS=$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + set -x; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs/freeradius/homeserver/radiusd.conf.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs/freeradius/load-generator/radiusd.conf.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/$$ENV_NAME.yml.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + + +test-5hs-autoaccept: env-5hs-autoaccept + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + TEST_NAME=$@; \ + \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/freeradius-multi-server; \ + . .venv/bin/activate; \ + \ + echo "INFO: Running $${TEST_NAME}"; \ + \ + set -x; \ + \ + DATA_PATH="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs" \ + make test-framework \ + -- $(DEBUG_ARG) $(VERBOSE_ARG) \ + --compose "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/env-5hs-autoaccept.yml" \ + --test "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/$$TEST_NAME.yml" \ + --use-files \ + --listener-dir "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)" \ + --log-dir "$(FREERADIUS_MULTI_SERVER_FRAMEWORK_LOG_DIR_ABS)" \ + --output "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/$$TEST_NAME-result.log" + +test-5hs-autoaccept-5min: env-5hs-autoaccept + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + TEST_NAME=$@; \ + \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/freeradius-multi-server; \ + . .venv/bin/activate; \ + \ + echo "INFO: Running $${TEST_NAME}"; \ + \ + set -x; \ + \ + DATA_PATH="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs" \ + make test-framework \ + -- $(DEBUG_ARG) $(VERBOSE_ARG) \ + --compose "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/env-5hs-autoaccept.yml" \ + --test "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/test-5hs-autoaccept-5min.yml" \ + --use-files \ + --listener-dir "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)" \ + --log-dir "$(FREERADIUS_MULTI_SERVER_FRAMEWORK_LOG_DIR_ABS)" \ + --output "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/$$TEST_NAME-result.log" + +env-1p-2hs-autoaccept: + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + ENV_NAME=$@; \ + \ + echo "INFO: FREERADIUS_SERVER_SRC_PATH_REL=$(FREERADIUS_SERVER_SRC_PATH_REL)"; \ + echo "INFO: FREERADIUS_SERVER_SRC_PATH_ABS=$(FREERADIUS_SERVER_SRC_PATH_ABS)"; \ + echo "INFO: FREERADIUS_SERVER_BUILD_DIR_PATH_ABS=$(FREERADIUS_SERVER_BUILD_DIR_PATH_ABS)"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS=$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS=$(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)"; \ + \ + mkdir -p "$(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)"; \ + mkdir -p "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)"; \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS); \ + \ + if [ ! -d freeradius-multi-server/.git ]; then \ + git clone $(FREERADIUS_MULTI_SERVER_FRAMEWORK_GIT_REPO); \ + else \ + #( cd freeradius-multi-server && git pull ); \ + ( cd freeradius-multi-server ); \ + fi; \ + \ + cd freeradius-multi-server; \ + $(MAKE) configure; \ + . .venv/bin/activate; \ + \ + echo "INFO: Currently in $$(pwd)"; \ + \ + MULTI_SERVER_ENV_VARS_FILE_PATH_ABS="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/jinja-vars/$$ENV_NAME.vars.yml"; \ + JINJA_RENDERING_SCOPE_PATH_ABS="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)"; \ + echo "INFO: MULTI_SERVER_ENV_VARS_FILE_PATH_ABS=$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS"; \ + echo "INFO: FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS=$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)"; \ + echo "INFO: JINJA_RENDERING_SCOPE_PATH_ABS=$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + set -x; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs/freeradius/homeserver/radiusd.conf.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs/freeradius/proxy/radiusd.conf.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs/freeradius/load-generator/radiusd.conf.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + \ + python3 src/config_builder.py \ + --vars-file "$$MULTI_SERVER_ENV_VARS_FILE_PATH_ABS" \ + --aux-file "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/$$ENV_NAME.yml.j2" \ + --include-path "$$JINJA_RENDERING_SCOPE_PATH_ABS"; \ + + +test-1p-2hs-autoaccept: env-1p-2hs-autoaccept + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + TEST_NAME=$@; \ + \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/freeradius-multi-server; \ + . .venv/bin/activate; \ + \ + echo "INFO: Running $${TEST_NAME}"; \ + \ + set -x; \ + \ + DATA_PATH="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs" \ + make test-framework \ + -- $(DEBUG_ARG) $(VERBOSE_ARG) \ + --compose "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/env-1p-2hs-autoaccept.yml" \ + --test "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/test-1p-2hs-autoaccept.yml" \ + --use-files \ + --listener-dir "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)" \ + --log-dir "$(FREERADIUS_MULTI_SERVER_FRAMEWORK_LOG_DIR_ABS)" \ + --output "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/$$TEST_NAME-result.log" + +test-1p-2hs-autoaccept-5min: env-1p-2hs-autoaccept + @LOG_FILE="$(MULTI_SERVER_TEST_COMBINED_LOG)"; \ + set -e; exec &> >(tee -a "$${LOG_FILE}"); \ + \ + TEST_NAME=$@; \ + \ + cd $(FREERADIUS_MULTI_SERVER_BUILD_DIR_PATH_ABS)/freeradius-multi-server; \ + . .venv/bin/activate; \ + \ + echo "INFO: Running $${TEST_NAME}"; \ + \ + set -x; \ + \ + DATA_PATH="$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/configs" \ + make test-framework \ + -- $(DEBUG_ARG) $(VERBOSE_ARG) \ + --compose "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/environments/docker-compose/env-1p-2hs-autoaccept.yml" \ + --test "$(FREERADIUS_MULTI_SERVER_TESTS_BASE_PATH_ABS)/$$TEST_NAME.yml" \ + --use-files \ + --listener-dir "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)" \ + --log-dir "$(FREERADIUS_MULTI_SERVER_FRAMEWORK_LOG_DIR_ABS)" \ + --output "$(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/$$TEST_NAME-result.log" + +combine-multi-server-test-linelog: + @echo "INFO: Combining multi-server test linelog message output into $(MULTI_SERVER_TEST_LINELOG_COMBINED_LOG)" + @rm -f $(MULTI_SERVER_TEST_LINELOG_COMBINED_LOG) + for f in $(FREERADIUS_MULTI_SERVER_TEST_RUNTIME_LOGS_DIR_ABS)/*.txt.bak; do \ + echo "$$f"; \ + cat "$$f"; \ + echo ""; \ + done > $(MULTI_SERVER_TEST_LINELOG_COMBINED_LOG) diff --git a/src/tests/multi-server/environments/configs/README.md b/src/tests/multi-server/environments/configs/README.md new file mode 100644 index 000000000000..7cbfa826766a --- /dev/null +++ b/src/tests/multi-server/environments/configs/README.md @@ -0,0 +1,2 @@ +Test environment configuration files which includes, and not limited to, FreeRADIUS configuration, and 3rd party +environment component configuration, etc. diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/always b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/always new file mode 100644 index 000000000000..18bbcb4136d5 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/always @@ -0,0 +1,7 @@ + +always ok { + rcode = ok +} +always handled { + rcode = handled +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/attr_filter b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/attr_filter new file mode 100644 index 000000000000..321ac61600e6 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/attr_filter @@ -0,0 +1,15 @@ + +attr_filter attr_filter.access_reject { + key = User-Name + filename = ${modconfdir}/${.:name}/access_reject +} + +attr_filter attr_filter.access_challenge { + key = User-Name + filename = ${modconfdir}/${.:name}/access_challenge +} + +attr_filter attr_filter.accounting_response { + key = User-Name + filename = ${modconfdir}/${.:name}/accounting_response +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/detail b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/detail new file mode 100644 index 000000000000..68e7fe7580ff --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/detail @@ -0,0 +1,7 @@ + +detail { + filename = "${radacctdir}/%{Net.Src.IP}/detail-%Y-%m-%d" + escape_filenames = no + permissions = 0600 + header = "%t" +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/files b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/files new file mode 100644 index 000000000000..1bf5ba079503 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/files @@ -0,0 +1,9 @@ + +files { + moddir = ${modconfdir}/${.:instance} + filename = ${moddir}/authorize +} + +files files_accounting { + filename = ${modconfdir}/files/accounting +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/json b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/json new file mode 100644 index 000000000000..f6693ab72053 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/json @@ -0,0 +1,8 @@ +json { + encode { + output_mode = object_simple + value { + binary_format = base16 + } + } +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog new file mode 100644 index 000000000000..3e89bdadd586 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog @@ -0,0 +1,20 @@ + +linelog { + format = "This is a log message for %{User-Name}" + destination = file + + file { + filename = ${logdir}/linelog + permissions = 0600 + escape_filenames = no + + # Disable message buffering + buffer_count = 0 + buffer_delay = 0 + buffer_expiry = 0 + } +} + +linelog log_stdout { + destination = stdout +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_file b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_file new file mode 100644 index 000000000000..3d92e0892004 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_file @@ -0,0 +1,15 @@ + +linelog linelog_test_framework { + destination = file + + file { + filename = /var/run/multi-server/$ENV{TEST_PROJECT_NAME}.txt + permissions = 0644 + escape_filenames = no + + # Disable message buffering + buffer_count = 0 + buffer_delay = 0 + buffer_expiry = 0 + } +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_socket b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_socket new file mode 100644 index 000000000000..9a211329300c --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/linelog_socket @@ -0,0 +1,19 @@ + +linelog linelog_test_framework { + destination = unix + format = "bar" + + unix { + filename = /var/run/multi-server/$ENV{TEST_PROJECT_NAME}.sock + pool { + start = 1 + min = 1 + max = 1 + spare = 0 + uses = 0 + retry_delay = 30 + lifetime = 0 + idle_timeout = 0 + } + } +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/mods-available/stats b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/stats new file mode 100644 index 000000000000..1114816e0055 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/mods-available/stats @@ -0,0 +1,4 @@ + +stats { + +} diff --git a/src/tests/multi-server/environments/configs/freeradius/common/policy.d/control b/src/tests/multi-server/environments/configs/freeradius/common/policy.d/control new file mode 100644 index 000000000000..c2f3893460b6 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/common/policy.d/control @@ -0,0 +1,6 @@ + +accept { + reply.Packet-Type := ::Access-Accept + + handled +} diff --git a/src/tests/multi-server/environments/configs/freeradius/env-setup.sh b/src/tests/multi-server/environments/configs/freeradius/env-setup.sh new file mode 100755 index 000000000000..ff46e3ab9434 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/env-setup.sh @@ -0,0 +1,7 @@ +apt-get update +apt-get install -y iputils-ping iproute2 ipcalc +IP_CIDR=$(ip -o -f inet addr show eth0 | awk '{print $4}') +TEST_SUBNET=$(ipcalc -n "$IP_CIDR" | grep Network | awk '{print $2}') +export TEST_SUBNET +echo "TEST_SUBNET=$TEST_SUBNET" >> /etc/environment +echo "Detected TEST_SUBNET: $TEST_SUBNET" diff --git a/src/tests/multi-server/environments/configs/freeradius/homeserver/radiusd.conf.j2 b/src/tests/multi-server/environments/configs/freeradius/homeserver/radiusd.conf.j2 new file mode 100644 index 000000000000..ba1fc7673ead --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/homeserver/radiusd.conf.j2 @@ -0,0 +1,231 @@ +name = homeserver + +raddbdir = /etc/freeradius +confdir = ${raddbdir} +modconfdir = ${confdir}/mods-config +logdir = /var/log/freeradius +radacctdir = ${logdir}/radacct + +security { + allow_core_dumps = yes +} + +trigger { + + server { + start = "%linelog('server_start homeserver starting')" + + stop = "%linelog('server_stop homeserver stopping')" + + max_requests = "%linelog('server_max_requests homeserver max requests reached')" + } + +} + +# logging configuration required for linelog module +log { + destination = files + file = ${logdir}/radius.log + syslog_facility = daemon + stripped_names = no + auth = yes + auth_badpass = yes + auth_goodpass = yes +} + +modules { + # Common linelog module configuration + {% include "environments/configs/freeradius/common/mods-available/linelog" %} + + # Test framework linelog module configuration based on OS environment + {% if listener_type == "unix" %} + {% include "environments/configs/freeradius/common/mods-available/linelog_socket" %} + {% elif listener_type == "file" %} + {% include "environments/configs/freeradius/common/mods-available/linelog_file" %} + {% endif %} + + # Common json module configuration + {% include "environments/configs/freeradius/common/mods-available/json" %} + + # Common always module configuration + {% include "environments/configs/freeradius/common/mods-available/always" %} + + # Common attr_filter module configuration + {% include "environments/configs/freeradius/common/mods-available/attr_filter" %} + + # Common files module configuration + {% include "environments/configs/freeradius/common/mods-available/files" %} + + # Common detail module configuration + {% include "environments/configs/freeradius/common/mods-available/detail" %} +} + +policy { + # Common control policy configuration + {% include "environments/configs/freeradius/common/policy.d/control" %} +} + +server hs-auto-accept { + + namespace = radius + + listen authentication { + type = Access-Request + type = Status-Server + transport = udp + require_message_authenticator = auto + limit_proxy_state = auto + limit { + max_clients = 256 + max_connections = 256 + idle_timeout = 60.0 + dynamic_timeout = 600.0 + nak_lifetime = 30.0 + cleanup_delay = 5.0 + } + udp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + tcp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + } + + listen authentication { + type = Access-Request + type = Status-Server + transport = tcp + tcp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + } + + listen accounting { + type = Accounting-Request + transport = udp + udp { + ipaddr = * + port = 1813 + } + } + + client upstream-proxy { + ipaddr = $ENV{TEST_SUBNET} + secret = testing123 + require_message_authenticator = auto + limit_proxy_state = auto + } + + recv Access-Request { + string Log-Timestamp + string Log-Label + string Log-Message + string Log-Homeserver-IP-Port + string Log-Request-Source-IP-Port + + # Initialization + Log-Timestamp := "%Y-%m-%d-%H:%G:%e" + Log-Label := "INFO" + Log-Message := "Access-Request received" + Log-Homeserver-IP-Port := "%{Net.Dst.IP}:%{Net.Dst.Port}" + Log-Request-Source-IP-Port := "%{Net.Src.IP}:%{Net.Src.Port}" + + {% raw %} + %linelog("homeserver-access-request {\"Log-Timestamp\": %{Log-Timestamp}, \"Log-Label\": %{Log-Label}, \"Log-Message\": %{Log-Message}, \"Log-Homeserver-IP-Port\": %{Log-Homeserver-IP-Port}, \"Log-Request-Source-IP-Port\": %{Log-Request-Source-IP-Port}}, \"User-Name\": \"%{%{User-Name}}\", \"Calling-Station-Id\": \"%{Calling-Station-Id}\"") + + {% endraw %} + accept + } + + send Access-Accept { + string Log-Timestamp + string Log-Label + string Log-Message + string Log-Homeserver-IP-Port + string Log-Request-Source-IP-Port + + # Initialization + Log-Timestamp := "%Y-%m-%d-%H:%G:%e" + Log-Label := "INFO" + Log-Message := "Access-Accept sent" + Log-Homeserver-IP-Port := "%{Net.Dst.IP}:%{Net.Dst.Port}" + Log-Request-Source-IP-Port := "%{Net.Src.IP}:%{Net.Src.Port}" + + {% raw %} + %linelog("homeserver-access-accept {\"Log-Timestamp\": %{Log-Timestamp}, \"Log-Label\": %{Log-Label}, \"Log-Message\": %{Log-Message}, \"Log-Homeserver-IP-Port\": %{Log-Homeserver-IP-Port}, \"Log-Request-Source-IP-Port\": %{Log-Request-Source-IP-Port}}") + {% endraw %} + + handled + } + + recv Status-Server { + ok + } + + send Access-Challenge { + attr_filter.access_challenge + } + + send Access-Reject { + string Log-Timestamp + string Log-Label + string Log-Message + string Log-Homeserver-IP-Port + string Log-Request-Source-IP-Port + + # Initialization + Log-Timestamp := "%Y-%m-%d-%H:%G:%e" + Log-Label := "ERROR" + Log-Message := "Access-Reject sent" + Log-Homeserver-IP-Port := "%{Net.Dst.IP}:%{Net.Dst.Port}" + Log-Request-Source-IP-Port := "%{Net.Src.IP}:%{Net.Src.Port}" + + {% raw %} + %linelog_test_framework("homeserver-access-reject {\"Log-Timestamp\": %{Log-Timestamp}, \"Log-Label\": %{Log-Label}, \"Log-Message\": %{Log-Message}, \"Log-Homeserver-IP-Port\": %{Log-Homeserver-IP-Port}, \"Log-Request-Source-IP-Port\": %{Log-Request-Source-IP-Port}}") + {% endraw %} + + attr_filter.access_reject + } + + recv Accounting-Request { + files_accounting + } + + accounting Start { + } + + accounting Stop { + } + + accounting Interim-Update { + } + + accounting Accounting-On { + } + + accounting Accounting-Off { + } + + accounting Failed { + } + + send Accounting-Response { + detail + attr_filter.accounting_response + } +} diff --git a/src/tests/multi-server/environments/configs/freeradius/load-generator/load-generator-packets/packet.conf b/src/tests/multi-server/environments/configs/freeradius/load-generator/load-generator-packets/packet.conf new file mode 100644 index 000000000000..46c2a8fd73c9 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/load-generator/load-generator-packets/packet.conf @@ -0,0 +1,3 @@ +User-Name = "testuser" +User-Password = "testpass" +Calling-Station-ID = "F1-F2-F3-F4-F5-F6" diff --git a/src/tests/multi-server/environments/configs/freeradius/load-generator/mods-config/files/authorize b/src/tests/multi-server/environments/configs/freeradius/load-generator/mods-config/files/authorize new file mode 100644 index 000000000000..eba3cb96136c --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/load-generator/mods-config/files/authorize @@ -0,0 +1 @@ +testuser Password.Cleartext := "testpass" diff --git a/src/tests/multi-server/environments/configs/freeradius/load-generator/radiusd.conf.j2 b/src/tests/multi-server/environments/configs/freeradius/load-generator/radiusd.conf.j2 new file mode 100644 index 000000000000..052bb3734a50 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/load-generator/radiusd.conf.j2 @@ -0,0 +1,223 @@ +name = load-generator + +raddbdir = /etc/freeradius +confdir = ${raddbdir} +modconfdir = ${confdir}/mods-config +logdir = /var/log/freeradius +radacctdir = ${logdir}/radacct + +templates { + {% include "environments/configs/freeradius/load-generator/template.d/load-generator-templates" %} +} + +security { + allow_core_dumps = yes +} + +# logging configuration required for linelog module +log { + destination = files + file = ${logdir}/radius.log + syslog_facility = daemon + stripped_names = no + auth = yes + auth_badpass = yes + auth_goodpass = yes +} + +modules { + # Common linelog module configuration + {% include "environments/configs/freeradius/common/mods-available/linelog" %} + + # Test framework linelog module configuration based on OS environment + {% if listener_type == "unix" %} + {% include "environments/configs/freeradius/common/mods-available/linelog_socket" %} + {% elif listener_type == "file" %} + {% include "environments/configs/freeradius/common/mods-available/linelog_file" %} + {% endif %} + + # Common json module configuration + {% include "environments/configs/freeradius/common/mods-available/json" %} + + # Common stats module configuration + {% include "environments/configs/freeradius/common/mods-available/stats" %} + + # radius module instance configuration + {% for i in range(1, (load_gen_num_of_dst_servers + 1)) %} + radius radius-module-dst-server{{ i }} { + $template radius-module-dst-server-tmpl + udp { + ipaddr = {{ load_gen_dst_server_name }}{{ i }} + } + } + {% endfor %} + +} + +server load-generator { + + namespace = radius + + listen load { + handler = load + type = Access-Request + transport = step + + step { + + # Default packet config to use by the load-generator + filename = ${confdir}/load-generator-packets/packet.conf + + csv = ${confdir}/stats/load-generator-client-stats.csv + + max_attributes = 64 + + # + # The load profile is configured via environment variables set + # in the testcase configuration files. + # + start_pps = $ENV{TEST_CONF_START_PPS} + max_pps = $ENV{TEST_CONF_MAX_PPS} + duration = $ENV{TEST_CONF_DURATION} + step = $ENV{TEST_CONF_STEP} + max_backlog = $ENV{TEST_CONF_MAX_BACKLOG} + parallel = $ENV{TEST_CONF_PARALLEL} + num_messages = $ENV{TEST_CONF_NUM_MESSAGES} + repeat = no + } + } + + listen authentication { + type = Access-Request + type = Status-Server + transport = udp + require_message_authenticator = auto + limit_proxy_state = auto + + limit { + max_clients = 256 + max_connections = 256 + idle_timeout = 60.0 + dynamic_timeout = 600.0 + nak_lifetime = 30.0 + cleanup_delay = 5.0 + } + + udp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + + tcp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + } + + listen authentication { + type = Access-Request + type = Status-Server + transport = tcp + + tcp { + ipaddr = * + port = 1812 + networks { + allow = 127/8 + allow = 192.0.2/24 + } + } + } + + client localhost { + shortname = client-localhost + ipaddr = * + secret = testing123 + } + + listen statusserver { + transport = udp + udp { + ipaddr = * + port = 1820 + } + + type = Status-Server + } + + # + # Receive a Status-Server packet + # + recv Status-Server { + uint32 Status-Server-Counter + uint32 Access-Request-Counter + uint32 Access-Accept-Counter + uint32 Access-Reject-Counter + string Status-Server-Result + string Status-Server-Message + + # Initialization + Status-Server-Counter := 0 + Access-Request-Counter := 0 + Access-Accept-Counter := 0 + Access-Reject-Counter := 0 + Status-Server-Result := "FAIL" + Status-Server-Message := "" + + # stats module required to have access to the Status-Server's global statistics + stats + + {%raw%} + Status-Server-Counter := %{reply.FreeRADIUS.Stats4.Packet-Counters.Status-Server || 0} + Access-Request-Counter := %{reply.FreeRADIUS.Stats4.Packet-Counters.Access-Request || 0} + Access-Accept-Counter := %{reply.FreeRADIUS.Stats4.Packet-Counters.Access-Accept || 0} + Access-Reject-Counter := %{reply.FreeRADIUS.Stats4.Packet-Counters.Access-Reject || 0} + + # The Stats Module documentation explicitly states: "When listed in a recv Status-Server section, it will add global server statistics to the packet, + # hence the reason "reply.FreeRADIUS.Stats4" is used below. + if ((reply.FreeRADIUS.Stats4.Packet-Counters.Access-Accept - reply.FreeRADIUS.Stats4.Packet-Counters.Status-Server) != reply.FreeRADIUS.Stats4.Packet-Counters.Access-Request) { + Status-Server-Result := "FAIL" + Status-Server-Message := "expected vs actual stat mismatch" + } + + if (reply.FreeRADIUS.Stats4.Packet-Counters.Access-Request == (reply.FreeRADIUS.Stats4.Packet-Counters.Access-Accept - reply.FreeRADIUS.Stats4.Packet-Counters.Status-Server)) { + Status-Server-Result := "PASS" + Status-Server-Message := "requests processed successfully" + } + + %linelog_test_framework("load-generator-status-server {\"Status-Server-Result\": %json.quote(%{Status-Server-Result}), \"Status-Server-Message\": %json.quote(%{Status-Server-Message}), \"Status-Server-Counter\": %{Status-Server-Counter}, \"Access-Request-Counter\": %{Access-Request-Counter}, \"Access-Accept-Counter\": %{Access-Accept-Counter}, \"Access-Reject-Counter\": %{Access-Reject-Counter}}") + + {%endraw%} + } + + recv Access-Request { + # Use the load-generator-proxy authenticate logic + control.Auth-Type := "load-generator-proxy" + } + + authenticate load-generator-proxy { + # Use redundant-load-balance to distribute requests to multiple home servers + redundant-load-balance { + {% for i in range(1, (load_gen_num_of_dst_servers + 1)) %} + radius-module-dst-server{{ i }} + {% endfor %} + } + } + + send Access-Accept { + stats + } + + send Access-Reject { + stats + } + +} diff --git a/src/tests/multi-server/environments/configs/freeradius/load-generator/stats/load-generator-client-stats.csv b/src/tests/multi-server/environments/configs/freeradius/load-generator/stats/load-generator-client-stats.csv new file mode 100644 index 000000000000..34c1880c5db7 --- /dev/null +++ b/src/tests/multi-server/environments/configs/freeradius/load-generator/stats/load-generator-client-stats.csv @@ -0,0 +1 @@ +"time","last_packet","rtt","rttvar","pps","pps_accepted","sent","received","backlog","max_backlog"," HS1 (auto-accept) +# load-generator --> Proxy1 +# --> HS2 (auto-accept) +# +# --------------------------------------------------------------- +x-common-config: &id001 + cap_add: + - NET_ADMIN + - SYS_PTRACE +services: +{% for i in range(1, (compose_num_of_home_servers + 1)) %} + homeserver{{ i }}: + image: freeradius-build:latest + volumes: + - ${DATA_PATH}/freeradius/homeserver/radiusd.conf:/etc/raddb/radiusd.conf + - ${DATA_PATH}/freeradius/env-setup.sh:/tmp/env-setup.sh + - ${LISTENER_DIR}/:/var/run/multi-server/ + command: radiusd -X + restart: unless-stopped + entrypoint: + - bash + - -lc + - | + set -euo pipefail + + # Next three lines based on test-framework test config example + source /tmp/env-setup.sh + export TEST_PROJECT_NAME=${COMPOSE_PROJECT_NAME} + + exec /docker-entrypoint.sh "$@" + sleep infinity + <<: *id001 +{% endfor %} +{% for i in range(1, (compose_num_of_proxy_servers + 1)) %} + proxy{{ i }}: + image: freeradius-build:latest + depends_on: + {% for i in range(1, (compose_num_of_home_servers + 1)) %} + - homeserver{{ i }} + {% endfor %} + volumes: + - ${DATA_PATH}/freeradius/proxy/radiusd.conf:/etc/raddb/radiusd.conf + - ${DATA_PATH}/freeradius/env-setup.sh:/tmp/env-setup.sh + - ${LISTENER_DIR}/:/var/run/multi-server/ + command: radiusd -X + restart: unless-stopped + entrypoint: + - bash + - -lc + - | + set -euo pipefail + + # Next three lines based on test-framework test config example + source /tmp/env-setup.sh + export TEST_PROJECT_NAME=${COMPOSE_PROJECT_NAME} + + exec /docker-entrypoint.sh "$@" + sleep infinity + <<: *id001 +{% endfor %} + load-generator: + image: freeradius-build:latest + ports: + # Expose RADIUS ports for load generator to allow us to access the server from outside docker + - "1812:1812/udp" + - "1813:1813/udp" + - "1820:1820/udp" + depends_on: + {% for i in range(1, (compose_num_of_proxy_servers + 1)) %} + - proxy{{ i }} + {% endfor %} + volumes: + # load-generator templates + - ${DATA_PATH}/freeradius/load-generator/template.d/load-generator-templates:/etc/raddb/template.d/load-generator-templates + + # Setup a testuser/testpass user for authentication testing with load-generator + # This is only really needed when testing the load-generator with radclient during development. + - ${DATA_PATH}/freeradius/load-generator/mods-config/files/authorize:/etc/raddb/mods-config/files/authorize + + # load-generator server config + - ${DATA_PATH}/freeradius/load-generator/radiusd.conf:/etc/raddb/radiusd.conf + + - ${DATA_PATH}/freeradius/env-setup.sh:/tmp/env-setup.sh + - ${DATA_PATH}/freeradius/load-generator/load-generator-packets/:/etc/raddb/load-generator-packets/ + - ${LISTENER_DIR}/:/var/run/multi-server/ + environment: + TEST_PROJECT_NAME: ${COMPOSE_PROJECT_NAME} + TEST_CONF_START_PPS: 5 + TEST_CONF_MAX_PPS: 10 + TEST_CONF_DURATION: 5 + TEST_CONF_STEP: 5 + TEST_CONF_PARALLEL: 1 + TEST_CONF_MAX_BACKLOG: 1000 + TEST_CONF_REPEAT: "no" + entrypoint: + - bash + - -lc + - | + set -euo pipefail + + source /tmp/env-setup.sh + export TEST_PROJECT_NAME=${COMPOSE_PROJECT_NAME} + + sleep infinity + <<: *id001 diff --git a/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml.j2 b/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml.j2 new file mode 100644 index 000000000000..35b8e09c3f53 --- /dev/null +++ b/src/tests/multi-server/environments/docker-compose/env-5hs-autoaccept.yml.j2 @@ -0,0 +1,87 @@ +# --------------------------------------------------------------- +# Docker Compose Test Environment: +# +# --> HS1 (auto-accept) +# +# --> HS2 (auto-accept) +# +# load-generator --> HS3 (auto-accept) +# +# --> HS4 (auto-accept) +# +# --> HS5 (auto-accept) +# +# --------------------------------------------------------------- +x-common-config: &id001 + cap_add: + - NET_ADMIN + - SYS_PTRACE +services: +{% for i in range(1, (compose_num_of_home_servers + 1)) %} + homeserver{{ i }}: + image: freeradius-build:latest + volumes: + - ${DATA_PATH}/freeradius/homeserver/radiusd.conf:/etc/raddb/radiusd.conf + - ${DATA_PATH}/freeradius/env-setup.sh:/tmp/env-setup.sh + - ${LISTENER_DIR}/:/var/run/multi-server/ + command: radiusd -X + restart: unless-stopped + entrypoint: + - bash + - -lc + - | + set -euo pipefail + + # Next three lines based on test-framework test config example + source /tmp/env-setup.sh + export TEST_PROJECT_NAME=${COMPOSE_PROJECT_NAME} + + exec /docker-entrypoint.sh "$@" + sleep infinity + <<: *id001 +{% endfor %} + load-generator: + image: freeradius-build:latest + ports: + # Expose RADIUS ports for load generator to allow us to access the server from outside docker + - "1812:1812/udp" + - "1813:1813/udp" + - "1820:1820/udp" + depends_on: +{% for i in range(1, (compose_num_of_home_servers + 1)) %} + - homeserver{{ i }} +{% endfor %} + volumes: + # load-generator templates + - ${DATA_PATH}/freeradius/load-generator/template.d/load-generator-templates:/etc/raddb/template.d/load-generator-templates + + # Setup a testuser/testpass user for authentication testing with load-generator + # This is only really needed when testing the load-generator with radclient during development. + - ${DATA_PATH}/freeradius/load-generator/mods-config/files/authorize:/etc/raddb/mods-config/files/authorize + + # load-generator server config + - ${DATA_PATH}/freeradius/load-generator/radiusd.conf:/etc/raddb/radiusd.conf + + - ${DATA_PATH}/freeradius/env-setup.sh:/tmp/env-setup.sh + - ${DATA_PATH}/freeradius/load-generator/load-generator-packets/:/etc/raddb/load-generator-packets/ + - ${LISTENER_DIR}/:/var/run/multi-server/ + environment: + TEST_PROJECT_NAME: ${COMPOSE_PROJECT_NAME} + TEST_CONF_START_PPS: 5 + TEST_CONF_MAX_PPS: 10 + TEST_CONF_DURATION: 5 + TEST_CONF_STEP: 5 + TEST_CONF_PARALLEL: 1 + TEST_CONF_MAX_BACKLOG: 1000 + TEST_CONF_REPEAT: "no" + entrypoint: + - bash + - -lc + - | + set -euo pipefail + + source /tmp/env-setup.sh + export TEST_PROJECT_NAME=${COMPOSE_PROJECT_NAME} + + sleep infinity + <<: *id001 diff --git a/src/tests/multi-server/environments/jinja-vars/env-1p-2hs-autoaccept.vars.yml b/src/tests/multi-server/environments/jinja-vars/env-1p-2hs-autoaccept.vars.yml new file mode 100644 index 000000000000..7d57ecb854bd --- /dev/null +++ b/src/tests/multi-server/environments/jinja-vars/env-1p-2hs-autoaccept.vars.yml @@ -0,0 +1,17 @@ +jinja_templates_to_render: + - environments/configs/freeradius/homeserver/radiusd.conf.j2 + - environments/configs/freeradius/proxy/radiusd.conf.j2 + - environments/configs/freeradius/load-generator/radiusd.conf.j2 + - environments/docker-compose/env-1p-2hs-autoaccept.yml.j2 + +# Docker compose Jinja template vars +compose_num_of_home_servers: 2 +compose_num_of_proxy_servers: 1 +# Load generator Jinja template vars +load_gen_num_of_dst_servers: 1 +load_gen_dst_server_name: proxy +# Proxy server Jinja template vars +proxy_num_of_dst_servers: 2 +proxy_dst_server_name: homeserver +# General Jinja template vars +listener_type: file diff --git a/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml b/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml new file mode 100644 index 000000000000..2c6c2ea936d6 --- /dev/null +++ b/src/tests/multi-server/environments/jinja-vars/env-5hs-autoaccept.vars.yml @@ -0,0 +1,12 @@ +jinja_templates_to_render: + - environments/configs/freeradius/homeserver/radiusd.conf.j2 + - environments/configs/freeradius/load-generator/radiusd.conf.j2 + - environments/docker-compose/env-5hs-autoaccept.yml.j2 + +# Docker compose Jinja template vars +compose_num_of_home_servers: 5 +# Load generator Jinja template vars +load_gen_num_of_dst_servers: 5 +load_gen_dst_server_name: homeserver +# General Jinja template vars +listener_type: file diff --git a/src/tests/multi-server/test-1p-2hs-autoaccept-5min.yml b/src/tests/multi-server/test-1p-2hs-autoaccept-5min.yml new file mode 100644 index 000000000000..991df0224916 --- /dev/null +++ b/src/tests/multi-server/test-1p-2hs-autoaccept-5min.yml @@ -0,0 +1,69 @@ +timeout: 370 +state_order: sequence +states: + state_1: + description: 5 minute load-generator test building off of baseline load-generator -> 1 proxy -> 2 home servers test. Home servers auto-accept requests. + host: + load-generator: + actions: + - execute_command: + command: | + # + # proto_load configuration via environment variables + # + + export TEST_CONF_START_PPS=300 + export TEST_CONF_MAX_PPS=350 + # Duration must be equal or greater than max pps for proto_load to calculate "pps_accepted" effectively + export TEST_CONF_DURATION=60 + export TEST_CONF_STEP=10 + export TEST_CONF_PARALLEL=1 + export TEST_CONF_MAX_BACKLOG=1000 + export TEST_CONF_REPEAT="no" + + TEST_CONF_NUM_MESSAGES=0 + for ((pps=$TEST_CONF_START_PPS; pps<=$TEST_CONF_MAX_PPS; pps+=$TEST_CONF_STEP)); do + TEST_CONF_NUM_MESSAGES=$((TEST_CONF_NUM_MESSAGES + TEST_CONF_DURATION * pps)) + done + export TEST_CONF_NUM_MESSAGES + + # + # Delay to allow the rest of the environment to startup before starting load generation + # + sleep 20 + + # + # Starting load-generator server which will generate traffic based on env configuration + # from above. + # + /docker-entrypoint.sh & + tail -f /dev/null + + detach: true + verify: + timeout: 360 + trigger_mode: unordered + state_2: + description: Check load-generator Status-Server stats + host: + load-generator: + actions: + - execute_command: + command: | + # This command will query the load-generator's built-in Status-Server for statistics. Port 1820 configured to be used for Status-Server. + printf 'User-Name := "testuser"\nUser-Password := "testpass"' | /usr/bin/radclient -x localhost:1820 status testing123 + verify: + timeout: 5 + trigger_mode: unordered + triggers: + - load-generator-status-server: + json: + Status-Server-Result: + pattern: + reg_pattern: PASS + Access-Request-Counter: + pattern: + reg_pattern: (\d+) + Access-Accept-Counter: + pattern: + reg_pattern: (\d+) diff --git a/src/tests/multi-server/test-1p-2hs-autoaccept.yml b/src/tests/multi-server/test-1p-2hs-autoaccept.yml new file mode 100644 index 000000000000..37349aa83daf --- /dev/null +++ b/src/tests/multi-server/test-1p-2hs-autoaccept.yml @@ -0,0 +1,79 @@ +timeout: 50 +state_order: sequence +states: + state_1: + description: Baseline load-generator test for load-generator -> 1 proxy -> 2 home servers. Home servers auto-accept requests. + host: + load-generator: + actions: + - execute_command: + command: | + # + # proto_load configuration via environment variables + # + + export TEST_CONF_START_PPS=5 + export TEST_CONF_MAX_PPS=10 + # Duration must be equal or greater than max pps for proto_load to calculate "pps_accepted" effectively + export TEST_CONF_DURATION=5 + export TEST_CONF_STEP=5 + export TEST_CONF_PARALLEL=1 + export TEST_CONF_MAX_BACKLOG=1000 + export TEST_CONF_REPEAT="no" + + TEST_CONF_NUM_MESSAGES=0 + for ((pps=$TEST_CONF_START_PPS; pps<=$TEST_CONF_MAX_PPS; pps+=$TEST_CONF_STEP)); do + TEST_CONF_NUM_MESSAGES=$((TEST_CONF_NUM_MESSAGES + TEST_CONF_DURATION * pps)) + done + export TEST_CONF_NUM_MESSAGES + + # + # Delay to allow the rest of the environment to startup before starting load generation. + # + sleep 20 + + # + # Starting load-generator server which will generate traffic based on env configuration + # from above. + # + printf "Starting load-generator with the following configuration:\n" + printf " Start PPS: %s\n" "$TEST_CONF_START_PPS" + printf " Max PPS: %s\n" "$TEST_CONF_MAX_PPS" + printf " Duration (secs): %s\n" "$TEST_CONF_DURATION" + printf " Step PPS: %s\n" "$TEST_CONF_STEP" + printf " Parallel: %s\n" "$TEST_CONF_PARALLEL" + printf " Max Backlog: %s\n" "$TEST_CONF_MAX_BACKLOG" + printf " Num Messages: %s\n" "$TEST_CONF_NUM_MESSAGES" + + freeradius & + + tail -f /dev/null + + detach: true + verify: + timeout: 40 + trigger_mode: unordered + state_2: + description: Check load-generator Status-Server stats + host: + load-generator: + actions: + - execute_command: + command: | + # This command will query the load-generator's built-in Status-Server for statistics. Port 1820 configured to be used for Status-Server. + printf 'User-Name := "testuser"\nUser-Password := "testpass"' | /usr/bin/radclient -x localhost:1820 status testing123 + verify: + timeout: 5 + trigger_mode: unordered + triggers: + - load-generator-status-server: + json: + Status-Server-Result: + pattern: + reg_pattern: PASS + Access-Request-Counter: + pattern: + reg_pattern: (\d+) + Access-Accept-Counter: + pattern: + reg_pattern: (\d+) diff --git a/src/tests/multi-server/test-5hs-autoaccept-5min.yml b/src/tests/multi-server/test-5hs-autoaccept-5min.yml new file mode 100644 index 000000000000..99f9dcf9b6a7 --- /dev/null +++ b/src/tests/multi-server/test-5hs-autoaccept-5min.yml @@ -0,0 +1,79 @@ +timeout: 370 +state_order: sequence +states: + state_1: + description: 5 minute load-generator test building off of baseline load-generator -> 5 home servers test. Home servers auto-accept requests. + host: + load-generator: + actions: + - execute_command: + command: | + # + # proto_load configuration via environment variables + # + + export TEST_CONF_START_PPS=300 + export TEST_CONF_MAX_PPS=350 + # Duration must be equal or greater than max pps for proto_load to calculate "pps_accepted" effectively + export TEST_CONF_DURATION=60 + export TEST_CONF_STEP=10 + export TEST_CONF_PARALLEL=1 + export TEST_CONF_MAX_BACKLOG=1000 + export TEST_CONF_REPEAT="no" + + TEST_CONF_NUM_MESSAGES=0 + for ((pps=$TEST_CONF_START_PPS; pps<=$TEST_CONF_MAX_PPS; pps+=$TEST_CONF_STEP)); do + TEST_CONF_NUM_MESSAGES=$((TEST_CONF_NUM_MESSAGES + TEST_CONF_DURATION * pps)) + done + export TEST_CONF_NUM_MESSAGES + + # + # Delay to allow the rest of the environment to startup before starting load generation. + # + sleep 20 + + # + # Starting load-generator server which will generate traffic based on env configuration + # from above. + # + printf "Starting load-generator with the following configuration:\n" + printf " Start PPS: %s\n" "$TEST_CONF_START_PPS" + printf " Max PPS: %s\n" "$TEST_CONF_MAX_PPS" + printf " Duration (secs): %s\n" "$TEST_CONF_DURATION" + printf " Step PPS: %s\n" "$TEST_CONF_STEP" + printf " Parallel: %s\n" "$TEST_CONF_PARALLEL" + printf " Max Backlog: %s\n" "$TEST_CONF_MAX_BACKLOG" + printf " Num Messages: %s\n" "$TEST_CONF_NUM_MESSAGES" + + freeradius & + + tail -f /dev/null + + detach: true + verify: + timeout: 360 + trigger_mode: unordered + state_2: + description: Check load-generator Status-Server stats + host: + load-generator: + actions: + - execute_command: + command: | + # This command will query the load-generator's built-in Status-Server for statistics. Port 1820 configured to be used for Status-Server. + printf 'User-Name := "testuser"\nUser-Password := "testpass"' | /usr/bin/radclient -x localhost:1820 status testing123 + verify: + timeout: 5 + trigger_mode: unordered + triggers: + - load-generator-status-server: + json: + Status-Server-Result: + pattern: + reg_pattern: PASS + Access-Request-Counter: + pattern: + reg_pattern: (\d+) + Access-Accept-Counter: + pattern: + reg_pattern: (\d+) diff --git a/src/tests/multi-server/test-5hs-autoaccept.yml b/src/tests/multi-server/test-5hs-autoaccept.yml new file mode 100644 index 000000000000..65305417e415 --- /dev/null +++ b/src/tests/multi-server/test-5hs-autoaccept.yml @@ -0,0 +1,79 @@ +timeout: 50 +state_order: sequence +states: + state_1: + description: Baseline load-generator test for load-generator -> 5 home servers. Home servers auto-accept requests. + host: + load-generator: + actions: + - execute_command: + command: | + # + # proto_load configuration via environment variables + # + + export TEST_CONF_START_PPS=5 + export TEST_CONF_MAX_PPS=10 + # Duration must be equal or greater than max pps for proto_load to calculate "pps_accepted" effectively + export TEST_CONF_DURATION=5 + export TEST_CONF_STEP=5 + export TEST_CONF_PARALLEL=1 + export TEST_CONF_MAX_BACKLOG=1000 + export TEST_CONF_REPEAT="no" + + TEST_CONF_NUM_MESSAGES=0 + for ((pps=$TEST_CONF_START_PPS; pps<=$TEST_CONF_MAX_PPS; pps+=$TEST_CONF_STEP)); do + TEST_CONF_NUM_MESSAGES=$((TEST_CONF_NUM_MESSAGES + TEST_CONF_DURATION * pps)) + done + export TEST_CONF_NUM_MESSAGES + + # + # Delay to allow the rest of the environment to startup before starting load generation. + # + sleep 20 + + # + # Starting load-generator server which will generate traffic based on env configuration + # from above. + # + printf "Starting load-generator with the following configuration:\n" + printf " Start PPS: %s\n" "$TEST_CONF_START_PPS" + printf " Max PPS: %s\n" "$TEST_CONF_MAX_PPS" + printf " Duration (secs): %s\n" "$TEST_CONF_DURATION" + printf " Step PPS: %s\n" "$TEST_CONF_STEP" + printf " Parallel: %s\n" "$TEST_CONF_PARALLEL" + printf " Max Backlog: %s\n" "$TEST_CONF_MAX_BACKLOG" + printf " Num Messages: %s\n" "$TEST_CONF_NUM_MESSAGES" + + freeradius & + + tail -f /dev/null + + detach: true + verify: + timeout: 40 + trigger_mode: unordered + state_2: + description: Check load-generator Status-Server stats + host: + load-generator: + actions: + - execute_command: + command: | + # This command will query the load-generator's built-in Status-Server for statistics. Port 1820 configured to be used for Status-Server. + printf 'User-Name := "testuser"\nUser-Password := "testpass"' | /usr/bin/radclient -x localhost:1820 status testing123 + verify: + timeout: 5 + trigger_mode: unordered + triggers: + - load-generator-status-server: + json: + Status-Server-Result: + pattern: + reg_pattern: PASS + Access-Request-Counter: + pattern: + reg_pattern: (\d+) + Access-Accept-Counter: + pattern: + reg_pattern: (\d+)