Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save turboBasic/de780d3103bdc89ed36ef13bbbfb5b41 to your computer and use it in GitHub Desktop.
Save turboBasic/de780d3103bdc89ed36ef13bbbfb5b41 to your computer and use it in GitHub Desktop.
create Lastpass groups and items using CLI client

Helpers for Lastpass CLI client (lpass)

Wrap operations related to creation of accounts in nested Lastpass folders (groups). Those operations have always been tricky in lpass because of cumbersome path separator (\) and shell escaping rules

lpass-add

Creates item with complex path eg. Folder1\Folder2/item.name. Creates parent folder objects if required.

Examples

lpass-add 'folder1\folder2/item.name' 'folder3\folder4/'

lpass-add-group

Create folder, also referred to as group in Lastpass documentation terms.

Examples

lpass-add 'folder1\folder2\folder3/'

#!/usr/bin/env bash
main() {
declare -a REMAINING_ARGS
parseArgs REMAINING_ARGS "$@"
set -- "${REMAINING_ARGS[@]}"
while (( $# > 0 )); do
local leaf=${1#*/}
[ "$leaf" = "$1" ] && leaf=
readarray -td '' pathItems < <(
awk '{ gsub(/\\/, "\0"); print; }' <<< "${1%/$leaf}"'\'
)
unset 'pathItems[-1]'
local i currentPath
for i in "${pathItems[@]}"; do
currentPath="${currentPath}${currentPath:+\\}${i}"
lpass-add-group "$currentPath/"
done
if [ -n "$leaf" ]; then
addLeaf "$currentPath/$leaf"
fi
shift
unset pathItems currentPath i leaf
done
}
addLeaf() {
{
printf 'Name: %s\n' "$1"
printf "URL: http://example.com\n"
printf "Username:\n"
printf "Password:\n"
printf "Notes:\n"
} \
| lpass add --sync now --non-interactive "$1"
waitNewId "$1"
}
waitNewId() {
local id=0
while [ "$id" = 0 ]; do
sleep 0.25
id=$(lpass show --sync now --id --quiet "$1")
done
echo $id
}
parseArgs() {
getopt --test &> /dev/null
if [ $? -ne 4 ]; then
die 'getopt from util-linux package is missing'
fi
declare -n varNameForArguments=${1?}
shift
local opts
opts=$(getopt --longoptions 'notes:,password:,url:,username:' --options '' --name "$NAME" -- "$@")
if [ $? -ne 0 ]; then
die 'getopt failed...'
fi
eval set -- "$opts"
while true; do
case "$1" in
'--notes')
LP_NOTES=$2
shift 2
continue
;;
'--password')
LP_PASSWORD=$2
shift 2
continue
;;
'--url')
LP_URL=$2
shift 2
continue
;;
'--username')
LP_USERNAME=$2
shift 2
continue
;;
'--')
shift
break
;;
*)
die 'Internal error'
;;
esac
done
varNameForArguments=( "$@" )
}
usage() {
cat <<-EOF
Usage:
$(basename $0) GROUP_NAME
EOF
}
die() {
printf '[%s] ERROR: %s\n' "$NAME" "$1"
shift
if [ $# -gt 0 ]; then
printf '\n%s\n' "$*"
fi
exit 1
}
LP_FOLDER=
LP_ITEM=
LP_NOTES=
LP_URL=
LP_USERNAME=
LP_PASSWORD=
NAME=$(basename "$0")
main "$@"
#!/usr/bin/env bash
main() {
{
printf "Name: %s/\n" "$1"
printf "URL: http://group\n"
printf "Username:\n"
printf "Password:\n"
printf "Notes:\n"
} \
| lpass add --sync=now --non-interactive "$1/" &> /dev/null
if [ $? -ne 0 ]; then
die 'lpass call failed' "$(usage)" 1>&2
fi
waitNewId "$1/"
}
waitNewId() {
local id=0
while [ "$id" = 0 ]; do
sleep 0.25
id=$(lpass show --sync now --id --quiet "$1")
done
echo $id
}
usage() {
cat <<-EOF
Usage:
$(basename $0) GROUP_NAME
EOF
}
die() {
printf '[%s] ERROR: %s\n' "$NAME" "$1"
shift
if [ $# -gt 0 ]; then
printf '\n%s\n' "$*"
fi
exit 1
}
NAME=$(basename "$0")
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment