Skip to content

Commit

Permalink
Add support for git https credentials
Browse files Browse the repository at this point in the history
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
  • Loading branch information
NikolausDemmel committed Aug 5, 2016
1 parent 743cf01 commit 8b7587a
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 4 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
!index.js
!ONVAULT
!package.json
!credentials
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
FROM mhart/alpine-node:0.10

RUN mkdir -p /vault /usr/src/app
RUN mkdir -p /vault /vault/store /usr/src/app

WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app/
RUN ln -s /usr/src/app/credentials /usr/bin/credentials

EXPOSE 3000
VOLUME /vault
Expand Down
35 changes: 32 additions & 3 deletions ONVAULT
Original file line number Diff line number Diff line change
Expand Up @@ -47,31 +47,60 @@ if curl -s "${VAULT_URI}/_ping"; then
cp -r ~/.ssh/* $tmp_ssh_vault
fi

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

log "Using ssh key: $VAULT_SSH_KEY"
if [ ! -f ~/.ssh/$VAULT_SSH_KEY ]; then
log "Did not find ssh key: $VAULT_SSH_KEY"
else
log "Using ssh key: $VAULT_SSH_KEY"
fi
if [[ "$VAULT_SSH_KEY" != "id_rsa" ]]; then
# configure the ssh to any host to use this ssh key
echo -e "\nHost *\nIdentityFile ~/.ssh/$VAULT_SSH_KEY" >> ~/.ssh/config
fi

# download git credential store to temporary location
tmp_git_credential_store=`mktemp ~/.git-credentials-XXXXXX`
curl -s "${VAULT_URI}/git-credentials" > "$tmp_git_credential_store"

# check number of credentials (== non-blank lines) for seeing if something is wrong
credential_count=`cat "$tmp_git_credential_store" | sed '/^\s*$/d' | wc -l`
if [ $credential_count -eq 0 ]; then
log "Did not find any git https credentials"
else
log "Using $credential_count git https credential(s)"
fi

# configure git
git_config_old_credential_helper=`git config --global credential.helper` || true
git_config_old_core_askpass=`git config --global core.askpass` || true
git config --global credential.helper "store --file=$tmp_git_credential_store"
git config --global core.askpass true

# restore 'no_proxy' for executing the actual command
export no_proxy="$no_proxy_old"

log "Executing command: $@"
eval $@

log "Removing private keys..."
log "Removing private keys and git credentials..."
rm -rf ~/.ssh/*

# copying backup to ssh directory
if [[ -n "$ssh_backup_enabled" ]]; then
cp -r $tmp_ssh_vault/* ~/.ssh
rm -rf $tmp_ssh_vault
fi

rm $tmp_git_credential_store

# restoring old setting
git config --global credential.helper "$git_config_old_credential_helper"
git config --global core.askpass "$git_config_old_core_askpass"

else
log "ERROR: Start the dockito/vault container before using ONVAULT!"
log "ex: docker run -d -p ${VAULT_HOST}:14242:3000 -v ~/.ssh:/vault/.ssh dockito/vault"
Expand Down
127 changes: 127 additions & 0 deletions credentials
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/bin/sh

# allow overriding location of credential store
: ${CREDENTIALFILE:=/vault/store/git-credentials}

usage () {
echo "Usage:
$(basename $0) set URL
$(basename $0) remove URL
$(basename $0) list
$(basename $0) clear
Examples:
$(basename $0) set github.com
$(basename $0) set gitlab.com/foo/bar
$(basename $0) remove github.com
"
}

# parse arguments
while [ $# -ge 1 ]; do
case "$1" in
set|remove)
if [ $# -eq 2 ]; then
CMD="credentials_$1 $2"
shift
fi
break
;;
list|clear)
CMD="credentials_$1"
break
;;
-h|--help)
usage
exit 0
;;
*)
usage
exit 1
;;
esac

shift
done

if [ $# -ne 1 ] || [ -z "$CMD" ]; then
usage
exit 1
fi

# helper to url-encode username and password using javascript
# proper escaping for username & password, see: https://gist.github.com/pierrevalade/6025241
encodeurl () {
node <<EOF
var escape = function(str) {
return encodeURIComponent(str).replace(/[!*()']/g, function(character) {
return '%' + character.charCodeAt(0).toString(16);
});
};
console.log(escape('$1'))
EOF
}

mask_passwords () {
# replace passwords with ****** and discard non-matching lines
sed -n 's|^\(.*://.*:\)\(.*\)\(@.*\)$|\1******\3|p'
}

credentials_remove () {
# remove leading https://
URL="$( echo "$1" | sed -e 's#^.*://##' )"

# remove existing entry
matching=`grep "@$URL\$" "$CREDENTIALFILE" 2>/dev/null`
if [ -n "$matching" ]; then
tempfile=`mktemp -t git-credentials-XXXXXX`
grep -v "@$URL\$" "$CREDENTIALFILE" > "$tempfile"
mv "$tempfile" "$CREDENTIALFILE"
else
echo "No credentials for '$URL'"
exit 1
fi
}

credentials_set () {
# remove leading https://
URL="$( echo "$1" | sed -e 's#^.*://##' )"

# remove existing entry
matching=`grep "@$URL\$" "$CREDENTIALFILE" 2>/dev/null`
if [ -n "$matching" ]; then
echo "Removing existing entries:"
echo "$matching" | mask_passwords
read -p "Continue? [yN]: " CONFIRM
if ! [ "$CONFIRM" = "y" ]; then
exit 1
fi
credentials_remove $URL
echo ""
fi

echo "Adding credentials for 'https://$URL'."
read -p "Username: " USER
read -p "Password: " -s PASSWORD
echo ""

USER=`encodeurl "$USER"`
PASSWORD=`encodeurl "$PASSWORD"`

echo "https://$USER:$PASSWORD@$URL" >> "$CREDENTIALFILE"
chmod 600 "$CREDENTIALFILE"
}

credentials_list () {
if [ -f "$CREDENTIALFILE" ]; then
# mask passwords and sort by URL (which starts after the "@")
cat "$CREDENTIALFILE" | mask_passwords | sort -k 2 -t "@"
fi
}

credentials_clear () {
echo "" > "$CREDENTIALFILE"
}


$CMD
18 changes: 18 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var express = require('express'),
exec = require('child_process').exec,
mime = require('mime'),
path = require('path'),
touch = require("touch"),
mkdirp = require('mkdirp');


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


/**
Route to get the credenial store
*/
app.get('/git-credentials', function (req, res) {
var file = '/vault/store/git-credentials';
touch(file);
var filename = path.basename(file);
var mimetype = mime.lookup(file);

res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);

var filestream = fs.createReadStream(file);
filestream.pipe(res);
});


/**
Route to get the ONVAULT utility to be used during build
*/
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"express": "^4.12.3",
"mime": "^1.3.4",
"touch": "^1.0.0",
"mkdirp": "^0.5.1"
}
}

0 comments on commit 8b7587a

Please sign in to comment.