Setting environment variable through SSH git push

2019-06-05 00:07发布

问题:

I'm reading Scott Chacon's Git book, and just wanted to confirm something. This part:

You also have access to the user doing the pushing if the push is being run over SSH. If you’ve allowed everyone to connect with a single user (like “git”) via public-key authentication, you may have to give that user a shell wrapper that determines which user is connecting based on the public key, and set an environment variable accordingly. Here we’ll assume the connecting user is in the $USER environment variable, so your update script begins by gathering all the information you need:

#!/usr/bin/env ruby

$refname = ARGV[0]
$oldrev  = ARGV[1]
$newrev  = ARGV[2]
$user    = ENV['USER']

puts "Enforcing Policies..."
puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})"

I presume that it's required for the pusher to install a script wrapping around the ssh command. For example, the script would perhaps set the GIT_SSH or GIT_SSH_COMMAND environment variable to point to a shell script that may have something like

#!/bin/bash

HOST=$1
shift
ssh -i ~/.ssh/id_rsa $HOST USER=foo $@

Now anytime a git push is done and the remote contains an ssh url, it will invoke that script and update the refs while passing the USER environment variable.

The other way would be to use "SendEnv USER" in ~/.ssh/config on the local machine and "AcceptEnv USER" in /etc/ssh/sshd_config on the remote git server.

Any other ways that come to mind that expand on the part in bold? I'm particularly looking for a way that doesn't require the pusher to do much work in regards to configuring his environment. Assume everyone's running some form of Windows and needs to setup ssh through some Unix emulator like Cygwin.

回答1:

This example is not about the shell or the ssh command.

It is taken from the "Server-Side Hook" section, and describe how to tailored the update hook based on the user (authenticated through ssh)

Here we’ll assume the connecting user is in the $USER environment variable

There is no indication on how this is done, but gitolite (a perl-based authorization layer, which very much needs the user authenticated id) is using ssh forced command: each public key in the ~git/.ssh/authorized_keys include the call to a wrapper script which takes in parameters the user id.
That script will:

  • execute the git command
  • fails if this the command is anything else but a git command

In the ~git/.ssh/authorized_keys, you don't have just the public key, but the call to the wrapper with the user id as a parameter:

command="/wrapper/script userid",no-port-forwarding,no-X11-for        warding,no-agent-forwarding,no-pty ssh-rsa AAAAB3N...
         ^^^^^^^^^^^^^^^
         (forced command)

You can see the environment variable being set by the (gitolite here) wrapper script in src/gitolite-shell#L102-L108.