From 9322b87aad3d207731dc71853f39cb9651ea8a18 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 27 Aug 2024 09:52:45 +0200 Subject: [PATCH v2 2/2] Convert sepgsql tests to TAP Add a TAP test for sepgsql. This automates the previously required manual setup before the test. The actual tests are still run by pg_regress, but not called from within the TAP Perl script. The previous manual test script (test_sepgsql) is left in place, since its purpose is (also) to test whether a running instance was properly initialized for sepgsql. But it has been changed to call pg_regress directly and no longer require make. Discussion: https://www.postgresql.org/message-id/flat/651a5baf-5c45-4a5a-a202-0c8453a4ebf8@eisentraut.org --- contrib/sepgsql/.gitignore | 4 +- contrib/sepgsql/Makefile | 2 + contrib/sepgsql/meson.build | 11 +- contrib/sepgsql/t/001_sepgsql.pl | 246 +++++++++++++++++++++++++++++++ contrib/sepgsql/test_sepgsql | 12 +- doc/src/sgml/regress.sgml | 11 ++ doc/src/sgml/sepgsql.sgml | 17 ++- meson.build | 2 + src/Makefile.global.in | 2 + 9 files changed, 294 insertions(+), 13 deletions(-) create mode 100644 contrib/sepgsql/t/001_sepgsql.pl diff --git a/contrib/sepgsql/.gitignore b/contrib/sepgsql/.gitignore index 31613e011f5..b1778d05bbd 100644 --- a/contrib/sepgsql/.gitignore +++ b/contrib/sepgsql/.gitignore @@ -3,5 +3,5 @@ /sepgsql-regtest.if /sepgsql-regtest.pp /tmp -# Generated subdirectories -/results/ +# Generated by test suite +/tmp_check/ diff --git a/contrib/sepgsql/Makefile b/contrib/sepgsql/Makefile index afca75b693f..90b4585a9e2 100644 --- a/contrib/sepgsql/Makefile +++ b/contrib/sepgsql/Makefile @@ -15,6 +15,8 @@ OBJS = \ DATA_built = sepgsql.sql PGFILEDESC = "sepgsql - SELinux integration" +TAP_TESTS = 1 + # Note: because we don't tell the Makefile there are any regression tests, # we have to clean those result files explicitly EXTRA_CLEAN = -r $(pg_regress_clean_files) tmp/ *.pp sepgsql-regtest.if sepgsql-regtest.fc diff --git a/contrib/sepgsql/meson.build b/contrib/sepgsql/meson.build index acff379b4b6..56316e4882d 100644 --- a/contrib/sepgsql/meson.build +++ b/contrib/sepgsql/meson.build @@ -40,4 +40,13 @@ contrib_targets += custom_target('sepgsql.sql', install_dir: dir_data / 'contrib', ) -# TODO: implement sepgsql tests +tests += { + 'name': 'sepgsql', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_sepgsql.pl', + ], + }, +} diff --git a/contrib/sepgsql/t/001_sepgsql.pl b/contrib/sepgsql/t/001_sepgsql.pl new file mode 100644 index 00000000000..cba51403518 --- /dev/null +++ b/contrib/sepgsql/t/001_sepgsql.pl @@ -0,0 +1,246 @@ + +# Copyright (c) 2024, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bsepgsql\b/) +{ + plan skip_all => + 'Potentially unsafe test sepgsql not enabled in PG_TEST_EXTRA'; +} + +note "checking selinux environment"; + +# matchpathcon must be present to assess whether the installation environment +# is OK. +note "checking for matchpathcon"; +if (system('matchpathcon -n . >/dev/null 2>&1') != 0) +{ + diag </dev/null 2>&1') != 0) +{ + diag </dev/null 2>&1') != 0) +{ + diag </dev/null`)[2]; +note "current user domain is '$DOMAIN'"; +if ($DOMAIN ne 'unconfined_t') +{ + diag <<'EOS'; + +The regression tests must be launched from the unconfined_t domain. + +The unconfined_t domain is typically the default domain for user +shell processes. If the default has been changed on your system, +you can revert the changes like this: + + $ sudo semanage login -d `whoami` + +Or, you can add a setting to log in using the unconfined_t domain: + + $ sudo semanage login -a -s unconfined_u -r s0-s0:c0.c255 `whoami` + +EOS + die; +} + +# SELinux must be configured in enforcing mode +note "checking selinux operating mode"; +my $CURRENT_MODE = + (split /: */, `LANG=C sestatus | grep '^Current mode:'`)[1]; +chomp $CURRENT_MODE; +note "current operating mode is '$CURRENT_MODE'"; +if ($CURRENT_MODE eq 'enforcing') +{ + # OK +} +elsif ($CURRENT_MODE eq 'permissive' || $CURRENT_MODE eq 'disabled') +{ + diag <<'EOS'; + +Before running the regression tests, SELinux must be enabled and +must be running in enforcing mode. + +If SELinux is currently running in permissive mode, you can +switch to enforcing mode using the 'setenforce' command. + + $ sudo setenforce 1 + +The system default setting is configured in /etc/selinux/config, +or using a kernel boot parameter. +EOS + die; +} +else +{ + diag <new('test'); +$node->init; +$node->append_conf('postgresql.conf', 'log_statement=none'); + +{ + local %ENV = $node->_get_env(); + + my $result = run_log( + [ + 'postgres', '--single', + '-F', '-c', + 'exit_on_error=true', '-D', + $node->data_dir, 'template0' + ], + '<', + $ENV{share_contrib_dir} . '/sepgsql.sql'); + ok($result, 'sepgsql installation script'); +} + +$node->append_conf('postgresql.conf', 'shared_preload_libraries=sepgsql'); +$node->start; + +my @tests = qw(label dml ddl alter misc); + +# Check if the truncate permission exists in the loaded policy, and if so, +# run the truncate test +# +# Testing the TRUNCATE regression test can be done by manually adding +# the permission with CIL if necessary: +# sudo semodule -cE base +# sudo sed -i -E 's/(class db_table.*?) \)/\1 truncate\)/' base.cil +# sudo semodule -i base.cil +push @tests, 'truncate' if -f '/sys/fs/selinux/class/db_table/perms/truncate'; + +$node->command_ok( + [ + $ENV{PG_REGRESS}, '--bindir=', '--inputdir=.', '--launcher', + './launcher', @tests + ], + 'sepgsql tests'); + +done_testing(); diff --git a/contrib/sepgsql/test_sepgsql b/contrib/sepgsql/test_sepgsql index 3a29556d1ff..23dae1bf037 100755 --- a/contrib/sepgsql/test_sepgsql +++ b/contrib/sepgsql/test_sepgsql @@ -4,10 +4,10 @@ # to try to ensure that the SELinux environment is set up appropriately and # the database is configured correctly. # -# Note that this must be run against an installed Postgres database. -# There's no equivalent of "make check", and that wouldn't be terribly useful -# since much of the value is in checking that you installed sepgsql into -# your database correctly. +# This must be run against an installed Postgres database. The +# purpose of this script is in checking that you installed sepgsql +# into your database correctly. For testing sepgsql during +# development, "make check", "meson test", etc. are also available. # # This must be run in the contrib/sepgsql directory of a Postgres build tree. # @@ -302,5 +302,5 @@ if [ -f /sys/fs/selinux/class/db_table/perms/truncate ]; then tests+=" truncate" fi -make REGRESS="$tests" REGRESS_OPTS="--launcher ./launcher" installcheck -# exit with the exit code provided by "make" +PGXS=`pg_config --pgxs` +"$(dirname $PGXS)/../../src/test/regress/pg_regress" --inputdir=. --bindir="$PG_BINDIR" --launcher=./launcher $tests diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml index d1042e02228..9aebd9f3bed 100644 --- a/doc/src/sgml/regress.sgml +++ b/doc/src/sgml/regress.sgml @@ -284,6 +284,17 @@ Additional Test Suites + + sepgsql + + + Runs the test suite under contrib/sepgsql. This + requires an SELinux environment that is set up in a specific way; see + . + + + + ssl diff --git a/doc/src/sgml/sepgsql.sgml b/doc/src/sgml/sepgsql.sgml index bc308e3142d..9217c1b3d68 100644 --- a/doc/src/sgml/sepgsql.sgml +++ b/doc/src/sgml/sepgsql.sgml @@ -151,14 +151,23 @@ Installation Regression Tests + + The sepgsql test suite is run if + PG_TEST_EXTRA contains sepgsql (see + ). This method is suitable during + development of PostgreSQL. Alternatively, there + is a way to run the tests to checks whether a database instance has been + set up properly for sepgsql. + + Due to the nature of SELinux, running the regression tests for sepgsql requires several extra configuration steps, some of which must be done as root. - The regression tests will not be run by an ordinary - make check or make installcheck command; you must - set up the configuration and then invoke the test script manually. - The tests must be run in the contrib/sepgsql directory + + + + The manual tests must be run in the contrib/sepgsql directory of a configured PostgreSQL build tree. Although they require a build tree, the tests are designed to be executed against an installed server, that is they are comparable to make installcheck not diff --git a/meson.build b/meson.build index ea07126f78e..c18340adc90 100644 --- a/meson.build +++ b/meson.build @@ -3518,6 +3518,8 @@ foreach test_dir : tests # also test/ for non-installed test binaries built separately. env = test_env env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test') + temp_install_datadir = '@0@@1@'.format(test_install_destdir, dir_prefix / dir_data) + env.set('share_contrib_dir', temp_install_datadir / 'contrib') foreach name, value : t.get('env', {}) env.set(name, value) diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 42f50b49761..190f5559acf 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -456,6 +456,7 @@ cd $(srcdir) && \ PATH="$(bindir):$(CURDIR):$$PATH" \ PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' \ PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' \ + share_contrib_dir='$(DESTDIR)$(datadir)/$(datamoduledir)' \ $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl) endef else # PGXS case @@ -483,6 +484,7 @@ cd $(srcdir) && \ $(with_temp_install) \ PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' \ PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' \ + share_contrib_dir='$(abs_top_builddir)/tmp_install$(datadir)/$(datamoduledir)' \ $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl) endef -- 2.46.0