Skip to content

Instantly share code, notes, and snippets.

@taikedz
Last active May 24, 2018 17:40
Show Gist options
  • Save taikedz/ac16d37822b8ad525a40522518793fda to your computer and use it in GitHub Desktop.
Save taikedz/ac16d37822b8ad525a40522518793fda to your computer and use it in GitHub Desktop.
Manipulate a Java key store with a simple purpose-driven tool, rather than remember all those `keytool` options...
#!/bin/bash
# This tool has since been integrated to https://github.com/taikedz/CertMaker
set -euo pipefail
scr="$(basename "$0")"
printhelp() {
cat <<EOF
Manipulate a Java Key Store using 'keytool' (which has too many options to remember for infrequent use ...)
There are typically 3 options to $scr:
-k KEYSTORE : the keystore to operate on
-a ALIAS : the alias to use for the operation, where appropriate
-f TARGETFILE : the file that will be read from or written to, changing depending on the command
$scr generate -k KEYSTORE -a ALIAS
create a new key store, with a key alias
$scr csr -k KEYSTORE -a ALIAS -f CSRFILE
derive a CSR from the KEYSTORE from the ALIAS entry
$scr add-ca -k KEYSTORE -a ALIAS -f CACERT
add a CA certificate file CACERT to the KEYSTORE under ALIAS
$scr add-cert -k KEYSTORE -a ALIAS -f CERT
add a certificate file CERT to the KEYSTORE under ALIAS
$scr add-key -k KEYSTORE -a ALIAS -f KEYFILE
add a key file KEYFILE to the KEYSTORE under ALIAS
The key file must be either in PEM or PKCS12 format
$scr delete -k KEYSTORE -a ALIAS
delete an alias ALIAS from the KEYSTORE
$scr view -k KEYSTORE [-a ALIAS]
view the contents of the keystore, or optionally the contents under the keystore alias
EOF
}
jks:dispatch() {
action="$1"; shift
case "$action" in
generate)
jks:gen ;;
csr)
jks:csr ;;
add-ca)
jks:add:cacert ;;
add-cert)
jks:add:cert ;;
add-key)
jks:add:key ;;
delete)
jks:delete ;;
view)
jks:view ;;
*)
out:fail "Unknown action '$action'" ;;
esac
}
jks:args() {
local flag
for flag in "$@"
do
case "$flag" in
-k)
keystore="$(args:get -k "${SCRIPT_ARGS[@]}")"
;;
-f)
targetfile="$(args:get -f "${SCRIPT_ARGS[@]}")"
;;
-a)
ksalias="$(args:get -a "${SCRIPT_ARGS[@]}")"
;;
esac
done
}
jks:gen() {
jks:args -k -a || out:fail "Keystore and Alias are required"
keytool -genkey -alias "$ksalias" -keyalg RSA -keystore "$keystore" -deststoretype pkcs12
}
jks:csr() {
jks:args -k -a -f || out:fail "Keystore, Alias and Output CSR file are required"
keytool -certreq -keyalg RSA -alias "$ksalias" -keystore "$keystore" -file "$targetfile"
}
jks:add:cacert() {
jks:args -k -a -f || out:fail "Keystore, Alias and CA cert are required"
keytool -import -alias "$ksalias" -keystore "$keystore" -trustcacerts -file "$targetfile"
}
jks:add:cert() {
jks:args -k -a -f || out:fail "Keystore, Alias and Cert are required"
keytool -import -alias "$ksalias" -keystore "$keystore" -file "$targetfile"
}
jks:ensure_pkcs12() {
if [[ "$targetfile" =~ \.*\.p12 ]]; then
cat "$targetfile"
elif grep -qP "PRIVATE KEY" "$targetfile"; then
local certfile="${targetfile%.*}.cer"
[[ -f "$certfile" ]] || out:fail "You must provide the certificate file as $certfile"
openssl pkcs12 -export -inkey "$targetfile" -in "$certfile"
else
out:fail "PEM or PKCS12 file required!"
fi
}
jks:add:key() {
# Annoyingly, keytool needs a PKCS12 store for importing - it can't simply add a key
jks:args -k -a -f || out:fail "Keystore, Alias and Key file (.pem or .p12) are required"
local p12data
p12data="$(jks:ensure_pkcs12)" # Should fail on its own here if bad file
keytool -importkeystore -srckeystore <(echo "$p12data") -destkeystore "$keystore" -srcstoretype pkcs12
}
jks:delete() {
jks:args -k -a || out:fail "Keystore and Alias are required"
keytool -delete -alias "$ksalias" -keystore "$keystore"
}
jks:view() {
jks:args -k || out:fail "Keystore is required"
jks:args -a || :
if [[ -n "${ksalias:-}" ]]; then
keytool -list -alias "$ksalias" -keystore "$keystore"
else
keytool -list -keystore "$keystore"
fi
}
out:warn() {
echo -e "\033[33;1m$*\033[0m" >&2
}
out:fail() {
echo -e "\033[31;1m$*\033[0m" >&2
echo "Try running '$0 --help'"
exit 1
}
args:get() {
local get token
flag="$1" ; shift
get=false
for token in "$@"; do
if [[ "$get" = true ]]; then
echo "$token"
return 0
elif [[ "$flag" = "$token" ]]; then
get=true
continue
fi
# else, nowt
done
return 1
}
main() {
if [[ -z "$*" ]] || [[ "$*" =~ --help ]]; then
printhelp
exit
fi
SCRIPT_ARGS=("$@")
jks:dispatch "$@"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment