From e8ace12d916514b1637db9247302a4b64d0d0d2e Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:58:16 -0500 Subject: [PATCH 01/11] added github auth handling --- lib/github | 68 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/lib/github b/lib/github index 4ab6c88..2a37854 100644 --- a/lib/github +++ b/lib/github @@ -7,11 +7,11 @@ github-ssh-key-add() { local ssh_key_path="$1" local ssh_keytag="$2" - if [[ -z "$ssh_keytag" || -z "$ssh_key_path" ]]; then + if [[ -z "$ssh_keytag" || -z "$ssh_key_path" ]]; then log "Error: ssh_keytag and ssh_key_path are required." return 1 fi - + prompt "Upload public key to GitHub for auth and commit signing using Github CLI? (Y/n) " read choice choice=${choice:-Y} @@ -35,29 +35,65 @@ github-ssh-key-add() { } github-auth() { + # Check if user is logged in to GitHub + gh auth status > /dev/null 2>&1 + auth_status=$? + + if [[ $auth_status -eq 0 ]]; then + logged_in_user=$(gh auth status | grep 'account ' | awk '{print $7}') + log >&2 "GitHub CLI: Logged in as ${logged_in_user}." + + prompt " Do you want to switch to another GitHub account? (y/N)" + read -r choice - # Ensure user is logged in to GitHub with required scopes + choice=${choice:-N} - # Show GitHub login status - gh auth status 2>&1 | grep 'Logged in to github.com as' >&2 - # Give user a chance to login or re-login as a different user + if [[ $choice =~ ^[Yy]$ ]]; then + gh auth logout + gh auth login \ + --web \ + --git-protocol https \ + --scopes admin:public_key,admin:ssh_signing_key + fi + + github-check-scopes + + elif [[ $auth_status -eq 1 ]]; then + log >&2 "GitHub CLI: User is not logged in." gh auth login \ --web \ --git-protocol https \ --scopes admin:public_key,admin:ssh_signing_key - local gh_auth_token_scopes - # If user is authenticated to GitHub - if gh_auth_token_scopes=$(gh auth status | grep scopes); then - if [[ $gh_auth_token_scopes =~ 'admin:public_key' ]] && [[ $gh_auth_token_scopes =~ 'admin:ssh_signing_key' ]] ; then - log >&2 "GitHub CLI: Required scopes are available." - else - log >&2 "GitHub CLI: Necessary scopes are not available. Requesting additional scopes..." - gh auth refresh -h github.com -s admin:public_key,admin:ssh_signing_key - fi - fi + else + log >&2 "GitHub CLI: Error: gh auth status returned $auth_status" + return 1 + fi } + +github-check-scopes() { + # check scopes + if github-auth-required-scopes; then + log >&2 "GitHub CLI: Token scopes:$(gh auth status | grep 'scopes' | cut -d':' -f2-)" + else + log >&2 "GitHub CLI: Missing scopes (admin:public_key, admin:ssh_signing_key). Requesting permissions..." + gh auth refresh -h github.com -s admin:public_key,admin:ssh_signing_key + fi + +} + +github-auth-required-scopes() { + local github_auth_scopes + github_auth_scopes=$(gh auth status | grep scopes) + if [[ $github_auth_scopes =~ 'admin:public_key' ]] && [[ $github_auth_scopes =~ 'admin:ssh_signing_key' ]]; then + return 0 + else + return 1 + fi +} + + github-ssh-keys() { github-auth gh ssh-key list From f2fa70604dd11bc183f5a875ca36acfc1577c868 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:43:07 -0500 Subject: [PATCH 02/11] revert --- lib/github | 68 +++++++++++++----------------------------------------- 1 file changed, 16 insertions(+), 52 deletions(-) diff --git a/lib/github b/lib/github index 2a37854..4ab6c88 100644 --- a/lib/github +++ b/lib/github @@ -7,11 +7,11 @@ github-ssh-key-add() { local ssh_key_path="$1" local ssh_keytag="$2" - if [[ -z "$ssh_keytag" || -z "$ssh_key_path" ]]; then + if [[ -z "$ssh_keytag" || -z "$ssh_key_path" ]]; then log "Error: ssh_keytag and ssh_key_path are required." return 1 fi - + prompt "Upload public key to GitHub for auth and commit signing using Github CLI? (Y/n) " read choice choice=${choice:-Y} @@ -35,65 +35,29 @@ github-ssh-key-add() { } github-auth() { - # Check if user is logged in to GitHub - gh auth status > /dev/null 2>&1 - auth_status=$? - - if [[ $auth_status -eq 0 ]]; then - logged_in_user=$(gh auth status | grep 'account ' | awk '{print $7}') - log >&2 "GitHub CLI: Logged in as ${logged_in_user}." - - prompt " Do you want to switch to another GitHub account? (y/N)" - read -r choice - choice=${choice:-N} + # Ensure user is logged in to GitHub with required scopes - if [[ $choice =~ ^[Yy]$ ]]; then - gh auth logout - gh auth login \ - --web \ - --git-protocol https \ - --scopes admin:public_key,admin:ssh_signing_key - fi - - github-check-scopes - - elif [[ $auth_status -eq 1 ]]; then - log >&2 "GitHub CLI: User is not logged in." + # Show GitHub login status + gh auth status 2>&1 | grep 'Logged in to github.com as' >&2 + # Give user a chance to login or re-login as a different user gh auth login \ --web \ --git-protocol https \ --scopes admin:public_key,admin:ssh_signing_key - else - log >&2 "GitHub CLI: Error: gh auth status returned $auth_status" - return 1 - fi -} - - -github-check-scopes() { - # check scopes - if github-auth-required-scopes; then - log >&2 "GitHub CLI: Token scopes:$(gh auth status | grep 'scopes' | cut -d':' -f2-)" - else - log >&2 "GitHub CLI: Missing scopes (admin:public_key, admin:ssh_signing_key). Requesting permissions..." - gh auth refresh -h github.com -s admin:public_key,admin:ssh_signing_key - fi - -} - -github-auth-required-scopes() { - local github_auth_scopes - github_auth_scopes=$(gh auth status | grep scopes) - if [[ $github_auth_scopes =~ 'admin:public_key' ]] && [[ $github_auth_scopes =~ 'admin:ssh_signing_key' ]]; then - return 0 - else - return 1 - fi + local gh_auth_token_scopes + # If user is authenticated to GitHub + if gh_auth_token_scopes=$(gh auth status | grep scopes); then + if [[ $gh_auth_token_scopes =~ 'admin:public_key' ]] && [[ $gh_auth_token_scopes =~ 'admin:ssh_signing_key' ]] ; then + log >&2 "GitHub CLI: Required scopes are available." + else + log >&2 "GitHub CLI: Necessary scopes are not available. Requesting additional scopes..." + gh auth refresh -h github.com -s admin:public_key,admin:ssh_signing_key + fi + fi } - github-ssh-keys() { github-auth gh ssh-key list From bebada25dd34e2703df20a091b10a806e1604505 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:52:03 -0500 Subject: [PATCH 03/11] add git-commit-sign script w/ usage --- ssh_config/scripts/git-commit-sign | 75 ++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100755 ssh_config/scripts/git-commit-sign diff --git a/ssh_config/scripts/git-commit-sign b/ssh_config/scripts/git-commit-sign new file mode 100755 index 0000000..0d4b309 --- /dev/null +++ b/ssh_config/scripts/git-commit-sign @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -e + +# Usage: +# git config [--global] gpg.format ssh +# git config [--global] user.signingkey "/path/to/ssh/key" +# [ git config [--global] gpg.ssh.program "/path/to/this/script" ] +# +# Now, when you commit: +# - If commit.gpgsign is true: Every commit will be signed automatically +# - Otherwise: Use 'git commit -S' to sign individual commits +# + +# Function to get Git config value, trying local then global +get_git_config() { + local value + value=$(git config --get "$1") + if [ -z "$value" ]; then + value=$(git config --global --get "$1") + fi + echo "$value" +} + +# Check Git version +git_version=$(git --version | awk '{print $3}') +if [ "$(printf '%s\n' "2.34" "$git_version" | sort -V | head -n1)" = "2.34" ]; then + echo "Error: Git version 2.34 or higher is required for SSH signing." + exit 1 +fi + +# Check if SSH agent is running +if [ -z "$SSH_AUTH_SOCK" ]; then + echo "Error: SSH agent is not running. Please start the SSH agent." + exit 1 +fi + +# Get the signing key +signing_key=$(get_git_config user.signingkey) +if [ -z "$signing_key" ]; then + echo "Error: No signing key found in Git config (local or global)." + exit 1 +fi + +# Handle relative paths and expand ~ +signing_key="${signing_key/#\~/$HOME}" +signing_key=$(realpath -m "$signing_key") + +# Check if the key file exists +if [ ! -f "$signing_key" ]; then + echo "Error: Signing key file does not exist: $signing_key" + exit 1 +fi + +# Check if ssh-keygen supports -Y option +if ! ssh-keygen -Y sign 2>&1 | grep -q "ssh-keygen -Y sign"; then + echo "Error: Your version of ssh-keygen does not support the -Y option for signing." + exit 1 +fi + +# Get the key fingerprint +key_info=$(ssh-keygen -lf "$signing_key" | awk '{gsub(/[()]/, "", $4); print $4 " " $2}') +if [ -z "$key_info" ]; then + echo "Error: Could not retrieve key information." + exit 1 +fi + +echo "Confirm user presence for key $key_info" + +# Use quotation marks to handle spaces in paths +if ! ssh-keygen -Y sign -n git -f "$signing_key" "$@"; then + echo "Error: Failed to sign with ssh-keygen." + exit 1 +fi + +echo "Signing successful." \ No newline at end of file From 4220379ed7c66ee246e1e7e4830a40a4877db8a5 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:58:58 -0500 Subject: [PATCH 04/11] adding git features to configure signing via keycutter --- bin/keycutter | 15 ++++ lib/functions | 1 + lib/git | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 lib/git diff --git a/bin/keycutter b/bin/keycutter index 47b2837..6125f3c 100755 --- a/bin/keycutter +++ b/bin/keycutter @@ -174,6 +174,21 @@ keycutter-list() { github-ssh-keys } +keycutter-git-signing-config() { + git-ssh-signing-check "$@" +} +keycutter-set-git-commit-sign() { + git-ssh-signing-setup "$@" +} + +keycutter-enable-commit-signing() { + git-commit-signing-enable "$@" +} + +keycutter-disable-commit-signing() { + git-commit-signing-disable "$@" +} + keycutter-update() { keycutter-update-git check_requirements diff --git a/lib/functions b/lib/functions index 34db1c1..50be0bd 100644 --- a/lib/functions +++ b/lib/functions @@ -6,5 +6,6 @@ KEYCUTTER_ROOT="$(readlink -f "$(dirname -- "${BASH_SOURCE[0]:-${0:A}}")/../")" [[ -z $SSH_CONNECTION ]] && : ${KEYCUTTER_ORIGIN:="$(hostname -s)"} source "${KEYCUTTER_ROOT}/lib/github" +source "${KEYCUTTER_ROOT}/lib/git" source "${KEYCUTTER_ROOT}/lib/ssh" source "${KEYCUTTER_ROOT}/lib/utils" diff --git a/lib/git b/lib/git new file mode 100644 index 0000000..10158d5 --- /dev/null +++ b/lib/git @@ -0,0 +1,226 @@ +# Git functions + +# Function to set Git config +git-config-set() { + local scope="$1" + local key="$2" + local value="$3" + local config_flag="" + [[ "$scope" == "global" ]] && config_flag="--global" + + git config $config_flag "$key" "$value" + log "Set $key to $value ($scope config)" +} + +# Function to get Git config +git-config-get() { + local scope="$1" + local key="$2" + local config_flag="" + [[ "$scope" == "global" ]] && config_flag="--global" + + local value + value=$(git config $config_flag --get "$key") + if [ -n "$value" ]; then + echo "$value" + else + echo "Not set" + fi +} + +# Function to check if a command exists +command-exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check Git version +git-version-check() { + local git_version + git_version=$(git --version | awk '{print $3}') + if [ "$(printf '%s\n' "2.34" "$git_version" | sort -V | head -n1)" = "2.34" ]; then + log "Error: Git version 2.34 or higher is required for SSH signing." + return 1 + fi + return 0 +} + +# Function to set up Git SSH signing config +git-ssh-signing-setup() { + local scope="" + local ssh_key="$DEFAULT_SSH_KEY" + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + --global) + scope="global" + shift + ;; + --local) + scope="local" + shift + ;; + *) + # Assume it's the SSH key path + ssh_key="$1" + shift + ;; + esac + done + + # If no scope was explicitly set, default to local + if [ -z "$scope" ]; then + log "No scope specified. Defaulting to 'local' config." + scope="local" + fi + + # Display proposed changes and ask for confirmation + log "Proposed Git SSH signing configuration:" + log " Scope: $scope" + log " SSH Key: $ssh_key" + log " gpg.format: ssh" + log " gpg.ssh.program: $HOME/.ssh/keycutter/scripts/git-commit-sign" + echo + prompt "Do you want to apply these changes? (y/N) " + read -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]] + then + log "Operation cancelled." + return 1 + fi + + log "Setting up Git SSH signing ($scope config)..." + + # Apply the configurations + git-config-set "$scope" "gpg.format" "ssh" + + local script_path="$HOME/.ssh/keycutter/scripts/git-commit-sign" + git-config-set "$scope" "gpg.ssh.program" "$script_path" + + if [ ! -f "$ssh_key" ]; then + log "Error: SSH key not found at $ssh_key" + return 1 + fi + + git-config-set "$scope" "user.signingkey" "$ssh_key" + log "Git SSH signing basic setup complete for $scope config!" + return 0 +} + +# Function to enable commit signing +git-commit-signing-enable() { + local scope="" + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + --global) + scope="global" + shift + ;; + --local) + scope="local" + shift + ;; + *) + log "Error: Unknown option $1" + return 1 + ;; + esac + done + + # If no scope was explicitly set, default to local + if [ -z "$scope" ]; then + log "No scope specified. Defaulting to 'local' config." + scope="local" + fi + + local config_flag="" + if [ "$scope" = "global" ]; then + config_flag="--global" + fi + + git config $config_flag "commit.gpgsign" "true" + log "Enabled commit signing for $scope config" +} + +# Function to disable commit signing +git-commit-signing-disable() { + local scope="" + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + --global) + scope="global" + shift + ;; + --local) + scope="local" + shift + ;; + *) + log "Error: Unknown option $1" + return 1 + ;; + esac + done + + # If no scope was explicitly set, default to local + if [ -z "$scope" ]; then + log "No scope specified. Defaulting to 'local' config." + scope="local" + fi + + local config_flag="" + if [ "$scope" = "global" ]; then + config_flag="--global" + fi + + git config $config_flag --unset "commit.gpgsign" + log "Disabled commit signing for $scope config" +} + +# Function to check Git SSH signing configuration +git-ssh-signing-check() { + local scope="$1" + + if [ -z "$scope" ]; then + log "Checking Git SSH signing configuration (local config):" + else + log "Checking Git SSH signing configuration ($scope config):" + fi + log "gpg.format: $(git-config-get "$scope" gpg.format)" + log "gpg.ssh.program: $(git-config-get "$scope" gpg.ssh.program)" + log "user.signingkey: $(git-config-get "$scope" user.signingkey)" + log "commit.gpgsign: $(git-config-get "$scope" commit.gpgsign)" +} + +# Function to print setup instructions +git-ssh-signing-instructions() { + local ssh_key="${1:-$DEFAULT_SSH_KEY}" + log "Setup instructions:" + log "1. Ensure your SSH key is added to the ssh-agent:" + log " ssh-add $ssh_key" + log "2. Make sure the Git SSH signing script is in place and executable:" + log " touch $HOME/.ssh/git-commit-sign" + log " chmod u+x $HOME/.ssh/git-commit-sign" + log "3. Copy the Git SSH signing script content into $HOME/.ssh/git-commit-sign" +} + +# Example usage function +git-ssh-signing-example() { + log "Example usage:" + log "source ./git_ssh_signing_functions.sh" + log "git-version-check" + log "git-ssh-signing-setup --global" + log "git-commit-signing-enable global" + log "git-ssh-signing-check global" + log "git-ssh-signing-instructions" +} + +# If this script is run directly, print example usage +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + example_usage +fi \ No newline at end of file From d38e8d9a551f983ec6a753df03592e7c4c88cdbe Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:59:26 -0500 Subject: [PATCH 05/11] fixing git-commit-sign behaviour --- lib/git | 4 +-- ssh_config/scripts/git-commit-sign | 53 ++---------------------------- 2 files changed, 5 insertions(+), 52 deletions(-) diff --git a/lib/git b/lib/git index 10158d5..848f427 100644 --- a/lib/git +++ b/lib/git @@ -37,8 +37,8 @@ command-exists() { git-version-check() { local git_version git_version=$(git --version | awk '{print $3}') - if [ "$(printf '%s\n' "2.34" "$git_version" | sort -V | head -n1)" = "2.34" ]; then - log "Error: Git version 2.34 or higher is required for SSH signing." + if [ "$(printf '%s\n' "2.34" "$git_version" | sort -V | head -n1)" != "2.34" ]; then + echo "Error: Git version 2.34 or higher is required for SSH signing." return 1 fi return 0 diff --git a/ssh_config/scripts/git-commit-sign b/ssh_config/scripts/git-commit-sign index 0d4b309..27845c1 100755 --- a/ssh_config/scripts/git-commit-sign +++ b/ssh_config/scripts/git-commit-sign @@ -1,16 +1,8 @@ #!/usr/bin/env bash -set -e - # Usage: # git config [--global] gpg.format ssh -# git config [--global] user.signingkey "/path/to/ssh/key" -# [ git config [--global] gpg.ssh.program "/path/to/this/script" ] -# -# Now, when you commit: -# - If commit.gpgsign is true: Every commit will be signed automatically -# - Otherwise: Use 'git commit -S' to sign individual commits -# - +# git config [--global] gpg.ssh.program "~/.ssh/keycutter/keys/scripts/git-commit-sign" +# git config [--global] user.signingkey "~/.ssh/keycutter/keys/{service}_user@{host}" # Function to get Git config value, trying local then global get_git_config() { local value @@ -20,56 +12,17 @@ get_git_config() { fi echo "$value" } - -# Check Git version -git_version=$(git --version | awk '{print $3}') -if [ "$(printf '%s\n' "2.34" "$git_version" | sort -V | head -n1)" = "2.34" ]; then - echo "Error: Git version 2.34 or higher is required for SSH signing." - exit 1 -fi - -# Check if SSH agent is running -if [ -z "$SSH_AUTH_SOCK" ]; then - echo "Error: SSH agent is not running. Please start the SSH agent." - exit 1 -fi - # Get the signing key signing_key=$(get_git_config user.signingkey) if [ -z "$signing_key" ]; then echo "Error: No signing key found in Git config (local or global)." exit 1 fi - -# Handle relative paths and expand ~ -signing_key="${signing_key/#\~/$HOME}" -signing_key=$(realpath -m "$signing_key") - -# Check if the key file exists -if [ ! -f "$signing_key" ]; then - echo "Error: Signing key file does not exist: $signing_key" - exit 1 -fi - -# Check if ssh-keygen supports -Y option -if ! ssh-keygen -Y sign 2>&1 | grep -q "ssh-keygen -Y sign"; then - echo "Error: Your version of ssh-keygen does not support the -Y option for signing." - exit 1 -fi - # Get the key fingerprint key_info=$(ssh-keygen -lf "$signing_key" | awk '{gsub(/[()]/, "", $4); print $4 " " $2}') if [ -z "$key_info" ]; then echo "Error: Could not retrieve key information." exit 1 fi - echo "Confirm user presence for key $key_info" - -# Use quotation marks to handle spaces in paths -if ! ssh-keygen -Y sign -n git -f "$signing_key" "$@"; then - echo "Error: Failed to sign with ssh-keygen." - exit 1 -fi - -echo "Signing successful." \ No newline at end of file +ssh-keygen -Y sign -n git -f "$signing_key" "$@" From 27510933bca2922cddaad340c3fcdbf5379c272a Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:00:33 -0500 Subject: [PATCH 06/11] spacing --- ssh_config/scripts/git-commit-sign | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ssh_config/scripts/git-commit-sign b/ssh_config/scripts/git-commit-sign index 27845c1..97ba032 100755 --- a/ssh_config/scripts/git-commit-sign +++ b/ssh_config/scripts/git-commit-sign @@ -1,9 +1,11 @@ #!/usr/bin/env bash + # Usage: # git config [--global] gpg.format ssh # git config [--global] gpg.ssh.program "~/.ssh/keycutter/keys/scripts/git-commit-sign" # git config [--global] user.signingkey "~/.ssh/keycutter/keys/{service}_user@{host}" # Function to get Git config value, trying local then global + get_git_config() { local value value=$(git config --get "$1") From e8ab6d2243a02df3102d915fa01caad9966267a2 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:49:56 -0500 Subject: [PATCH 07/11] added better error handling --- ssh_config/scripts/git-commit-sign | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ssh_config/scripts/git-commit-sign b/ssh_config/scripts/git-commit-sign index 97ba032..fcfa345 100755 --- a/ssh_config/scripts/git-commit-sign +++ b/ssh_config/scripts/git-commit-sign @@ -1,11 +1,14 @@ #!/usr/bin/env bash +set -eo pipefail + # Usage: +# # git config [--global] gpg.format ssh # git config [--global] gpg.ssh.program "~/.ssh/keycutter/keys/scripts/git-commit-sign" # git config [--global] user.signingkey "~/.ssh/keycutter/keys/{service}_user@{host}" -# Function to get Git config value, trying local then global +# Function to get Git config value, trying local then global get_git_config() { local value value=$(git config --get "$1") @@ -20,11 +23,23 @@ if [ -z "$signing_key" ]; then echo "Error: No signing key found in Git config (local or global)." exit 1 fi + +# Check if the signing key file exists +if [ ! -f "$signing_key" ]; then + log_error "Signing key file '$signing_key' does not exist." + exit 1 +fi + # Get the key fingerprint key_info=$(ssh-keygen -lf "$signing_key" | awk '{gsub(/[()]/, "", $4); print $4 " " $2}') if [ -z "$key_info" ]; then echo "Error: Could not retrieve key information." exit 1 fi -echo "Confirm user presence for key $key_info" -ssh-keygen -Y sign -n git -f "$signing_key" "$@" +echo "Confirm user presence for key $key_info" >&2 + +# Sign the commit +if ! ssh-keygen -Y sign -n git -f "$signing_key" "$@"; then + log_error "Signing failed." + exit 1 +fi \ No newline at end of file From ae8c5ec7e89c6473a971cfc68b0e548d27690be1 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:13:45 -0500 Subject: [PATCH 08/11] added git-commit-sign --- bin/keycutter | 6 +++- lib/git | 79 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/bin/keycutter b/bin/keycutter index 6125f3c..c262425 100755 --- a/bin/keycutter +++ b/bin/keycutter @@ -177,7 +177,7 @@ keycutter-list() { keycutter-git-signing-config() { git-ssh-signing-check "$@" } -keycutter-set-git-commit-sign() { +keycutter-git-signing-setup() { git-ssh-signing-setup "$@" } @@ -189,6 +189,10 @@ keycutter-disable-commit-signing() { git-commit-signing-disable "$@" } +keycutter-signing-help() { + git-ssh-signing-instructions +} + keycutter-update() { keycutter-update-git check_requirements diff --git a/lib/git b/lib/git index 848f427..6d0f93f 100644 --- a/lib/git +++ b/lib/git @@ -47,7 +47,48 @@ git-version-check() { # Function to set up Git SSH signing config git-ssh-signing-setup() { local scope="" - local ssh_key="$DEFAULT_SSH_KEY" + local ssh_key="" + + # Function to display help + show_help() { + echo "Usage: git-ssh-signing-setup [OPTIONS] [SSH_KEY_PATH]" + echo + echo "Set up Git SSH signing configuration." + echo + echo "Options:" + echo " --global Set the configuration globally" + echo " --local Set the configuration locally (default if not specified)" + echo " help Display this help message" + echo + echo "If SSH_KEY_PATH is not provided, you'll be prompted to select a key from \$KEYCUTTER_SSH_KEY_DIR" + } + + # Function to select SSH key + select_ssh_key() { + if command -v fzf &> /dev/null; then + ssh_key=$(find "$KEYCUTTER_SSH_KEY_DIR" -type f -not -name '*.pub' | fzf --prompt="Select SSH key: " --preview="ssh-keygen -lf {}") + else + echo "Select an SSH key:" + local keys=() + while IFS= read -r -d $'\0' file; do + keys+=("$file") + done < <(find "$KEYCUTTER_SSH_KEY_DIR" -type f -not -name '*.pub' -print0) + + select key in "${keys[@]}"; do + if [ -n "$key" ]; then + ssh_key="$key" + break + else + echo "Invalid selection. Please try again." + fi + done + fi + + if [ -z "$ssh_key" ]; then + log "No SSH key selected. Exiting." + return 1 + fi + } # Parse arguments while [[ $# -gt 0 ]]; do @@ -60,6 +101,10 @@ git-ssh-signing-setup() { scope="local" shift ;; + help) + show_help + return 0 + ;; *) # Assume it's the SSH key path ssh_key="$1" @@ -74,12 +119,17 @@ git-ssh-signing-setup() { scope="local" fi + # If no SSH key was provided, use select_ssh_key function to choose one + if [ -z "$ssh_key" ]; then + select_ssh_key || return 1 + fi + # Display proposed changes and ask for confirmation log "Proposed Git SSH signing configuration:" - log " Scope: $scope" - log " SSH Key: $ssh_key" - log " gpg.format: ssh" - log " gpg.ssh.program: $HOME/.ssh/keycutter/scripts/git-commit-sign" + log " Scope: $scope" + log " SSH Key: $ssh_key" + log " gpg.format: ssh" + log " gpg.ssh.program: $HOME/.ssh/keycutter/scripts/git-commit-sign" echo prompt "Do you want to apply these changes? (y/N) " read -n 1 -r @@ -94,15 +144,14 @@ git-ssh-signing-setup() { # Apply the configurations git-config-set "$scope" "gpg.format" "ssh" - local script_path="$HOME/.ssh/keycutter/scripts/git-commit-sign" git-config-set "$scope" "gpg.ssh.program" "$script_path" - + if [ ! -f "$ssh_key" ]; then log "Error: SSH key not found at $ssh_key" return 1 fi - + git-config-set "$scope" "user.signingkey" "$ssh_key" log "Git SSH signing basic setup complete for $scope config!" return 0 @@ -199,14 +248,14 @@ git-ssh-signing-check() { # Function to print setup instructions git-ssh-signing-instructions() { - local ssh_key="${1:-$DEFAULT_SSH_KEY}" + local ssh_key="${1:-$KEYCUTTER_SSH_KEY_DIR}" log "Setup instructions:" - log "1. Ensure your SSH key is added to the ssh-agent:" - log " ssh-add $ssh_key" - log "2. Make sure the Git SSH signing script is in place and executable:" - log " touch $HOME/.ssh/git-commit-sign" - log " chmod u+x $HOME/.ssh/git-commit-sign" - log "3. Copy the Git SSH signing script content into $HOME/.ssh/git-commit-sign" + log "1. Create a key via keycutter:" + log " \`keycutter create\`" + log "2. Make sure the Git SSH signing script is in place:" + log " \`keycutter update-ssh-config\`" + log "3. Set up Git SSH signing:" + log " \`keycutter git-signing-setup\`" } # Example usage function From bd01a6f6bc4294e028903cc7425fc06ad9a46fb7 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:55:10 -0500 Subject: [PATCH 09/11] added name changes --- bin/keycutter | 16 ++++++++-------- lib/git | 23 ++++++----------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/bin/keycutter b/bin/keycutter index c262425..c69717f 100755 --- a/bin/keycutter +++ b/bin/keycutter @@ -175,22 +175,22 @@ keycutter-list() { } keycutter-git-signing-config() { - git-ssh-signing-check "$@" + git-signing-config "$@" } keycutter-git-signing-setup() { - git-ssh-signing-setup "$@" + git-signing-setup "$@" } -keycutter-enable-commit-signing() { - git-commit-signing-enable "$@" +keycutter-enable-git-commit-signing() { + enable-git-commit-signing "$@" } -keycutter-disable-commit-signing() { - git-commit-signing-disable "$@" +keycutter-disable-git-commit-signing() { + disable-git-commit-signing "$@" } -keycutter-signing-help() { - git-ssh-signing-instructions +keycutter-git-signing-help() { + git-signing-help } keycutter-update() { diff --git a/lib/git b/lib/git index 6d0f93f..5f2e987 100644 --- a/lib/git +++ b/lib/git @@ -45,7 +45,7 @@ git-version-check() { } # Function to set up Git SSH signing config -git-ssh-signing-setup() { +git-signing-setup() { local scope="" local ssh_key="" @@ -158,7 +158,7 @@ git-ssh-signing-setup() { } # Function to enable commit signing -git-commit-signing-enable() { +enable-git-commit-signing() { local scope="" # Parse arguments @@ -195,7 +195,7 @@ git-commit-signing-enable() { } # Function to disable commit signing -git-commit-signing-disable() { +disable-git-commit-signing() { local scope="" # Parse arguments @@ -232,7 +232,7 @@ git-commit-signing-disable() { } # Function to check Git SSH signing configuration -git-ssh-signing-check() { +git-signing-config() { local scope="$1" if [ -z "$scope" ]; then @@ -247,28 +247,17 @@ git-ssh-signing-check() { } # Function to print setup instructions -git-ssh-signing-instructions() { +git-signing-help() { local ssh_key="${1:-$KEYCUTTER_SSH_KEY_DIR}" log "Setup instructions:" log "1. Create a key via keycutter:" - log " \`keycutter create\`" + log " \`keycutter create github.com_me@pc\`" log "2. Make sure the Git SSH signing script is in place:" log " \`keycutter update-ssh-config\`" log "3. Set up Git SSH signing:" log " \`keycutter git-signing-setup\`" } -# Example usage function -git-ssh-signing-example() { - log "Example usage:" - log "source ./git_ssh_signing_functions.sh" - log "git-version-check" - log "git-ssh-signing-setup --global" - log "git-commit-signing-enable global" - log "git-ssh-signing-check global" - log "git-ssh-signing-instructions" -} - # If this script is run directly, print example usage if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then example_usage From 2905b9a04b20a476a438d2d844f872adbcacf5bc Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:25:51 -0500 Subject: [PATCH 10/11] changed naming --- bin/keycutter | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/keycutter b/bin/keycutter index c69717f..ee0d26f 100755 --- a/bin/keycutter +++ b/bin/keycutter @@ -181,11 +181,11 @@ keycutter-git-signing-setup() { git-signing-setup "$@" } -keycutter-enable-git-commit-signing() { +keycutter-git-commit-signing-enable() { enable-git-commit-signing "$@" } -keycutter-disable-git-commit-signing() { +keycutter-git-commit-signing-disable() { disable-git-commit-signing "$@" } From 3fe9959e49c9c82db506e707d3c35905b99099c4 Mon Sep 17 00:00:00 2001 From: lukeburciu <31502276+lukeburciu@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:22:13 -0600 Subject: [PATCH 11/11] configured colours for better readability --- lib/git | 74 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/lib/git b/lib/git index 5f2e987..7293c8f 100644 --- a/lib/git +++ b/lib/git @@ -1,3 +1,20 @@ +# Define colors globally +color_reset=$(tput sgr0) +color_local=$(tput setaf 2) # Green for local +color_global=$(tput setaf 4) # Blue for global + +# Function to format the scope with appropriate color +format_scope() { + local scope="$1" + if [[ "$scope" == "local" ]]; then + echo "${color_local}${scope}${color_reset}" + elif [[ "$scope" == "global" ]]; then + echo "${color_global}${scope}${color_reset}" + else + echo "$scope" # Default to no color if not local or global + fi +} + # Git functions # Function to set Git config @@ -9,7 +26,7 @@ git-config-set() { [[ "$scope" == "global" ]] && config_flag="--global" git config $config_flag "$key" "$value" - log "Set $key to $value ($scope config)" + log "Set $key to $value ($(format_scope $scope) config)" } # Function to get Git config @@ -24,7 +41,7 @@ git-config-get() { if [ -n "$value" ]; then echo "$value" else - echo "Not set" + echo "Not set ($(format_scope $scope) config)" fi } @@ -126,10 +143,11 @@ git-signing-setup() { # Display proposed changes and ask for confirmation log "Proposed Git SSH signing configuration:" - log " Scope: $scope" + log " Scope: $(format_scope $scope)" log " SSH Key: $ssh_key" + log " gpg.ssh.program: ~/.ssh/keycutter/scripts/git-commit-sign" log " gpg.format: ssh" - log " gpg.ssh.program: $HOME/.ssh/keycutter/scripts/git-commit-sign" + echo prompt "Do you want to apply these changes? (y/N) " read -n 1 -r @@ -140,7 +158,7 @@ git-signing-setup() { return 1 fi - log "Setting up Git SSH signing ($scope config)..." + log "Setting up Git SSH signing ($(format_scope $scope) config)..." # Apply the configurations git-config-set "$scope" "gpg.format" "ssh" @@ -153,15 +171,13 @@ git-signing-setup() { fi git-config-set "$scope" "user.signingkey" "$ssh_key" - log "Git SSH signing basic setup complete for $scope config!" + log "Git SSH signing basic setup complete for $(format_scope $scope) config!" return 0 } # Function to enable commit signing enable-git-commit-signing() { local scope="" - - # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --global) @@ -179,26 +195,20 @@ enable-git-commit-signing() { esac done - # If no scope was explicitly set, default to local if [ -z "$scope" ]; then - log "No scope specified. Defaulting to 'local' config." + log "No scope specified. Defaulting to $(format_scope local) config." scope="local" fi local config_flag="" - if [ "$scope" = "global" ]; then - config_flag="--global" - fi - + [[ "$scope" == "global" ]] && config_flag="--global" git config $config_flag "commit.gpgsign" "true" - log "Enabled commit signing for $scope config" + log "Enabled commit signing for $(format_scope $scope) config" } # Function to disable commit signing disable-git-commit-signing() { local scope="" - - # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --global) @@ -216,36 +226,46 @@ disable-git-commit-signing() { esac done - # If no scope was explicitly set, default to local if [ -z "$scope" ]; then - log "No scope specified. Defaulting to 'local' config." + log "No scope specified. Defaulting to $(format_scope local) config." scope="local" fi local config_flag="" - if [ "$scope" = "global" ]; then - config_flag="--global" - fi - + [[ "$scope" == "global" ]] && config_flag="--global" git config $config_flag --unset "commit.gpgsign" - log "Disabled commit signing for $scope config" + log "Disabled commit signing for $(format_scope $scope) config" } # Function to check Git SSH signing configuration git-signing-config() { local scope="$1" + local git_dir="" - if [ -z "$scope" ]; then - log "Checking Git SSH signing configuration (local config):" + # Get the current Git directory, if available + if git rev-parse --show-toplevel &>/dev/null; then + git_dir=$(git rev-parse --show-toplevel) else - log "Checking Git SSH signing configuration ($scope config):" + git_dir="Not a Git repository" fi + + if [[ "$scope" != "global" && "$scope" != "local" && -n "$scope" ]]; then + log "Invalid scope provided. Scope must be either 'global' or 'local'." + return 1 + fi + + if [ -z "$scope" ]; then + scope="local" + fi + + log "Checking $(format_scope $scope) Git SSH signing configuration for directory: $git_dir" log "gpg.format: $(git-config-get "$scope" gpg.format)" log "gpg.ssh.program: $(git-config-get "$scope" gpg.ssh.program)" log "user.signingkey: $(git-config-get "$scope" user.signingkey)" log "commit.gpgsign: $(git-config-get "$scope" commit.gpgsign)" } + # Function to print setup instructions git-signing-help() { local ssh_key="${1:-$KEYCUTTER_SSH_KEY_DIR}"