git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: avoiding anonymous commits from root/shared accounts

From
Alex Vandiver <alex@chmrr.net>
Date
May 10, 2010, 21:11 UTC
Message-ID
<1273525498-sup-6628@utwig>
In-Reply-To
<4BE83CCD.2090505@letterboxes.org>
At Mon May 10 13:05:17 -0400 2010, Nick wrote:
Show 7 quoted lines
> [snip]
> The best idea I've come across seems to be some sort of wrapper for git, which
> if no $GIT_USER_* is defined, can use $SUDO_USER and/or `who am i` to identify
> the original log-in account, and sets $GIT_AUTHOR_NAME etc. - else if it can't
> do this, it refuses to commit.  Or perhaps it would be a script which spawns a
> shell with the right environment to invoke git commands from, after successfully
> determining the identity.

At work, we have a number of repositories which we store server configurations in, most of which are only writable as root. We use the script below to ensure that git mostly doesn't lie about the authors of commits. This won't solve your problem of people logging in under shared credentials -- and it also _does_ allow commits as 'root' if you logged in directly as root -- but it's perhaps a partial solution for you.

 - Alex

-------------------->8-------------------- #!/usr/bin/perl

use strict; use warnings; use constant EMAIL_DOMAIN => "example.com";

setenv( get_user($$) ); exec("/usr/bin/git", @ARGV);

sub setenv {
    my $user = shift;
    # If they're _really_ _really_ root, just bail now
    return if $user eq "root";
    # Ditto if we can't find the user (?!)
    my @getpw = getpwnam($user);
    return unless @getpw;
    my $name;
    my $email;
    # See if we can pull from the user's config
    my $gitconfig = "$getpw[7]/.gitconfig";
    if (-r $gitconfig) {
        $name  = `/usr/bin/git config --file $gitconfig user.name`;
        chomp $name;
        $email = `/usr/bin/git config --file $gitconfig user.email`;
        chomp $email;
    }
    # Fall back to getent
    $name  ||= $getpw[6] || $user;
    $email ||= $user . '@' . EMAIL_DOMAIN;
    $ENV{GIT_AUTHOR_NAME} = $name;
    $ENV{GIT_AUTHOR_EMAIL} = $email;
}
sub get_user {
    my $pid = shift;
    # See if the PID is bogus
    return "root" unless $pid and kill 0, $pid;
    # Pull out the env from it
    my %env = getenv($pid);
    # Simplest case -- check USER first
    if ($env{USER} and $env{USER} ne "root") {
        return $env{USER};
    }
    # Or we're running under sudo
    if ($env{SUDO_USER} and $env{SUDO_USER} ne "root") {
        return $env{SUDO_USER};
    }
    # They did something like `sudo su -`
    return get_user(parent_pid($pid));
}
sub getenv {
    my $pid = shift;
    my $env = do {local @ARGV = ("/proc/$pid/environ"); local $/; <>};
    my @lines = split /\0/, $env;
    return () unless grep {/=/} @lines;
    my %env = map {split /=/, $_, 2} @lines;
    return %env;
}
sub parent_pid {
    my $pid = shift;
    my $stat = do {local @ARGV = ("/proc/$pid/stat"); local $/; <>};
    my (undef, undef, undef, $ppid) = split ' ', $stat;
    return $ppid;
}
-- 
Networking -- only one letter away from not working
Previous: Nick
Message 2 of 2 in “avoiding anonymous commits from root/shared accounts”
  1. NickMay 10, 2010
  2. Alex VandiverMay 10, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.