Skip to content

Instantly share code, notes, and snippets.

@ceelian
Last active March 21, 2025 13:42
Show Gist options
  • Save ceelian/9aacf077437c7710355c066ec351f69e to your computer and use it in GitHub Desktop.
Save ceelian/9aacf077437c7710355c066ec351f69e to your computer and use it in GitHub Desktop.
This script fetches secrets from 1Password using the provided argument (op://<vault>/<item>/<field>) to be sourced in the current shell environment.
#!/bin/sh
# ==========================================================================================================
# This shell script fetches secrets from 1Password using the provided argument (op://<vault>/<item>/<field>)
# to be sourced in the current shell environment. It requires that op cli is installed
# It should be compatible with all POSX compatible shells.
# The secret format in 1Password should be a text field with .env style format MYKEY=myval
# It validates the format of the secrets, ignoring blank lines and comments.
# Valid lines are exported as environment variables.
#
# Example Secret Format:
# MY_SECRET="pssst"
# MY_OTHER_SECRET=quotes are optional
# # Comment lines and blank lines are supported
#
# MY_THIRD_SECRET="123"
# ==========================================================================================================
# Save shell options
old_opts=$(set +o)
# disable -e for safe parsing
set +e
# Detect if the script is sourced
_sourced=1
(return 0 2>/dev/null) || _sourced=0
if [ "$_sourced" -ne 1 ]; then
echo "❌ This script must be sourced, not executed."
echo "ℹ️ Use: source $(basename "$0") op://<vault>/<item>/<field>"
return 1 2>/dev/null || exit 1
fi
# Check if the required argument is provided
if [ -z "$1" ]; then
echo "❌ Missing argument: op://<vault>/<item>/<field>"
return 1 2>/dev/null || exit 1
fi
# Check if op CLI is installed
if ! command -v op > /dev/null 2>&1; then
echo "Error: 1Password CLI (op) is not installed or not in PATH"
echo "Please install from https://1password.com/downloads/command-line/"
return 1 2>/dev/null || exit 1
fi
# Use the provided argument to fetch secrets
secrets="$(op read "$1")"
# Validate format of secret: ignore blank and comment lines starting with "#", validate only real lines
invalid_line=$(printf '%s\n' "$secrets" \
| sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//' \
| grep -vE '^$|^#' \
| grep -vE '^[A-Za-z_][A-Za-z0-9_]*=.*$')
if [ -n "$invalid_line" ]; then
echo "❌ Invalid line(s) in secret data:"
echo "$invalid_line"
return 1 2>/dev/null || exit 1
fi
# Export valid lines
while IFS= read -r line || [ -n "$line" ]; do
# Trim leading/trailing whitespace
trimmed=$(echo "$line" | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')
# Skip empty lines and comments
case "$trimmed" in
''|\#*) continue ;;
esac
key="${trimmed%%=*}"
value="${trimmed#*=}"
# Remove surrounding quotes from the value if present
value=$(echo "$value" | sed -E 's/^"(.*)"$/\1/')
if [ -n "$key" ]; then
export "$key=$value"
fi
done <<EOF
$secrets
EOF
# Restore previous shell options
eval "$old_opts"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment