diff --git a/docs/git-1password-setup.md b/docs/git-1password-setup.md index 2148304..8e4d786 100644 --- a/docs/git-1password-setup.md +++ b/docs/git-1password-setup.md @@ -114,8 +114,31 @@ op signin ```bash # Test the credential helper directly echo -e "protocol=https\nhost=github.com\n" | ~/.dotfiles/scripts/git-credential-1password.sh get + +# Debug: List all 1Password items to see what's available +op item list --format=json | jq -r '.[] | "\(.title) - \(.id)"' + +# Debug: See the structure of a specific item +op item get "YOUR_ITEM_ID" --format=json | jq + +# Debug: Check what fields are available in an item +op item get "YOUR_ITEM_ID" --format=json | jq -r '.fields[] | "\(.label // .id): \(.value // "empty")"' ``` +### Common Issues + +**jq null matching errors:** + +- This happens when 1Password items have missing fields +- The updated script handles null values gracefully +- Make sure your items have proper username and password fields + +**Field naming issues:** + +- The script looks for fields with labels containing: "username", "user", "login" +- For passwords, it looks for: "password", "token", "secret", "pass" +- If your fields have different names, rename them in 1Password + ## Security Benefits - Credentials are never stored in plain text on disk diff --git a/scripts/git-credential-1password.sh b/scripts/git-credential-1password.sh index ee26a07..7f96ee2 100755 --- a/scripts/git-credential-1password.sh +++ b/scripts/git-credential-1password.sh @@ -58,18 +58,19 @@ get_credentials() { local item_uuid if ! item_uuid=$(op item list --format=json 2>/dev/null | jq -r --arg host "$search_term" ' .[] | select( - (.urls[]?.href // "" | test($host; "i")) or - (.title | test($host; "i")) or - (.additional_information | test($host; "i")) - ) | .id' | head -1); then - return 1 + ((.urls // [])[] | select(.href != null and (.href | type) == "string") | .href | test($host; "i")) or + ((.title // "") | type == "string" and test($host; "i")) or + ((.additional_information // "") | type == "string" and test($host; "i")) + ) | .id' | head -1 2>/dev/null); then + # If the complex search fails, try a simpler approach + item_uuid="" fi if [ -z "$item_uuid" ]; then - # Fallback: search by title containing the host + # Fallback: simple search by title containing the host if ! item_uuid=$(op item list --format=json 2>/dev/null | jq -r --arg host "$search_term" ' - .[] | select(.title | test($host; "i")) | .id' | head -1); then - return 1 + .[] | select((.title // "") != "" and ((.title // "") | type == "string") and ((.title // "") | test($host; "i"))) | .id' | head -1 2>/dev/null); then + item_uuid="" fi fi @@ -87,11 +88,22 @@ get_credentials() { # Extract username and password local op_username op_password - op_username=$(echo "$item_json" | jq -r '.fields[] | select(.id == "username" or .label == "username") | .value // empty' | head -1) - op_password=$(echo "$item_json" | jq -r '.fields[] | select(.id == "repo_token" or .label == "repo_token") | .value // empty' | head -1) + op_username=$(echo "$item_json" | jq -r '(.fields // [])[] | select((.id // "") == "username" or ((.label // "") | type == "string" and test("username"; "i"))) | .value // empty' | head -1 2>/dev/null) + op_password=$(echo "$item_json" | jq -r '(.fields // [])[] | select((.id // "") == "password" or ((.label // "") | type == "string" and test("password|token"; "i"))) | .value // empty' | head -1 2>/dev/null) + + # If standard fields don't work, try common field names + if [ -z "$op_username" ]; then + op_username=$(echo "$item_json" | jq -r '(.fields // [])[] | select((.label // "") | type == "string" and test("user|login"; "i")) | .value // empty' | head -1 2>/dev/null) + fi + + if [ -z "$op_password" ]; then + op_password=$(echo "$item_json" | jq -r '(.fields // [])[] | select((.label // "") | type == "string" and test("pass|token|secret"; "i")) | .value // empty' | head -1 2>/dev/null) + fi if [ -z "$op_username" ] || [ -z "$op_password" ]; then echo "Username or password not found in 1Password item" >&2 + echo "Available fields:" >&2 + echo "$item_json" | jq -r '(.fields // [])[] | " - \(.label // .id // "unknown")"' 2>/dev/null >&2 return 1 fi diff --git a/stow/bash/.bash_aliases b/stow/bash/.bash_aliases index 0a1b86b..bb9638f 100644 --- a/stow/bash/.bash_aliases +++ b/stow/bash/.bash_aliases @@ -34,3 +34,5 @@ alias update_list='sudo apt update && sudo apt list --upgradable' # Git + 1Password helpers alias test_git_1p='echo "Testing Git 1Password credential helper for github.com:" && echo -e "protocol=https\nhost=github.com\n" | ~/.dotfiles/scripts/git-credential-1password.sh get' alias op_signin='op signin' +alias op_list='op item list --format=json | jq -r ".[] | \"\(.title) - \(.id)\""' +alias op_debug_item='function _op_debug() { op item get "$1" --format=json | jq -r ".fields[] | \"\(.label // .id): \(.value // \"empty\")\""; }; _op_debug'