From 526a05e75b22f265928db824377723fe20c023b2 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Mon, 26 Jun 2017 13:38:15 -0700
Subject: [PATCH 01/18] Revert "Merge branch
 'dm-revert-authorized-files-toggle-master' into 'master'"

This reverts commit fce9c01b28e2b3f7a79a6020fba4f408a07ccc3c, reversing
changes made to b10034088c9f77ac4f1edc9955ca6694dceb1a1e.

To reiterate: this reverts a revert.
---
 .../admin/application_settings_controller.rb  |   3 +-
 .../application_settings/_form.html.haml      |  16 +++
 doc/administration/operations.md              |   1 +
 .../img/write_to_authorized_keys_setting.png  | Bin 0 -> 94218 bytes
 doc/administration/operations/speed_up_ssh.md |  12 +++
 lib/gitlab/shell.rb                           |  12 +++
 spec/lib/gitlab/shell_spec.rb                 | 100 ++++++++++++++++--
 7 files changed, 137 insertions(+), 7 deletions(-)
 create mode 100644 doc/administration/operations/img/write_to_authorized_keys_setting.png

diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index c5a2c3b8d8bf9620..480d4bbcf0652633 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -180,7 +180,8 @@ def application_setting_params_ee
       :check_namespace_plan,
       :mirror_max_delay,
       :mirror_max_capacity,
-      :mirror_capacity_threshold
+      :mirror_capacity_threshold,
+      :authorized_keys_enabled
     ]
   end
 end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 2d6cf92d0cef2b93..befb1c677474e71b 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -671,6 +671,22 @@
           installations. Set to 0 to completely disable polling.
           = link_to icon('question-circle'), help_page_path('administration/polling')
 
+  %fieldset
+    %legend Performance optimization
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :authorized_keys_enabled do
+            = f.check_box :authorized_keys_enabled
+            Write to "authorized_keys" file
+          .help-block
+            By default, we write to the "authorized_keys" file to support Git
+            over SSH without additional configuration. GitLab can be optimized
+            to authenticate SSH keys via the database file. Only uncheck this
+            if you have configured your OpenSSH server to use the
+            AuthorizedKeysCommand. Click on the help icon for more details.
+            = link_to icon('question-circle'), help_page_path('administration/operations/speed_up_ssh', anchor: 'the-solution')
+
   - if Gitlab::Geo.license_allows?
     %fieldset
       %legend GitLab Geo
diff --git a/doc/administration/operations.md b/doc/administration/operations.md
index b43fdddd7e621a87..472b50739f5c4426 100644
--- a/doc/administration/operations.md
+++ b/doc/administration/operations.md
@@ -6,3 +6,4 @@
 - [Cleaning up Redis sessions](operations/cleaning_up_redis_sessions.md)
 - [Understanding Unicorn and unicorn-worker-killer](operations/unicorn.md)
 - [Moving repositories to a new location](operations/moving_repositories.md)
+- [Speed up SSH operations](operations/speed_up_ssh.md)
diff --git a/doc/administration/operations/img/write_to_authorized_keys_setting.png b/doc/administration/operations/img/write_to_authorized_keys_setting.png
new file mode 100644
index 0000000000000000000000000000000000000000..232765f1917960eb3858ed8dd3ab939ebc757e96
GIT binary patch
literal 94218
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

literal 0
HcmV?d00001

diff --git a/doc/administration/operations/speed_up_ssh.md b/doc/administration/operations/speed_up_ssh.md
index 99d177522797bf30..7012c192a05581df 100644
--- a/doc/administration/operations/speed_up_ssh.md
+++ b/doc/administration/operations/speed_up_ssh.md
@@ -51,6 +51,18 @@ sudo service sshd reload
 
 Confirm that SSH is working by removing your user's SSH key in the UI, adding a new one, and attempting to pull a repo.
 
+> **Warning:** Do not disable writes until SSH is confirmed to be working perfectly because the file will quickly become out-of-date.
+
+In the case of lookup failures (which are not uncommon), the `authorized_keys` file will still be scanned. So git SSH performance will still be slow for many users as long as a large file exists.
+
+You can disable any more writes to the `authorized_keys` file by unchecking `Write to "authorized_keys" file` in the Application Settings of your GitLab installation.
+
+![Write to authorized keys setting](img/write_to_authorized_keys_setting.png)
+
+Again, confirm that SSH is working by removing your user's SSH key in the UI, adding a new one, and attempting to pull a repo.
+
+Then you can backup and delete your `authorized_keys` file for best performance.
+
 ## How to go back to using the `authorized_keys` file
 
 This is a brief overview. Please refer to the above instructions for more context.
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 5fa5b94daffb4cda..63cd946894037444 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -197,6 +197,8 @@ def remove_repository(storage, name)
     #   add_key("key-42", "sha-rsa ...")
     #
     def add_key(key_id, key_content)
+      return unless self.authorized_keys_enabled?
+
       Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                    'add-key', key_id, self.class.strip_key(key_content)])
     end
@@ -206,6 +208,8 @@ def add_key(key_id, key_content)
     # Ex.
     #   batch_add_keys { |adder| adder.add_key("key-42", "sha-rsa ...") }
     def batch_add_keys(&block)
+      return unless self.authorized_keys_enabled?
+
       IO.popen(%W(#{gitlab_shell_path}/bin/gitlab-keys batch-add-keys), 'w') do |io|
         yield(KeyAdder.new(io))
       end
@@ -217,6 +221,8 @@ def batch_add_keys(&block)
     #   remove_key("key-342", "sha-rsa ...")
     #
     def remove_key(key_id, key_content)
+      return unless self.authorized_keys_enabled?
+
       Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                    'rm-key', key_id, key_content])
     end
@@ -227,6 +233,8 @@ def remove_key(key_id, key_content)
     #   remove_all_keys
     #
     def remove_all_keys
+      return unless self.authorized_keys_enabled?
+
       Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear'])
     end
 
@@ -356,5 +364,9 @@ def gitlab_shell_projects_path
     def gitlab_shell_keys_path
       File.join(gitlab_shell_path, 'bin', 'gitlab-keys')
     end
+
+    def authorized_keys_enabled?
+      current_application_settings.authorized_keys_enabled
+    end
   end
 end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 22c69eeef2f027e3..74a207c36b87238d 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -104,13 +104,101 @@
   end
 
   describe '#add_key' do
