Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
609bea29
Commit
609bea29
authored
Sep 28, 2018
by
Ash McKenzie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use .netrc over credentials in URL
parent
818177da
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
74 additions
and
36 deletions
+74
-36
qa/qa/git/repository.rb
qa/qa/git/repository.rb
+70
-28
qa/spec/git/repository_spec.rb
qa/spec/git/repository_spec.rb
+4
-8
No files found.
qa/qa/git/repository.rb
View file @
609bea29
...
...
@@ -3,14 +3,22 @@
require
'cgi'
require
'uri'
require
'open3'
require
'fileutils'
require
'tmpdir'
module
QA
module
Git
class
Repository
include
Scenario
::
Actable
attr_writer
:password
attr_accessor
:env_vars
def
initialize
@ssh_cmd
=
""
# We set HOME to the current working directory (which is a
# temporary directory created in .perform()) so the temporarily dropped
# .netrc can be utilised
self
.
env_vars
=
[
%Q{HOME="
#{
File
.
dirname
(
netrc_file_path
)
}
"}
]
end
def
self
.
perform
(
*
args
)
...
...
@@ -23,14 +31,9 @@ module QA
@uri
=
URI
(
address
)
end
def
username
=
(
name
)
@username
=
name
uri
.
user
=
name
end
def
password
=
(
pass
)
@password
=
pass
uri
.
password
=
CGI
.
escape
(
pass
).
gsub
(
'+'
,
'%20'
)
def
username
=
(
username
)
@username
=
username
@uri
.
user
=
username
end
def
use_default_credentials
...
...
@@ -41,10 +44,12 @@ module QA
self
.
username
=
Runtime
::
User
.
username
self
.
password
=
Runtime
::
User
.
password
end
add_credentials_to_netrc
unless
ssh_key_set?
end
def
clone
(
opts
=
''
)
run
_and_redact_credentials
(
build_git_command
(
"git clone
#{
opts
}
#{
uri
}
./"
)
)
run
(
"git clone
#{
opts
}
#{
uri
}
./"
)
end
def
checkout
(
branch_name
)
...
...
@@ -60,12 +65,10 @@ module QA
end
def
configure_identity
(
name
,
email
)
`git config user.name
#{
name
}
`
`git config user.email
#{
email
}
`
end
run
(
%Q{git config user.name
#{
name
}
}
)
run
(
%Q{git config user.email
#{
email
}
}
)
def
configure_ssh_command
(
command
)
@ssh_cmd
=
"GIT_SSH_COMMAND='
#{
command
}
'"
add_credentials_to_netrc
end
def
commit_file
(
name
,
contents
,
message
)
...
...
@@ -84,9 +87,7 @@ module QA
end
def
push_changes
(
branch
=
'master'
)
output
,
_
=
run_and_redact_credentials
(
build_git_command
(
"git push
#{
uri
}
#{
branch
}
"
))
output
run
(
"git push
#{
uri
}
#{
branch
}
"
)
end
def
commits
...
...
@@ -104,28 +105,69 @@ module QA
keyscan_params
<<
uri
.
host
run_and_redact_credentials
(
"ssh-keyscan
#{
keyscan_params
.
join
(
' '
)
}
>>
#{
known_hosts_file
.
path
}
"
)
configure_ssh_command
(
"ssh -i
#{
private_key_file
.
path
}
-o UserKnownHostsFile=
#{
known_hosts_file
.
path
}
"
)
self
.
env_vars
<<
%Q{GIT_SSH_COMMAND="ssh -i
#{
private_key_file
.
path
}
-o UserKnownHostsFile=
#{
known_hosts_file
.
path
}
"}
end
def
delete_ssh_key
return
unless
private_key_file
return
unless
ssh_key_set?
private_key_file
.
close
(
true
)
known_hosts_file
.
close
(
true
)
end
def
build_git_command
(
command_str
)
[
ssh_cmd
,
command_str
].
compact
.
join
(
' '
)
private
attr_reader
:uri
,
:username
,
:password
,
:known_hosts_file
,
:private_key_file
def
debug?
Runtime
::
Env
.
respond_to?
(
:verbose?
)
&&
Runtime
::
Env
.
verbose?
end
private
def
ssh_key_set?
!
private_key_file
.
nil?
end
def
run
(
command_str
)
command
=
[
env_vars
,
command_str
,
'2>&1'
].
compact
.
join
(
' '
)
warn
"DEBUG: command=[
#{
command
}
]"
if
debug?
output
,
_
=
Open3
.
capture2
(
command
)
output
=
output
.
chomp
.
gsub
(
/\s+$/
,
''
)
warn
"DEBUG: output=[
#{
output
}
]"
if
debug?
output
end
def
tmp_netrc_directory
@tmp_netrc_directory
||=
File
.
join
(
Dir
.
tmpdir
,
"qa-netrc-credentials"
,
$$
.
to_s
)
end
def
netrc_file_path
@netrc_file_path
||=
File
.
join
(
tmp_netrc_directory
,
'.netrc'
)
end
def
netrc_content
"machine
#{
uri
.
host
}
login
#{
username
}
password
#{
password
}
"
end
def
netrc_already_contains_content?
File
.
exist?
(
netrc_file_path
)
&&
File
.
readlines
(
netrc_file_path
).
grep
(
/^
#{
netrc_content
}
$/
).
any?
end
attr_reader
:uri
,
:username
,
:password
,
:ssh_cmd
,
:known_hosts_file
,
:private_key_file
def
add_credentials_to_netrc
# Despite libcurl supporting a custom .netrc location through the
# CURLOPT_NETRC_FILE environment variable, git does not support it :(
# Info: https://curl.haxx.se/libcurl/c/CURLOPT_NETRC_FILE.html
#
# This will create a .netrc in the correct working directory, which is
# a temporary directory created in .perform()
#
return
if
netrc_already_contains_content?
# Since the remote URL contains the credentials, and git occasionally
# outputs the URL. Note that stderr is redirected to stdout.
def
run_and_redact_credentials
(
command
)
Open3
.
capture2
(
"
#{
command
}
2>&1 | sed -E 's#://[^@]+@#://****@#g'"
)
FileUtils
.
mkdir_p
(
tmp_netrc_directory
)
File
.
open
(
netrc_file_path
,
'a'
)
{
|
file
|
file
.
puts
(
netrc_content
)
}
File
.
chmod
(
0600
,
netrc_file_path
)
end
end
end
...
...
qa/spec/git/repository_spec.rb
View file @
609bea29
...
...
@@ -8,10 +8,8 @@ describe QA::Git::Repository do
end
describe
'#clone'
do
it
'redacts credentials from the URI in output'
do
output
,
_
=
repository
.
clone
expect
(
output
).
to
include
(
"fatal: unable to access 'http://****@foo/bar.git/'"
)
it
'is unable to resolve host'
do
expect
(
repository
.
clone
).
to
include
(
"fatal: unable to access 'http://root@foo/bar.git/'"
)
end
end
...
...
@@ -20,10 +18,8 @@ describe QA::Git::Repository do
`git init`
# need a repo to push from
end
it
'redacts credentials from the URI in output'
do
output
,
_
=
repository
.
push_changes
expect
(
output
).
to
include
(
"error: failed to push some refs to 'http://****@foo/bar.git'"
)
it
'fails to push changes'
do
expect
(
repository
.
push_changes
).
to
include
(
"error: failed to push some refs to 'http://root@foo/bar.git'"
)
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment