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@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@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