-    it 'removes trailing garbage' do
-      allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
-      expect(Gitlab::Utils).to receive(:system_silent).with(
-        [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar']
-      )
+    context 'when authorized_keys_enabled is true' do
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with(
+          [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar']
+        )
+
+        gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage')
+      end
+    end
+
+    context 'when authorized_keys_enabled is false' do
+      before do
+        stub_application_setting(authorized_keys_enabled: false)
+      end
+
+      it 'does nothing' do
+        expect(Gitlab::Utils).not_to receive(:system_silent)
+
+        gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage')
+      end
+    end
+  end
+
+  describe '#batch_add_keys' do
+    context 'when authorized_keys_enabled is true' do
+      it 'instantiates KeyAdder' do
+        expect_any_instance_of(Gitlab::Shell::KeyAdder).to receive(:add_key).with('key-123', 'ssh-rsa foobar')
+
+        gitlab_shell.batch_add_keys do |adder|
+          adder.add_key('key-123', 'ssh-rsa foobar')
+        end
+      end
+    end
+
+    context 'when authorized_keys_enabled is false' do
+      before do
+        stub_application_setting(authorized_keys_enabled: false)
+      end
+
+      it 'does nothing' do
+        expect_any_instance_of(Gitlab::Shell::KeyAdder).not_to receive(:add_key)
+
+        gitlab_shell.batch_add_keys do |adder|
+          adder.add_key('key-123', 'ssh-rsa foobar')
+        end
+      end
+    end
+  end
 
-      gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage')
+  describe '#remove_key' do
+    context 'when authorized_keys_enabled is true' do
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with(
+          [:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar']
+        )
+
+        gitlab_shell.remove_key('key-123', 'ssh-rsa foobar')
+      end
+    end
+
+    context 'when authorized_keys_enabled is false' do
+      before do
+        stub_application_setting(authorized_keys_enabled: false)
+      end
+
+      it 'does nothing' do
+        expect(Gitlab::Utils).not_to receive(:system_silent)
+
+        gitlab_shell.remove_key('key-123', 'ssh-rsa foobar')
+      end
+    end
+  end
+
+  describe '#remove_all_keys' do
+    context 'when authorized_keys_enabled is true' do
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with([:gitlab_shell_keys_path, 'clear'])
+
+        gitlab_shell.remove_all_keys
+      end
+    end
+
+    context 'when authorized_keys_enabled is false' do
+      before do
+        stub_application_setting(authorized_keys_enabled: false)
+      end
+
+      it 'does nothing' do
+        expect(Gitlab::Utils).not_to receive(:system_silent)
+
+        gitlab_shell.remove_all_keys
+      end
     end
   end
 
-- 
GitLab


From a97f5f739810917660e5f236d366007732130e33 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Mon, 26 Jun 2017 14:40:08 -0700
Subject: [PATCH 02/18] Retroactively fix migration

This allows us to identify customers who ran the broken migration. Their `authorized_keys_enabled` column does not have a default at this point.

We will fix the column after we fix the `authorized_keys` file.
---
 ...uthorized_keys_enabled_to_application_settings.rb | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb b/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
index fdae309946cd9d23..1d86a531eb3dca43 100644
--- a/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
+++ b/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
@@ -7,9 +7,13 @@ class AddAuthorizedKeysEnabledToApplicationSettings < ActiveRecord::Migration
   # Set this constant to true if this migration requires downtime.
   DOWNTIME = false
 
-  def change
-    # allow_null: true because we want to set the default based on if the
-    # instance is configured to use AuthorizedKeysCommand
-    add_column :application_settings, :authorized_keys_enabled, :boolean, allow_null: true
+  disable_ddl_transaction!
+
+  def up
+    add_column_with_default :application_settings, :authorized_keys_enabled, :boolean, default: true, allow_null: false
+  end
+
+  def down
+    remove_column :application_settings, :authorized_keys_enabled
   end
 end
-- 
GitLab


From febc26e40fbbeadbd025d8f5f42b8b2e1d2f5e0a Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Tue, 27 Jun 2017 14:14:35 -0700
Subject: [PATCH 03/18] Fix authorized_keys file if needed

---
 GITLAB_SHELL_VERSION                          |   2 +-
 app/workers/gitlab_shell_worker.rb            |  15 +-
 ...70626202753_update_authorized_keys_file.rb | 114 +++++++++
 db/schema.rb                                  |   2 +-
 lib/gitlab/shell.rb                           |  55 ++++-
 spec/lib/gitlab/shell_spec.rb                 | 102 ++++++++
 .../update_authorized_keys_file_spec.rb       | 232 ++++++++++++++++++
 spec/workers/gitlab_shell_worker_spec.rb      |  37 +++
 8 files changed, 553 insertions(+), 6 deletions(-)
 create mode 100644 db/migrate/20170626202753_update_authorized_keys_file.rb
 create mode 100644 spec/migrations/update_authorized_keys_file_spec.rb
 create mode 100644 spec/workers/gitlab_shell_worker_spec.rb

diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index c20c645d7e49c40c..831446cbd27a6de4 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-5.0.6
+5.1.0
diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb
index 964287a1793a03d7..ddb476226d12244d 100644
--- a/app/workers/gitlab_shell_worker.rb
+++ b/app/workers/gitlab_shell_worker.rb
@@ -4,6 +4,19 @@ class GitlabShellWorker
   include DedicatedSidekiqQueue
 
   def perform(action, *arg)
-    gitlab_shell.send(action, *arg)
+    if action.to_s == 'batch_add_keys_in_db_starting_from'
+      batch_add_keys_in_db_starting_from(arg.first)
+    else
+      gitlab_shell.send(action, *arg)
+    end
+  end
+
+  # Not added to Gitlab::Shell because I don't expect this to be used again
+  def batch_add_keys_in_db_starting_from(start_id)
+    gitlab_shell.batch_add_keys do |adder|
+      Key.find_each(start: start_id, batch_size: 1000) do |key|
+        adder.add_key(key.shell_id, key.key)
+      end
+    end
   end
 end
diff --git a/db/migrate/20170626202753_update_authorized_keys_file.rb b/db/migrate/20170626202753_update_authorized_keys_file.rb
new file mode 100644
index 0000000000000000..f696489ea4a8aac0
--- /dev/null
+++ b/db/migrate/20170626202753_update_authorized_keys_file.rb
@@ -0,0 +1,114 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class UpdateAuthorizedKeysFile < ActiveRecord::Migration
+  include Gitlab::Database::MigrationHelpers
+
+  class ApplicationSetting < ActiveRecord::Base; end
+  class Key < ActiveRecord::Base; end
+
+  # Set this constant to true if this migration requires downtime.
+  DOWNTIME = false
+
+  # We started deploying 9.3.0 to GitLab.com at 2017-06-22T17:24:00+00:00.
+  # TODO look at the time we pushed to the package server
+  DATETIME_9_3_0_RELEASED = DateTime.parse('2017-06-22T17:24:00+00:00')
+
+  def up
+    if authorized_keys_file_in_use_and_stale?
+      # Update nil authorized_keys_enabled to true to ensure that Gitlab::Shell
+      # key methods work properly for workers running 9.3.0 during the
+      # migration. If the setting remained nil, the workers would not edit the
+      # file.
+      update_nil_setting_to_true
+
+      update_authorized_keys_file_since(DATETIME_9_3_0_RELEASED)
+    end
+  end
+
+  def down
+    # Do nothing
+  end
+
+  def authorized_keys_file_in_use_and_stale?
+    return false unless ran_broken_migration?
+
+    uncached_setting = ApplicationSetting.last
+
+    # If there is no ApplicationSetting record in the DB, then the instance was
+    # never in a state where `authorized_keys_enabled` field was `nil`. So the
+    # file is not stale.
+    return false unless uncached_setting
+
+    if uncached_setting.authorized_keys_enabled == false # not falsey!
+      # If authorized_keys_enabled is explicitly false, then the file is not in
+      # use, so it doesn't need to be fixed. I.e. GitLab.com.
+      #
+      # Unfortunately it is possible some users may have saved Application
+      # Settings without realizing the new option existed, and since it
+      # mistakenly defaulted to unchecked, now it is explicitly false. These
+      # users need this warning.
+      say false_negative_warning
+      return false
+    end
+
+    # If authorized_keys_enabled is true or nil, then we need to rebuild the
+    # file in case it is stale.
+    true
+  end
+
+  def ran_broken_migration?
+    # If the column is already fixed, then the migration wasn't run before now.
+    if Gitlab::Database.postgresql?
+      !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: 'true', null: false)
+    else
+      !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: '1', null: false)
+    end
+  end
+
+  def false_negative_warning
+    <<-MSG.strip_heredoc
+      WARNING
+
+      If you did not intentionally disable the "Write to authorized_keys file"
+      option in Application Settings as outlined in the Speed up SSH
+      documentation,
+
+      https://docs.gitlab.com/ee/administration/operations/speed_up_ssh.html
+
+      then the authorized_keys file may be out-of-date, affecting SSH
+      operations.
+
+      If you are affected, please check the "Write to authorized_keys file"
+      checkbox, and Save. Then rebuild the authorized_keys file as shown here:
+
+      https://docs.gitlab.com/ee/administration/raketasks/maintenance.html#rebuild-authorized_keys-file
+
+      For more information, see the issue:
+
+      https://gitlab.com/gitlab-org/gitlab-ee/issues/2738
+    MSG
+  end
+
+  def update_nil_setting_to_true
+    setting = ApplicationSetting.last # guaranteed to be found since authorized_keys_file_in_use_and_stale? is true
+    setting.update!(authorized_keys_enabled: true) if setting.authorized_keys_enabled.nil?
+  end
+
+  def update_authorized_keys_file_since(cutoff_datetime)
+    add_keys_since(cutoff_datetime)
+
+    remove_keys_not_found_in_db
+  end
+
+  def add_keys_since(cutoff_datetime)
+    start_key = Key.where("created_at >= ?", cutoff_datetime).first
+    if start_key
+      GitlabShellWorker.perform_async(:batch_add_keys_in_db_starting_from, start_key.id)
+    end
+  end
+
+  def remove_keys_not_found_in_db
+    GitlabShellWorker.perform_async(:remove_keys_not_found_in_db)
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 205a1a039d73146c..71a2d84f7a01ef9e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20170622162730) do
+ActiveRecord::Schema.define(version: 20170626202753) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 63cd946894037444..f0942b1c135bf4cb 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -220,11 +220,12 @@ def batch_add_keys(&block)
     # Ex.
     #   remove_key("key-342", "sha-rsa ...")
     #
-    def remove_key(key_id, key_content)
+    def remove_key(key_id, key_content = nil)
       return unless self.authorized_keys_enabled?
 
-      Gitlab::Utils.system_silent([gitlab_shell_keys_path,
-                                   'rm-key', key_id, key_content])
+      args = [gitlab_shell_keys_path, 'rm-key', key_id]
+      args << key_content if key_content
+      Gitlab::Utils.system_silent(args)
     end
 
     # Remove all ssh keys from gitlab shell
@@ -238,6 +239,54 @@ def remove_all_keys
       Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear'])
     end
 
+    # Remove ssh keys from gitlab shell that are not in the DB
+    #
+    # Ex.
+    #   remove_keys_not_found_in_db
+    #
+    def remove_keys_not_found_in_db
+      return unless self.authorized_keys_enabled?
+
+      batch_read_key_ids do |ids_in_file|
+        keys_in_db = Key.where(id: ids_in_file)
+        if ids_in_file.size > keys_in_db.count
+          ids_to_remove = ids_in_file - keys_in_db.pluck(:id)
+          ids_to_remove.each do |id|
+            remove_key("key-#{id}")
+          end
+        end
+      end
+    end
+
+    # Iterate over all ssh key IDs from gitlab shell, in batches
+    #
+    # Ex.
+    #   batch_read_key_ids { |batch| keys = Key.where(id: batch) }
+    #
+    def batch_read_key_ids(batch_size: 100, &block)
+      return unless self.authorized_keys_enabled?
+
+      list_key_ids do |key_id_stream|
+        key_id_stream.lazy.each_slice(batch_size) do |lines|
+          key_ids = lines.map { |l| l.chomp.to_i }
+          yield(key_ids)
+        end
+      end
+    end
+
+    # Stream all ssh key IDs from gitlab shell, separated by newlines
+    #
+    # Ex.
+    #   list_key_ids
+    #
+    def list_key_ids(&block)
+      return unless self.authorized_keys_enabled?
+
+      IO.popen(%W(#{gitlab_shell_path}/bin/gitlab-keys list-key-ids)) do |key_id_stream|
+        yield(key_id_stream)
+      end
+    end
+
     # Add empty directory for storing repositories
     #
     # Ex.
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 74a207c36b87238d..6713ab0b1f4bcb95 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -177,6 +177,17 @@
         gitlab_shell.remove_key('key-123', 'ssh-rsa foobar')
       end
     end
+
+    context 'when key content is not given' do
+      it 'calls rm-key with only one argument' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with(
+          [:gitlab_shell_keys_path, 'rm-key', 'key-123']
+        )
+
+        gitlab_shell.remove_key('key-123')
+      end
+    end
   end
 
   describe '#remove_all_keys' do
@@ -202,6 +213,89 @@
     end
   end
 
+  describe '#remove_keys_not_found_in_db' do
+    context 'when keys are in the file that are not in the DB' do
+      before do
+        gitlab_shell.remove_all_keys
+        gitlab_shell.add_key('key-1234', 'ssh-rsa ASDFASDF')
+        gitlab_shell.add_key('key-9876', 'ssh-rsa ASDFASDF')
+        @another_key = create(:key) # this one IS in the DB
+      end
+
+      it 'removes the keys' do
+        expect(find_in_authorized_keys_file(1234)).to be_truthy
+        expect(find_in_authorized_keys_file(9876)).to be_truthy
+        expect(find_in_authorized_keys_file(@another_key.id)).to be_truthy
+        gitlab_shell.remove_keys_not_found_in_db
+        expect(find_in_authorized_keys_file(1234)).to be_falsey
+        expect(find_in_authorized_keys_file(9876)).to be_falsey
+        expect(find_in_authorized_keys_file(@another_key.id)).to be_truthy
+      end
+    end
+  end
+
+  describe '#batch_read_key_ids' do
+    context 'when there are keys in the authorized_keys file' do
+      before do
+        gitlab_shell.remove_all_keys
+        (1..4).each do |i|
+          gitlab_shell.add_key("key-#{i}", "ssh-rsa ASDFASDF#{i}")
+        end
+      end
+
+      it 'iterates over the key IDs in the file, in batches' do
+        loop_count = 0
+        first_batch = [1, 2]
+        second_batch = [3, 4]
+
+        gitlab_shell.batch_read_key_ids(batch_size: 2) do |batch|
+          expected = (loop_count == 0 ? first_batch : second_batch)
+          expect(batch).to eq(expected)
+          loop_count += 1
+        end
+      end
+    end
+  end
+
+  describe '#list_key_ids' do
+    context 'when there are keys in the authorized_keys file' do
+      before do
+        gitlab_shell.remove_all_keys
+        (1..4).each do |i|
+          gitlab_shell.add_key("key-#{i}", "ssh-rsa ASDFASDF#{i}")
+        end
+      end
+
+      it 'outputs the key IDs in the file, separated by newlines' do
+        ids = []
+        gitlab_shell.list_key_ids do |io|
+          io.each do |line|
+            ids << line
+          end
+        end
+
+        expect(ids).to eq(["1\n", "2\n", "3\n", "4\n"])
+      end
+    end
+
+    context 'when there are no keys in the authorized_keys file' do
+      before do
+        gitlab_shell.remove_all_keys
+      end
+
+      it 'outputs nothing, not even an empty string' do
+        ids = []
+        gitlab_shell.list_key_ids do |io|
+          io.each do |line|
+            ids << line
+          end
+        end
+
+        expect(ids).to eq([])
+      end
+    end
+  end
+
   describe Gitlab::Shell::KeyAdder, lib: true do
     describe '#add_key' do
       it 'removes trailing garbage' do
@@ -276,4 +370,12 @@
       end
     end
   end
+
+  def find_in_authorized_keys_file(key_id)
+    gitlab_shell.batch_read_key_ids do |ids|
+      return true if ids.include?(key_id)
+    end
+
+    false
+  end
 end
diff --git a/spec/migrations/update_authorized_keys_file_spec.rb b/spec/migrations/update_authorized_keys_file_spec.rb
new file mode 100644
index 0000000000000000..dbb3b8d5fbef8cee
--- /dev/null
+++ b/spec/migrations/update_authorized_keys_file_spec.rb
@@ -0,0 +1,232 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20170626202753_update_authorized_keys_file.rb')
+
+describe UpdateAuthorizedKeysFile do
+  let(:migration) { described_class.new }
+
+  describe '#up' do
+    context 'when authorized_keys_enabled is nil' do
+      before do
+        # Ensure the column can be null for the test
+        ActiveRecord::Base.connection.change_column_null :application_settings, :authorized_keys_enabled, true
+        ActiveRecord::Base.connection.change_column :application_settings, :authorized_keys_enabled, :boolean, default: nil
+
+        ApplicationSetting.create!(authorized_keys_enabled: nil)
+      end
+
+      it 'sets authorized_keys_enabled to true' do
+        migration.up
+
+        expect(ApplicationSetting.last.authorized_keys_enabled).to be_truthy
+      end
+
+      context 'there are keys created before and after the cutoff datetime' do
+        before do
+          Timecop.freeze
+        end
+        after do
+          Timecop.return
+        end
+
+        before do
+          @cutoff_datetime = UpdateAuthorizedKeysFile::DATETIME_9_3_0_RELEASED
+          @keys = []
+          Timecop.travel(@cutoff_datetime - 1.day)
+          2.times { @keys << create(:key) } # 2 keys before cutoff
+          Timecop.travel(@cutoff_datetime + 1.day)
+          2.times { @keys << create(:key) } # 2 keys after cutoff
+        end
+
+        it 'adds the keys created after the cutoff datetime to the authorized_keys file' do
+          Gitlab::Shell.new.remove_all_keys
+
+          migration.up
+
+          file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
+          expect(file.scan(/ssh-rsa/).count).to eq(2)
+
+          expect(file).not_to include(Gitlab::Shell.strip_key(@keys[0].key))
+          expect(file).not_to include(Gitlab::Shell.strip_key(@keys[1].key))
+          expect(file).to include(Gitlab::Shell.strip_key(@keys[2].key))
+          expect(file).to include(Gitlab::Shell.strip_key(@keys[3].key))
+        end
+      end
+
+      context 'when an SSH key exists in authorized_keys but not in the DB' do
+        before do
+          @key_to_stay = create(:key)
+          @key_to_delete = create(:key)
+          @key_to_delete.delete
+        end
+
+        it 'deletes the SSH key from authorized_keys' do
+          file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
+          expect(file).to include(Gitlab::Shell.strip_key(@key_to_stay.key))
+          expect(file).to include(Gitlab::Shell.strip_key(@key_to_delete.key))
+
+          migration.up
+
+          file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
+          expect(file).to include(Gitlab::Shell.strip_key(@key_to_stay.key))
+          expect(file).not_to include(Gitlab::Shell.strip_key(@key_to_delete.key))
+        end
+      end
+    end
+  end
+
+  describe '#authorized_keys_file_in_use_and_stale?' do
+    subject { migration.authorized_keys_file_in_use_and_stale? }
+
+    context 'when the customer ran the broken migration' do
+      before do
+        allow(migration).to receive(:ran_broken_migration?).and_return(true)
+      end
+
+      context 'when is a record in application_settings table' do
+        before do
+          ApplicationSetting.create!(authorized_keys_enabled: true)
+        end
+
+        context 'when authorized_keys_enabled is true' do
+          it { is_expected.to be_truthy }
+        end
+
+        context 'when authorized_keys_enabled is nil' do
+          before do
+            # Ensure the column can be null for the test
+            ActiveRecord::Base.connection.change_column_null :application_settings, :authorized_keys_enabled, true
+            ActiveRecord::Base.connection.change_column :application_settings, :authorized_keys_enabled, :boolean, default: nil
+
+            ApplicationSetting.first.update(authorized_keys_enabled: nil)
+          end
+
+          it { is_expected.to be_truthy }
+        end
+
+        context 'when authorized_keys_enabled is explicitly false' do
+          before do
+            ApplicationSetting.first.update(authorized_keys_enabled: false)
+          end
+
+          it { is_expected.to be_falsey }
+
+          it 'outputs a warning message for users who unintentionally Saved the setting unchecked' do
+            expect{ subject }.to output(/warning.*intentionally/mi).to_stdout
+          end
+        end
+      end
+
+      context 'when there is no record in application_settings table' do
+        before do
+          expect(ApplicationSetting.count).to eq(0)
+        end
+
+        it { is_expected.to be_falsey }
+      end
+    end
+
+    context 'when the customer did not run the broken migration' do
+      before do
+        allow(migration).to receive(:ran_broken_migration?).and_return(false)
+      end
+
+      it { is_expected.to be_falsey }
+    end
+  end
+
+  describe '#ran_broken_migration?' do
+    subject { migration.ran_broken_migration? }
+
+    context 'for unaffected customers: the authorized_keys_enabled column has a default (so the fixed migration ran)' do
+      before do
+        ActiveRecord::Base.connection.change_column :application_settings, :authorized_keys_enabled, :boolean, default: true
+        ActiveRecord::Base.connection.change_column_null :application_settings, :authorized_keys_enabled, false, true
+      end
+
+      it 'returns false' do
+        expect(subject).to be_falsey
+      end
+    end
+
+    context 'for affected customers: the authorized_keys_enabled column does not have a default (so the broken migration ran)' do
+      before do
+        ActiveRecord::Base.connection.change_column_null :application_settings, :authorized_keys_enabled, true
+        ActiveRecord::Base.connection.change_column :application_settings, :authorized_keys_enabled, :boolean, default: nil
+      end
+
+      it 'returns true' do
+        expect(subject).to be_truthy
+      end
+    end
+  end
+
+  describe '#update_authorized_keys_file_since' do
+    let!(:cutoff_datetime) { DateTime.now }
+
+    subject { migration.update_authorized_keys_file_since(cutoff_datetime) }
+
+    context 'when an SSH key was created after the cutoff datetime' do
+      before do
+        Timecop.freeze
+      end
+      after do
+        Timecop.return
+      end
+
+      before do
+        Timecop.travel 1.day.from_now
+        @key = create(:key)
+      end
+
+      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
+        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
+        allow(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+        subject
+      end
+    end
+
+    it 'queues a remove_keys_not_found_in_db call to GitlabShellWorker' do
+      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+      subject
+    end
+  end
+
+  describe '#add_keys_since' do
+    let!(:cutoff_datetime) { DateTime.now }
+
+    subject { migration.add_keys_since(cutoff_datetime) }
+
+    before do
+      Timecop.freeze
+    end
+    after do
+      Timecop.return
+    end
+
+    context 'when an SSH key was created after the cutoff datetime' do
+      before do
+        Timecop.travel 1.day.from_now
+        @key = create(:key)
+      end
+
+      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
+        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
+        subject
+      end
+    end
+
+    context 'when an SSH key was not created after the cutoff datetime' do
+      it 'does not use GitlabShellWorker' do
+        expect(GitlabShellWorker).not_to receive(:perform_async)
+        subject
+      end
+    end
+  end
+
+  describe '#remove_keys_not_found_in_db' do
+    it 'queues a rm_keys_not_in_db call to GitlabShellWorker' do
+      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+      migration.remove_keys_not_found_in_db
+    end
+  end
+end
diff --git a/spec/workers/gitlab_shell_worker_spec.rb b/spec/workers/gitlab_shell_worker_spec.rb
new file mode 100644
index 0000000000000000..6147a24760c0ca69
--- /dev/null
+++ b/spec/workers/gitlab_shell_worker_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe GitlabShellWorker do
+  let(:worker) { described_class.new }
+
+  describe '#perform with add_key' do
+    it 'calls add_key on Gitlab::Shell' do
+      expect_any_instance_of(Gitlab::Shell).to receive(:add_key).with('foo', 'bar')
+      worker.perform(:add_key, 'foo', 'bar')
+    end
+  end
+
+  describe '#perform with batch_add_keys_in_db_starting_from' do
+    context 'when there are many keys in the DB' do
+      before do
+        @keys = []
+        10.times do
+          @keys << create(:key)
+        end
+      end
+
+      it 'adds all the keys in the DB, starting from the given ID, to the authorized_keys file' do
+        Gitlab::Shell.new.remove_all_keys
+
+        worker.perform(:batch_add_keys_in_db_starting_from, @keys[3].id)
+
+        file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
+        expect(file.scan(/ssh-rsa/).count).to eq(7)
+
+        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[0].key))
+        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[2].key))
+        expect(file).to include(Gitlab::Shell.strip_key(@keys[3].key))
+        expect(file).to include(Gitlab::Shell.strip_key(@keys[9].key))
+      end
+    end
+  end
+end
-- 
GitLab


