Merge branch 'lm/credential-netrc'
Update credential-netrc helper (in contrib/) to allow customizing the GPG used to decrypt the encrypted .netrc file. * lm/credential-netrc: git-credential-netrc: accept gpg option git-credential-netrc: adapt to test framework for git
This commit is contained in:
commit
017b7c52fc
@ -1,5 +1,5 @@
|
||||
test:
|
||||
./test.pl
|
||||
./t-git-credential-netrc.sh
|
||||
|
||||
testverbose:
|
||||
./test.pl -d -v
|
||||
./t-git-credential-netrc.sh -d -v
|
||||
|
@ -2,11 +2,13 @@
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use autodie;
|
||||
|
||||
use Getopt::Long;
|
||||
use File::Basename;
|
||||
use Git;
|
||||
|
||||
my $VERSION = "0.1";
|
||||
my $VERSION = "0.2";
|
||||
|
||||
my %options = (
|
||||
help => 0,
|
||||
@ -54,6 +56,7 @@ GetOptions(\%options,
|
||||
"insecure|k",
|
||||
"verbose|v",
|
||||
"file|f=s@",
|
||||
'gpg|g:s',
|
||||
);
|
||||
|
||||
if ($options{help}) {
|
||||
@ -62,21 +65,25 @@ if ($options{help}) {
|
||||
|
||||
print <<EOHIPPUS;
|
||||
|
||||
$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
|
||||
$0 [(-f <authfile>)...] [-g <program>] [-d] [-v] [-k] get
|
||||
|
||||
Version $VERSION by tzz\@lifelogs.com. License: BSD.
|
||||
|
||||
Options:
|
||||
|
||||
-f|--file AUTHFILE : specify netrc-style files. Files with the .gpg extension
|
||||
will be decrypted by GPG before parsing. Multiple -f
|
||||
arguments are OK. They are processed in order, and the
|
||||
first matching entry found is returned via the credential
|
||||
helper protocol (see below).
|
||||
-f|--file <authfile>: specify netrc-style files. Files with the .gpg
|
||||
extension will be decrypted by GPG before parsing.
|
||||
Multiple -f arguments are OK. They are processed in
|
||||
order, and the first matching entry found is returned
|
||||
via the credential helper protocol (see below).
|
||||
|
||||
When no -f option is given, .authinfo.gpg, .netrc.gpg,
|
||||
.authinfo, and .netrc files in your home directory are used
|
||||
in this order.
|
||||
.authinfo, and .netrc files in your home directory are
|
||||
used in this order.
|
||||
|
||||
-g|--gpg <program> : specify the program for GPG. By default, this is the
|
||||
value of gpg.program in the git repository or global
|
||||
option or gpg.
|
||||
|
||||
-k|--insecure : ignore bad file ownership or permissions
|
||||
|
||||
@ -99,8 +106,9 @@ in the path.)
|
||||
|
||||
git config credential.helper '$shortname -f AUTHFILE -v'
|
||||
|
||||
Only "get" mode is supported by this credential helper. It opens every AUTHFILE
|
||||
and looks for the first entry that matches the requested search criteria:
|
||||
Only "get" mode is supported by this credential helper. It opens every
|
||||
<authfile> and looks for the first entry that matches the requested search
|
||||
criteria:
|
||||
|
||||
'port|protocol':
|
||||
The protocol that will be used (e.g., https). (protocol=X)
|
||||
@ -120,7 +128,7 @@ host=github.com
|
||||
protocol=https
|
||||
username=tzz
|
||||
|
||||
this credential helper will look for the first entry in every AUTHFILE that
|
||||
this credential helper will look for the first entry in every <authfile> that
|
||||
matches
|
||||
|
||||
machine github.com port https login tzz
|
||||
@ -137,8 +145,8 @@ Then, the helper will print out whatever tokens it got from the entry, including
|
||||
back to "protocol". Any redundant entry tokens (part of the original query) are
|
||||
skipped.
|
||||
|
||||
Again, note that only the first matching entry from all the AUTHFILEs, processed
|
||||
in the sequence given on the command line, is used.
|
||||
Again, note that only the first matching entry from all the <authfile>s,
|
||||
processed in the sequence given on the command line, is used.
|
||||
|
||||
Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
|
||||
|
||||
@ -152,7 +160,7 @@ EOHIPPUS
|
||||
my $mode = shift @ARGV;
|
||||
|
||||
# Credentials must get a parameter, so die if it's missing.
|
||||
die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
|
||||
die "Syntax: $0 [(-f <authfile>)...] [-d] get" unless defined $mode;
|
||||
|
||||
# Only support 'get' mode; with any other unsupported ones we just exit.
|
||||
exit 0 unless $mode eq 'get';
|
||||
@ -172,6 +180,8 @@ unless (scalar @$files) {
|
||||
$files = $options{file} = [ map { glob $_ } @candidates ];
|
||||
}
|
||||
|
||||
load_config(\%options);
|
||||
|
||||
my $query = read_credential_data_from_stdin();
|
||||
|
||||
FILE:
|
||||
@ -233,7 +243,7 @@ sub load_netrc {
|
||||
|
||||
my $io;
|
||||
if ($gpgmode) {
|
||||
my @cmd = (qw(gpg --decrypt), $file);
|
||||
my @cmd = ($options{'gpg'}, qw(--decrypt), $file);
|
||||
log_verbose("Using GPG to open $file: [@cmd]");
|
||||
open $io, "-|", @cmd;
|
||||
} else {
|
||||
@ -410,6 +420,14 @@ sub print_credential_data {
|
||||
printf "%s=%s\n", $git_token, $entry->{$git_token};
|
||||
}
|
||||
}
|
||||
sub load_config {
|
||||
# load settings from git config
|
||||
my $options = shift;
|
||||
# set from command argument, gpg.program option, or default to gpg
|
||||
$options->{'gpg'} //= Git->repository()->config('gpg.program')
|
||||
// 'gpg';
|
||||
log_verbose("using $options{'gpg'} for GPG operations");
|
||||
}
|
||||
sub log_verbose {
|
||||
return unless $options{verbose};
|
||||
printf STDERR @_;
|
||||
|
31
contrib/credential/netrc/t-git-credential-netrc.sh
Executable file
31
contrib/credential/netrc/t-git-credential-netrc.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
(
|
||||
cd ../../../t
|
||||
test_description='git-credential-netrc'
|
||||
. ./test-lib.sh
|
||||
|
||||
if ! test_have_prereq PERL; then
|
||||
skip_all='skipping perl interface tests, perl not available'
|
||||
test_done
|
||||
fi
|
||||
|
||||
perl -MTest::More -e 0 2>/dev/null || {
|
||||
skip_all="Perl Test::More unavailable, skipping test"
|
||||
test_done
|
||||
}
|
||||
|
||||
# set up test repository
|
||||
|
||||
test_expect_success \
|
||||
'set up test repository' \
|
||||
'git config --add gpg.program test.git-config-gpg'
|
||||
|
||||
# The external test will outputs its own plan
|
||||
test_external_has_tap=1
|
||||
|
||||
test_external \
|
||||
'git-credential-netrc' \
|
||||
perl "$TEST_DIRECTORY"/../contrib/credential/netrc/test.pl
|
||||
|
||||
test_done
|
||||
)
|
2
contrib/credential/netrc/test.command-option-gpg
Executable file
2
contrib/credential/netrc/test.command-option-gpg
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
echo machine command-option-gpg login username password password
|
2
contrib/credential/netrc/test.git-config-gpg
Executable file
2
contrib/credential/netrc/test.git-config-gpg
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
echo machine git-config-gpg login username password password
|
0
contrib/credential/netrc/test.netrc.gpg
Normal file
0
contrib/credential/netrc/test.netrc.gpg
Normal file
@ -1,83 +1,115 @@
|
||||
#!/usr/bin/perl
|
||||
use lib (split(/:/, $ENV{GITPERLLIB}));
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use Test;
|
||||
use Test::More qw(no_plan);
|
||||
use File::Basename;
|
||||
use File::Spec::Functions qw(:DEFAULT rel2abs);
|
||||
use IPC::Open2;
|
||||
|
||||
BEGIN { plan tests => 15 }
|
||||
BEGIN {
|
||||
# t-git-credential-netrc.sh kicks off our testing, so we have to go
|
||||
# from there.
|
||||
Test::More->builder->current_test(1);
|
||||
Test::More->builder->no_ending(1);
|
||||
}
|
||||
|
||||
my @global_credential_args = @ARGV;
|
||||
my $netrc = './test.netrc';
|
||||
print "# Testing insecure file, nothing should be found\n";
|
||||
my $scriptDir = dirname rel2abs $0;
|
||||
my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; }
|
||||
qw(test.netrc
|
||||
test.netrc.gpg
|
||||
git-credential-netrc);
|
||||
local $ENV{PATH} = join ':'
|
||||
, $scriptDir
|
||||
, $ENV{PATH}
|
||||
? $ENV{PATH}
|
||||
: ();
|
||||
|
||||
diag "Testing insecure file, nothing should be found\n";
|
||||
chmod 0644, $netrc;
|
||||
my $cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'github.com' });
|
||||
|
||||
ok(scalar keys %$cred, 0, "Got 0 keys from insecure file");
|
||||
ok(scalar keys %$cred == 0, "Got 0 keys from insecure file");
|
||||
|
||||
print "# Testing missing file, nothing should be found\n";
|
||||
diag "Testing missing file, nothing should be found\n";
|
||||
chmod 0644, $netrc;
|
||||
$cred = run_credential(['-f', '///nosuchfile///', 'get'],
|
||||
{ host => 'github.com' });
|
||||
|
||||
ok(scalar keys %$cred, 0, "Got 0 keys from missing file");
|
||||
ok(scalar keys %$cred == 0, "Got 0 keys from missing file");
|
||||
|
||||
chmod 0600, $netrc;
|
||||
|
||||
print "# Testing with invalid data\n";
|
||||
diag "Testing with invalid data\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
"bad data");
|
||||
ok(scalar keys %$cred, 4, "Got first found keys with bad data");
|
||||
ok(scalar keys %$cred == 4, "Got first found keys with bad data");
|
||||
|
||||
print "# Testing netrc file for a missing corovamilkbar entry\n";
|
||||
diag "Testing netrc file for a missing corovamilkbar entry\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'corovamilkbar' });
|
||||
|
||||
ok(scalar keys %$cred, 0, "Got no corovamilkbar keys");
|
||||
ok(scalar keys %$cred == 0, "Got no corovamilkbar keys");
|
||||
|
||||
print "# Testing netrc file for a github.com entry\n";
|
||||
diag "Testing netrc file for a github.com entry\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'github.com' });
|
||||
|
||||
ok(scalar keys %$cred, 2, "Got 2 Github keys");
|
||||
ok(scalar keys %$cred == 2, "Got 2 Github keys");
|
||||
|
||||
ok($cred->{password}, 'carolknows', "Got correct Github password");
|
||||
ok($cred->{username}, 'carol', "Got correct Github username");
|
||||
is($cred->{password}, 'carolknows', "Got correct Github password");
|
||||
is($cred->{username}, 'carol', "Got correct Github username");
|
||||
|
||||
print "# Testing netrc file for a username-specific entry\n";
|
||||
diag "Testing netrc file for a username-specific entry\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'imap', username => 'bob' });
|
||||
|
||||
ok(scalar keys %$cred, 2, "Got 2 username-specific keys");
|
||||
ok(scalar keys %$cred == 2, "Got 2 username-specific keys");
|
||||
|
||||
ok($cred->{password}, 'bobwillknow', "Got correct user-specific password");
|
||||
ok($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
|
||||
is($cred->{password}, 'bobwillknow', "Got correct user-specific password");
|
||||
is($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
|
||||
|
||||
print "# Testing netrc file for a host:port-specific entry\n";
|
||||
diag "Testing netrc file for a host:port-specific entry\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'imap2:1099' });
|
||||
|
||||
ok(scalar keys %$cred, 2, "Got 2 host:port-specific keys");
|
||||
ok(scalar keys %$cred == 2, "Got 2 host:port-specific keys");
|
||||
|
||||
ok($cred->{password}, 'tzzknow', "Got correct host:port-specific password");
|
||||
ok($cred->{username}, 'tzz', "Got correct host:port-specific username");
|
||||
is($cred->{password}, 'tzzknow', "Got correct host:port-specific password");
|
||||
is($cred->{username}, 'tzz', "Got correct host:port-specific username");
|
||||
|
||||
print "# Testing netrc file that 'host:port kills host' entry\n";
|
||||
diag "Testing netrc file that 'host:port kills host' entry\n";
|
||||
$cred = run_credential(['-f', $netrc, 'get'],
|
||||
{ host => 'imap2' });
|
||||
|
||||
ok(scalar keys %$cred, 2, "Got 2 'host:port kills host' keys");
|
||||
ok(scalar keys %$cred == 2, "Got 2 'host:port kills host' keys");
|
||||
|
||||
ok($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
|
||||
ok($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
|
||||
is($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
|
||||
is($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
|
||||
|
||||
diag 'Testing netrc file decryption by git config gpg.program setting\n';
|
||||
$cred = run_credential( ['-f', $netrcGpg, 'get']
|
||||
, { host => 'git-config-gpg' }
|
||||
);
|
||||
|
||||
ok(scalar keys %$cred == 2, 'Got keys decrypted by git config option');
|
||||
|
||||
diag 'Testing netrc file decryption by gpg option\n';
|
||||
$cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get']
|
||||
, { host => 'command-option-gpg' }
|
||||
);
|
||||
|
||||
ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
|
||||
|
||||
sub run_credential
|
||||
{
|
||||
my $args = shift @_;
|
||||
my $data = shift @_;
|
||||
my $pid = open2(my $chld_out, my $chld_in,
|
||||
'./git-credential-netrc', @global_credential_args,
|
||||
$gcNetrc, @global_credential_args,
|
||||
@$args);
|
||||
|
||||
die "Couldn't open pipe to netrc credential helper: $!" unless $pid;
|
||||
|
Loading…
Reference in New Issue
Block a user