Add rule_number to pg_hba_file_rules and map_number to pg_ident_file_mappings
authorMichael Paquier <[email protected]>
Wed, 26 Oct 2022 06:22:15 +0000 (15:22 +0900)
committerMichael Paquier <[email protected]>
Wed, 26 Oct 2022 06:22:15 +0000 (15:22 +0900)
These numbers are strictly-monotone identifiers assigned to each rule
of pg_hba_file_rules and each map of pg_ident_file_mappings when loading
the HBA and ident configuration files, indicating the order in which
they are checked at authentication time, until a match is found.

With only one file loaded currently, this is equivalent to the line
numbers assigned to the entries loaded if one wants to know their order,
but this becomes mandatory once the inclusion of external files is
added to the HBA and ident files to be able to know in which order the
rules and/or maps are applied at authentication.  Note that NULL is used
when a HBA or ident entry cannot be parsed or validated, aka when an
error exists, contrary to the line number.

Bump catalog version.

Author: Julien Rouhaud
Discussion: https://postgr.es/m/20220223045959.35ipdsvbxcstrhya@jrouhaud

doc/src/sgml/system-views.sgml
src/backend/utils/adt/hbafuncs.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/test/regress/expected/rules.out

index 1ca7c3f9bfcd5129283c88fea5bdd51c6d6fcf19..1951d1b5a2102e0699835eac5ecf15f459c76283 100644 (file)
     </thead>
 
     <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>rule_number</structfield> <type>int4</type>
+      </para>
+      <para>
+       Number of this rule, if valid, otherwise <literal>NULL</literal>.
+       This indicates the order in which each rule is considered
+       until a match is found during authentication.
+      </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>line_number</structfield> <type>int4</type>
     </thead>
 
     <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>map_number</structfield> <type>int4</type>
+      </para>
+      <para>
+       Number of this map, in priority order, if valid, otherwise
+       <literal>NULL</literal>
+      </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>line_number</structfield> <type>int4</type>
index cfdc4d8b3912b5b8aa2e34a88c07e4dc95f227a0..e12ff8ca72004402a19a93336f39f91b6bfa2038 100644 (file)
 
 static ArrayType *get_hba_options(HbaLine *hba);
 static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
-                         int lineno, HbaLine *hba, const char *err_msg);
+                         int rule_number, int lineno, HbaLine *hba,
+                         const char *err_msg);
 static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
 static void fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
-                           int lineno, IdentLine *ident, const char *err_msg);
+                           int map_number, int lineno, IdentLine *ident,
+                           const char *err_msg);
 static void fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
 
 
@@ -157,7 +159,7 @@ get_hba_options(HbaLine *hba)
 }
 
 /* Number of columns in pg_hba_file_rules view */
-#define NUM_PG_HBA_FILE_RULES_ATTS  9
+#define NUM_PG_HBA_FILE_RULES_ATTS  10
 
 /*
  * fill_hba_line
@@ -165,6 +167,7 @@ get_hba_options(HbaLine *hba)
  *
  * tuple_store: where to store data
  * tupdesc: tuple descriptor for the view
+ * rule_number: unique identifier among all valid rules
  * lineno: pg_hba.conf line number (must always be valid)
  * hba: parsed line data (can be NULL, in which case err_msg should be set)
  * err_msg: error message (NULL if none)
@@ -174,7 +177,8 @@ get_hba_options(HbaLine *hba)
  */
 static void
 fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
-             int lineno, HbaLine *hba, const char *err_msg)
+             int rule_number, int lineno, HbaLine *hba,
+             const char *err_msg)
 {
    Datum       values[NUM_PG_HBA_FILE_RULES_ATTS];
    bool        nulls[NUM_PG_HBA_FILE_RULES_ATTS];
@@ -193,6 +197,12 @@ fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
    memset(nulls, 0, sizeof(nulls));
    index = 0;
 
+   /* rule_number, nothing on error */
+   if (err_msg)
+       nulls[index++] = true;
+   else
+       values[index++] = Int32GetDatum(rule_number);
+
    /* line_number */
    values[index++] = Int32GetDatum(lineno);
 
@@ -336,7 +346,7 @@ fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
    else
    {
        /* no parsing result, so set relevant fields to nulls */
-       memset(&nulls[1], true, (NUM_PG_HBA_FILE_RULES_ATTS - 2) * sizeof(bool));
+       memset(&nulls[2], true, (NUM_PG_HBA_FILE_RULES_ATTS - 3) * sizeof(bool));
    }
 
    /* error */
@@ -359,6 +369,7 @@ fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
    FILE       *file;
    List       *hba_lines = NIL;
    ListCell   *line;
+   int         rule_number = 0;
    MemoryContext linecxt;
    MemoryContext hbacxt;
    MemoryContext oldcxt;
@@ -393,8 +404,12 @@ fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
        if (tok_line->err_msg == NULL)
            hbaline = parse_hba_line(tok_line, DEBUG3);
 
-       fill_hba_line(tuple_store, tupdesc, tok_line->line_num,
-                     hbaline, tok_line->err_msg);
+       /* No error, set a new rule number */
+       if (tok_line->err_msg == NULL)
+           rule_number++;
+
+       fill_hba_line(tuple_store, tupdesc, rule_number,
+                     tok_line->line_num, hbaline, tok_line->err_msg);
    }
 
    /* Free tokenizer memory */
@@ -431,7 +446,7 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
 }
 
 /* Number of columns in pg_ident_file_mappings view */
