Last active
December 12, 2022 20:36
-
-
Save fuhry/ef95907857fec09fc1e0f0baa4429452 to your computer and use it in GitHub Desktop.
git-credential helper for zx2c4's passwordstore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Git credential helper for pass(1) (https://passwordstore.org/). | |
# To set up, first install this script into your PATH with the name `git-credential-pass`. | |
# Then, you will need to create a credential map file (see below) within your pass repository. | |
# Finally, configure git as follows: | |
# | |
# git config credential.helper pass | |
# git config credential.useHttpPath true | |
# The `pass` path to your credential map. The format is described below. Typing | |
# `pass ${CREDENTIAL_MAP_PASSOBJ}` at a shell should output the credential map | |
# to standard output. | |
CREDENTIAL_MAP_PASSOBJ=Websites/github.com/CredentialMap | |
# The format of the credential map is as follows: | |
# protocol <TAB> host <TAB> path <TAB> pass_object | |
# | |
# For example: | |
# https github.com someuser/somerepo.git Websites/github.com/PersonalAccessToken/someuser | |
# | |
# It's permitted to use `.*` in the "path" portion to match any substring. The default input | |
# validation in this script is rather strict, but you may modify the regular expressions | |
# below to allow for more complex regexps in the path if you desire. | |
# | |
# The password file must be formatted as follows: | |
# | |
# username=foo | |
# password=bar | |
# | |
# Lines that do not begin with "username=" or "password=" will not be printed back to git. | |
declare -r CREDENTIAL_PROTOCOL_REGEXP="[a-z]+" | |
declare -r CREDENTIAL_HOST_REGEXP="[a-z0-9-]+(\\.[a-z0-9-]+)*" | |
declare -r CREDENTIAL_PATH_REGEXP="[A-Za-z0-9_\\.\\*-]+(/[A-Za-z0-9\\.\\*_-]+)*" | |
declare -r CREDENTIAL_PASSOBJ_REGEXP="[A-Za-z0-9_-]+(/[A-Za-z0-9_-]+)*" | |
declare -r CREDENTIAL_LINE_REGEXP="^${CREDENTIAL_PROTOCOL_REGEXP}\\t${CREDENTIAL_HOST_REGEXP}\\t${CREDENTIAL_PATH_REGEXP}\\t${CREDENTIAL_PASSOBJ_REGEXP}$" | |
case "$1" in | |
get) | |
protocol= | |
host= | |
path= | |
while read line; do | |
if [[ "$line" =~ ^protocol=(${CREDENTIAL_PROTOCOL_REGEXP})$ ]]; then | |
protocol="${BASH_REMATCH[1]}" | |
elif [[ "$line" =~ ^host=(${CREDENTIAL_HOST_REGEXP})$ ]]; then | |
host="${BASH_REMATCH[1]}" | |
elif [[ "$line" =~ ^path=(${CREDENTIAL_PATH_REGEXP})$ ]]; then | |
path="${BASH_REMATCH[1]}" | |
else | |
echo "Invalid input line: $line" >&2 | |
exit 1 | |
fi | |
done | |
for v in protocol host path; do | |
if [ -z "${!v}" ]; then | |
echo "Invalid input: '$v' was not set" >&2 | |
exit 1 | |
fi | |
done | |
while read line; do | |
IFS="$(echo -en "\t")" read line_protocol line_host line_repo_regexp cred_name <<< "$line" | |
if [ "$protocol" = "$line_protocol" -a "$host" = "$line_host" ]; then | |
if [[ "$path" =~ ^${line_repo_regexp}$ ]]; then | |
pass "${cred_name}" | grep -E '^(username|password)=' && exit 0 | |
fi | |
fi | |
done < <(pass "${CREDENTIAL_MAP_PASSOBJ}" | grep -Px "${CREDENTIAL_LINE_REGEXP}") | |
echo "$0: No match found for protocol=${protocol} host=${host} path=${path}" >&2 | |
exit 2 | |
;; | |
store|erase) | |
# Not implemented. | |
echo "The action '$1' is not implemented." >&2 | |
exit 1 | |
;; | |
*) | |
echo "Usage: $0 (get|store|erase)" >&2 | |
echo 'See `man 1 git-credential` for details.' >&2 | |
exit 1 | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment