bdf405e2c1
SSH-ключи и Gitea API до clone Rules; init-cursor копирует из локального $HOME/CursorRules.
161 lines
4.2 KiB
Bash
161 lines
4.2 KiB
Bash
#!/usr/bin/env bash
|
|
# Генерирует SSH-ключи и ~/.ssh/config для Git-хостов из local/git-ssh-hosts.conf.
|
|
set -euo pipefail
|
|
|
|
CONFIG_DIR="${CONFIG_DIR:-$HOME/CursorRules/local}"
|
|
HOSTS_CONFIG="${HOSTS_CONFIG:-$CONFIG_DIR/git-ssh-hosts.conf}"
|
|
WHAT_IF="${WHAT_IF:-0}"
|
|
|
|
log_step() { printf '[*] %s\n' "$1"; }
|
|
log_ok() { printf '[+] %s\n' "$1"; }
|
|
log_warn() { printf '[!] %s\n' "$1"; }
|
|
|
|
if [[ ! -f "$HOSTS_CONFIG" ]]; then
|
|
echo "Config not found: $HOSTS_CONFIG" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SSH_DIR="$HOME/.ssh"
|
|
SSH_CONFIG="$SSH_DIR/config"
|
|
mkdir -p "$SSH_DIR"
|
|
chmod 700 "$SSH_DIR"
|
|
|
|
declare -A PROFILE_KEYNAME PROFILE_COMMENT PROFILE_GITEA
|
|
declare -A HOST_HOSTNAME HOST_PORT HOST_USER HOST_PROFILE
|
|
|
|
current_section=''
|
|
current_name=''
|
|
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
line="${line%%#*}"
|
|
line="${line%"${line##*[![:space:]]}"}"
|
|
[[ -z "$line" ]] && continue
|
|
|
|
if [[ "$line" =~ ^\[profile:(.+)\]$ ]]; then
|
|
current_section='profile'
|
|
current_name="${BASH_REMATCH[1]}"
|
|
continue
|
|
fi
|
|
if [[ "$line" =~ ^\[host:(.+)\]$ ]]; then
|
|
current_section='host'
|
|
current_name="${BASH_REMATCH[1]}"
|
|
HOST_HOSTNAME["$current_name"]=''
|
|
continue
|
|
fi
|
|
if [[ "$line" != *=* ]]; then
|
|
continue
|
|
fi
|
|
|
|
key="${line%%=*}"
|
|
value="${line#*=}"
|
|
key="${key%"${key##*[![:space:]]}"}"
|
|
value="${value#"${value%%[![:space:]]*}"}"
|
|
|
|
if [[ "$current_section" == 'profile' ]]; then
|
|
case "$key" in
|
|
KeyName) PROFILE_KEYNAME["$current_name"]="$value" ;;
|
|
KeyComment) PROFILE_COMMENT["$current_name"]="$value" ;;
|
|
GiteaConfig) PROFILE_GITEA["$current_name"]="$value" ;;
|
|
esac
|
|
elif [[ "$current_section" == 'host' ]]; then
|
|
case "$key" in
|
|
HostName) HOST_HOSTNAME["$current_name"]="$value" ;;
|
|
Port) HOST_PORT["$current_name"]="$value" ;;
|
|
User) HOST_USER["$current_name"]="$value" ;;
|
|
Profile) HOST_PROFILE["$current_name"]="$value" ;;
|
|
esac
|
|
fi
|
|
done < "$HOSTS_CONFIG"
|
|
|
|
declare -A SEEN_KEYS
|
|
|
|
for profile in "${!PROFILE_KEYNAME[@]}"; do
|
|
key_name="${PROFILE_KEYNAME[$profile]}"
|
|
[[ -z "$key_name" || -n "${SEEN_KEYS[$key_name]:-}" ]] && continue
|
|
SEEN_KEYS["$key_name"]=1
|
|
|
|
key_path="$SSH_DIR/$key_name"
|
|
comment="${PROFILE_COMMENT[$profile]:-$key_name}"
|
|
|
|
if [[ ! -f "$key_path" ]]; then
|
|
log_step "Generating $key_name"
|
|
if [[ "$WHAT_IF" == '1' ]]; then
|
|
log_warn "WhatIf: ssh-keygen -t ed25519 -f $key_path"
|
|
else
|
|
ssh-keygen -t ed25519 -f "$key_path" -N '' -C "$comment" -q
|
|
chmod 600 "$key_path"
|
|
log_ok "key $key_name created"
|
|
fi
|
|
else
|
|
log_ok "key $key_name exists"
|
|
fi
|
|
done
|
|
|
|
update_ssh_block() {
|
|
local host_alias="$1"
|
|
local block="$2"
|
|
local begin="# BEGIN Setup-SshAccess:$host_alias"
|
|
local end="# END Setup-SshAccess:$host_alias"
|
|
local tmp
|
|
tmp="$(mktemp)"
|
|
|
|
if [[ -f "$SSH_CONFIG" ]]; then
|
|
awk -v begin="$begin" -v end="$end" -v block="$block" '
|
|
$0 == begin { skip=1; next }
|
|
$0 == end { skip=0; next }
|
|
skip { next }
|
|
{ print }
|
|
END {
|
|
if (block != "") {
|
|
print block
|
|
}
|
|
}
|
|
' block="$block" "$SSH_CONFIG" > "$tmp"
|
|
else
|
|
printf '%s\n' "$block" > "$tmp"
|
|
fi
|
|
|
|
if [[ "$WHAT_IF" != '1' ]]; then
|
|
mv "$tmp" "$SSH_CONFIG"
|
|
chmod 600 "$SSH_CONFIG"
|
|
else
|
|
rm -f "$tmp"
|
|
fi
|
|
}
|
|
|
|
for host_alias in $(printf '%s\n' "${!HOST_HOSTNAME[@]}" | sort); do
|
|
profile="${HOST_PROFILE[$host_alias]:-}"
|
|
key_name="${PROFILE_KEYNAME[$profile]:-}"
|
|
if [[ -z "$profile" || -z "$key_name" ]]; then
|
|
echo "Host $host_alias: unknown profile" >&2
|
|
exit 1
|
|
fi
|
|
|
|
block="# BEGIN Setup-SshAccess:$host_alias
|
|
Host $host_alias
|
|
HostName ${HOST_HOSTNAME[$host_alias]}
|
|
User ${HOST_USER[$host_alias]}
|
|
Port ${HOST_PORT[$host_alias]}
|
|
IdentityFile ~/.ssh/$key_name
|
|
IdentitiesOnly yes
|
|
AddKeysToAgent yes
|
|
StrictHostKeyChecking accept-new
|
|
# END Setup-SshAccess:$host_alias"
|
|
|
|
if [[ "$WHAT_IF" == '1' ]]; then
|
|
log_step "WhatIf: ssh config block for $host_alias"
|
|
else
|
|
update_ssh_block "$host_alias" "$block"
|
|
log_ok "ssh config: $host_alias"
|
|
fi
|
|
done
|
|
|
|
if [[ "$WHAT_IF" != '1' ]]; then
|
|
eval "$(ssh-agent -s)" >/dev/null
|
|
for key_name in "${!SEEN_KEYS[@]}"; do
|
|
[[ -f "$SSH_DIR/$key_name" ]] && ssh-add "$SSH_DIR/$key_name" >/dev/null 2>&1 || true
|
|
done
|
|
fi
|
|
|
|
log_ok 'SSH setup complete'
|