Skip to content

Commit

Permalink
WIP policy_is_permissive, policy_is_restrictive
Browse files Browse the repository at this point in the history
  • Loading branch information
iamed2 committed Nov 29, 2024
1 parent 2e4be23 commit 1804be5
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 1 deletion.
101 changes: 101 additions & 0 deletions sql/pgtap.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -10624,6 +10624,107 @@ RETURNS TEXT AS $$
);
$$ LANGUAGE sql;

/*
* Internal function to test whether the specified policy on the specified
* table in the specified schema is permissive (true) or restrictive (false).
*/
CREATE OR REPLACE FUNCTION _permissive( NAME, NAME, NAME )
RETURNS BOOLEAN AS $$
-- restrictive policies did not exist before postgresql 10
SELECT CASE WHEN pg_version_num() >= 100000 THEN pp.polpermissive ELSE TRUE END AS permissive
FROM pg_catalog.pg_policy AS pp
JOIN pg_catalog.pg_class AS pc ON pc.oid = pp.polrelid
JOIN pg_catalog.pg_namespace AS pn ON pn.oid = pc.relnamespace
WHERE pn.nspname = $1
AND pc.relname = $2
AND pp.polname = $3;
$$ LANGUAGE SQL;

/*
* Internal function to test whether the specified policy on the specified
* table is permissive (true) or restrictive (false).
*/
CREATE OR REPLACE FUNCTION _permissive( NAME, NAME )
RETURNS BOOLEAN AS $$
-- restrictive policies did not exist before postgresql 10
SELECT CASE WHEN pg_version_num() >= 100000 THEN pp.polpermissive ELSE TRUE END AS permissive
FROM pg_catalog.pg_policy AS pp
JOIN pg_catalog.pg_class AS pc ON pc.oid = pp.polrelid
JOIN pg_catalog.pg_namespace AS pn ON pn.oid = pc.relnamespace
WHERE pc.relname = $1
AND pp.polname = $2
AND pn.nspname NOT IN ('pg_catalog', 'information_schema');
$$ LANGUAGE SQL;

-- policy_is_permissive( schema, table, policy, description )
CREATE OR REPLACE FUNCTION policy_is_permissive( NAME, NAME, NAME, text )
RETURNS TEXT AS $$
SELECT ok( _permissive( $1, $2, $3 ), $4 );
$$ LANGUAGE SQL;

-- policy_is_permissive( schema, table, policy )
CREATE OR REPLACE FUNCTION policy_is_permissive( NAME, NAME, NAME )
RETURNS TEXT AS $$
SELECT policy_is_permissive(
$1, $2, $3,
'Policy ' || quote_ident($3)
|| ' for table ' || quote_ident($1) || '.' || quote_ident($2)
|| ' should be permissive, not restrictive'
);
$$ LANGUAGE SQL;

-- policy_is_permissive( table, policy, description )
CREATE OR REPLACE FUNCTION policy_is_permissive( NAME, NAME, text )
RETURNS TEXT AS $$
SELECT ok( _permissive( $1, $2 ), $3 );
$$ LANGUAGE SQL;

-- policy_is_permissive( table, policy )
CREATE OR REPLACE FUNCTION policy_is_permissive( NAME, NAME )
RETURNS TEXT AS $$
SELECT policy_is_permissive(
$1, $2,
'Policy ' || quote_ident($2)
|| ' for table ' || quote_ident($1)
|| ' should be permissive, not restrictive'
);
$$ LANGUAGE SQL;

-- policy_is_restrictive( schema, table, policy, description )
CREATE OR REPLACE FUNCTION policy_is_restrictive( NAME, NAME, NAME, text )
RETURNS TEXT AS $$
SELECT ok( NOT _permissive( $1, $2, $3 ), $4 );
END;
$$ LANGUAGE SQL;

-- policy_is_restrictive( schema, table, policy )
CREATE OR REPLACE FUNCTION policy_is_restrictive( NAME, NAME, NAME )
RETURNS TEXT AS $$
SELECT policy_is_restrictive(
$1, $2, $3,
'Policy ' || quote_ident($3)
|| ' for table ' || quote_ident($1) || '.' || quote_ident($2)
|| ' should be restrictive, not permissive'
);
$$ LANGUAGE SQL;

