Pattern Match Group Membership in the attribute list

Vlad Kratsberg vkratsberg at gmail.com
Fri Jul 1 17:38:46 UTC 2022


Hi Alan,

Thank you for your response.   I decided to follow your recommendation and
use session-state:

In my inner-tunnel authorize section, I call ldap module to get a list of
groups the user is memberOf and save them to session state:

       ldap
       update session-state {
               &LDAP-Group += &control:LDAP-Group[*]        #### I had to
add [*] so that &LDAP-Group saves all groups, not just the last one.
               }
       debug_session_state

rlm_ldap (ldap): Bind successful
(6)       [ldap] = ok
(6)         update session-state {
(6)           &LDAP-Group += &control:LDAP-Group[*] ->
'network_engineering-inf-eng'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'ad_jira-developers'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'engineering'
(6)           &LDAP-Group += &control:LDAP-Group[*] ->
'ad_jira-administrators'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'infrastructure-eng'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'ad_employees'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'no-phc-infra'
(6)           &LDAP-Group += &control:LDAP-Group[*] -> 'networks-inf-eng'
(6)         } # update session-state = noop.

#####. I can see groups are added to session state:

(6)       policy debug_session_state {
(6)         if ("%{debug_attr:session-state:}" == '') {
(6)         Attributes matching "session-state:"
(6)           &session-state:LDAP-Group += network_engineering-inf-eng
(6)           &session-state:LDAP-Group += ad_jira-developers
(6)           &session-state:LDAP-Group += engineering
(6)           &session-state:LDAP-Group += ad_jira-administrators
(6)           &session-state:LDAP-Group += infrastructure-eng
(6)           &session-state:LDAP-Group += ad_employees
(6)           &session-state:LDAP-Group += no-phc-infra
(6)           &session-state:LDAP-Group += networks-inf-eng
(6)         EXPAND %{debug_attr:session-state:}
(6)            -->
(6)         if ("%{debug_attr:session-state:}" == '')  -> TRUE
(6)         if ("%{debug_attr:session-state:}" == '')  {
(6)           [noop] = noop
(6)         } # if ("%{debug_attr:session-state:}" == '')  = noop
(6)       } # policy debug_session_state = noop
(6)     } # authorize = ok

In packet 8 where policies are evaluated, session-state doesn't contain
session-state:LDAP-Group.

