Skip to content

Commit 8b7587a

Browse files
Add support for git https credentials
This implements dockito#21. It is a simple way to provide git credentials not only for ssh via keys, but also for https. In corporate settings with internet access through proxies, ssh is often not allowed and one is forced to use https. There are two ways to use this, either you provide a credential store and mount it when running `vault`. ``` docker run -p 172.17.0.1:14242:3000 -v $PWD/store:/vault/store vault ``` Alternatively you can also start the vault with an empty store and interactively add / remove credentials. ``` docker run -p 172.17.0.1:14242:3000 --name vault vault # the following prompts you for a username and password which are stored in the # running container docker exec -it vault credentials set github.com ``` The usage inside a `Dockerfile` is the same as for the ssh key. Simply prepend your `git clone` or other commands with `ONVAULT`. The changes are really fairly simple: - One route is added in `index.js` to download the file with the credentials. - ONVAULT is extended to download the additional file and configure git, as well as revert the changes after executing the passed command. - The `credential` helper script is added to the container. This is actually not essential, but more of a convenience such that you don't need to create the credential files manually. I did not yet update the README, but I can do that before merge if you are willing to include this addition. closes dockito#21
1 parent 743cf01 commit 8b7587a

File tree

6 files changed

+181
-4
lines changed

6 files changed

+181
-4
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
!index.js
33
!ONVAULT
44
!package.json
5+
!credentials

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
FROM mhart/alpine-node:0.10
22

3-
RUN mkdir -p /vault /usr/src/app
3+
RUN mkdir -p /vault /vault/store /usr/src/app
44

55
WORKDIR /usr/src/app
66
COPY package.json /usr/src/app/
77
RUN npm install
88
COPY . /usr/src/app/
9+
RUN ln -s /usr/src/app/credentials /usr/bin/credentials
910

1011
EXPOSE 3000
1112
VOLUME /vault

