]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add and document cache_groups
authorAlan T. DeKok <aland@freeradius.org>
Thu, 24 Aug 2023 15:25:55 +0000 (11:25 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 24 Aug 2023 15:26:33 +0000 (11:26 -0400)
doc/antora/modules/raddb/pages/mods-available/sql.adoc
raddb/mods-available/sql
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h

index bfeed9af1a91459d144bf907bee1272a9cd01b0c..0d76b0743bf04b94117e6bfed0e3ca9b3d91e5d0 100644 (file)
@@ -196,10 +196,10 @@ sql sql2 {
 
 start:: Connections to create during module instantiation.
 
-If the server cannot create specified number of connections during instantiation
-it will exit.
-
-Set to `0` to allow the server to start without the database being available.
+If the server cannot create specified number of
+connections during instantiation it will exit.
+Set to `0` to allow the server to start without the
+external service being available.
 
 
 
@@ -209,14 +209,18 @@ min:: Minimum number of connections to keep open.
 
 max:: Maximum number of connections.
 
-If these connections are all in use and a new one is requested, the request
-will NOT get a connection.
+If these connections are all in use and a new one
+is requested, the request will NOT get a connection.
+
+Setting `max` to *LESS* than the number of threads means
+that some threads may starve, and you will see errors
+like _No connections available and at max connection limit_.
 
-Setting `max` to LESS than the number of threads means that some threads may starve,
-and you will see errors like _No connections available and at max connection limit_.
+Setting `max` to MORE than the number of threads means
+that there are more connections than necessary.
 
-Setting `max` to MORE than the number of threads means that there are more
-connections than necessary.
+If `max` is not specified, then it defaults to the number
+of workers configured.
 
 
 
@@ -280,6 +284,36 @@ When that happens, it will open a new connection.  It will also log a WARNING me
 
 group_attribute:: The group attribute specific to this instance of `rlm_sql`.
 
+The "group_membership_query" is used to select which groups the user is a member of.
+
+The module loops over all groups, and places the group name into the "group_attribute".
+
+The group attribute is used in the "authorize_group_check_query" and "authorize_group_check_query"
+to select entries which match that particular group.
+
+If caching is enabled, then the module is done looping over groups, the module adds the names of
+groups to the `control` list.  The "group_attribute" can then be used to check group membership.
+That check will be done internally, and will not result in a database lookup.  This also means that
+it is now possible to do group comparisons based on regular expressions.
+
+It is possible to force a dynamic group lookup via the expansion `%{sql.group:foo}`.  This
+expansion returns `true` if the user is a member of that SQL group, and `false` otherwise.
+
+NOTE: The `SQL-Group` attribute is only available after the SQL module has been run.
+
+The name of the group attribute is automatically determined from the module name.  By default, the
+name is `SQL-Group`.  if the module is an instance such as `sql sql1 { ... }`, then the name of the
+group attribute is `SQL1-Group`.
+
+
+
+cache_groups: whether or not we cache the list of SQL groups
+
+The groups are cached in the `control` list.  So any comparisons must be done as
+`&control.SQL-Group = ...`
+
+Default is `no`.
+
 
 
 .Read database-specific queries.
@@ -327,6 +361,7 @@ sql {
                connect_timeout = 3.0
        }
        group_attribute = "${.:instance}-Group"
+#      cache_groups = no
        $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf
 }
 ```
index 8cf2e5007a2d788c7f438cb838ea2e4c3516c72f..57263315fa80aca937c4556610d74b057b82d189 100644 (file)
@@ -345,6 +345,16 @@ sql {
        #
        group_attribute = "${.:instance}-Group"
 
+       #
+       #  cache_groups: whether or not we cache the list of SQL groups
+       #
+       #  The groups are cached in the `control` list.  So any comparisons must be done as
+       #  `&control.SQL-Group = ...`
+       #
+       #  Default is `no`.
+       #
+#      cache_groups = no
+
        #
        #  .Read database-specific queries.
        #
index 8a2f0d74d720fb9fc30cbcd57a128bc279483dd2..a075bb10456bd67748a0e3475e25832c4151d322 100644 (file)
@@ -900,13 +900,15 @@ static unlang_action_t rlm_sql_process_groups(rlm_rcode_t *p_result,
 
        entry = head;
        do {
+               bool added;
+               fr_pair_t       *vp;
+
        next:
                fr_assert(entry != NULL);
                fr_pair_value_strdup(sql_group, entry->name, true);
+               added = false;
 
                if (inst->config.authorize_group_check_query) {
-                       fr_pair_t       *vp;
-
                        /*
                         *      Expand the group query
                         */
@@ -956,10 +958,15 @@ static unlang_action_t rlm_sql_process_groups(rlm_rcode_t *p_result,
                        radius_pairmove(request, &request->control_pairs, &check_tmp);
 
                        fr_pair_list_free(&check_tmp);
+
+                       if (inst->config.cache_groups) {
+                               MEM(pair_update_control(&vp, inst->group_da) >= 0);
+                               fr_pair_value_strdup(vp, entry->name, true);
+                               added = true;
+                       }
                }
 
                if (inst->config.authorize_group_reply_query) {
-
                        /*
                         *      Now get the reply pairs since the paircmp matched
                         */
@@ -1002,6 +1009,11 @@ static unlang_action_t rlm_sql_process_groups(rlm_rcode_t *p_result,
                        *do_fall_through = FALL_THROUGH_DEFAULT;
                }
 
+               if (inst->config.cache_groups && !added) {
+                       MEM(pair_update_control(&vp, inst->group_da) >= 0);
+                       fr_pair_value_strdup(vp, entry->name, true);
+               }
+
                entry = entry->next;
        } while (entry != NULL && (*do_fall_through == FALL_THROUGH_YES));
 
index e9dd9a1af4704dde058ddfad7ffcf7b5b6f54dd5..dd94e34a8b63bb95eada2d6e83d912528bf5eecf 100644 (file)
@@ -106,6 +106,8 @@ typedef struct {
        char const              *authorize_group_reply_query;   //!< Query used get reply VPs for a group.
        char const              *groupmemb_query;               //!< Query to determine group membership.
 
+       bool                    cache_groups;                   //!< cache group names in &control.SQL-Group
+
        bool                    read_groups;                    //!< Read user groups by default.
                                                                //!< If false, Fall-Through = yes is required
                                                                //!< in the previous reply list to process