From f6ace56eefb5a05d00085dc82478bf2388c5436e Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Fri, 23 Jun 2017 19:27:41 -0700
Subject: [PATCH 04/18] Ensure `authorized_keys_enabled` defaults to true

Locally, if Spring was not restarted, `current_application_settings` was still cached, which prevented the migration from editing the file. This will also ensure that any app server somehow hitting old cache data will properly default this setting regardless.
---
 lib/gitlab/shell.rb           |  2 ++
 spec/lib/gitlab/shell_spec.rb | 57 +++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index f0942b1c135bf4cb..15b0e1511ae30cdd 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -415,6 +415,8 @@ def gitlab_shell_keys_path
     end
 
     def authorized_keys_enabled?
+      return true if current_application_settings.authorized_keys_enabled.nil?
+
       current_application_settings.authorized_keys_enabled
     end
   end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 6713ab0b1f4bcb95..ff533e6ffecb8ec0 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -126,6 +126,21 @@
         gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage')
       end
     end
+
+    context 'when authorized_keys_enabled is nil' do
+      before do
+        stub_application_setting(authorized_keys_enabled: nil)
+      end
+
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with(
+          [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar']
+        )
+
+        gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage')
+      end
+    end
   end
 
   describe '#batch_add_keys' do
@@ -152,6 +167,20 @@
         end
       end
     end
+
+    context 'when authorized_keys_enabled is nil' do
+      before do
+        stub_application_setting(authorized_keys_enabled: nil)
+      end
+
+      it 'instantiates KeyAdder' do
+        expect_any_instance_of(Gitlab::Shell::KeyAdder).to receive(:add_key).with('key-123', 'ssh-rsa foobar')
+
+        gitlab_shell.batch_add_keys do |adder|
+          adder.add_key('key-123', 'ssh-rsa foobar')
+        end
+      end
+    end
   end
 
   describe '#remove_key' do
@@ -178,6 +207,21 @@
       end
     end
 
+    context 'when authorized_keys_enabled is nil' do
+      before do
+        stub_application_setting(authorized_keys_enabled: nil)
+      end
+
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with(
+          [:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar']
+        )
+
+        gitlab_shell.remove_key('key-123', 'ssh-rsa foobar')
+      end
+    end
+
     context 'when key content is not given' do
       it 'calls rm-key with only one argument' do
         allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
@@ -211,6 +255,19 @@
         gitlab_shell.remove_all_keys
       end
     end
+
+    context 'when authorized_keys_enabled is nil' do
+      before do
+        stub_application_setting(authorized_keys_enabled: nil)
+      end
+
+      it 'removes trailing garbage' do
+        allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
+        expect(Gitlab::Utils).to receive(:system_silent).with([:gitlab_shell_keys_path, 'clear'])
+
+        gitlab_shell.remove_all_keys
+      end
+    end
   end
 
   describe '#remove_keys_not_found_in_db' do
-- 
GitLab


From 002363394e023cecf670209565d15367fd923977 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Tue, 27 Jun 2017 14:24:12 -0700
Subject: [PATCH 05/18] Add default to authorized_keys_enabled setting

Reminder: The original migration was fixed retroactively a few commits ago, so people who did not ever run GitLab 9.3.0 already have a column that defaults to true and disallows nulls. I have tested on PostgreSQL and MySQL that it is safe to run this migration regardless.

Affected customers who did run 9.3.0 are the ones who need this migration to fix the authorized_keys_enabled column.

The reason for the retroactive fix plus this migration is that it allows us to run a migration in between to fix the authorized_keys file only for those who ran 9.3.0.
---
 ...orized_keys_enabled_application_setting.rb | 20 +++++++++++++++++++
 db/schema.rb                                  |  4 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 db/migrate/20170627211700_add_default_to_authorized_keys_enabled_application_setting.rb

diff --git a/db/migrate/20170627211700_add_default_to_authorized_keys_enabled_application_setting.rb b/db/migrate/20170627211700_add_default_to_authorized_keys_enabled_application_setting.rb
new file mode 100644
index 0000000000000000..aa26af35b8fa7a48
--- /dev/null
+++ b/db/migrate/20170627211700_add_default_to_authorized_keys_enabled_application_setting.rb
@@ -0,0 +1,20 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddDefaultToAuthorizedKeysEnabledApplicationSetting < ActiveRecord::Migration
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  disable_ddl_transaction!
+
+  def up
+    change_column :application_settings, :authorized_keys_enabled, :boolean, default: true
+    change_column_null :application_settings, :authorized_keys_enabled, false, true
+  end
+
+  def down
+    change_column_null :application_settings, :authorized_keys_enabled, true
+    change_column :application_settings, :authorized_keys_enabled, :boolean, default: nil
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 71a2d84f7a01ef9e..b07fd912fba1e3d0 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20170626202753) do
+ActiveRecord::Schema.define(version: 20170627211700) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -141,7 +141,7 @@
     t.integer "mirror_max_delay", default: 5, null: false
     t.integer "mirror_max_capacity", default: 100, null: false
     t.integer "mirror_capacity_threshold", default: 50, null: false
-    t.boolean "authorized_keys_enabled"
+    t.boolean "authorized_keys_enabled", default: true, null: false
     t.boolean "help_page_hide_commercial_content", default: false
     t.string "help_page_support_url"
   end
-- 
GitLab


From 4b3d8f3873db033d30c0eeb37f35f124fbacfc73 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 12:14:25 -0700
Subject: [PATCH 06/18] Tweaks to address feedback

---
 ...70626202753_update_authorized_keys_file.rb | 33 ++++++++++---------
 lib/gitlab/shell.rb                           |  6 ++--
 2 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/db/migrate/20170626202753_update_authorized_keys_file.rb b/db/migrate/20170626202753_update_authorized_keys_file.rb
index f696489ea4a8aac0..ef9e935387b7f956 100644
--- a/db/migrate/20170626202753_update_authorized_keys_file.rb
+++ b/db/migrate/20170626202753_update_authorized_keys_file.rb
@@ -4,15 +4,19 @@
 class UpdateAuthorizedKeysFile < ActiveRecord::Migration
   include Gitlab::Database::MigrationHelpers
 
-  class ApplicationSetting < ActiveRecord::Base; end
-  class Key < ActiveRecord::Base; end
+  class ApplicationSetting < ActiveRecord::Base
+    self.table_name = 'application_settings'
+  end
+  class Key < ActiveRecord::Base
+    self.table_name = 'keys'
+  end
 
   # Set this constant to true if this migration requires downtime.
   DOWNTIME = false
 
-  # We started deploying 9.3.0 to GitLab.com at 2017-06-22T17:24:00+00:00.
-  # TODO look at the time we pushed to the package server
-  DATETIME_9_3_0_RELEASED = DateTime.parse('2017-06-22T17:24:00+00:00')
+  # We started deploying 9.3.0 to GitLab.com at 2017-06-22 17:24 UTC, and the
+  # package was pushed some time before that. Some buffer room is included here.
+  DATETIME_9_3_0_RELEASED = DateTime.parse('2017-06-22T00:00:00+00:00')
 
   def up
     if authorized_keys_file_in_use_and_stale?
@@ -33,14 +37,14 @@ def down
   def authorized_keys_file_in_use_and_stale?
     return false unless ran_broken_migration?
 
-    uncached_setting = ApplicationSetting.last
+    @uncached_application_setting = ApplicationSetting.last
 
     # If there is no ApplicationSetting record in the DB, then the instance was
     # never in a state where `authorized_keys_enabled` field was `nil`. So the
     # file is not stale.
-    return false unless uncached_setting
+    return false unless @uncached_application_setting
 
-    if uncached_setting.authorized_keys_enabled == false # not falsey!
+    if @uncached_application_setting.authorized_keys_enabled == false # not falsey!
       # If authorized_keys_enabled is explicitly false, then the file is not in
       # use, so it doesn't need to be fixed. I.e. GitLab.com.
       #
@@ -59,11 +63,9 @@ def authorized_keys_file_in_use_and_stale?
 
   def ran_broken_migration?
     # If the column is already fixed, then the migration wasn't run before now.
-    if Gitlab::Database.postgresql?
-      !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: 'true', null: false)
-    else
-      !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: '1', null: false)
-    end
+    default_value = Gitlab::Database.postgresql? ? 'true' : '1'
+
+    !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: default_value, null: false)
   end
 
   def false_negative_warning
