So the first question is: Is it normal that I have to use mod_rewrite to check for group membership ? I tried hundred of syntaxes with SetEnvIf or SetEnvIfExpr but I never managed to get it working. I'm not sure why but I guess it's somehow related to "race condition" (lazy evaluation) while evaluating environment variable, does it makes sense ?SetEnvIf[expr] is evaluated very early, long before authn/authz occurs and those environment variables can be filled out.Second question is: I cannot use "$" to make a proper regex matcher. If the group is not the last one, I can match it with ;.*$, if it is the last one, I should be able to match [...]DC=internal$, however that does not work. There's is one unknown character and I have no idea what it is. Matching with DC=internal.?$ works, so that's one SINGLE char... Any idea ?
Hello,
Thanks a lot for your help. I ended up going for a completely different way because I found it was too messy... So here is the LUA script I use instead:
require 'apache2'
local admin_profiles = {
'CN=Group1,OU=Groups,DC=domain,DC=com',
'CG=Group2,DC=domain,DC=com',
}
local manager_profiles = {
'CN=Group1,OU=Groups,DC=domain,DC=com',
'CN=Group3,OU=Groups,DC=domain,DC=com',
}
local operator_profiles = {
}
local viewer_profiles = {
'CN=Group4,OU=Groups,DC=domain,DC=com',
'CN=Group5,OU=Groups,DC=domain,DC=com',
}
local function has_value_case_insensitive(tab, val)
for index, value in ipairs(tab) do
if value:lower() == val:lower() then
return true
end
end
return false
end
function authcheck_hook(r)
-- Extract username and group list from Active Directory
authentication
local sam_account_name =
r.subprocess_env['AUTHENTICATE_SAMACCOUNTNAME']
local member_of = r.subprocess_env['AUTHENTICATE_MEMBEROF']
-- Check if Active Directory variables are not set, if so,
return 403 and log error
if (sam_account_name == nil or sam_account_name == '') then
r:err("ActiveDirectory group to PCC profile LUA script called
but AUTHENTICATE_SAMACCOUNTNAME was not set")
return 403
end
if (member_of == nil or member_of == '') then
r:err("ActiveDirectory group to PCC profile LUA script called
but AUTHENTICATE_MEMBEROF was not set")
return 403
end
-- Split group member ship into an array and match corresponding
profile
local member_of_split_regex = '([^;%s*]+)'
local member_of_profiles = {}
for member_of_entry in member_of:gmatch(member_of_split_regex)
do
local member_of_entry_profiles = {}
if has_value_case_insensitive(admin_profiles, member_of_entry)
then
if not has_value_case_insensitive(member_of_entry_profiles,
"admin") then
table.insert(member_of_entry_profiles, "admin")
end
if not has_value_case_insensitive(member_of_profiles,
"admin") then
table.insert(member_of_profiles, "admin")
end
end
if has_value_case_insensitive(manager_profiles,
member_of_entry) then
if not has_value_case_insensitive(member_of_entry_profiles,
"manager") then
table.insert(member_of_entry_profiles, "manager")
end
if not has_value_case_insensitive(member_of_profiles,
"manager") then
table.insert(member_of_profiles, "manager")
end
end
if has_value_case_insensitive(operator_profiles,
member_of_entry) then
if not has_value_case_insensitive(member_of_entry_profiles,
"operator") then
table.insert(member_of_entry_profiles, "operator")
end
if not has_value_case_insensitive(member_of_profiles,
"operator") then
table.insert(member_of_profiles, "operator")
end
end
if has_value_case_insensitive(viewer_profiles,
member_of_entry) then
if not has_value_case_insensitive(member_of_entry_profiles,
"viewer") then
table.insert(member_of_entry_profiles, "viewer")
end
if not has_value_case_insensitive(member_of_profiles,
"viewer") then
table.insert(member_of_profiles, "viewer")
end
end
if next(member_of_entry_profiles) == nil then
r:debug(("Username %s ActiveDirectory group %s gives no PCC
privileges"):format(sam_account_name, member_of_entry))
else
r:debug(("Username %s ActiveDirectory group %s gives PCC
privileges: %s"):format(sam_account_name, member_of_entry,
table.concat(member_of_entry_profiles, ', ')))
end
end
-- Compare all matched group resulting profile and get the one
with highest privileges
if has_value_case_insensitive(member_of_profiles, "admin") then
r:info(("Username %s authorized with PCC admin
privileges"):format(sam_account_name, member_of_entry))
r.headers_in['X-PCC-Group'] = "admin"
elseif has_value_case_insensitive(member_of_profiles, "manager")
then
r:info(("Username %s authorized with PCC manager
privileges"):format(sam_account_name, member_of_entry))
r.headers_in['X-PCC-Group'] = "manager"
elseif has_value_case_insensitive(member_of_profiles,
"operator") then
r:err(("Username %s authorized with PCC operator
privileges"):format(sam_account_name, member_of_entry))
r.headers_in['X-PCC-Group'] = "operator"
elseif has_value_case_insensitive(member_of_profiles, "viewer")
then
r:err(("Username %s authorized with PCC viewer
privileges"):format(sam_account_name, member_of_entry))
r.headers_in['X-PCC-Group'] = "viewer"
else
r:err(("Username %s ActiveDirectory groups did not give ANY
PCC privileges, it should have NOT been authorized to
login"):format(sam_account_name))
return 403
end
return apache2.OK
end
Which is called from config using:
LuaHookFixups /etc/apache2/snippets/active_directory_to_pcc_profile.lua authcheck_hook
It seems to be working as expected, and is also working with my auth_form / cookie_session setup, which is great !
Any comment is welcome is you see something borked...
Regards, Adam.