diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2025-01-24 11:37:20 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2025-01-24 12:39:47 +0100 |
commit | aeb8ea361a0a321a0e1cbc79a4cd3ec0b1191bf2 (patch) | |
tree | 64d994d2c2bdae615ac2fbc1fc382758be25964f | |
parent | 02ed3c2bdcefab453b548bc9c7e0e8874a502790 (diff) | |
download | postgresql-aeb8ea361a0a321a0e1cbc79a4cd3ec0b1191bf2.tar.gz postgresql-aeb8ea361a0a321a0e1cbc79a4cd3ec0b1191bf2.zip |
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, as before, but now 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.
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Discussion: https://www.postgresql.org/message-id/flat/651a5baf-5c45-4a5a-a202-0c8453a4ebf8@eisentraut.org
-rw-r--r-- | contrib/sepgsql/.gitignore | 4 | ||||
-rw-r--r-- | contrib/sepgsql/Makefile | 2 | ||||
-rw-r--r-- | contrib/sepgsql/meson.build | 11 | ||||
-rw-r--r-- | contrib/sepgsql/t/001_sepgsql.pl | 246 | ||||
-rwxr-xr-x | contrib/sepgsql/test_sepgsql | 12 | ||||
-rw-r--r-- | doc/src/sgml/regress.sgml | 11 | ||||
-rw-r--r-- | doc/src/sgml/sepgsql.sgml | 17 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | src/Makefile.global.in | 2 |
9 files changed, 294 insertions, 13 deletions
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 d8085b10ee5..6bf69783729 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 <<EOS; + +The matchpathcon command must be available. +Please install it or update your PATH to include it +(it is typically in '/usr/sbin', which might not be in your PATH). +matchpathcon is typically included in the libselinux-utils package. +EOS + die; +} + +# runcon must be present to launch psql using the correct environment +note "checking for runcon"; +if (system('runcon --help >/dev/null 2>&1') != 0) +{ + diag <<EOS; + +The runcon command must be available. +runcon is typically included in the coreutils package. +EOS + die; +} + +# check sestatus too, since that lives in yet another package +note "checking for sestatus"; +if (system('sestatus >/dev/null 2>&1') != 0) +{ + diag <<EOS; + +The sestatus command must be available. +sestatus is typically included in the policycoreutils package. +EOS + die; +} + +# check that the user is running in the unconfined_t domain +note "checking current user domain"; +my $DOMAIN = (split /:/, `id -Z 2>/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 <<EOS; + +Unable to determine the current selinux operating mode. Please +verify that the sestatus command is installed and in your PATH. +EOS + die; +} + +# 'sepgsql-regtest' policy module must be loaded +note "checking for sepgsql-regtest policy"; +my $SELINUX_MNT = (split /: */, `sestatus | grep '^SELinuxfs mount:'`)[1]; +chomp $SELINUX_MNT; +if ($SELINUX_MNT eq "") +{ + diag <<EOS; + +Unable to find SELinuxfs mount point. + +The sestatus command should report the location where SELinuxfs +is mounted, but did not do so. +EOS + die; +} +if (!-e "${SELINUX_MNT}/booleans/sepgsql_regression_test_mode") +{ + diag <<'EOS'; + +The 'sepgsql-regtest' policy module appears not to be installed. +Without this policy installed, the regression tests will fail. +You can install this module using the following commands: + + $ make -f /usr/share/selinux/devel/Makefile + $ sudo semodule -u sepgsql-regtest.pp + +To confirm that the policy package is installed, use this command: + + $ sudo semodule -l | grep sepgsql + +EOS + die; +} + +# Verify that sepgsql_regression_test_mode is active. +note "checking whether policy is enabled"; +foreach + my $policy ('sepgsql_regression_test_mode', 'sepgsql_enable_users_ddl') +{ + my $POLICY_STATUS = (split ' ', `getsebool $policy`)[2]; + note "$policy is '$POLICY_STATUS'"; + if ($POLICY_STATUS ne "on") + { + diag <<EOS; + +The SELinux boolean '$policy' must be +turned on in order to enable the rules necessary to run the +regression tests. + +EOS + + if ($POLICY_STATUS eq "") + { + diag <<EOS; +We attempted to determine the state of this Boolean using +'getsebool', but that command did not produce the expected +output. Please verify that getsebool is available and in +your PATH. +EOS + } + else + { + diag <<EOS; +You can turn on this variable using the following commands: + + \$ sudo setsebool $policy on + +For security reasons, it is suggested that you turn off this +variable when regression testing is complete and the associated +rules are no longer needed. +EOS + } + die; + } +} + + +# +# checking complete - let's run the tests +# + +note "running sepgsql regression tests"; + +my $node; + +$node = PostgreSQL::Test::Cluster->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 f4cef9e80f7..7c474559bdf 100644 --- a/doc/src/sgml/regress.sgml +++ b/doc/src/sgml/regress.sgml @@ -285,6 +285,17 @@ make check-world PG_TEST_EXTRA='kerberos ldap ssl load_balance libpq_encryption' </varlistentry> <varlistentry> + <term><literal>sepgsql</literal></term> + <listitem> + <para> + Runs the test suite under <filename>contrib/sepgsql</filename>. This + requires an SELinux environment that is set up in a specific way; see + <xref linkend="sepgsql-regression"/>. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><literal>ssl</literal></term> <listitem> <para> diff --git a/doc/src/sgml/sepgsql.sgml b/doc/src/sgml/sepgsql.sgml index ca038d71042..03ed7d1c90d 100644 --- a/doc/src/sgml/sepgsql.sgml +++ b/doc/src/sgml/sepgsql.sgml @@ -152,13 +152,22 @@ $ for DBNAME in template0 template1 postgres; do <title>Regression Tests</title> <para> + The <filename>sepgsql</filename> test suite is run if + <literal>PG_TEST_EXTRA</literal> contains <literal>sepgsql</literal> (see + <xref linkend="regress-additional"/>). This method is suitable during + development of <productname>PostgreSQL</productname>. Alternatively, there + is a way to run the tests to checks whether a database instance has been + set up properly for <literal>sepgsql</literal>. + </para> + + <para> Due to the nature of <productname>SELinux</productname>, running the regression tests for <filename>sepgsql</filename> requires several extra configuration steps, some of which must be done as root. - The regression tests will not be run by an ordinary - <literal>make check</literal> or <literal>make installcheck</literal> command; you must - set up the configuration and then invoke the test script manually. - The tests must be run in the <filename>contrib/sepgsql</filename> directory + </para> + + <para> + The manual tests must be run in the <filename>contrib/sepgsql</filename> 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 <literal>make installcheck</literal> not diff --git a/meson.build b/meson.build index 32fc89f3a4b..8e128f4982a 100644 --- a/meson.build +++ b/meson.build @@ -3473,6 +3473,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 1278b7744f4..bbe11e75bf0 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -454,6 +454,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 @@ -481,6 +482,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 |