require 'optparse'
require 'open3'
+def ensure_dir(path, mode, owner, group)
+ begin
+ Dir.mkdir(path, mode)
+ rescue Errno::EEXIST
+ # No change needed
+ false
+ else
+ FileUtils.chown(owner, group, path)
+ true
+ end
+end
+
req_envs = %w(ARVADOS_API_HOST ARVADOS_API_TOKEN ARVADOS_VIRTUAL_MACHINE_UUID)
req_envs.each do |k|
unless ENV[k]
arv = Arvados.new({ :suppress_ssl_warnings => false })
logincluster_host = ENV['ARVADOS_API_HOST']
logincluster_name = arv.cluster_config['Login']['LoginCluster'] or ''
+ # Requiring the fuse group was previous hardcoded behavior
+ minimum_groups = arv.cluster_config['Login']['SyncRequiredGroups'] || ['fuse']
if logincluster_name != '' and logincluster_name != arv.cluster_config['ClusterID']
logincluster_host = arv.cluster_config['RemoteClusters'][logincluster_name]['Host']
seen = Hash.new()
- current_user_groups = Hash.new
+ all_groups = []
+ current_user_groups = Hash.new { |hash, key| hash[key] = [] }
while (ent = Etc.getgrent()) do
+ all_groups << ent.name
ent.mem.each do |member|
- current_user_groups[member] ||= Array.new
- current_user_groups[member].push ent.name
+ current_user_groups[member] << ent.name
end
end
Etc.endgrent()
end
end
+ user_gid = pwnam[username].gid
homedir = pwnam[l[:username]].dir
if !File.exist?(homedir)
STDERR.puts "Cannot set up user #{username} because their home directory #{homedir} does not exist. Skipping."
next
end
- existing_groups = current_user_groups[username] || []
- groups = l[:groups] || []
- # Adding users to the FUSE group has long been hardcoded behavior.
- groups << "fuse"
- groups << username
- groups.select! { |g| Etc.getgrnam(g) rescue false }
-
- groups.each do |addgroup|
- if existing_groups.index(addgroup).nil?
- # User should be in group, but isn't, so add them.
- STDERR.puts "Add user #{username} to #{addgroup} group"
- out, st = Open3.capture2e("usermod", "-aG", addgroup, username)
- if st.exitstatus != 0
- STDERR.puts "Failed to add #{username} to #{addgroup} group:\n#{out}"
- end
+ have_groups = current_user_groups[username]
+ want_groups = l[:groups] || []
+ want_groups |= minimum_groups
+ want_groups &= all_groups
+
+ (want_groups - have_groups).each do |addgroup|
+ # User should be in group, but isn't, so add them.
+ STDERR.puts "Add user #{username} to #{addgroup} group"
+ out, st = Open3.capture2e("usermod", "-aG", addgroup, username)
+ if st.exitstatus != 0
+ STDERR.puts "Failed to add #{username} to #{addgroup} group:\n#{out}"
end
end
- existing_groups.each do |removegroup|
- if groups.index(removegroup).nil?
- # User is in a group, but shouldn't be, so remove them.
- STDERR.puts "Remove user #{username} from #{removegroup} group"
- out, st = Open3.capture2e("gpasswd", "-d", username, removegroup)
- if st.exitstatus != 0
- STDERR.puts "Failed to remove user #{username} from #{removegroup} group:\n#{out}"
- end
+ (have_groups - want_groups).each do |removegroup|
+ # User is in a group, but shouldn't be, so remove them.
+ STDERR.puts "Remove user #{username} from #{removegroup} group"
+ out, st = Open3.capture2e("gpasswd", "-d", username, removegroup)
+ if st.exitstatus != 0
+ STDERR.puts "Failed to remove user #{username} from #{removegroup} group:\n#{out}"
end
end
userdotssh = File.join(homedir, ".ssh")
- Dir.mkdir(userdotssh) if !File.exist?(userdotssh)
+ ensure_dir(userdotssh, 0700, username, user_gid)
newkeys = "###\n###\n" + keys[l[:username]].join("\n") + "\n###\n###\n"
keysfile = File.join(userdotssh, "authorized_keys")
-
- if File.exist?(keysfile)
- oldkeys = IO::read(keysfile)
- else
+ begin
+ oldkeys = File.read(keysfile)
+ rescue Errno::ENOENT
oldkeys = ""
end
end
if oldkeys != newkeys then
- f = File.new(keysfile, 'w')
- f.write(newkeys)
- f.close()
+ File.open(keysfile, 'w', 0600) do |f|
+ f.write(newkeys)
+ end
+ FileUtils.chown(username, user_gid, keysfile)
end
userdotconfig = File.join(homedir, ".config")
- if !File.exist?(userdotconfig)
- Dir.mkdir(userdotconfig)
- end
-
+ ensure_dir(userdotconfig, 0755, username, user_gid)
configarvados = File.join(userdotconfig, "arvados")
- Dir.mkdir(configarvados) if !File.exist?(configarvados)
+ ensure_dir(configarvados, 0700, username, user_gid)
tokenfile = File.join(configarvados, "settings.conf")
if File.exist?(tokenfile)
# check if the token is still valid
myToken = ENV["ARVADOS_API_TOKEN"]
- userEnv = IO::read(tokenfile)
+ userEnv = File.read(tokenfile)
if (m = /^ARVADOS_API_TOKEN=(.*?\n)/m.match(userEnv))
begin
tmp_arv = Arvados.new({ :api_host => logincluster_host,
aca_params.merge!(expires_at: (Time.now + options[:"token-lifetime"]))
end
user_token = logincluster_arv.api_client_authorization.create(api_client_authorization: aca_params)
- f = File.new(tokenfile, 'w')
- f.write("ARVADOS_API_HOST=#{ENV['ARVADOS_API_HOST']}\n")
- f.write("ARVADOS_API_TOKEN=v2/#{user_token[:uuid]}/#{user_token[:api_token]}\n")
- f.close()
+ File.open(tokenfile, 'w', 0600) do |f|
+ f.write("ARVADOS_API_HOST=#{ENV['ARVADOS_API_HOST']}\n")
+ f.write("ARVADOS_API_TOKEN=v2/#{user_token[:uuid]}/#{user_token[:api_token]}\n")
+ end
+ FileUtils.chown(username, user_gid, tokenfile)
end
rescue => e
STDERR.puts "Error setting token for #{l[:username]}: #{e}"
end
-
- FileUtils.chown_R(l[:username], nil, userdotssh)
- FileUtils.chown_R(l[:username], nil, userdotconfig)
- File.chmod(0700, userdotssh)
- File.chmod(0700, userdotconfig)
- File.chmod(0700, configarvados)
- File.chmod(0750, homedir)
- File.chmod(0600, keysfile)
- if File.exist?(tokenfile)
- File.chmod(0600, tokenfile)
- end
end
rescue Exception => bang