@@ -91,8 +93,7 @@ def false_negative_warning
   end
 
   def update_nil_setting_to_true
-    setting = ApplicationSetting.last # guaranteed to be found since authorized_keys_file_in_use_and_stale? is true
-    setting.update!(authorized_keys_enabled: true) if setting.authorized_keys_enabled.nil?
+    @uncached_application_setting.update_attribute(:authorized_keys_enabled, true)
   end
 
   def update_authorized_keys_file_since(cutoff_datetime)
@@ -102,7 +103,7 @@ def update_authorized_keys_file_since(cutoff_datetime)
   end
 
   def add_keys_since(cutoff_datetime)
-    start_key = Key.where("created_at >= ?", cutoff_datetime).first
+    start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).take
     if start_key
       GitlabShellWorker.perform_async(:batch_add_keys_in_db_starting_from, start_key.id)
     end
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 15b0e1511ae30cdd..528beeda6ae1b9d5 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -282,9 +282,7 @@ def batch_read_key_ids(batch_size: 100, &block)
     def list_key_ids(&block)
       return unless self.authorized_keys_enabled?
 
-      IO.popen(%W(#{gitlab_shell_path}/bin/gitlab-keys list-key-ids)) do |key_id_stream|
-        yield(key_id_stream)
-      end
+      IO.popen(%W(#{gitlab_shell_path}/bin/gitlab-keys list-key-ids), &block)
     end
 
     # Add empty directory for storing repositories
@@ -415,6 +413,8 @@ def gitlab_shell_keys_path
     end
 
     def authorized_keys_enabled?
+      # Return true if nil to ensure the authorized_keys methods work while
+      # fixing the authorized_keys file during migration.
       return true if current_application_settings.authorized_keys_enabled.nil?
 
       current_application_settings.authorized_keys_enabled
-- 
GitLab


From 12d0a64debb75ec4f0c436a58d268d725a827d06 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 12:35:00 -0700
Subject: [PATCH 07/18] Extract work into background migration

---
 ...70626202753_update_authorized_keys_file.rb | 19 +----
 .../update_authorized_keys_file_since.rb      | 26 +++++++
 .../update_authorized_keys_file_since_spec.rb | 73 +++++++++++++++++++
 .../update_authorized_keys_file_spec.rb       | 70 ------------------
 4 files changed, 101 insertions(+), 87 deletions(-)
 create mode 100644 lib/gitlab/background_migration/update_authorized_keys_file_since.rb
 create mode 100644 spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb

diff --git a/db/migrate/20170626202753_update_authorized_keys_file.rb b/db/migrate/20170626202753_update_authorized_keys_file.rb
index ef9e935387b7f956..4e0119d1a5d5c62f 100644
--- a/db/migrate/20170626202753_update_authorized_keys_file.rb
+++ b/db/migrate/20170626202753_update_authorized_keys_file.rb
@@ -7,9 +7,6 @@ class UpdateAuthorizedKeysFile < ActiveRecord::Migration
   class ApplicationSetting < ActiveRecord::Base
     self.table_name = 'application_settings'
   end
-  class Key < ActiveRecord::Base
-    self.table_name = 'keys'
-  end
 
   # Set this constant to true if this migration requires downtime.
   DOWNTIME = false
@@ -97,19 +94,7 @@ def update_nil_setting_to_true
   end
 
   def update_authorized_keys_file_since(cutoff_datetime)
-    add_keys_since(cutoff_datetime)
-
-    remove_keys_not_found_in_db
-  end
-
-  def add_keys_since(cutoff_datetime)
-    start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).take
-    if start_key
-      GitlabShellWorker.perform_async(:batch_add_keys_in_db_starting_from, start_key.id)
-    end
-  end
-
-  def remove_keys_not_found_in_db
-    GitlabShellWorker.perform_async(:remove_keys_not_found_in_db)
+    job = ['UpdateAuthorizedKeysFileSince', [cutoff_datetime]]
+    BackgroundMigrationWorker.perform_bulk(job)
   end
 end
diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
new file mode 100644
index 0000000000000000..0fc7fe1dea738b9a
--- /dev/null
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -0,0 +1,26 @@
+module Gitlab
+  module BackgroundMigration
+    class UpdateAuthorizedKeysFileSince
+      class Key < ActiveRecord::Base
+        self.table_name = 'keys'
+      end
+
+      def perform(cutoff_datetime)
+        add_keys_since(cutoff_datetime)
+
+        remove_keys_not_found_in_db
+      end
+
+      def add_keys_since(cutoff_datetime)
+        start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).take
+        if start_key
+          GitlabShellWorker.perform_async(:batch_add_keys_in_db_starting_from, start_key.id)
+        end
+      end
+
+      def remove_keys_not_found_in_db
+        GitlabShellWorker.perform_async(:remove_keys_not_found_in_db)
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
new file mode 100644
index 0000000000000000..57e822040f094189
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince do
+  describe '#perform' do
+    let!(:cutoff_datetime) { DateTime.now }
+
+    subject { described_class.new.perform(cutoff_datetime) }
+
+    context 'when an SSH key was created after the cutoff datetime' do
+      before do
+        Timecop.freeze
+      end
+      after do
+        Timecop.return
+      end
+
+      before do
+        Timecop.travel 1.day.from_now
+        @key = create(:key)
+      end
+
+      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
+        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
+        allow(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+        subject
+      end
+    end
+
+    it 'queues a remove_keys_not_found_in_db call to GitlabShellWorker' do
+      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+      subject
+    end
+  end
+
+  describe '#add_keys_since' do
+    let!(:cutoff_datetime) { DateTime.now }
+
+    subject { described_class.new.add_keys_since(cutoff_datetime) }
+
+    before do
+      Timecop.freeze
+    end
+    after do
+      Timecop.return
+    end
+
+    context 'when an SSH key was created after the cutoff datetime' do
+      before do
+        Timecop.travel 1.day.from_now
+        @key = create(:key)
+      end
+
+      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
+        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
+        subject
+      end
+    end
+
+    context 'when an SSH key was not created after the cutoff datetime' do
+      it 'does not use GitlabShellWorker' do
+        expect(GitlabShellWorker).not_to receive(:perform_async)
+        subject
+      end
+    end
+  end
+
+  describe '#remove_keys_not_found_in_db' do
+    it 'queues a rm_keys_not_in_db call to GitlabShellWorker' do
+      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+      described_class.new.remove_keys_not_found_in_db
+    end
+  end
+end
diff --git a/spec/migrations/update_authorized_keys_file_spec.rb b/spec/migrations/update_authorized_keys_file_spec.rb
index dbb3b8d5fbef8cee..15b85366ac1a1f1c 100644
--- a/spec/migrations/update_authorized_keys_file_spec.rb
+++ b/spec/migrations/update_authorized_keys_file_spec.rb
@@ -159,74 +159,4 @@
       end
     end
   end
-
-  describe '#update_authorized_keys_file_since' do
-    let!(:cutoff_datetime) { DateTime.now }
-
-    subject { migration.update_authorized_keys_file_since(cutoff_datetime) }
-
-    context 'when an SSH key was created after the cutoff datetime' do
-      before do
-        Timecop.freeze
-      end
-      after do
-        Timecop.return
-      end
-
-      before do
-        Timecop.travel 1.day.from_now
-        @key = create(:key)
-      end
-
-      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
-        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
-        allow(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
-        subject
-      end
-    end
-
-    it 'queues a remove_keys_not_found_in_db call to GitlabShellWorker' do
-      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
-      subject
-    end
-  end
-
-  describe '#add_keys_since' do
-    let!(:cutoff_datetime) { DateTime.now }
-
-    subject { migration.add_keys_since(cutoff_datetime) }
-
-    before do
-      Timecop.freeze
-    end
-    after do
-      Timecop.return
-    end
-
-    context 'when an SSH key was created after the cutoff datetime' do
-      before do
-        Timecop.travel 1.day.from_now
-        @key = create(:key)
-      end
-
-      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
-        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
-        subject
-      end
-    end
-
-    context 'when an SSH key was not created after the cutoff datetime' do
-      it 'does not use GitlabShellWorker' do
-        expect(GitlabShellWorker).not_to receive(:perform_async)
-        subject
-      end
-    end
-  end
-
-  describe '#remove_keys_not_found_in_db' do
-    it 'queues a rm_keys_not_in_db call to GitlabShellWorker' do
-      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
-      migration.remove_keys_not_found_in_db
-    end
-  end
 end
-- 
GitLab


From 8d6e72f3e952bafa919e2c23906dd4ff335fd10f Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 12:48:03 -0700
Subject: [PATCH 08/18] Move batch-add-logic to background migration

Do the work synchronously to avoid multiple workers attempting to add batches of keys at the same time.

Also, make the delete portion wait until after adding is done.
---
 app/workers/gitlab_shell_worker.rb            | 15 +-----
 .../update_authorized_keys_file_since.rb      | 19 +++++++-
 .../update_authorized_keys_file_since_spec.rb | 46 +++++++++++++++----
 spec/workers/gitlab_shell_worker_spec.rb      | 25 ----------
 4 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb
index ddb476226d12244d..964287a1793a03d7 100644
--- a/app/workers/gitlab_shell_worker.rb
+++ b/app/workers/gitlab_shell_worker.rb
@@ -4,19 +4,6 @@ class GitlabShellWorker
   include DedicatedSidekiqQueue
 
   def perform(action, *arg)
-    if action.to_s == 'batch_add_keys_in_db_starting_from'
-      batch_add_keys_in_db_starting_from(arg.first)
-    else
-      gitlab_shell.send(action, *arg)
-    end
-  end
-
-  # Not added to Gitlab::Shell because I don't expect this to be used again
-  def batch_add_keys_in_db_starting_from(start_id)
-    gitlab_shell.batch_add_keys do |adder|
-      Key.find_each(start: start_id, batch_size: 1000) do |key|
-        adder.add_key(key.shell_id, key.key)
-      end
-    end
+    gitlab_shell.send(action, *arg)
   end
 end
diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index 0fc7fe1dea738b9a..9b9fb9efc2d136d3 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -3,6 +3,10 @@ module BackgroundMigration
     class UpdateAuthorizedKeysFileSince
       class Key < ActiveRecord::Base
         self.table_name = 'keys'
+
+        def shell_id
+          "key-#{id}"
+        end
       end
 
       def perform(cutoff_datetime)
@@ -14,13 +18,26 @@ def perform(cutoff_datetime)
       def add_keys_since(cutoff_datetime)
         start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).take
         if start_key
-          GitlabShellWorker.perform_async(:batch_add_keys_in_db_starting_from, start_key.id)
+          batch_add_keys_in_db_starting_from(start_key.id)
         end
       end
 
       def remove_keys_not_found_in_db
         GitlabShellWorker.perform_async(:remove_keys_not_found_in_db)
       end
+
+      # Not added to Gitlab::Shell because I don't expect this to be used again
+      def batch_add_keys_in_db_starting_from(start_id)
+        gitlab_shell.batch_add_keys do |adder|
+          Key.find_each(start: start_id, batch_size: 1000) do |key|
+            adder.add_key(key.shell_id, key.key)
+          end
+        end
+      end
+
+      def gitlab_shell
+        @gitlab_shell ||= Gitlab::Shell.new
+      end
     end
   end
 end
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
index 57e822040f094189..fdc31006b80fbed9 100644
--- a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -1,10 +1,12 @@
 require 'spec_helper'
 
 describe Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince do
+  let(:background_migration) { described_class.new }
+
   describe '#perform' do
     let!(:cutoff_datetime) { DateTime.now }
 
-    subject { described_class.new.perform(cutoff_datetime) }
+    subject { background_migration.perform(cutoff_datetime) }
 
     context 'when an SSH key was created after the cutoff datetime' do
       before do
@@ -19,9 +21,8 @@
         @key = create(:key)
       end
 
-      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
-        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
-        allow(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+      it 'calls batch_add_keys_in_db_starting_from with the start key ID' do
+        expect(background_migration).to receive(:batch_add_keys_in_db_starting_from).with(@key.id)
         subject
       end
     end
@@ -35,7 +36,7 @@
   describe '#add_keys_since' do
     let!(:cutoff_datetime) { DateTime.now }
 
-    subject { described_class.new.add_keys_since(cutoff_datetime) }
+    subject { background_migration.add_keys_since(cutoff_datetime) }
 
     before do
       Timecop.freeze
@@ -50,15 +51,15 @@
         @key = create(:key)
       end
 
-      it 'queues a batch_add_keys_from call to GitlabShellWorker, including the start key ID' do
-        expect(GitlabShellWorker).to receive(:perform_async).with(:batch_add_keys_in_db_starting_from, @key.id)
+      it 'calls batch_add_keys_in_db_starting_from with the start key ID' do
+        expect(background_migration).to receive(:batch_add_keys_in_db_starting_from).with(@key.id)
         subject
       end
     end
 
     context 'when an SSH key was not created after the cutoff datetime' do
-      it 'does not use GitlabShellWorker' do
-        expect(GitlabShellWorker).not_to receive(:perform_async)
+      it 'does not call batch_add_keys_in_db_starting_from' do
+        expect(background_migration).not_to receive(:batch_add_keys_in_db_starting_from)
         subject
       end
     end
@@ -67,7 +68,32 @@
   describe '#remove_keys_not_found_in_db' do
     it 'queues a rm_keys_not_in_db call to GitlabShellWorker' do
       expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
-      described_class.new.remove_keys_not_found_in_db
+      background_migration.remove_keys_not_found_in_db
+    end
+  end
+
+  describe '#batch_add_keys_in_db_starting_from' do
+    context 'when there are many keys in the DB' do
+      before do
+        @keys = []
+        10.times do
+          @keys << create(:key)
+        end
+      end
+
+      it 'adds all the keys in the DB, starting from the given ID, to the authorized_keys file' do
+        Gitlab::Shell.new.remove_all_keys
+
+        background_migration.batch_add_keys_in_db_starting_from(@keys[3].id)
+
+        file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
+        expect(file.scan(/ssh-rsa/).count).to eq(7)
+
+        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[0].key))
+        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[2].key))
+        expect(file).to include(Gitlab::Shell.strip_key(@keys[3].key))
+        expect(file).to include(Gitlab::Shell.strip_key(@keys[9].key))
+      end
     end
   end
 end
