arvados-login-sync 2.6.3 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/arvados-login-sync +122 -91
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e91705a1939f5956d6e25e9faa476686231bf5288f61026e15fcfab13538d3b9
|
4
|
+
data.tar.gz: c493a0f547b305b9dec02a7630dad3577997c0b076a94f4ff89ab880823ec269
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1082c1d9286f75180b2deda92c5f4d5ff949c91b99e5aa1f90d6b8e3d53e8b2e79da5fd1c355d28f6ae5257e6287175c6ca928b2654aec94c188be54c9cb4375
|
7
|
+
data.tar.gz: 36109d2c86044efb9c14d9b65e6f9c150d553beef169e3440595f0b3f7c5d01d2d3258dee3bcf809d37f37904bb67752232d5025f2b7047e1aa256873f7a532c
|
data/bin/arvados-login-sync
CHANGED
@@ -12,6 +12,18 @@ require 'yaml'
|
|
12
12
|
require 'optparse'
|
13
13
|
require 'open3'
|
14
14
|
|
15
|
+
def ensure_dir(path, mode, owner, group)
|
16
|
+
begin
|
17
|
+
Dir.mkdir(path, mode)
|
18
|
+
rescue Errno::EEXIST
|
19
|
+
# No change needed
|
20
|
+
false
|
21
|
+
else
|
22
|
+
FileUtils.chown(owner, group, path)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
15
27
|
req_envs = %w(ARVADOS_API_HOST ARVADOS_API_TOKEN ARVADOS_VIRTUAL_MACHINE_UUID)
|
16
28
|
req_envs.each do |k|
|
17
29
|
unless ENV[k]
|
@@ -34,6 +46,15 @@ exclusive_banner = "############################################################
|
|
34
46
|
start_banner = "### BEGIN Arvados-managed keys -- changes between markers will be overwritten\n"
|
35
47
|
end_banner = "### END Arvados-managed keys -- changes between markers will be overwritten\n"
|
36
48
|
|
49
|
+
actions = {
|
50
|
+
# These names correspond to the names in the cluster Users configuration.
|
51
|
+
# Managing everything was the original behavior.
|
52
|
+
SyncUserAccounts: true,
|
53
|
+
SyncUserGroups: true,
|
54
|
+
SyncUserSSHKeys: true,
|
55
|
+
SyncUserAPITokens: true,
|
56
|
+
}
|
57
|
+
|
37
58
|
keys = ''
|
38
59
|
|
39
60
|
begin
|
@@ -45,6 +66,17 @@ begin
|
|
45
66
|
logincluster_host = ENV['ARVADOS_API_HOST']
|
46
67
|
logincluster_name = arv.cluster_config['Login']['LoginCluster'] or ''
|
47
68
|
|
69
|
+
# Requiring the fuse group was previous hardcoded behavior
|
70
|
+
minimum_groups = arv.cluster_config['Users']['SyncRequiredGroups'] || ['fuse']
|
71
|
+
ignored_groups = arv.cluster_config['Users']['SyncIgnoredGroups'] || []
|
72
|
+
(minimum_groups & ignored_groups).each do |group_name|
|
73
|
+
STDERR.puts "WARNING: #{group_name} is listed in both SyncRequiredGroups and SyncIgnoredGroups. It will be ignored."
|
74
|
+
end
|
75
|
+
|
76
|
+
actions.each_pair do |key, default|
|
77
|
+
actions[key] = arv.cluster_config['Users'].fetch(key.to_s, default)
|
78
|
+
end
|
79
|
+
|
48
80
|
if logincluster_name != '' and logincluster_name != arv.cluster_config['ClusterID']
|
49
81
|
logincluster_host = arv.cluster_config['RemoteClusters'][logincluster_name]['Host']
|
50
82
|
end
|
@@ -112,11 +144,12 @@ begin
|
|
112
144
|
|
113
145
|
seen = Hash.new()
|
114
146
|
|
115
|
-
|
147
|
+
all_groups = []
|
148
|
+
current_user_groups = Hash.new { |hash, key| hash[key] = [] }
|
116
149
|
while (ent = Etc.getgrent()) do
|
150
|
+
all_groups << ent.name
|
117
151
|
ent.mem.each do |member|
|
118
|
-
current_user_groups[member]
|
119
|
-
current_user_groups[member].push ent.name
|
152
|
+
current_user_groups[member] << ent.name
|
120
153
|
end
|
121
154
|
end
|
122
155
|
Etc.endgrent()
|
@@ -128,6 +161,10 @@ begin
|
|
128
161
|
username = l[:username]
|
129
162
|
|
130
163
|
unless pwnam[l[:username]]
|
164
|
+
unless actions[:SyncUserAccounts]
|
165
|
+
STDERR.puts "User #{username} does not exist and SyncUserAccounts=false. Skipping."
|
166
|
+
next
|
167
|
+
end
|
131
168
|
STDERR.puts "Creating account #{l[:username]}"
|
132
169
|
# Create new user
|
133
170
|
out, st = Open3.capture2e("useradd", "-m",
|
@@ -146,15 +183,21 @@ begin
|
|
146
183
|
end
|
147
184
|
end
|
148
185
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
186
|
+
user_gid = pwnam[username].gid
|
187
|
+
homedir = pwnam[l[:username]].dir
|
188
|
+
if !File.exist?(homedir)
|
189
|
+
STDERR.puts "Cannot set up user #{username} because their home directory #{homedir} does not exist. Skipping."
|
190
|
+
next
|
191
|
+
end
|
192
|
+
|
193
|
+
if actions[:SyncUserGroups]
|
194
|
+
have_groups = current_user_groups[username] - ignored_groups
|
195
|
+
want_groups = l[:groups] || []
|
196
|
+
want_groups |= minimum_groups
|
197
|
+
want_groups -= ignored_groups
|
198
|
+
want_groups &= all_groups
|
155
199
|
|
156
|
-
|
157
|
-
if existing_groups.index(addgroup).nil?
|
200
|
+
(want_groups - have_groups).each do |addgroup|
|
158
201
|
# User should be in group, but isn't, so add them.
|
159
202
|
STDERR.puts "Add user #{username} to #{addgroup} group"
|
160
203
|
out, st = Open3.capture2e("usermod", "-aG", addgroup, username)
|
@@ -162,10 +205,8 @@ begin
|
|
162
205
|
STDERR.puts "Failed to add #{username} to #{addgroup} group:\n#{out}"
|
163
206
|
end
|
164
207
|
end
|
165
|
-
end
|
166
208
|
|
167
|
-
|
168
|
-
if groups.index(removegroup).nil?
|
209
|
+
(have_groups - want_groups).each do |removegroup|
|
169
210
|
# User is in a group, but shouldn't be, so remove them.
|
170
211
|
STDERR.puts "Remove user #{username} from #{removegroup} group"
|
171
212
|
out, st = Open3.capture2e("gpasswd", "-d", username, removegroup)
|
@@ -175,96 +216,86 @@ begin
|
|
175
216
|
end
|
176
217
|
end
|
177
218
|
|
178
|
-
|
179
|
-
|
180
|
-
|
219
|
+
if actions[:SyncUserSSHKeys]
|
220
|
+
userdotssh = File.join(homedir, ".ssh")
|
221
|
+
ensure_dir(userdotssh, 0700, username, user_gid)
|
181
222
|
|
182
|
-
|
223
|
+
newkeys = "###\n###\n" + keys[l[:username]].join("\n") + "\n###\n###\n"
|
183
224
|
|
184
|
-
|
225
|
+
keysfile = File.join(userdotssh, "authorized_keys")
|
226
|
+
begin
|
227
|
+
oldkeys = File.read(keysfile)
|
228
|
+
rescue Errno::ENOENT
|
229
|
+
oldkeys = ""
|
230
|
+
end
|
185
231
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
232
|
+
if options[:exclusive]
|
233
|
+
newkeys = exclusive_banner + newkeys
|
234
|
+
elsif oldkeys.start_with?(exclusive_banner)
|
235
|
+
newkeys = start_banner + newkeys + end_banner
|
236
|
+
elsif (m = /^(.*?\n|)#{start_banner}(.*?\n|)#{end_banner}(.*)/m.match(oldkeys))
|
237
|
+
newkeys = m[1] + start_banner + newkeys + end_banner + m[3]
|
238
|
+
else
|
239
|
+
newkeys = start_banner + newkeys + end_banner + oldkeys
|
240
|
+
end
|
191
241
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
else
|
199
|
-
newkeys = start_banner + newkeys + end_banner + oldkeys
|
242
|
+
if oldkeys != newkeys then
|
243
|
+
File.open(keysfile, 'w', 0600) do |f|
|
244
|
+
f.write(newkeys)
|
245
|
+
end
|
246
|
+
FileUtils.chown(username, user_gid, keysfile)
|
247
|
+
end
|
200
248
|
end
|
201
249
|
|
202
|
-
if
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
250
|
+
if actions[:SyncUserAPITokens]
|
251
|
+
userdotconfig = File.join(homedir, ".config")
|
252
|
+
ensure_dir(userdotconfig, 0755, username, user_gid)
|
253
|
+
configarvados = File.join(userdotconfig, "arvados")
|
254
|
+
ensure_dir(configarvados, 0700, username, user_gid)
|
207
255
|
|
208
|
-
|
209
|
-
if !File.exist?(userdotconfig)
|
210
|
-
Dir.mkdir(userdotconfig)
|
211
|
-
end
|
256
|
+
tokenfile = File.join(configarvados, "settings.conf")
|
212
257
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
STDERR.puts "Account #{l[:username]} token not valid, creating new token."
|
234
|
-
newToken = true
|
235
|
-
else
|
236
|
-
raise
|
258
|
+
begin
|
259
|
+
STDERR.puts "Processing #{tokenfile} ..." if debug
|
260
|
+
newToken = false
|
261
|
+
if File.exist?(tokenfile)
|
262
|
+
# check if the token is still valid
|
263
|
+
myToken = ENV["ARVADOS_API_TOKEN"]
|
264
|
+
userEnv = File.read(tokenfile)
|
265
|
+
if (m = /^ARVADOS_API_TOKEN=(.*?\n)/m.match(userEnv))
|
266
|
+
begin
|
267
|
+
tmp_arv = Arvados.new({ :api_host => logincluster_host,
|
268
|
+
:api_token => (m[1]),
|
269
|
+
:suppress_ssl_warnings => false })
|
270
|
+
tmp_arv.user.current
|
271
|
+
rescue Arvados::TransactionFailedError => e
|
272
|
+
if e.to_s =~ /401 Unauthorized/
|
273
|
+
STDERR.puts "Account #{l[:username]} token not valid, creating new token."
|
274
|
+
newToken = true
|
275
|
+
else
|
276
|
+
raise
|
277
|
+
end
|
237
278
|
end
|
238
279
|
end
|
280
|
+
elsif !File.exist?(tokenfile) || options[:"rotate-tokens"]
|
281
|
+
STDERR.puts "Account #{l[:username]} token file not found, creating new token."
|
282
|
+
newToken = true
|
239
283
|
end
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
284
|
+
if newToken
|
285
|
+
aca_params = {owner_uuid: l[:user_uuid], api_client_id: 0}
|
286
|
+
if options[:"token-lifetime"] && options[:"token-lifetime"] > 0
|
287
|
+
aca_params.merge!(expires_at: (Time.now + options[:"token-lifetime"]))
|
288
|
+
end
|
289
|
+
user_token = logincluster_arv.api_client_authorization.create(api_client_authorization: aca_params)
|
290
|
+
File.open(tokenfile, 'w', 0600) do |f|
|
291
|
+
f.write("ARVADOS_API_HOST=#{ENV['ARVADOS_API_HOST']}\n")
|
292
|
+
f.write("ARVADOS_API_TOKEN=v2/#{user_token[:uuid]}/#{user_token[:api_token]}\n")
|
293
|
+
end
|
294
|
+
FileUtils.chown(username, user_gid, tokenfile)
|
248
295
|
end
|
249
|
-
|
250
|
-
|
251
|
-
f.write("ARVADOS_API_HOST=#{ENV['ARVADOS_API_HOST']}\n")
|
252
|
-
f.write("ARVADOS_API_TOKEN=v2/#{user_token[:uuid]}/#{user_token[:api_token]}\n")
|
253
|
-
f.close()
|
296
|
+
rescue => e
|
297
|
+
STDERR.puts "Error setting token for #{l[:username]}: #{e}"
|
254
298
|
end
|
255
|
-
rescue => e
|
256
|
-
STDERR.puts "Error setting token for #{l[:username]}: #{e}"
|
257
|
-
end
|
258
|
-
|
259
|
-
FileUtils.chown_R(l[:username], nil, userdotssh)
|
260
|
-
FileUtils.chown_R(l[:username], nil, userdotconfig)
|
261
|
-
File.chmod(0700, userdotssh)
|
262
|
-
File.chmod(0700, userdotconfig)
|
263
|
-
File.chmod(0700, configarvados)
|
264
|
-
File.chmod(0750, homedir)
|
265
|
-
File.chmod(0600, keysfile)
|
266
|
-
if File.exist?(tokenfile)
|
267
|
-
File.chmod(0600, tokenfile)
|
268
299
|
end
|
269
300
|
end
|
270
301
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arvados-login-sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arvados Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: arvados
|
@@ -79,7 +79,7 @@ dependencies:
|
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0.12'
|
81
81
|
description: Creates and updates local login accounts for Arvados users. Built from
|
82
|
-
git commit
|
82
|
+
git commit b5dad64d1faa5063482db0d33d22805912abdda6
|
83
83
|
email: packaging@arvados.org
|
84
84
|
executables:
|
85
85
|
- arvados-login-sync
|