10 # This script does the actual account/key management on disk for the shell machine(s).
12 # Ward Vandewege <ward@curoverse.com>
14 # Default is development
15 production = ARGV[0] == "production"
17 ENV["RAILS_ENV"] = "development"
18 ENV["RAILS_ENV"] = "production" if production
22 # load and merge in the environment-specific application config info
23 # if present, overriding base config parameters as specified
24 path = File.dirname(__FILE__) + '/config/arvados-clients.yml'
25 if File.exists?(path) then
26 cp_config = YAML.load_file(path)[ENV['RAILS_ENV']]
28 puts "Please create a\n " + File.dirname(__FILE__) + "/config/arvados-clients.yml\n file"
32 shell_hostname = cp_config['arvados_shell_hostname']
34 ENV['ARVADOS_API_HOST'] = cp_config['arvados_api_host']
35 ENV['ARVADOS_API_TOKEN'] = cp_config['arvados_api_token']
43 uids = Hash[Etc.to_enum(:passwd).map { |ent| [ent.name, ent.uid] }]
44 gids = Hash[Etc.to_enum(:group).map { |ent| [ent.name, ent.gid] }]
45 arv = Arvados.new( { :suppress_ssl_warnings => false } )
48 logins = arv.virtual_machine.get_all_logins(limit: 10000, uuid: cp_config['vm_uuid'])[:items]
50 logins = arv.virtual_machine.logins(:uuid => cp_config['vm_uuid'])[:items]
52 logins = [] if logins.nil?
53 logins = logins.reject { |l| l[:username].nil? or l[:hostname].nil? or l[:public_key].nil? or l[:hostname] != shell_hostname }
57 open("/etc/login.defs", encoding: "utf-8") do |login_defs|
58 login_defs.each_line do |line|
59 next unless match = /^UID_MIN\s+(\S+)$/.match(line)
60 if match[1].start_with?("0x")
62 elsif match[1].start_with?("0")
67 new_uid_min = match[1].to_i(base)
68 uid_min = new_uid_min if (new_uid_min > 0)
71 logins.reject! { |l| (uids[l[:username]] || 65535) < uid_min }
77 keys[l[:username]] = Array.new() if not keys.has_key?(l[:username])
79 # Handle putty-style ssh public keys
80 key.sub!(/^(Comment: "r[^\n]*\n)(.*)$/m,'ssh-rsa \2 \1')
81 key.sub!(/^(Comment: "d[^\n]*\n)(.*)$/m,'ssh-dss \2 \1')
85 keys[l[:username]].push(key) if not keys[l[:username]].include?(key)
89 devnull = open("/dev/null", "w")
92 next if seen[l[:username]]
93 seen[l[:username]] = true if not seen.has_key?(l[:username])
94 @homedir = "/home/#{l[:username]}"
96 unless uids[l[:username]]
97 STDERR.puts "Creating account #{l[:username]}"
98 groups = l[:groups] || []
99 # Adding users to the FUSE group has long been hardcoded behavior.
101 groups.select! { |name| gids[name] }
103 next unless system("/usr/sbin/useradd", "-m",
106 "-G", groups.join(","),
110 # Create .ssh directory if necessary
111 userdotssh = File.join(@homedir, ".ssh")
112 Dir.mkdir(userdotssh) if !File.exists?(userdotssh)
113 @key = "#######################################################################################
114 # THIS FILE IS MANAGED BY #{$0} -- CHANGES WILL BE OVERWRITTEN #
115 #######################################################################################\n\n"
116 @key += keys[l[:username]].join("\n") + "\n"
117 userauthkeys = File.join(userdotssh, "authorized_keys")
118 if !File.exists?(userauthkeys) or IO::read(userauthkeys) != @key then
119 f = File.new(userauthkeys, 'w')
123 FileUtils.chown_R(l[:username], l[:username], userdotssh)
124 File.chmod(0700, userdotssh)
125 File.chmod(0750, @homedir)
129 rescue Exception => bang
130 puts "Error: " + bang.to_s
131 puts bang.backtrace.join("\n")