20663: Use set operations for group management
[arvados.git] / services / login-sync / bin / arvados-login-sync
index a3150b8fd20a7d7edad9f2bd557c03d14aa0022c..df68a4030c5b293ab820ef17940ac90e877e3eb6 100755 (executable)
@@ -56,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']
@@ -124,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()
@@ -165,32 +168,26 @@ begin
       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