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
pull/198/head
Peter Eisentraut 5 months ago
parent 02ed3c2bdc
commit aeb8ea361a
  1. 4
      contrib/sepgsql/.gitignore
  2. 2
      contrib/sepgsql/Makefile
  3. 11
      contrib/sepgsql/meson.build
  4. 246
      contrib/sepgsql/t/001_sepgsql.pl
  5. 12
      contrib/sepgsql/test_sepgsql
  6. 11
      doc/src/sgml/regress.sgml
  7. 17
      doc/src/sgml/sepgsql.sgml
  8. 2
      meson.build
  9. 2
      src/Makefile.global.in

@ -3,5 +3,5 @@
/sepgsql-regtest.if
/sepgsql-regtest.pp
/tmp
# Generated subdirectories
/results/
# Generated by test suite
/tmp_check/

@ -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

@ -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',
],
},
}

@ -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();

@ -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

@ -284,6 +284,17 @@ make check-world PG_TEST_EXTRA='kerberos ldap ssl load_balance libpq_encryption'
</listitem>
</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>

@ -151,14 +151,23 @@ $ for DBNAME in template0 template1 postgres; do
<sect2 id="sepgsql-regression">
<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

@ -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)

@ -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

Loading…
Cancel
Save