diff --git a/spec/workers/gitlab_shell_worker_spec.rb b/spec/workers/gitlab_shell_worker_spec.rb
index 6147a24760c0ca69..6b222af454d8c819 100644
--- a/spec/workers/gitlab_shell_worker_spec.rb
+++ b/spec/workers/gitlab_shell_worker_spec.rb
@@ -9,29 +9,4 @@
       worker.perform(:add_key, 'foo', 'bar')
     end
   end
-
-  describe '#perform with batch_add_keys_in_db_starting_from' do
-    context 'when there are many keys in the DB' do
-      before do
-        @keys = []
-        10.times do
-          @keys << create(:key)
-        end
-      end
-
-      it 'adds all the keys in the DB, starting from the given ID, to the authorized_keys file' do
-        Gitlab::Shell.new.remove_all_keys
-
-        worker.perform(:batch_add_keys_in_db_starting_from, @keys[3].id)
-
-        file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
-        expect(file.scan(/ssh-rsa/).count).to eq(7)
-
-        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[0].key))
-        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[2].key))
-        expect(file).to include(Gitlab::Shell.strip_key(@keys[3].key))
-        expect(file).to include(Gitlab::Shell.strip_key(@keys[9].key))
-      end
-    end
-  end
 end
-- 
GitLab