-- policy_is_restrictive( table, policy, description )
CREATE OR REPLACE FUNCTION policy_is_restrictive( NAME, NAME, text )
RETURNS TEXT AS $$
SELECT ok( NOT _permissive( $1, $2 ), $3 );
$$ LANGUAGE SQL;

-- policy_is_restrictive( table, policy )
CREATE OR REPLACE FUNCTION policy_is_restrictive( NAME, NAME )
RETURNS TEXT AS $$
SELECT policy_is_restrictive(
$1, $2,
'Policy ' || quote_ident($2)
|| ' for table ' || quote_ident($1)
|| ' should be restrictive, not permissive'
);
$$ LANGUAGE SQL;

/******************** INHERITANCE ***********************************************/
/*
* Internal function to test whether the specified table in the specified schema
Expand Down
104 changes: 103 additions & 1 deletion test/sql/policy.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
\unset ECHO
\i test/setup.sql

SELECT plan(180);
SELECT plan(192);
--SELECT * FROM no_plan();

-- This will be rolled back. :-)
Expand Down Expand Up @@ -579,6 +579,108 @@ SELECT * FROM check_test(
want: DELETE'
);

/****************************************************************************/
-- Test policy_is_permissive().

SELECT * FROM check_test(
policy_is_permissive( 'public', 'passwd', 'root_all'::NAME ),
true,
'policy_is_permissive(schema, table, policy)',
'Policy root_all for table public.passwd should be permissive, not restrictive',
''
);

SELECT * FROM check_test(
policy_is_permissive( 'public', 'passwd', 'doesnt_exist'::NAME ),
true,
'policy_is_permissive(schema, table, policy) for nonexistent policy',
'Policy root_all for table public.passwd should be permissive, not restrictive',
'(test result was NULL)'
);

SELECT * FROM check_test(
policy_is_permissive( 'public', 'passwd', 'root_all', 'whatever' ),
true,
'policy_is_permissive(schema, table, policy, desc)',
'whatever',
''
);

SELECT * FROM check_test(
policy_is_permissive( 'passwd', 'root_all' ),
true,
'policy_is_permissive(table, policy)',
'Policy root_all for table passwd should be permissive, not restrictive',
''
);

SELECT * FROM check_test(
policy_is_permissive( 'passwd', 'doesnt_exist' ),
true,
'policy_is_permissive(table, policy) for nonexistent policy',
'Policy root_all for table passwd should be permissive, not restrictive',
'(test result was NULL)'
);

SELECT * FROM check_test(
policy_is_permissive( 'passwd', 'root_all', 'whatever' ),
true,
'policy_is_permissive(table, policy, desc)',
'whatever',
''
);

/****************************************************************************/
-- Test policy_is_restrictive().

SELECT * FROM check_test(
policy_is_restrictive( 'public', 'passwd', 'root_all'::NAME ),
false,
'policy_is_permissive(schema, table, policy)',
'Policy root_all for table public.passwd should be permissive, not restrictive',
''
);

SELECT * FROM check_test(
policy_is_restrictive( 'public', 'passwd', 'doesnt_exist'::NAME ),
false,
'policy_is_permissive(schema, table, policy) for nonexistent policy',
'Policy doesnt_exist for table public.passwd should be permissive, not restrictive',
'(test result was NULL)'
);

SELECT * FROM check_test(
policy_is_restrictive( 'public', 'passwd', 'root_all', 'whatever' ),
false,
'policy_is_permissive(schema, table, policy, desc)',
'whatever',
''
);

SELECT * FROM check_test(
policy_is_restrictive( 'passwd', 'root_all' ),
false,
'policy_is_permissive(table, policy)',
'Policy root_all for table passwd should be permissive, not restrictive',
''
);

SELECT * FROM check_test(
policy_is_restrictive( 'passwd', 'doesnt_exist' ),
false,
'policy_is_permissive(table, policy) for nonexistent policy',
'Policy doesnt_exist for table passwd should be permissive, not restrictive',
'(test result was NULL)'
);

SELECT * FROM check_test(
policy_is_restrictive( 'passwd', 'root_all', 'whatever' ),
false,
'policy_is_permissive(table, policy, desc)',
'whatever',
''
);

/****************************************************************************/
-- Finish the tests and clean up.
SELECT * FROM finish();
Expand Down

0 comments on commit 1804be5

Please sign in to comment.