redmine-git-hosting / redmine_git_hosting

A Redmine plugin which makes configuring your own Git hosting easy ;)
http://redmine-git-hosting.io
MIT License
275 stars 116 forks source link

Concept: Using SSH to maintain remote gitolite #779

Open venix1 opened 3 years ago

venix1 commented 3 years ago

SSH support is hiding in plain sight, and is trivial to implement with 3.X and 4.X release. I have not upgraded/tested this on 5.X, so I cannot comment on that, but if all management is still exclusively done through sudo, it works with that too.

The FAQ indicates gitolite and Redmine can exist on different servers if NFS is used, this is an improvement from 3.X which had no listed workaround, but still not desirable. Since gitolite already uses SSH, having an SSH solution it just better.

The secret is ssh can be swapped for sudo and the input/output of the command is unchanged. This allows all logic using sudo to also work using SSH. The versions mentioned do not try to manipulate gitolite directly outside of sudo, as long as that barrier is maintained, the swap can be done.

An example,

sudo prefix ssh prefix
sudo -n -u git -i ssh -T -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22 -i/home/redmine/.ssh/redmine_gitolite_sudo git@git.repo.local
sudo -n -u git -i git --git-dir repositories/repo.git tag ssh -T -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22 -i/home/redmine/.ssh/redmine_gitolite_sudo git@git.repo.local git --git-dir repositories/repo.git tag

This is the hack I wrote to support this. Step 1, is to override the sudo function to return the necessary SSH arguments. Step 2, is to write the function to return SSH arguments.

diff --git a/lib/redmine_git_hosting/commands/sudo.rb b/lib/redmine_git_hosting/commands/sudo.rb
index 65448567..3aea4644 100644
--- a/lib/redmine_git_hosting/commands/sudo.rb
+++ b/lib/redmine_git_hosting/commands/sudo.rb
@@ -181,11 +181,37 @@ module RedmineGitHosting
         def sudo
           if RedmineGitHosting::Config.gitolite_use_sudo?
             ['sudo', *sudo_shell_params]
+            ['ssh', *sudo_ssh_shell_params]
           else
             []
           end
         end

+        # Returns the ssh prefix arguments for all sudo_* commands.
+        #
+        # These are as follows:
+        # * (-T) Never request tty
+        # * (-i <gitolite_ssh_private_key>) Use the SSH keys given in Settings
+        # * (-p <gitolite_server_port>) Use port from settings
+        # * (-o BatchMode=yes) Never ask for a password
+        # * <gitolite_user>@<gitolite_server_host> (see +gitolite_url+)
+        #
+        def sudo_ssh_shell_params
+          # need ssh shell key
+          # gitolite user
+          # git ssh host
+          [
+            '-T',
+            '-o', 'BatchMode=yes',
+            '-o', 'UserKnownHostsFile=/dev/null',
+            '-o', 'StrictHostKeyChecking=no',
+            '-p', RedmineGitHosting::Config.gitolite_server_port,
+            '-i/home/redmine/.ssh/redmine_gitolite_sudo',
+            # RedmineGitHosting::Config.gitolite_sudo_private_key,
+            RedmineGitHosting::Config.gitolite_url
+          ]
+        end
+

         # Returns the sudo prefix to all sudo_* commands.
         #

Two things I know are missing before this could be included as an experimental feature are management of the "sudo" key, and a toggle to activate SSH mode. Both of which I hardcode in the hack. I've been managing a low traffic redmine, using SSH instead of sudo or NFS and have not encountered any issues and all features, appear to work as expected.

My use case for this, was a migration from a VM to kubernetes, which resulted in splitting apart gitolite and redmine.