-#define NUM_PG_IDENT_FILE_MAPPINGS_ATTS     5
+#define NUM_PG_IDENT_FILE_MAPPINGS_ATTS     6
 
 /*
  * fill_ident_line: build one row of pg_ident_file_mappings view, add it to
@@ -439,6 +454,7 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
  *
  * tuple_store: where to store data
  * tupdesc: tuple descriptor for the view
+ * map_number: unique identifier among all valid maps
  * lineno: pg_ident.conf line number (must always be valid)
  * ident: parsed line data (can be NULL, in which case err_msg should be set)
  * err_msg: error message (NULL if none)
@@ -448,7 +464,8 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
  */
 static void
 fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
-               int lineno, IdentLine *ident, const char *err_msg)
+               int map_number, int lineno, IdentLine *ident,
+               const char *err_msg)
 {
    Datum       values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
    bool        nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
@@ -461,6 +478,12 @@ fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
    memset(nulls, 0, sizeof(nulls));
    index = 0;
 
+   /* map_number, nothing on error */
+   if (err_msg)
+       nulls[index++] = true;
+   else
+       values[index++] = Int32GetDatum(map_number);
+
    /* line_number */
    values[index++] = Int32GetDatum(lineno);
 
@@ -473,7 +496,7 @@ fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
    else
    {
        /* no parsing result, so set relevant fields to nulls */
-       memset(&nulls[1], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 2) * sizeof(bool));
+       memset(&nulls[2], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 3) * sizeof(bool));
    }
 
    /* error */
@@ -495,6 +518,7 @@ fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
    FILE       *file;
    List       *ident_lines = NIL;
    ListCell   *line;
+   int         map_number = 0;
    MemoryContext linecxt;
    MemoryContext identcxt;
    MemoryContext oldcxt;
@@ -529,7 +553,12 @@ fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
        if (tok_line->err_msg == NULL)
            identline = parse_ident_line(tok_line, DEBUG3);
 
-       fill_ident_line(tuple_store, tupdesc, tok_line->line_num, identline,
+       /* no error, set a new mapping number */
+       if (tok_line->err_msg == NULL)
+           map_number++;
+
+       fill_ident_line(tuple_store, tupdesc, map_number,
+                       tok_line->line_num, identline,
                        tok_line->err_msg);
    }
 
index 4c930c189bb92fe060551b8fa5fe14799c242e96..de6783a27b646c6df525ed86f76616a3d2c6c187 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202210141
+#define CATALOG_VERSION_NO 202210261
 
 #endif
index 62a5b8e655df261e16d2b98247890e5577b6159a..20f5aa56eab3c756ca1de4cab9a57037a4926224 100644 (file)
 { oid => '3401', descr => 'show pg_hba.conf rules',
   proname => 'pg_hba_file_rules', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
-  proallargtypes => '{int4,text,_text,_text,text,text,text,_text,text}',
-  proargmodes => '{o,o,o,o,o,o,o,o,o}',
-  proargnames => '{line_number,type,database,user_name,address,netmask,auth_method,options,error}',
+  proallargtypes => '{int4,int4,text,_text,_text,text,text,text,_text,text}',
+  proargmodes => '{o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{rule_number,line_number,type,database,user_name,address,netmask,auth_method,options,error}',
   prosrc => 'pg_hba_file_rules' },
 { oid => '6250', descr => 'show pg_ident.conf mappings',
   proname => 'pg_ident_file_mappings', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
-  proallargtypes => '{int4,text,text,text,text}', proargmodes => '{o,o,o,o,o}',
-  proargnames => '{line_number,map_name,sys_name,pg_username,error}',
+  proallargtypes => '{int4,int4,text,text,text,text}',
+  proargmodes => '{o,o,o,o,o,o}',
+  proargnames => '{map_number,line_number,map_name,sys_name,pg_username,error}',
   prosrc => 'pg_ident_file_mappings' },
 { oid => '1371', descr => 'view system lock information',
   proname => 'pg_lock_status', prorows => '1000', proretset => 't',
index bfcd8ac9a06d3ef3cab33e6172785d3a103249e3..624d0e5aae18b1e34d8af5c0cc1b9f79f37823a0 100644 (file)
@@ -1337,7 +1337,8 @@ pg_group| SELECT pg_authid.rolname AS groname,
           WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist
    FROM pg_authid
   WHERE (NOT pg_authid.rolcanlogin);
-pg_hba_file_rules| SELECT a.line_number,
+pg_hba_file_rules| SELECT a.rule_number,
+    a.line_number,
     a.type,
     a.database,
     a.user_name,
@@ -1346,13 +1347,14 @@ pg_hba_file_rules| SELECT a.line_number,
     a.auth_method,
     a.options,
     a.error
-   FROM pg_hba_file_rules() a(line_number, type, database, user_name, address, netmask, auth_method, options, error);
-pg_ident_file_mappings| SELECT a.line_number,
+   FROM pg_hba_file_rules() a(rule_number, line_number, type, database, user_name, address, netmask, auth_method, options, error);
+pg_ident_file_mappings| SELECT a.map_number,
+    a.line_number,
     a.map_name,
     a.sys_name,
     a.pg_username,
     a.error
-   FROM pg_ident_file_mappings() a(line_number, map_name, sys_name, pg_username, error);
+   FROM pg_ident_file_mappings() a(map_number, line_number, map_name, sys_name, pg_username, error);
 pg_indexes| SELECT n.nspname AS schemaname,
     c.relname AS tablename,
     i.relname AS indexname,