Skip to content

Commit

Permalink
Improve SSL mode testing
Browse files Browse the repository at this point in the history
  • Loading branch information
nyurik committed Sep 30, 2023
1 parent ae8e070 commit f3f4cde
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 15 deletions.
40 changes: 32 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -337,25 +337,28 @@ jobs:
path: tests/output/*
retention-days: 5

test-legacy:
name: Test Legacy DB
test-service:
name: Test PG ${{ matrix.img_ver }}, sslmode=${{ matrix.sslmode }}
runs-on: ubuntu-latest
needs: [ build ]
strategy:
fail-fast: true
matrix:
include:
# These must match the versions of postgres used in the docker-compose.yml
- image: postgis/postgis:11-3.0-alpine
- img_ver: 11-3.0-alpine
args: postgres
sslmode: disable
- image: postgis/postgis:14-3.3-alpine
- img_ver: 14-3.3-alpine
args: postgres
sslmode: disable
# alpine images don't support SSL, so for this we use the debian images
- image: postgis/postgis:15-3.3
- img_ver: 15-3.3
args: postgres -c ssl=on -c ssl_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem -c ssl_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
sslmode: require
- img_ver: 15-3.3
args: postgres -c ssl=on -c ssl_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem -c ssl_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
sslmode: verify-ca
env:
# PG_* variables are used by psql
PGDATABASE: test
Expand All @@ -364,7 +367,7 @@ jobs:
PGPASSWORD: postgres
services:
postgres:
image: ${{ matrix.image }}
image: postgis/postgis:${{ matrix.img_ver }}
ports:
# will assign a random free host port
- 5432/tcp
Expand All @@ -382,7 +385,7 @@ jobs:
--health-timeout 5s
--health-retries 5
--entrypoint sh
${{ matrix.image }}
postgis/postgis:${{ matrix.img_ver }}
-c "exec docker-entrypoint.sh ${{ matrix.args }}"
steps:
- name: Checkout sources
Expand All @@ -393,13 +396,28 @@ jobs:
run: tests/fixtures/initdb.sh
env:
PGPORT: ${{ job.services.postgres.ports[5432] }}
- name: Download DB SSL cert
if: matrix.sslmode == 'verify-ca' || matrix.sslmode == 'verify-full'
run: |
mkdir -p target/certs
docker cp ${{ job.services.postgres.id }}:/etc/ssl/certs/ssl-cert-snakeoil.pem target/certs/server.crt
docker cp ${{ job.services.postgres.id }}:/etc/ssl/private/ssl-cert-snakeoil.key target/certs/server.key
cat target/certs/server.crt
openssl s_client -showcerts -connect localhost:${{ job.services.postgres.ports[5432] }} </dev/null 2>/dev/null | openssl x509 -outform PEM > target/certs/server2.crt
cat target/certs/server2.crt
diff target/certs/server.crt target/certs/server2.crt
- name: Download build artifact build-x86_64-unknown-linux-gnu
uses: actions/download-artifact@v3
with:
name: build-x86_64-unknown-linux-gnu
path: target_releases/
- name: Integration Tests
run: |
if [[ "${{ matrix.sslmode }}" == "verify-ca" ]]; then
export PGSSLROOTCERT=target/certs/server.crt
elif [[ "${{ matrix.sslmode }}" == "verify-full" ]]; then
export PGSSLROOTCERT=target/certs/server.crt
fi
export MARTIN_BUILD=-
export MARTIN_BIN=target_releases/martin
export MBTILES_BUILD=-
Expand All @@ -417,6 +435,11 @@ jobs:
- name: Tests Debian package
run: |
sudo dpkg -i target_releases/debian-x86_64.deb
if [[ "${{ matrix.sslmode }}" == "verify-ca" ]]; then
export PGSSLROOTCERT=target/certs/server.crt
elif [[ "${{ matrix.sslmode }}" == "verify-full" ]]; then
export PGSSLROOTCERT=target/certs/server.crt
fi
export MARTIN_BUILD=-
export MARTIN_BIN=/usr/bin/martin
export MBTILES_BUILD=-
Expand All @@ -427,6 +450,7 @@ jobs:
env:
DATABASE_URL: postgres://${{ env.PGUSER }}:${{ env.PGUSER }}@${{ env.PGHOST }}:${{ job.services.postgres.ports[5432] }}/${{ env.PGDATABASE }}?sslmode=${{ matrix.sslmode }}
- name: Unit Tests
if: matrix.sslmode != 'verify-ca' && matrix.sslmode != 'verify-full'
run: |
echo "Running unit tests, connecting to DATABASE_URL=$DATABASE_URL"
echo "Same but as base64 to prevent GitHub obfuscation (this is not a secret):"
Expand All @@ -447,7 +471,7 @@ jobs:
package:
name: Package ${{ matrix.target }}
runs-on: ${{ matrix.os }}
needs: [ docker, test, test-legacy ]
needs: [ docker, test, test-service ]
strategy:
fail-fast: true
matrix:
Expand Down
28 changes: 28 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@ services:
- ./tests/fixtures/initdb-dc-ssl.sh:/docker-entrypoint-initdb.d/10_martin.sh
- ./tests/fixtures/initdb-dc.sh:/docker-entrypoint-initdb.d/20_martin.sh

db-ssl-cert:
# This should match the version of postgres used in the CI workflow
image: postgis/postgis:15-3.3
command:
- "postgres"
- "-c"
- "ssl=on"
- "-c"
- "ssl_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem"
- "-c"
- "ssl_key_file=/etc/ssl/private/ssl-cert-snakeoil.key"
restart: unless-stopped
ports:
- "${PGPORT:-5411}:5432"
environment:
# POSTGRES_* variables are used by the postgis/postgres image
# PG_* variables are used by psql
- POSTGRES_DB=db
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- PGDATABASE=db
- PGUSER=postgres
- PGPASSWORD=postgres
volumes:
- ./tests/fixtures:/fixtures
- ./tests/fixtures/initdb-dc-ssl-cert.sh:/docker-entrypoint-initdb.d/10_martin.sh
- ./tests/fixtures/initdb-dc.sh:/docker-entrypoint-initdb.d/20_martin.sh

db-legacy:
# This should match the version of postgres used in the CI workflow
image: postgis/postgis:11-3.0-alpine
Expand Down
29 changes: 26 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,25 @@ clean-test:
rm -rf tests/output

# Start a test database
start: (docker-up "db")
start: (docker-up "db") docker-is-ready

# Start an ssl-enabled test database
start-ssl: (docker-up "db-ssl")
start-ssl: (docker-up "db-ssl") docker-is-ready

# Start an ssl-enabled test database that requires a client certificate
start-ssl-cert: (docker-up "db-ssl-cert") docker-is-ready

# Start a legacy test database
start-legacy: (docker-up "db-legacy")
start-legacy: (docker-up "db-legacy") docker-is-ready

# Start a specific test database, e.g. db or db-legacy
[private]
docker-up name:
docker-compose up -d {{ name }}

# Wait for the test database to be ready
[private]
docker-is-ready:
docker-compose run -T --rm db-is-ready

alias _down := stop
Expand Down Expand Up @@ -87,6 +94,22 @@ test: start test-unit test-int
test-ssl: start-ssl test-unit clean-test
tests/test.sh

# Run all tests using an SSL connection with client cert to a test database. Expected output won't match.
test-ssl-cert: start-ssl-cert
#!/usr/bin/env bash
set -euxo pipefail
# copy client cert to the tests folder from the docker container
KEY_DIR=target/certs
mkdir -p $KEY_DIR
docker cp martin-db-ssl-cert-1:/etc/ssl/certs/ssl-cert-snakeoil.pem $KEY_DIR/ssl-cert-snakeoil.pem
docker cp martin-db-ssl-cert-1:/etc/ssl/private/ssl-cert-snakeoil.key $KEY_DIR/ssl-cert-snakeoil.key
# export DATABASE_URL="$DATABASE_URL?sslmode=verify-full&sslrootcert=$KEY_DIR/ssl-cert-snakeoil.pem&sslcert=$KEY_DIR/ssl-cert-snakeoil.pem&sslkey=$KEY_DIR/ssl-cert-snakeoil.key"
export PGSSLROOTCERT="$KEY_DIR/ssl-cert-snakeoil.pem"
export PGSSLCERT="$KEY_DIR/ssl-cert-snakeoil.pem"
export PGSSLKEY="$KEY_DIR/ssl-cert-snakeoil.key"
{{just_executable()}} test-unit clean-test
tests/test.sh
# Run all tests using the oldest supported version of the database
test-legacy: start-legacy test-unit test-int

Expand Down
18 changes: 18 additions & 0 deletions tests/fixtures/initdb-dc-ssl-cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env sh
set -e

mv /var/lib/postgresql/data/pg_hba.conf /var/lib/postgresql/data/pg_hba.conf.bak
cat > /var/lib/postgresql/data/pg_hba.conf <<EOF
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
#local all all trust
# localhost connections
#host all all 127.0.0.1/32 trust
# external connections
hostssl all all all cert
# clientcert=verify-full
EOF
11 changes: 7 additions & 4 deletions tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ MARTIN_BIN="${MARTIN_BIN:-cargo run --} ${MARTIN_ARGS}"
MBTILES_BUILD="${MBTILES_BUILD:-cargo build -p martin-mbtiles}"
MBTILES_BIN="${MBTILES_BIN:-target/debug/mbtiles}"

TMP_DIR="${TMP_DIR:-target/tmp}"
mkdir -p "$TMP_DIR"

function wait_for_martin {
# Seems the --retry-all-errors option is not available on older curl versions, but maybe in the future we can just use this:
# timeout -k 20s 20s curl --retry 10 --retry-all-errors --retry-delay 1 -sS "$MARTIN_URL/health"
Expand Down Expand Up @@ -152,7 +155,7 @@ mkdir -p "$TEST_OUT_DIR"

ARG=(--default-srid 900913 --disable-bounds --save-config "$(dirname "$0")/output/generated_config.yaml" tests/fixtures/mbtiles tests/fixtures/pmtiles)
set -x
$MARTIN_BIN "${ARG[@]}" 2>&1 | tee test_log_1.txt &
$MARTIN_BIN "${ARG[@]}" 2>&1 | tee "${TMP_DIR}/test_log_1.txt" &
PROCESS_ID=`jobs -p`

{ set +x; } 2> /dev/null
Expand Down Expand Up @@ -227,7 +230,7 @@ test_pbf mb_mvt_2_3_1 world_cities/2/3/1
test_pbf points_empty_srid_0_0_0 points_empty_srid/0/0/0

kill_process $PROCESS_ID
validate_log test_log_1.txt
validate_log "${TMP_DIR}/test_log_1.txt"


echo "------------------------------------------------------------------------------------------------------------------------"
Expand All @@ -237,7 +240,7 @@ mkdir -p "$TEST_OUT_DIR"

ARG=(--config tests/config.yaml --max-feature-count 1000 --save-config "$(dirname "$0")/output/given_config.yaml" -W 1)
set -x
$MARTIN_BIN "${ARG[@]}" 2>&1 | tee test_log_2.txt &
$MARTIN_BIN "${ARG[@]}" 2>&1 | tee "${TMP_DIR}/test_log_2.txt" &
PROCESS_ID=`jobs -p`
{ set +x; } 2> /dev/null
trap "kill -9 $PROCESS_ID 2> /dev/null || true" EXIT
Expand Down Expand Up @@ -266,7 +269,7 @@ test_jsn spr_cmp_2x sprite/src1,[email protected]
test_png spr_cmp_2x sprite/src1,[email protected]

kill_process $PROCESS_ID
validate_log test_log_2.txt
validate_log "${TMP_DIR}/test_log_2.txt"

remove_line "$(dirname "$0")/output/given_config.yaml" " connection_string: "
remove_line "$(dirname "$0")/output/generated_config.yaml" " connection_string: "
Expand Down

0 comments on commit f3f4cde

Please sign in to comment.