Skip to content

Commit 017b7c5

Browse files
committed
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
2 parents ab48bc0 + 786ef50 commit 017b7c5

File tree

7 files changed

+135
-50
lines changed

7 files changed

+135
-50
lines changed

contrib/credential/netrc/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
test:
2-
./test.pl
2+
./t-git-credential-netrc.sh
33

44
testverbose:
5-
./test.pl -d -v
5+
./t-git-credential-netrc.sh -d -v

contrib/credential/netrc/git-credential-netrc

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
use strict;
44
use warnings;
5+
use autodie;
56

67
use Getopt::Long;
78
use File::Basename;
9+
use Git;
810

9-
my $VERSION = "0.1";
11+
my $VERSION = "0.2";
1012

1113
my %options = (
1214
help => 0,
@@ -54,6 +56,7 @@ GetOptions(\%options,
5456
"insecure|k",
5557
"verbose|v",
5658
"file|f=s@",
59+
'gpg|g:s',
5760
);
5861

5962
if ($options{help}) {
@@ -62,27 +65,31 @@ if ($options{help}) {
6265

6366
print <<EOHIPPUS;
6467
65-
$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
68+
$0 [(-f <authfile>)...] [-g <program>] [-d] [-v] [-k] get
6669
6770
Version $VERSION by tzz\@lifelogs.com. License: BSD.
6871
6972
Options:
7073
71-
-f|--file AUTHFILE : specify netrc-style files. Files with the .gpg extension
72-
will be decrypted by GPG before parsing. Multiple -f
73-
arguments are OK. They are processed in order, and the
74-
first matching entry found is returned via the credential
75-
helper protocol (see below).
74+
-f|--file <authfile>: specify netrc-style files. Files with the .gpg
75+
extension will be decrypted by GPG before parsing.
76+
Multiple -f arguments are OK. They are processed in
77+
order, and the first matching entry found is returned
78+
via the credential helper protocol (see below).
7679
77-
When no -f option is given, .authinfo.gpg, .netrc.gpg,
78-
.authinfo, and .netrc files in your home directory are used
79-
in this order.
80+
When no -f option is given, .authinfo.gpg, .netrc.gpg,
81+
.authinfo, and .netrc files in your home directory are
82+
used in this order.
8083
81-
-k|--insecure : ignore bad file ownership or permissions
84+
-g|--gpg <program> : specify the program for GPG. By default, this is the
85+
value of gpg.program in the git repository or global
86+
option or gpg.
8287
83-
-d|--debug : turn on debugging (developer info)
88+
-k|--insecure : ignore bad file ownership or permissions
8489
85-
-v|--verbose : be more verbose (show files and information found)
90+
-d|--debug : turn on debugging (developer info)
91+
92+
-v|--verbose : be more verbose (show files and information found)
8693
8794
To enable this credential helper:
8895
@@ -99,8 +106,9 @@ in the path.)
99106
100107
git config credential.helper '$shortname -f AUTHFILE -v'
101108
102-
Only "get" mode is supported by this credential helper. It opens every AUTHFILE
103-
and looks for the first entry that matches the requested search criteria:
109+
Only "get" mode is supported by this credential helper. It opens every
110+
<authfile> and looks for the first entry that matches the requested search
111+
criteria:
104112
105113
'port|protocol':
106114
The protocol that will be used (e.g., https). (protocol=X)
@@ -120,7 +128,7 @@ host=github.com
120128
protocol=https
121129
username=tzz
122130
123-
this credential helper will look for the first entry in every AUTHFILE that
131+
this credential helper will look for the first entry in every <authfile> that
124132
matches
125133
126134
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
137145
back to "protocol". Any redundant entry tokens (part of the original query) are
138146
skipped.
139147
140-
Again, note that only the first matching entry from all the AUTHFILEs, processed
141-
in the sequence given on the command line, is used.
148+
Again, note that only the first matching entry from all the <authfile>s,
149+
processed in the sequence given on the command line, is used.
142150
143151
Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
144152
@@ -152,7 +160,7 @@ EOHIPPUS
152160
my $mode = shift @ARGV;
153161

154162
# Credentials must get a parameter, so die if it's missing.
155-
die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
163+
die "Syntax: $0 [(-f <authfile>)...] [-d] get" unless defined $mode;
156164

157165
# Only support 'get' mode; with any other unsupported ones we just exit.
158166
exit 0 unless $mode eq 'get';
@@ -172,6 +180,8 @@ unless (scalar @$files) {
172180
$files = $options{file} = [ map { glob $_ } @candidates ];
173181
}
174182

183+
load_config(\%options);
184+
175185
my $query = read_credential_data_from_stdin();
176186

177187
FILE:
@@ -233,7 +243,7 @@ sub load_netrc {
233243

234244
my $io;
235245
if ($gpgmode) {
236-
my @cmd = (qw(gpg --decrypt), $file);
246+
my @cmd = ($options{'gpg'}, qw(--decrypt), $file);
237247
log_verbose("Using GPG to open $file: [@cmd]");
238248
open $io, "-|", @cmd;
239249
} else {
@@ -410,6 +420,14 @@ sub print_credential_data {
410420
printf "%s=%s\n", $git_token, $entry->{$git_token};
411421
}
412422
}
423+
sub load_config {
424+
# load settings from git config
425+
my $options = shift;
426+
# set from command argument, gpg.program option, or default to gpg
427+
$options->{'gpg'} //= Git->repository()->config('gpg.program')
428+
// 'gpg';
429+
log_verbose("using $options{'gpg'} for GPG operations");
430+
}
413431
sub log_verbose {
414432
return unless $options{verbose};
415433
printf STDERR @_;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/sh
2+
(
3+
cd ../../../t
4+
test_description='git-credential-netrc'
5+
. ./test-lib.sh
6+
7+
if ! test_have_prereq PERL; then
8+
skip_all='skipping perl interface tests, perl not available'
9+
test_done
10+
fi
11+
12+
perl -MTest::More -e 0 2>/dev/null || {
13+
skip_all="Perl Test::More unavailable, skipping test"
14+
test_done
15+
}
16+
17+
# set up test repository
18+
19+
test_expect_success \
20+
'set up test repository' \
21+
'git config --add gpg.program test.git-config-gpg'
22+
23+
# The external test will outputs its own plan
24+
test_external_has_tap=1
25+
26+
test_external \
27+
'git-credential-netrc' \
28+
perl "$TEST_DIRECTORY"/../contrib/credential/netrc/test.pl
29+
30+
test_done
31+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
echo machine command-option-gpg login username password password
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
echo machine git-config-gpg login username password password

contrib/credential/netrc/test.netrc.gpg

Whitespace-only changes.

contrib/credential/netrc/test.pl

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,115 @@
11
#!/usr/bin/perl
2+
use lib (split(/:/, $ENV{GITPERLLIB}));
23

34
use warnings;
45
use strict;
5-
use Test;
6+
use Test::More qw(no_plan);
7+
use File::Basename;
8+
use File::Spec::Functions qw(:DEFAULT rel2abs);
69
use IPC::Open2;
710

8-
BEGIN { plan tests => 15 }
11+
BEGIN {
12+
# t-git-credential-netrc.sh kicks off our testing, so we have to go
13+
# from there.
14+
Test::More->builder->current_test(1);
15+
Test::More->builder->no_ending(1);
16+
}
917

1018
my @global_credential_args = @ARGV;
11-
my $netrc = './test.netrc';
12-
print "# Testing insecure file, nothing should be found\n";
19+
my $scriptDir = dirname rel2abs $0;
20+
my ($netrc, $netrcGpg, $gcNetrc) = map { catfile $scriptDir, $_; }
21+
qw(test.netrc
22+
test.netrc.gpg
23+
git-credential-netrc);
24+
local $ENV{PATH} = join ':'
25+
, $scriptDir
26+
, $ENV{PATH}
27+
? $ENV{PATH}
28+
: ();
29+
30+
diag "Testing insecure file, nothing should be found\n";
1331
chmod 0644, $netrc;
1432
my $cred = run_credential(['-f', $netrc, 'get'],
1533
{ host => 'github.com' });
1634

17-
ok(scalar keys %$cred, 0, "Got 0 keys from insecure file");
35+
ok(scalar keys %$cred == 0, "Got 0 keys from insecure file");
1836

19-
print "# Testing missing file, nothing should be found\n";
37+
diag "Testing missing file, nothing should be found\n";
2038
chmod 0644, $netrc;
2139
$cred = run_credential(['-f', '///nosuchfile///', 'get'],
2240
{ host => 'github.com' });
2341

24-
ok(scalar keys %$cred, 0, "Got 0 keys from missing file");
42+
ok(scalar keys %$cred == 0, "Got 0 keys from missing file");
2543

2644
chmod 0600, $netrc;
2745

28-
print "# Testing with invalid data\n";
46+
diag "Testing with invalid data\n";
2947
$cred = run_credential(['-f', $netrc, 'get'],
3048
"bad data");
31-
ok(scalar keys %$cred, 4, "Got first found keys with bad data");
49+
ok(scalar keys %$cred == 4, "Got first found keys with bad data");
3250

33-
print "# Testing netrc file for a missing corovamilkbar entry\n";
51+
diag "Testing netrc file for a missing corovamilkbar entry\n";
3452
$cred = run_credential(['-f', $netrc, 'get'],
3553
{ host => 'corovamilkbar' });
3654

37-
ok(scalar keys %$cred, 0, "Got no corovamilkbar keys");
55+
ok(scalar keys %$cred == 0, "Got no corovamilkbar keys");
3856

39-
print "# Testing netrc file for a github.com entry\n";
57+
diag "Testing netrc file for a github.com entry\n";
4058
$cred = run_credential(['-f', $netrc, 'get'],
4159
{ host => 'github.com' });
4260

43-
ok(scalar keys %$cred, 2, "Got 2 Github keys");
61+
ok(scalar keys %$cred == 2, "Got 2 Github keys");
4462

45-
ok($cred->{password}, 'carolknows', "Got correct Github password");
46-
ok($cred->{username}, 'carol', "Got correct Github username");
63+
is($cred->{password}, 'carolknows', "Got correct Github password");
64+
is($cred->{username}, 'carol', "Got correct Github username");
4765

48-
print "# Testing netrc file for a username-specific entry\n";
66+
diag "Testing netrc file for a username-specific entry\n";
4967
$cred = run_credential(['-f', $netrc, 'get'],
5068
{ host => 'imap', username => 'bob' });
5169

52-
ok(scalar keys %$cred, 2, "Got 2 username-specific keys");
70+
ok(scalar keys %$cred == 2, "Got 2 username-specific keys");
5371

54-
ok($cred->{password}, 'bobwillknow', "Got correct user-specific password");
55-
ok($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
72+
is($cred->{password}, 'bobwillknow', "Got correct user-specific password");
73+
is($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
5674

57-
print "# Testing netrc file for a host:port-specific entry\n";
75+
diag "Testing netrc file for a host:port-specific entry\n";
5876
$cred = run_credential(['-f', $netrc, 'get'],
5977
{ host => 'imap2:1099' });
6078

61-
ok(scalar keys %$cred, 2, "Got 2 host:port-specific keys");
79+
ok(scalar keys %$cred == 2, "Got 2 host:port-specific keys");
6280

63-
ok($cred->{password}, 'tzzknow', "Got correct host:port-specific password");
64-
ok($cred->{username}, 'tzz', "Got correct host:port-specific username");
81+
is($cred->{password}, 'tzzknow', "Got correct host:port-specific password");
82+
is($cred->{username}, 'tzz', "Got correct host:port-specific username");
6583

66-
print "# Testing netrc file that 'host:port kills host' entry\n";
84+
diag "Testing netrc file that 'host:port kills host' entry\n";
6785
$cred = run_credential(['-f', $netrc, 'get'],
6886
{ host => 'imap2' });
6987

70-
ok(scalar keys %$cred, 2, "Got 2 'host:port kills host' keys");
88+
ok(scalar keys %$cred == 2, "Got 2 'host:port kills host' keys");
89+
90+
is($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
91+
is($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
92+
93+
diag 'Testing netrc file decryption by git config gpg.program setting\n';
94+
$cred = run_credential( ['-f', $netrcGpg, 'get']
95+
, { host => 'git-config-gpg' }
96+
);
97+
98+
ok(scalar keys %$cred == 2, 'Got keys decrypted by git config option');
99+
100+
diag 'Testing netrc file decryption by gpg option\n';
101+
$cred = run_credential( ['-f', $netrcGpg, '-g', 'test.command-option-gpg', 'get']
102+
, { host => 'command-option-gpg' }
103+
);
71104

72-
ok($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
73-
ok($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
105+
ok(scalar keys %$cred == 2, 'Got keys decrypted by command option');
74106

75107
sub run_credential
76108
{
77109
my $args = shift @_;
78110
my $data = shift @_;
79111
my $pid = open2(my $chld_out, my $chld_in,
80-
'./git-credential-netrc', @global_credential_args,
112+
$gcNetrc, @global_credential_args,
81113
@$args);
82114

83115
die "Couldn't open pipe to netrc credential helper: $!" unless $pid;

0 commit comments

Comments
 (0)