Pattern Match Group Membership in the attribute list

Vlad Kratsberg vkratsberg at gmail.com
Fri Jul 1 18:10:24 UTC 2022


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


Below is my test:

        if (&User-Name == "vkratsberg") {
                update reply {
                         Reply-Message += "contains
%{outer.session-state:LDAP-Group[*]}"
                }
        }

(8)       if (&User-Name == "vkratsberg") {
(8)       if (&User-Name == "vkratsberg")  -> TRUE
(8)       if (&User-Name == "vkratsberg")  {
(8)         update reply {
(8)           EXPAND contains %{outer.session-state:LDAP-Group[*]}
(8)              --> 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 += 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
(8)       } # if (&User-Name == "vkratsberg")  = noop
(8)       if (User-Name == "svc-radius") {

I can see the list of groups are available in session state.

And here is my policy evaluation.

(8)       if (&outer.session-state:LDAP-Group[*] == "networks-inf-eng") {
(8)       if (&outer.session-state:LDAP-Group[*] == "networks-inf-eng")  ->
TRUE
(8)       if (&outer.session-state:LDAP-Group[*] == "networks-inf-eng")  {

All is good, thank you for pointing in the right direction.

On Fri, Jul 1, 2022 at 1:38 PM Vlad Kratsberg <vkratsberg at gmail.com> wrote:

> 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