ONVAULT

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,60 @@ if curl -s "${VAULT_URI}/_ping"; then
4747
cp -r ~/.ssh/* $tmp_ssh_vault
4848
fi
4949

50-
log "Downloading private keys..."
50+
log "Downloading private keys and git credentials ..."
5151
curl -s "${VAULT_URI}/ssh.tgz" | tar -C ~/.ssh/ -zxf -
5252
chown -f `whoami` ~/.ssh/* || true
5353
chmod -f 600 ~/.ssh/* || true
5454

55-
log "Using ssh key: $VAULT_SSH_KEY"
55+
if [ ! -f ~/.ssh/$VAULT_SSH_KEY ]; then
56+
log "Did not find ssh key: $VAULT_SSH_KEY"
57+
else
58+
log "Using ssh key: $VAULT_SSH_KEY"
59+
fi
5660
if [[ "$VAULT_SSH_KEY" != "id_rsa" ]]; then
5761
# configure the ssh to any host to use this ssh key
5862
echo -e "\nHost *\nIdentityFile ~/.ssh/$VAULT_SSH_KEY" >> ~/.ssh/config
5963
fi
6064

65+
# download git credential store to temporary location
66+
tmp_git_credential_store=`mktemp ~/.git-credentials-XXXXXX`
67+
curl -s "${VAULT_URI}/git-credentials" > "$tmp_git_credential_store"
68+
69+
# check number of credentials (== non-blank lines) for seeing if something is wrong
70+
credential_count=`cat "$tmp_git_credential_store" | sed '/^\s*$/d' | wc -l`
71+
if [ $credential_count -eq 0 ]; then
72+
log "Did not find any git https credentials"
73+
else
74+
log "Using $credential_count git https credential(s)"
75+
fi
76+
77+
# configure git
78+
git_config_old_credential_helper=`git config --global credential.helper` || true
79+
git_config_old_core_askpass=`git config --global core.askpass` || true
80+
git config --global credential.helper "store --file=$tmp_git_credential_store"
81+
git config --global core.askpass true
82+
6183
# restore 'no_proxy' for executing the actual command
6284
export no_proxy="$no_proxy_old"
6385

6486
log "Executing command: $@"
6587
eval $@
6688

67-
log "Removing private keys..."
89+
log "Removing private keys and git credentials..."
6890
rm -rf ~/.ssh/*
6991

7092
# copying backup to ssh directory
7193
if [[ -n "$ssh_backup_enabled" ]]; then
7294
cp -r $tmp_ssh_vault/* ~/.ssh
7395
rm -rf $tmp_ssh_vault
7496
fi
97+
98+
rm $tmp_git_credential_store
99+
100+
# restoring old setting
101+
git config --global credential.helper "$git_config_old_credential_helper"
102+
git config --global core.askpass "$git_config_old_core_askpass"
103+
75104
else
76105
log "ERROR: Start the dockito/vault container before using ONVAULT!"
77106
log "ex: docker run -d -p ${VAULT_HOST}:14242:3000 -v ~/.ssh:/vault/.ssh dockito/vault"

credentials

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/sh
2+
3+
# allow overriding location of credential store
4+
: ${CREDENTIALFILE:=/vault/store/git-credentials}
5+
6+
usage () {
7+
echo "Usage:
8+
$(basename $0) set URL
9+
$(basename $0) remove URL
10+
$(basename $0) list
11+
$(basename $0) clear
12+
13+
Examples:
14+
$(basename $0) set github.com
15+
$(basename $0) set gitlab.com/foo/bar
16+
$(basename $0) remove github.com
17+
"
18+
}
19+
20+
# parse arguments
21+
while [ $# -ge 1 ]; do
22+
case "$1" in
23+
set|remove)
24+
if [ $# -eq 2 ]; then
25+
CMD="credentials_$1 $2"
26+
shift
27+
fi
28+
break
29+
;;
30+
list|clear)
31+
CMD="credentials_$1"
32+
break
33+
;;
34+
-h|--help)
35+
usage
36+
exit 0
37+
;;
38+
*)
39+
usage
40+
exit 1
41+
;;
42+
esac
43+
44+
shift
45+
done
46+
47+
if [ $# -ne 1 ] || [ -z "$CMD" ]; then
48+
usage
49+
exit 1
50+
fi
51+
52+
# helper to url-encode username and password using javascript
53+
# proper escaping for username & password, see: https://gist.github.com/pierrevalade/6025241
54+
encodeurl () {
55+
node <<EOF
56+
var escape = function(str) {
57+
return encodeURIComponent(str).replace(/[!*()']/g, function(character) {
58+
return '%' + character.charCodeAt(0).toString(16);
59+
});
60+
};
61+
console.log(escape('$1'))
62+
EOF
63+
}
64+
65+
mask_passwords () {
66+
# replace passwords with ****** and discard non-matching lines
67+
sed -n 's|^\(.*://.*:\)\(.*\)\(@.*\)$|\1******\3|p'
68+
}
69+
70+
credentials_remove () {
71+
# remove leading https://
72+
URL="$( echo "$1" | sed -e 's#^.*://##' )"
73+
74+
# remove existing entry
75+
matching=`grep "@$URL\$" "$CREDENTIALFILE" 2>/dev/null`
76+
if [ -n "$matching" ]; then
77+
tempfile=`mktemp -t git-credentials-XXXXXX`
78+
grep -v "@$URL\$" "$CREDENTIALFILE" > "$tempfile"
79+
mv "$tempfile" "$CREDENTIALFILE"
80+
else
81+
echo "No credentials for '$URL'"
82+
exit 1
83+
fi
84+
}
85+
86+
credentials_set () {
87+
# remove leading https://
88+
URL="$( echo "$1" | sed -e 's#^.*://##' )"
89+
90+
# remove existing entry
91+
matching=`grep "@$URL\$" "$CREDENTIALFILE" 2>/dev/null`
92+
if [ -n "$matching" ]; then
93+
echo "Removing existing entries:"
94+
echo "$matching" | mask_passwords
95+
read -p "Continue? [yN]: " CONFIRM
96+
if ! [ "$CONFIRM" = "y" ]; then
97+
exit 1
98+
fi
99+
credentials_remove $URL
100+
echo ""
101+
fi
102+
103+
echo "Adding credentials for 'https://$URL'."
104+
read -p "Username: " USER
105+
read -p "Password: " -s PASSWORD
106+
echo ""
107+
108+
USER=`encodeurl "$USER"`
109+
PASSWORD=`encodeurl "$PASSWORD"`
110+
111+
echo "https://$USER:$PASSWORD@$URL" >> "$CREDENTIALFILE"
112+
chmod 600 "$CREDENTIALFILE"
113+
}
114+
115+
credentials_list () {
116+
if [ -f "$CREDENTIALFILE" ]; then
117+
# mask passwords and sort by URL (which starts after the "@")
118+
cat "$CREDENTIALFILE" | mask_passwords | sort -k 2 -t "@"
119+
fi
120+
}
121+
122+
credentials_clear () {
123+
echo "" > "$CREDENTIALFILE"
124+
}
125+
126+
127+
$CMD

index.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var express = require('express'),
33
exec = require('child_process').exec,
44
mime = require('mime'),
55
path = require('path'),
6+
touch = require("touch"),
67
mkdirp = require('mkdirp');
78

89

@@ -41,6 +42,23 @@ app.get('/ssh.tgz', function (req, res) {
4142
});
4243

4344

45+
/**
46+
Route to get the credenial store
47+
*/
48+
app.get('/git-credentials', function (req, res) {
49+
var file = '/vault/store/git-credentials';
50+
touch(file);
51+
var filename = path.basename(file);
52+
var mimetype = mime.lookup(file);
53+
54+
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
55+
res.setHeader('Content-type', mimetype);
56+
57+
var filestream = fs.createReadStream(file);
58+
filestream.pipe(res);
59+
});
60+
61+
4462
/**
4563
Route to get the ONVAULT utility to be used during build
4664
*/

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dependencies": {
1313
"express": "^4.12.3",
1414
"mime": "^1.3.4",
15+
"touch": "^1.0.0",
1516
"mkdirp": "^0.5.1"
1617
}
1718
}

0 commit comments

Comments
 (0)