Skip to content

Commit

Permalink
Allow UID to be returned by the mapper script. (#3795)
Browse files Browse the repository at this point in the history
Allow UID to be returned by the mapper script. Using a UID is useful in multi-domain situations where "username" may be different people in different domains.
  • Loading branch information
guruevi authored Sep 25, 2024
1 parent 14ff2f7 commit ab63139
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 13 deletions.
7 changes: 7 additions & 0 deletions mod_ood_proxy/lib/ood/user_map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ function map(r, user_map_match, user_map_cmd, remote_user)
handle:close()
end

-- if sys_user is a number, then it's the uid, so convert to username
if tonumber(sys_user) then
local pwd = require "posix.pwd"
sys_user = pwd.getpwuid(tonumber(sys_user)).pw_name
end

time_user_map = (r:clock() - now)/1000.0
r:debug("Mapped '" .. remote_user .. "' => '" .. (sys_user or "") .. "' [" .. time_user_map .. " ms]")

Expand All @@ -25,6 +31,7 @@ function map(r, user_map_match, user_map_cmd, remote_user)
return nil
end


r.subprocess_env['MAPPED_USER'] = sys_user -- set as CGI variable for later hooks (i.e., analytics)
r.subprocess_env['OOD_TIME_USER_MAP'] = time_user_map -- set as CGI variable for later hooks (i.e., analytics)
return sys_user
Expand Down
51 changes: 38 additions & 13 deletions nginx_stage/lib/nginx_stage/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,37 @@ class User
# @param user [String] the user name defining this object
# @raise [ArgumentError] if user or primary group doesn't exist on local system
def initialize(user)
@passwd = Etc.getpwnam user.to_s
@group = Etc.getgrgid gid
@groups = get_groups

if name.to_s != user.to_s
err_msg = <<~HEREDOC
Username '#{user}' is being mapped to '#{name}' in SSSD and they don't match.
Users with domain names cannot be mapped correctly. If '#{name}' still has the
domain in it you'll need to set SSSD's full_name_format to '%1$s'.
# See if user is all numbers (potentially uid), regexp is 8% faster than integer conversion
# Benchmark: 0.13 microseconds per call (1M cycles)
if user.match?(/\A\d+\z/)
# The user is composed of all numbers, (numeric string)
# 10 microseconds per call if it matches
# 203 microseconds per call if it doesn't match (only happens if username is all numbers but not a uid)
begin
@passwd = Etc.getpwuid(user.to_i)
rescue ArgumentError
# We got a number as a username but we failed the lookup, fallthrough to the string lookup
end
end

See https://github.com/OSC/ondemand/issues/1759 for more details.
HEREDOC
# Variable is not set, so the user is a string
unless @passwd
# Benchmark: 13 microseconds per call (1M cycles)
@passwd = Etc.getpwnam(user)
if name.to_s != user.to_s
err_msg = <<~HEREDOC
Username '#{user}' is being mapped to '#{name}' in SSSD and they don't match.
Users with domain names cannot be mapped correctly. If '#{name}' still has the
domain in it you'll need to set SSSD's full_name_format to '%1$s'.
See https://github.com/OSC/ondemand/issues/1759 for more details.
HEREDOC

raise StandardError, err_msg
raise StandardError, err_msg
end
end
@group = Etc.getgrgid gid
@groups = get_groups
end

# User's primary group name
Expand Down Expand Up @@ -79,7 +95,16 @@ def to_str
# Use `id` to get list of groups as the /etc/group file can give
# erroneous results
def get_groups
`id -nG #{name}`.split(' ')
# Group names can contain spaces, prevent "domain users" people from being added to the "users" group
# We retrieve GIDs and convert to names (or GID)
`id -G #{name}`.split(' ').map(&:to_i).map do |gid|
begin
Etc.getgrgid(gid).name
rescue ArgumentError
# Still return the GID as a string if the group doesn't exist
gid.to_s
end
end
end
end
end

0 comments on commit ab63139

Please sign in to comment.