1

I try on PostgreSQL 9.3 to get the lines of pg_hba.conf where the authentication method is trust from user with minimal privileges. I wrote a function, but it doesn't work:

create function public.get_pghba_with_trust() 
  returns TABLE (
    TYPE            text
  , DATABASE        text
  , PGUSER            text
  , ADDRESS         text
  , METHOD          text) 
as
$$ 
  SELECT * 
  FROM regexp_split_to_table(pg_read_file('pg_hba.conf'),'\n') t(a) 
  WHERE a ~ '^[^#].*trust\s*$';
$$
language sql
security definer;

This returns an error:

ERROR:  return type mismatch in function declared to return record
DETAIL:  Final statement returns too few columns.
CONTEXT:  SQL function "get_pghba_with_trust"

Grant execute on function

grant execute on function get_pghba_with_trust() to redcheck;

Try other function

CREATE OR REPLACE FUNCTION get_pghba_with_trust() RETURNS text AS $$
DECLARE
  trust text;
BEGIN
  SELECT * INTO trust from regexp_split_to_table(pg_read_file('pg_hba.conf'),'\n') t(a) WHERE a ~ '^[^#].*trust\s*$';
  IF NOT FOUND THEN
    RETURN 'not used';
  ELSE
    RETURN trust;
  END IF;
END;
$$ LANGUAGE plpgsql security definer;

Grant execute on function

grant execute on function get_pghba_with_trust() to redcheck;

Try run function get_pghba_with_trust

SELECT * FROM get_pghba_with_trust();

Error:

ERROR: must be superuser TO READ files 
CONTEXT: SQL STATEMENT "SELECT * from regexp_split_to_table(pg_read_file('pg_hba.conf'),'\n') t(a) WHERE a ~ '^[^#].*trust\s*$'" PL/pgSQL FUNCTION get_pghba_with_trust() line 5 AT SQL STATEMENT

How get lines of pg_hba.conf on PostgreSQL 9.3 with trust method from user with minimal privileges?

  • regexp_split_to_table(pg_read_file('pg_hba.conf'),'\n') returns a single line of text, you should split it again – McNets Apr 9 '18 at 13:50
  • 3
    Please move your edit to a separate question, as it addresses a totally different problem. – dezso Apr 9 '18 at 14:38
  • Hello! Added PostgreSQL 9.3 to question. Sorry, I misspelled the question. So I did make a clarification in the question – Anton Patsev Apr 10 '18 at 5:51
3

You are nearly there, just have to process the output from pg_read_file() as it returns each line of pg_hba.conf as a single value. The following query will do the trick:

WITH file (line) AS (
    SELECT regexp_split_to_array(a, '\t+') 
      FROM regexp_split_to_table(pg_read_file('pg_hba.conf'), '\n') AS t(a)
     WHERE a ~ '^[^#].*trust\s*$'
)
SELECT line[1] AS type, 
       line[2] AS database, 
       line[3] AS username, 
       CASE WHEN array_length(line, 1) = 4 THEN NULL ELSE line[4] END AS range, 
       CASE WHEN array_length(line, 1) = 4 THEN line[4] ELSE line[5] END AS method
  FROM file;

This might not work in all cases that are possible in pg_hba.conf, though - you can tweak this query if you need to.

As you already noticed, pg_read_file() can be run only by superusers. This is the very reason why you need SECURITY DEFINER on your function. In order to make it work, you have to create the function as a superuser. (Note that changing owner after a non-superuser created the function doesn't work. If this is your case, drop the function first an create it anew, as a superuser this time.)

  • Hello! Thank you for answer. I changed quiestion – Anton Patsev Apr 9 '18 at 14:48
  • 2
    @AntonPatsev: please do not change your question or extend the scope of it once you get answers. – a_horse_with_no_name Apr 9 '18 at 20:15
  • Sorry, I misspelled the question. So I will make a clarification in the question – Anton Patsev Apr 10 '18 at 5:18
2

Starting with PostgreSQL 10, there's a built-in pg_hba_file_rules system view that provides this information. From https://www.postgresql.org/docs/10/static/view-pg-hba-file-rules.html :

The view pg_hba_file_rules provides a summary of the contents of the client authentication configuration file, pg_hba.conf. A row appears in this view for each non-empty, non-comment line in the file, with annotations indicating whether the rule could be applied successfully.

This view can be helpful for checking whether planned changes in the authentication configuration file will work, or for diagnosing a previous failure. Note that this view reports on the current contents of the file, not on what was last loaded by the server.

The permission to read on this view and the underlying function can be granted to a non-superuser:

grant execute on function pg_catalog.pg_hba_file_rules() to somerole;
grant select on pg_catalog.pg_hba_file_rules to somerole;

which then has just to run:

select * from pg_hba_file_rules WHERE auth_method = 'trust';
  • Hello! Added PostgreSQL 9.3 to question. Sorry, I misspelled the question. So I did make a clarification in the question – Anton Patsev Apr 10 '18 at 5:51
0

CREATE FUNCTION PUBLIC.list_settings

CREATE FUNCTION PUBLIC.list_settings 
  () returns setof pg_catalog.pg_settings 
AS 
  $$ 
  SELECT * 
  FROM   pg_catalog.pg_settings; 

  $$ LANGUAGE SQL security definer;

Then grant execute on that function to your user:

GRANT EXECUTE ON FUNCTION PUBLIC.list_settings() TO the_user; 

which then has just to run:

SELECT * 
FROM   regexp_split_to_table(PUBLIC.list_settings(),'\n') t(a) 
WHERE  a ~ '^[^#].*trust\s*$';

Or other choice

CREATE FUNCTION f_showfile

CREATE FUNCTION f_showfile(myfile text) RETURNS text AS $x$
BEGIN
RETURN pg_read_file(myfile, 0, 1000000);
END;
$x$ LANGUAGE PLPGSQL SECURITY DEFINER;

GRANT EXECUTE ON FUNCTION public.f_showfile

GRANT EXECUTE ON FUNCTION public.f_showfile (text) TO the_user;

Get lines with trust string from pg_hba.conf

SELECT *
FROM regexp_split_to_table(f_showfile('pg_hba.conf'),'\n') t(a)
WHERE a ~ '^[^#].*trust\s*$';

Get lines with primary_conninfo string from recovery.conf

SELECT *
FROM regexp_split_to_table(f_showfile('recovery.conf'),'\n') t(a)
WHERE a ~ '^ *primary_conninfo';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.