arvados-login-sync 2.6.3 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: c9b0950157ae5cff15171e2c96d7fd5bbdf4684a7fd2bac988a5f772abffb42e
|
4
|
+
data.tar.gz: 89dde3501d31d77bd5c5400abbc159b4f0d7bf0101239292b156cb0b9b7269d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e93ed77b495997e94bb662d8de19e19bd27867a882180598ae0d863cd0d2a13f1dbae8f9696f7a25a30db69509982948fc55ca21dac91ea006e1a8f36ebc78f
|
7
|
+
data.tar.gz: 193c3497f9cbab45f1170d3ea86ad832bacfb400fe965c375002d937972e66492eaaf896e76faeb6cee11068f9daf1e16300d93ce96af2ead21ceae6b020e9f8
|
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.1
|
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
|