diff --git a/.github/workflows/test_code.yaml b/.github/workflows/test_code.yaml new file mode 100644 index 0000000..541c3a1 --- /dev/null +++ b/.github/workflows/test_code.yaml @@ -0,0 +1,30 @@ +--- +name: Test code + +# Run workflow on PRs and pushes to matching branches +on: # yamllint disable-line rule:truthy + push: + branches: [main] + pull_request: + +jobs: + test_bash: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install bats + run: sudo apt-get update && sudo apt-get install bats + - name: Install ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.4 + - name: Install ruby dependencies + run: gem install mustache + - name: Install yq + run: | + VERSION=v4.44.1 + BINARY=yq_linux_amd64 + wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz -O - | tar xz && sudo mv ${BINARY} /usr/bin/yq + - name: Run tests + run: bats tests diff --git a/README.md b/README.md index 79ea828..079312c 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,16 @@ Synchronise a Guacamole PostgreSQL database with an LDAP server, such as Microso - POSTGRESQL_PORT: PostgreSQL server port (default: '5432') - POSTGRESQL_USERNAME: Username of PostgreSQL user - REPEAT_INTERVAL: How often (in seconds) to wait before attempting to synchronise again (default: '300') + +## Tests + +To run the tests you will need to install + +- `bats-core` +- `yq` + +The tests can be run with: + +```console +$ bats tests +``` diff --git a/tests/common.bash b/tests/common.bash new file mode 100644 index 0000000..834c5e2 --- /dev/null +++ b/tests/common.bash @@ -0,0 +1,48 @@ +#! /usr/bin/env bats + +common_setup() { + # Use $BATS_TEST_FILENAME to get the containing directory of this file + # instead of ${BASH_SOURCE[0]}, which points to the bats executable, or + # $0, which points to the preprocessed file. + + # shellcheck disable=SC2034 + TEST_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" +} + +assert_output() { + # This is a light version of the function with the same name in `bats-assert` + is_mode_partial=0 + while (($# > 0)); do + case "$1" in + -p | --partial) + is_mode_partial=1 + shift + ;; + --) + shift + break + ;; + *) break ;; + esac + done + + expected=$1 + if ((is_mode_partial)); then + # shellcheck disable=SC2154 + if [[ $output != *"$expected"* ]]; then + echo "-- output does not contain substring --" + echo "substring $expected" + echo "output $output" + echo "--" + return 1 + fi + else + if [[ $output != *"$expected"* ]]; then + echo "-- output differs --" + echo "expected $expected" + echo "actual $output" + echo "--" + return 1 + fi + fi +} diff --git a/tests/test_expand_pg_ldap_sync.bats b/tests/test_expand_pg_ldap_sync.bats new file mode 100644 index 0000000..efb8d43 --- /dev/null +++ b/tests/test_expand_pg_ldap_sync.bats @@ -0,0 +1,156 @@ +#! /usr/bin/env bats +# bats file_tags=ruby:expand_pg_ldap_sync + +setup() { + load 'common' + common_setup +} + +query_pg_ldap_sync() { + query_string="$1" + ${TEST_DIR}/../scripts/expand_pg_ldap_sync.rb | yq eval "$query_string" +} + +@test "Test setting LDAP_BIND_DN" { + export LDAP_BIND_DN="CN=user,DC=example,DC=com" + run query_pg_ldap_sync ".ldap_connection.auth.username" + export -n LDAP_BIND_DN + assert_output "CN=user,DC=example,DC=com" +} + +@test "Test setting LDAP_BIND_PASSWORD only" { + export LDAP_BIND_PASSWORD="!a#b%c" + run query_pg_ldap_sync ".ldap_connection.auth.password" + export -n LDAP_BIND_PASSWORD + assert_output null +} + +@test "Test setting LDAP_BIND_PASSWORD with LDAP_BIND_DN" { + export LDAP_BIND_DN="CN=user,DC=example,DC=com" + export LDAP_BIND_PASSWORD="!a#b%c" + run query_pg_ldap_sync ".ldap_connection.auth.password" + export -n LDAP_BIND_DN LDAP_BIND_PASSWORD + assert_output "!a#b%c" +} + +@test "Test setting LDAP_GROUP_BASE_DN" { + export LDAP_GROUP_BASE_DN="OU=groups,DC=example,DC=com" + run query_pg_ldap_sync ".ldap_groups.base" + export -n LDAP_GROUP_BASE_DN + assert_output "OU=groups,DC=example,DC=com" +} + +@test "Test setting LDAP_GROUP_FILTER" { + export LDAP_GROUP_FILTER="(objectClass=posixGroup)" + run query_pg_ldap_sync ".ldap_groups.filter" + export -n LDAP_GROUP_FILTER + assert_output "(objectClass=posixGroup)" +} + +@test "Test setting LDAP_GROUP_NAME_ATTR" { + export LDAP_GROUP_NAME_ATTR="samAccountName" + run query_pg_ldap_sync ".ldap_groups.name_attribute" + export -n LDAP_GROUP_NAME_ATTR + assert_output "samAccountName" +} + +@test "Test default LDAP_GROUP_NAME_ATTR" { + export -n LDAP_GROUP_NAME_ATTR + run query_pg_ldap_sync ".ldap_groups.name_attribute" + assert_output "cn" +} + +@test "Test setting LDAP_HOST" { + export LDAP_HOST="ldap.example.com" + run query_pg_ldap_sync ".ldap_connection.host" + export -n LDAP_HOST + assert_output "ldap.example.com" +} + +@test "Test setting LDAP_PORT" { + export LDAP_PORT="1234" + run query_pg_ldap_sync ".ldap_connection.port" + export -n LDAP_PORT + assert_output "1234" +} + +@test "Test default LDAP_PORT" { + export -n LDAP_PORT + run query_pg_ldap_sync ".ldap_connection.port" + assert_output "389" +} + +@test "Test setting LDAP_USER_BASE_DN" { + export LDAP_USER_BASE_DN="OU=users,DC=example,DC=com" + run query_pg_ldap_sync ".ldap_users.base" + export -n LDAP_USER_BASE_DN + assert_output "OU=users,DC=example,DC=com" +} + +@test "Test setting LDAP_USER_FILTER" { + export LDAP_USER_FILTER="(objectClass=posixAccount)" + run query_pg_ldap_sync ".ldap_users.filter" + export -n LDAP_USER_FILTER + assert_output "(objectClass=posixAccount)" +} + +@test "Test setting LDAP_USER_NAME_ATTR" { + export LDAP_USER_NAME_ATTR="samAccountName" + run query_pg_ldap_sync ".ldap_users.name_attribute" + export -n LDAP_USER_NAME_ATTR + assert_output "samAccountName" +} + +@test "Test default LDAP_USER_NAME_ATTR" { + export -n LDAP_USER_NAME_ATTR + run query_pg_ldap_sync ".ldap_users.name_attribute" + assert_output "userPrincipalName" +} + +@test "Test setting POSTGRESQL_DB_NAME" { + export POSTGRESQL_DB_NAME="custom-db-name" + run query_pg_ldap_sync ".pg_connection.dbname" + export -n POSTGRESQL_DB_NAME + assert_output "custom-db-name" +} + +@test "Test default POSTGRESQL_DB_NAME" { + export -n POSTGRESQL_DB_NAME + run query_pg_ldap_sync ".pg_connection.dbname" + export -n POSTGRESQL_DB_NAME + assert_output "guacamole" +} + +@test "Test setting POSTGRESQL_HOST" { + export POSTGRESQL_HOST="postgresql.example.com" + run query_pg_ldap_sync ".pg_connection.host" + export -n POSTGRESQL_HOST + assert_output "postgresql.example.com" +} + +@test "Test setting POSTGRESQL_PASSWORD" { + export POSTGRESQL_PASSWORD="!a#b%c" + run query_pg_ldap_sync ".pg_connection.password" + export -n POSTGRESQL_PASSWORD + assert_output "!a#b%c" +} + +@test "Test setting POSTGRESQL_PORT" { + export POSTGRESQL_PORT="1234" + run query_pg_ldap_sync ".pg_connection.port" + export -n POSTGRESQL_PORT + assert_output "1234" +} + +@test "Test default POSTGRESQL_PORT" { + export -n POSTGRESQL_PORT + run query_pg_ldap_sync ".pg_connection.port" + assert_output "5432" +} + +@test "Test setting POSTGRESQL_USERNAME" { + export POSTGRESQL_USERNAME="psqladmin" + run query_pg_ldap_sync ".pg_connection.user" + export -n POSTGRESQL_USERNAME + assert_output "psqladmin" +} diff --git a/tests/test_expand_psql.bats b/tests/test_expand_psql.bats new file mode 100644 index 0000000..0b1649a --- /dev/null +++ b/tests/test_expand_psql.bats @@ -0,0 +1,46 @@ +#! /usr/bin/env bats +# bats file_tags=ruby:expand_psql + +setup() { + load 'common' + common_setup +} + +expand_psql() { + ${TEST_DIR}/../scripts/expand_psql.rb +} + +@test "Test setting POSTGRESQL_PASSWORD" { + export POSTGRESQL_PASSWORD="!a#b%c" + run expand_psql + export -n POSTGRESQL_PASSWORD + assert_output --partial "PGPASSWORD='!a#b%c'" +} + +@test "Test setting POSTGRESQL_HOST" { + export POSTGRESQL_HOST="postgresql.example.com" + run expand_psql + export -n POSTGRESQL_HOST + assert_output --partial "-h 'postgresql.example.com'" +} + +@test "Test setting POSTGRESQL_PORT" { + export POSTGRESQL_PORT="1234" + run expand_psql + export -n POSTGRESQL_PORT + assert_output --partial "-p '1234'" +} + +@test "Test setting POSTGRESQL_DB_NAME" { + export POSTGRESQL_DB_NAME="custom-db-name" + run expand_psql + export -n POSTGRESQL_DB_NAME + assert_output --partial "-d 'custom-db-name'" +} + +@test "Test setting POSTGRESQL_USERNAME" { + export POSTGRESQL_USERNAME="postgresqladmin" + run expand_psql + export -n POSTGRESQL_USERNAME + assert_output --partial "-U 'postgresqladmin'" +}