X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/08078f621c8dbc1ecbd6e030bb0fac848cb6a01c..62aae5c096dbee2a5a26c0865c1b05b2c0d646d9:/services/login-sync/bin/arvados-login-sync diff --git a/services/login-sync/bin/arvados-login-sync b/services/login-sync/bin/arvados-login-sync index 915541baf5..df68a4030c 100755 --- a/services/login-sync/bin/arvados-login-sync +++ b/services/login-sync/bin/arvados-login-sync @@ -12,6 +12,18 @@ require 'yaml' 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] @@ -44,6 +56,8 @@ begin 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'] @@ -112,11 +126,12 @@ begin 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() @@ -146,46 +161,45 @@ begin end 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 + 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 + + 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 - homedir = pwnam[l[:username]].dir 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 @@ -200,18 +214,16 @@ begin 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") @@ -221,7 +233,7 @@ begin 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, @@ -247,25 +259,15 @@ begin 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