From 405a75c4dc2b95ce07c06bf9e4103c0dde9778b2 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 13:34:29 -0700
Subject: [PATCH 09/18] Do read and delete work in background migration

---
 .../update_authorized_keys_file_since.rb                  | 2 +-
 .../update_authorized_keys_file_since_spec.rb             | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index 9b9fb9efc2d136d3..6d257a532a2cb486 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -23,7 +23,7 @@ def add_keys_since(cutoff_datetime)
       end
 
       def remove_keys_not_found_in_db
-        GitlabShellWorker.perform_async(:remove_keys_not_found_in_db)
+        gitlab_shell.remove_keys_not_found_in_db
       end
 
       # Not added to Gitlab::Shell because I don't expect this to be used again
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
index fdc31006b80fbed9..94a6b7987a9ea12e 100644
--- a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -27,8 +27,8 @@
       end
     end
 
-    it 'queues a remove_keys_not_found_in_db call to GitlabShellWorker' do
-      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+    it 'calls remove_keys_not_found_in_db on Gitlab::Shell' do
+      expect(background_migration.gitlab_shell).to receive(:remove_keys_not_found_in_db)
       subject
     end
   end
@@ -66,8 +66,8 @@
   end
 
   describe '#remove_keys_not_found_in_db' do
-    it 'queues a rm_keys_not_in_db call to GitlabShellWorker' do
-      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_keys_not_found_in_db)
+    it 'calls remove_keys_not_found_in_db on Gitlab::Shell' do
+      expect(background_migration.gitlab_shell).to receive(:remove_keys_not_found_in_db)
       background_migration.remove_keys_not_found_in_db
     end
   end
-- 
GitLab


From 56e7548bf321b829c62bbf4c80aab391b4b857c3 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 13:48:43 -0700
Subject: [PATCH 10/18] Fix Rubocop offenses

---
 .../update_authorized_keys_file_since.rb                    | 6 ++----
 .../update_authorized_keys_file_since_spec.rb               | 4 ++--
 spec/lib/gitlab/shell_spec.rb                               | 2 +-
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index 6d257a532a2cb486..ec05d4f9822e6a8e 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -9,6 +9,8 @@ def shell_id
         end
       end
 
+      delegate :remove_keys_not_found_in_db, to: :gitlab_shell
+
       def perform(cutoff_datetime)
         add_keys_since(cutoff_datetime)
 
@@ -22,10 +24,6 @@ def add_keys_since(cutoff_datetime)
         end
       end
 
-      def remove_keys_not_found_in_db
-        gitlab_shell.remove_keys_not_found_in_db
-      end
-
       # Not added to Gitlab::Shell because I don't expect this to be used again
       def batch_add_keys_in_db_starting_from(start_id)
         gitlab_shell.batch_add_keys do |adder|
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
index 94a6b7987a9ea12e..ba3283785157727a 100644
--- a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -89,8 +89,8 @@
         file = File.read(Rails.root.join('tmp/tests/.ssh/authorized_keys'))
         expect(file.scan(/ssh-rsa/).count).to eq(7)
 
-        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[0].key))
-        expect(file).to_not include(Gitlab::Shell.strip_key(@keys[2].key))
+        expect(file).not_to include(Gitlab::Shell.strip_key(@keys[0].key))
+        expect(file).not_to include(Gitlab::Shell.strip_key(@keys[2].key))
         expect(file).to include(Gitlab::Shell.strip_key(@keys[3].key))
         expect(file).to include(Gitlab::Shell.strip_key(@keys[9].key))
       end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index ff533e6ffecb8ec0..39b1ccf9554efed9 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -331,7 +331,7 @@
           end
         end
 
-        expect(ids).to eq(["1\n", "2\n", "3\n", "4\n"])
+        expect(ids).to eq(%W{1\n 2\n 3\n 4\n})
       end
     end
 
-- 
GitLab


From ad12feafbd628b71647998081581a318afafe944 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 13:52:55 -0700
Subject: [PATCH 11/18] Add changelog entry

---
 .../fix-authorized-keys-enabled-default-2738.yml              | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 changelogs/unreleased-ee/fix-authorized-keys-enabled-default-2738.yml

diff --git a/changelogs/unreleased-ee/fix-authorized-keys-enabled-default-2738.yml b/changelogs/unreleased-ee/fix-authorized-keys-enabled-default-2738.yml
new file mode 100644
index 0000000000000000..6b1f7b67c7873a1e
--- /dev/null
+++ b/changelogs/unreleased-ee/fix-authorized-keys-enabled-default-2738.yml
@@ -0,0 +1,4 @@
+---
+title: Fix locked and stale SSH keys file from 9.3.0 upgrade
+merge_request: 2240
+author:
-- 
GitLab


From e4e7e9c32505f133a4e7600ee87be85dfd1e3cdb Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 15:48:12 -0700
Subject: [PATCH 12/18] Inform the user of actions taken or not taken

---
 db/migrate/20170626202753_update_authorized_keys_file.rb | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/db/migrate/20170626202753_update_authorized_keys_file.rb b/db/migrate/20170626202753_update_authorized_keys_file.rb
index 4e0119d1a5d5c62f..aea5fbb56a305442 100644
--- a/db/migrate/20170626202753_update_authorized_keys_file.rb
+++ b/db/migrate/20170626202753_update_authorized_keys_file.rb
@@ -17,6 +17,8 @@ class ApplicationSetting < ActiveRecord::Base
 
   def up
     if authorized_keys_file_in_use_and_stale?
+      say 'The authorized_keys file is in use, and may be stale. Now bringing it up-to-date in the background...'
+
       # Update nil authorized_keys_enabled to true to ensure that Gitlab::Shell
       # key methods work properly for workers running 9.3.0 during the
       # migration. If the setting remained nil, the workers would not edit the
@@ -24,6 +26,8 @@ def up
       update_nil_setting_to_true
 
       update_authorized_keys_file_since(DATETIME_9_3_0_RELEASED)
+    else
+      say 'The authorized_keys file does not need to be updated. Skipping...'
     end
   end
 
@@ -62,7 +66,10 @@ def ran_broken_migration?
     # If the column is already fixed, then the migration wasn't run before now.
     default_value = Gitlab::Database.postgresql? ? 'true' : '1'
 
-    !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: default_value, null: false)
+    column_has_no_default = !column_exists?(:application_settings, :authorized_keys_enabled, :boolean, default: default_value, null: false)
+    say "This GitLab installation was #{'never ' unless column_has_no_default}upgraded to exactly version 9.3.0."
+
+    column_has_no_default
   end
 
   def false_negative_warning
-- 
GitLab


From 17fc5fc557b043b49b0bfef1a487e9b40e303d89 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 16:01:42 -0700
Subject: [PATCH 13/18] Prevent unnecessary `select`s and `remove_key`s

---
 lib/gitlab/shell.rb           | 12 +++++++-----
 spec/lib/gitlab/shell_spec.rb | 37 +++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 528beeda6ae1b9d5..4253100ed8894d6e 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -248,12 +248,14 @@ def remove_keys_not_found_in_db
       return unless self.authorized_keys_enabled?
 
       batch_read_key_ids do |ids_in_file|
+        ids_in_file.uniq!
         keys_in_db = Key.where(id: ids_in_file)
-        if ids_in_file.size > keys_in_db.count
-          ids_to_remove = ids_in_file - keys_in_db.pluck(:id)
-          ids_to_remove.each do |id|
-            remove_key("key-#{id}")
-          end
+
+        return unless ids_in_file.size > keys_in_db.count # optimization
+
+        ids_to_remove = ids_in_file - keys_in_db.pluck(:id)
+        ids_to_remove.each do |id|
+          remove_key("key-#{id}")
         end
       end
     end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 39b1ccf9554efed9..0754990c6f7c1795 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -289,6 +289,43 @@
         expect(find_in_authorized_keys_file(@another_key.id)).to be_truthy
       end
     end