post-auth {
    debug_session_state

        if (LDAP-Group == "networks-inf-eng") {
                update reply {
                        ....
                        }
                }

(8) server inner-tunnel {
(8)   session-state: No cached attributes.  ##### No cached attributes
(8)   # Executing section authorize from file
/etc/raddb/sites-enabled/inner-tunnel

(8)   # Executing section post-auth from file
/etc/raddb/sites-enabled/inner-tunnel
(8)     post-auth {
(8)       policy debug_session_state {
(8)         if ("%{debug_attr:session-state:}" == '') {
(8)         Attributes matching "session-state:"
(8)         EXPAND %{debug_attr:session-state:}
(8)            -->
(8)         if ("%{debug_attr:session-state:}" == '')  -> TRUE
(8)         if ("%{debug_attr:session-state:}" == '')  {
(8)           [noop] = noop
(8)         } # if ("%{debug_attr:session-state:}" == '')  = noop
(8)       } # policy debug_session_state = noop
(8)       if (LDAP-Group == "networks-inf-eng") {
(8)       Searching for user in group "networks-inf-eng"

Why is the LDAP-Group attribute not available in packet #8 locally for
policy evaluation ?   It looks like session-state is empty when packet #8
is being processed.

===============================================================

On Jun 30, 2022, at 3:12 PM, Vlad Kratsberg <vkratsberg at gmail.com> wrote:
> We are trying to configure LDAP group membership to work to avoid repeated
> calls to Active Directory.

  When the server does LDAP group checking, it also keeps a copy of the
LDAP-Group attribute while the request is active.

  If you need to do LDAP group checking across multiple EAP rounds, you can
copy the LDAP-Group attributes to the session-state list:

        update session-state {
                        &LDAP-Group += &control:LDAP-Group
        }

  The server will then save / restore LDAP-Group for one EAP session,
across multiple packets.

  There isn't much benefit to using the "cache" module to save LDAP-Group
information.

> ### Recording a list of groups:
>
> (6) ldap: Adding cacheable user object memberships
> (6) ldap:   &control:LDAP-Cached-Membership +=
"network_engineering-inf-eng"

  That's saving it locally...

> ### Caching it:
> (6) cache: Creating new cache entry
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'network_engineering-inf-eng'

  That's not necessary.


> #### Verifying that LDAP-Cached-Membership[*] contains all the groups:
>
> (8)           EXPAND Attribute contains: %{LDAP-Cached-Membership[*]}
> (8)              --> Attribute contains:
>
network_engineering-inf-eng,ad_jira-developers,engineering,ad_jira-administrators,infrastructure-eng,ad_employees,no-phc-infra,networks-inf-eng

  That is a string version of all of the LDAP-Cached-Membership attributes,
with commas between the values.  So that's fine.

> ### In Post-Auth section, when evaluating policies, I can't match any of
> the values stored in the LDAP-Cached-Membership[*].
>
> (8) cache: Found entry for "xxxxxxx"
> (8)       [cache] = ok
> (8)       if (notfound) {
> (8)       if (notfound)  -> FALSE
> (8)       elsif (ok) {
> (8)       elsif (ok)  -> TRUE
> (8)       elsif (ok)  {
> (8)         if (LDAP-Cached-Membership[*] =~ /.*networks-inf-eng.*/) {

  Uh... why LDAP-Cached-Membership[*]?  Why not just LDAP-Cached-Membership?

  And why a regular expression match?  If you know the group names, you can
just match that.

  Try:

        if (LDAP-Cached-Membership == network_engineering-inf-eng) {
                ...
        }

  and it should work

> Appreciate your help in pointing me in the right direction.

  I don't know why you're using LDAP-Cached-Membership[*].  That really
doesn't do what you want.  See "man unlang".  Just check for one value, and
the server will automatically return true if there's many attributes, with
one matching the value.

  The &Attribute[*] reference is really only useful when you're printing
all of the attributes to a string.  For everything else, it really doesn't
do what you want.

  Alan DeKok.

On Thu, Jun 30, 2022 at 3:12 PM Vlad Kratsberg <vkratsberg at gmail.com> wrote:

> Hello,
> We are trying to configure LDAP group membership to work to avoid repeated
> calls to Active Directory.
>
> 90% of work is done:
> FR 3.0.25
>
> ### Recording a list of groups:
>
> (6) ldap: Adding cacheable user object memberships
> (6) ldap:   &control:LDAP-Cached-Membership +=
> "network_engineering-inf-eng"
> (6) ldap:   &control:LDAP-Cached-Membership += "ad_jira-developers"
> (6) ldap:   &control:LDAP-Cached-Membership += "engineering"
> (6) ldap:   &control:LDAP-Cached-Membership += "ad_jira-administrators"
> (6) ldap:   &control:LDAP-Cached-Membership += "infrastructure-eng"
> (6) ldap:   &control:LDAP-Cached-Membership += "ad_employees"
> (6) ldap:   &control:LDAP-Cached-Membership += "no-phc-infra"
> (6) ldap:   &control:LDAP-Cached-Membership += "networks-inf-eng"
>
> ### Caching it:
> (6) cache: Creating new cache entry
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'network_engineering-inf-eng'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'ad_jira-developers'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'engineering'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'ad_jira-administrators'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'infrastructure-eng'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'ad_employees'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'no-phc-infra'
> (6) cache:   &LDAP-Cached-Membership += &control:LDAP-Cached-Membership[*]
> -> 'networks-inf-eng'
> (6) cache: EXPAND Cache last updated at %t
> (6) cache:    --> Cache last updated at Thu Jun 30 18:55:55 2022
> (6) cache:   &reply:Reply-Message += Cache last updated at Thu Jun 30
> 18:55:55 2022
> (6) cache: EXPAND %{randstr:ssssssssssssssssssssssssssssssss}
> (6) cache:    --> Oae2Ugjv9rHP5rxlxNP64mal.P4ggAC4
> (6) cache:   &reply:Class :=
> 0x4f61653255676a76397248503572786c784e5036346d616c2e50346767414334
> (6) cache: Merging cache entry into request
> (6) cache:   &request:LDAP-Cached-Membership +=
> "network_engineering-inf-eng"
> (6) cache:   &request:LDAP-Cached-Membership += "ad_jira-developers"
> (6) cache:   &request:LDAP-Cached-Membership += "engineering"
> (6) cache:   &request:LDAP-Cached-Membership += "ad_jira-administrators"
> (6) cache:   &request:LDAP-Cached-Membership += "infrastructure-eng"
> (6) cache:   &request:LDAP-Cached-Membership += "ad_employees"
> (6) cache:   &request:LDAP-Cached-Membership += "no-phc-infra"
> (6) cache:   &request:LDAP-Cached-Membership += "networks-inf-eng"
> (6) cache:   &reply:Reply-Message += "Cache last updated at Thu Jun 30
> 18:55:55 2022"
> (6) cache:   &reply:Class :=
> 0x4f61653255676a76397248503572786c784e5036346d616c2e50346767414334
> (6) cache: Committed entry, TTL 10 seconds
>
> #### Verifying that LDAP-Cached-Membership[*] contains all the groups:
>
> (8)           EXPAND Attribute contains: %{LDAP-Cached-Membership[*]}
> (8)              --> Attribute contains:
> network_engineering-inf-eng,ad_jira-developers,engineering,ad_jira-administrators,infrastructure-eng,ad_employees,no-phc-infra,networks-inf-eng
> (8)           Reply-Message += Attribute contains:
> network_engineering-inf-eng,ad_jira-developers,engineering,ad_jira-administrators,infrastructure-eng,ad_employees,no-phc-infra,networks-inf-eng
> (8)         } # update reply = noop
>
> ### In Post-Auth section, when evaluating policies, I can't match any of
> the values stored in the LDAP-Cached-Membership[*].
>
> (8) cache: Found entry for "xxxxxxx"
> (8)       [cache] = ok
> (8)       if (notfound) {
> (8)       if (notfound)  -> FALSE
> (8)       elsif (ok) {
> (8)       elsif (ok)  -> TRUE
> (8)       elsif (ok)  {
> (8)         if (LDAP-Cached-Membership[*] =~ /.*networks-inf-eng.*/) {
> (8)         if (LDAP-Cached-Membership[*] =~ /.*networks-inf-eng.*/)  ->
> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~
> /.*corporate_it-inf-eng.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~
> /.*corporate_it-inf-eng.*/)  -> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*security-eng.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*security-eng.*/)  ->
> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~
> /.*workplace_services-peo.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~
> /.*workplace_services-peo.*/)  -> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*infrastructure-eng./) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*infrastructure-eng./)
>  -> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*engineering.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*engineering.*/)  ->
> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*finance.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*finance.*/)  -> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*people.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*people.*/)  -> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*ad_contractors.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*ad_contractors.*/)  ->
> FALSE
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*ad_employees.*/) {
> (8)         elsif (LDAP-Cached-Membership[*] =~ /.*ad_employees.*/)  ->
> FALSE
> (8)       } # elsif (ok)  = ok
>
> Appreciate your help in pointing me in the right direction.
>
> Thank you
>


More information about the Freeradius-Users mailing list