+
+    context 'when keys there are duplicate keys in the file that are not in the DB' do
+      before do
+        gitlab_shell.remove_all_keys
+        gitlab_shell.add_key('key-1234', 'ssh-rsa ASDFASDF')
+        gitlab_shell.add_key('key-1234', 'ssh-rsa ASDFASDF')
+      end
+
+      it 'removes the keys' do
+        expect(find_in_authorized_keys_file(1234)).to be_truthy
+        gitlab_shell.remove_keys_not_found_in_db
+        expect(find_in_authorized_keys_file(1234)).to be_falsey
+      end
+
+      it 'does not run remove more than once per key (in a batch)' do
+        expect(gitlab_shell).to receive(:remove_key).with('key-1234').once
+        gitlab_shell.remove_keys_not_found_in_db
+      end
+    end
+
+    context 'when keys there are duplicate keys in the file that ARE in the DB' do
+      before do
+        gitlab_shell.remove_all_keys
+        @key = create(:key)
+        gitlab_shell.add_key(@key.shell_id, @key.key)
+      end
+
+      it 'does not remove the key' do
+        gitlab_shell.remove_keys_not_found_in_db
+        expect(find_in_authorized_keys_file(@key.id)).to be_truthy
+      end
+
+      it 'does not need to run a SELECT query for that batch, on account of that key' do
+        expect_any_instance_of(ActiveRecord::Relation).not_to receive(:pluck)
+        gitlab_shell.remove_keys_not_found_in_db
+      end
+    end
   end
 
   describe '#batch_read_key_ids' do
-- 
GitLab


From 4949edce6dfbfbdb145f862d0597bd9c2f1f5190 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 16:09:19 -0700
Subject: [PATCH 14/18] Add logs for action taken

---
 .../background_migration/update_authorized_keys_file_since.rb  | 2 ++
 lib/gitlab/shell.rb                                            | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index ec05d4f9822e6a8e..be5f24d2cefec487 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -26,6 +26,8 @@ def add_keys_since(cutoff_datetime)
 
       # Not added to Gitlab::Shell because I don't expect this to be used again
       def batch_add_keys_in_db_starting_from(start_id)
+        Rails.logger.info("Adding all keys starting from ID: #{start_id}")
+
         gitlab_shell.batch_add_keys do |adder|
           Key.find_each(start: start_id, batch_size: 1000) do |key|
             adder.add_key(key.shell_id, key.key)
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 4253100ed8894d6e..d6147c9b6e80f64a 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -247,6 +247,8 @@ def remove_all_keys
     def remove_keys_not_found_in_db
       return unless self.authorized_keys_enabled?
 
+      Rails.logger.info("Removing keys not found in DB")
+
       batch_read_key_ids do |ids_in_file|
         ids_in_file.uniq!
         keys_in_db = Key.where(id: ids_in_file)
@@ -255,6 +257,7 @@ def remove_keys_not_found_in_db
 
         ids_to_remove = ids_in_file - keys_in_db.pluck(:id)
         ids_to_remove.each do |id|
+          Rails.logger.info("Removing key-#{id} not found in DB")
           remove_key("key-#{id}")
         end
       end
-- 
GitLab


From 9756deec94cf49d1bd15f6e3a537794178fb1a71 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 17:04:46 -0700
Subject: [PATCH 15/18] Fix optimization

---
 lib/gitlab/shell.rb           |  2 +-
 spec/lib/gitlab/shell_spec.rb | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index d6147c9b6e80f64a..91a21b73724f7c69 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -253,7 +253,7 @@ def remove_keys_not_found_in_db
         ids_in_file.uniq!
         keys_in_db = Key.where(id: ids_in_file)
 
-        return unless ids_in_file.size > keys_in_db.count # optimization
+        next unless ids_in_file.size > keys_in_db.count # optimization
 
         ids_to_remove = ids_in_file - keys_in_db.pluck(:id)
         ids_to_remove.each do |id|
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 0754990c6f7c1795..efc836da7d426128 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -326,6 +326,22 @@
         gitlab_shell.remove_keys_not_found_in_db
       end
     end
+
+    unless ENV['CI'] # Skip in CI, it takes 1 minute
+      context 'when the first batch can be skipped, but the next batch has keys that are not in the DB' do
+        before do
+          gitlab_shell.remove_all_keys
+          100.times { |i| create(:key) } # first batch is all in the DB
+          gitlab_shell.add_key('key-1234', 'ssh-rsa ASDFASDF')
+        end
+
+        it 'removes the keys not in the DB' do
+          expect(find_in_authorized_keys_file(1234)).to be_truthy
+          gitlab_shell.remove_keys_not_found_in_db
+          expect(find_in_authorized_keys_file(1234)).to be_falsey
+        end
+      end
+    end
   end
 
   describe '#batch_read_key_ids' do
-- 
GitLab


From 07e79989cefd66ee94299f97d5a59bc6d82dcd3f Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 17:11:56 -0700
Subject: [PATCH 16/18] Reuse `Gitlab::ShellAdapter`

---
 .../update_authorized_keys_file_since.rb                    | 6 ++----
 .../update_authorized_keys_file_since_spec.rb               | 4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index be5f24d2cefec487..eed5179129681401 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -1,6 +1,8 @@
 module Gitlab
   module BackgroundMigration
     class UpdateAuthorizedKeysFileSince
+      include Gitlab::ShellAdapter
+
       class Key < ActiveRecord::Base
         self.table_name = 'keys'
 
@@ -34,10 +36,6 @@ def batch_add_keys_in_db_starting_from(start_id)
           end
         end
       end
-
-      def gitlab_shell
-        @gitlab_shell ||= Gitlab::Shell.new
-      end
     end
   end
 end
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
index ba3283785157727a..a94900c4493c8613 100644
--- a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -28,7 +28,7 @@
     end
 
     it 'calls remove_keys_not_found_in_db on Gitlab::Shell' do
-      expect(background_migration.gitlab_shell).to receive(:remove_keys_not_found_in_db)
+      expect_any_instance_of(Gitlab::Shell).to receive(:remove_keys_not_found_in_db)
       subject
     end
   end
@@ -67,7 +67,7 @@
 
   describe '#remove_keys_not_found_in_db' do
     it 'calls remove_keys_not_found_in_db on Gitlab::Shell' do
-      expect(background_migration.gitlab_shell).to receive(:remove_keys_not_found_in_db)
+      expect_any_instance_of(Gitlab::Shell).to receive(:remove_keys_not_found_in_db)
       background_migration.remove_keys_not_found_in_db
     end
   end
-- 
GitLab


From 5ea374fecaadccfb6a0db42b1be41a256d8531d4 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 17:13:44 -0700
Subject: [PATCH 17/18] Guarantee the earliest key

---
 .../background_migration/update_authorized_keys_file_since.rb   | 2 +-
 .../update_authorized_keys_file_since_spec.rb                   | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
index eed5179129681401..134e583b78f17b7a 100644
--- a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -20,7 +20,7 @@ def perform(cutoff_datetime)
       end
 
       def add_keys_since(cutoff_datetime)
-        start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).take
+        start_key = Key.select(:id).where("created_at >= ?", cutoff_datetime).order('id ASC').take
         if start_key
           batch_add_keys_in_db_starting_from(start_key.id)
         end
diff --git a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
index a94900c4493c8613..be4e6f7734ed078b 100644
--- a/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_authorized_keys_file_since_spec.rb
@@ -49,6 +49,7 @@
       before do
         Timecop.travel 1.day.from_now
         @key = create(:key)
+        create(:key) # other key
       end
 
       it 'calls batch_add_keys_in_db_starting_from with the start key ID' do
-- 
GitLab


From e1289a64fadf77dc948ae596df0936c472ff6787 Mon Sep 17 00:00:00 2001
From: Michael Kozono <mkozono@gmail.com>
Date: Wed, 28 Jun 2017 17:25:37 -0700
Subject: [PATCH 18/18] Fix migration spec for MySQL

---
 spec/migrations/update_authorized_keys_file_spec.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/spec/migrations/update_authorized_keys_file_spec.rb b/spec/migrations/update_authorized_keys_file_spec.rb
index 15b85366ac1a1f1c..43642d2f25acb72e 100644
--- a/spec/migrations/update_authorized_keys_file_spec.rb
+++ b/spec/migrations/update_authorized_keys_file_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 require Rails.root.join('db', 'migrate', '20170626202753_update_authorized_keys_file.rb')
 
-describe UpdateAuthorizedKeysFile do
+describe UpdateAuthorizedKeysFile, :migration do
   let(:migration) { described_class.new }
 
   describe '#up' do
@@ -105,7 +105,7 @@
 
         context 'when authorized_keys_enabled is explicitly false' do
           before do
-            ApplicationSetting.first.update(authorized_keys_enabled: false)
+            ApplicationSetting.first.update!(authorized_keys_enabled: false)
           end
 
           it { is_expected.to be_falsey }
-- 
GitLab