Jak uzyskać wszystkie odciski palców dla pliku .ssh / Author_keys (2)

39

Czy istnieje prosty sposób na uzyskanie listy wszystkich odcisków palców wprowadzonych w .ssh / uprawnionych_kluczykach || Plik .ssh / Author_keys2?

ssh-keygen -l -f .ssh/authorized_keys 

zwróci tylko odcisk palca pierwszego wiersza / wpisu / klucza publicznego

włamać się z awk:

awk 'BEGIN { 
    while (getline < ".ssh/authorized_keys") {
        if ($1!~"ssh-(r|d)sa") {continue}
        print "Fingerprint for "$3
        system("echo " "\""$0"\"> /tmp/authorizedPublicKey.scan; \
            ssh-keygen -l -f /tmp/authorizedPublicKey.scan; \
            rm /tmp/authorizedPublicKey.scan"
        )
    }
}'

ale czy istnieje prostszy sposób lub polecenie ssh, którego nie znalazłem?

childno͡.de
źródło
Aby zrobić to niezawodnie, należy wziąć pod uwagę pole opcji w authorized_keyspliku, w którym ssh-keygenbaulks. Szukałem niezawodnego sposobu na jego przeanalizowanie, ale najlepsze, jakie mogłem wymyślić, obejmuje ta odpowiedź .
starfry

Odpowiedzi:

45

Oto kolejny hack wykorzystujący zwykły bash bez plików tymczasowych:

while read l; do
  [[ -n $l && ${l###} = $l ]] && ssh-keygen -l -f /dev/stdin <<<$l;
done < .ssh/authorized_keys

Możesz łatwo ustawić tę funkcję w .bashrc:

function fingerprints() {
  local file="${1:-$HOME/.ssh/authorized_keys}"
  while read l; do
    [[ -n $l && ${l###} = $l ]] && ssh-keygen -l -f /dev/stdin <<<$l
  done < "${file}"
}

i nazwij to:

$ fingerprints .ssh/authorized_keys
Inkaphink
źródło
1
nice @Raphink, dziękuję. dodano code.childno.de/marcel/changeset/afdce0dd ;) Jedna uwaga: ssh-keygen -l -f /dev/stdinwydaje się, że nie działa na komputerze Mac .. nie dotyczy to jednak serwerów, ale gnaa apple, czy jest to problem z BSD /dev/stdin is not a public key file.?
childno͡.de
1
Czytanie z /dev/stdinnie jest ogólnie świetnym pomysłem, lepiej go używać -, ale z jakiegoś powodu ssh-keygennie wie o -...
inkaphink
Nie działa na komputerze Mac?
Czy
1
To nie działa, jeśli klucze są poprzedzone opcjami.
starfry
1
@ ℝaphink: Chciałbym local file="${1:-$HOME/.ssh/authorized_keys}"pozwolić, aby działał bez żadnych argumentów i domyślnie do zwykłego ~/.ssh/authorized_keyspliku i zacytował < "$file"użyty jako dane wejściowe do whilepętli.
0xC0000022L,
8

Oto przenośny sposób wyświetlania wszystkich kluczowych odcisków palców dla danego pliku, przetestowanego na komputerach Mac i Linux:

#!/bin/bash

fingerprint_keys()
{
    if (( $# != 1 )); then
        echo "Usage: ${FUNCNAME} <authorized keys file>" >&2
        return 1
    fi

    local file="$1"
    if [ ! -r "$file" ]; then
        echo "${FUNCNAME}: File '${file}' does not exist or isn't readable." >&2
        return 1
    fi

    # Must be declared /before/ assignment, because of bash weirdness, in
    # order to get exit code in $?.
    local TMPFILE

    TEMPFILE=$(mktemp -q -t "$0.XXXXXXXXXX")
    if (( $? != 0 )); then
        echo "${FUNCNAME}: Can't create temporary file." >&2
        return 1
    fi

    while read line; do
        # Make sure lone isn't a comment or blank.
        if [[ -n "$line" ]] && [ "${line###}" == "$line" ]; then
            # Insert key into temporary file (ignoring noclobber).
            echo "$line" >| "$TEMPFILE"

            # Fingerprint time.
            ssh-keygen -l -f "$TEMPFILE"

            # OVerwrite the file ASAP (ignoring noclobber) to not leave keys
            # sitting in temp files.
            >| "$TEMPFILE"
        fi
    done < "$file"

    rm -f "$TEMPFILE"
    if (( $? != 0 )); then
        echo "${FUNCNAME}: Failed to remove temporary file." >&2
        return 1
    fi
}

Przykładowe użycie:

bash $ fingerprint_keys ~/.ssh/authorized_keys
2048 xx:xx:xx:xx:xx:xx:xx:xx:bb:xx:xx:xx:xx:xx:xx:xx  x@x.local (RSA)
bash $ 
Będzie
źródło
przykro mi to mówić, ale to nie jest ani „prostsze”, ani „mniejsze”, nawet „mądrzejsze” i nie przyjmuje innego podejścia niż wymienione powyżej. tylko skrypt używający więcej
programów
3
Co czyni to bezpieczniejszym, prawda? Możesz wprowadzać zmiany, ale dlaczego głosować? Nie zaproponowałem, aby było to lepsze rozwiązanie niż twoje ... Uważam, że bezpieczny plik tymczasowy jest lepszy i że potrzebne jest większe bezpieczeństwo do celów skryptowych. Ponadto powyższa wersja jest bezpieczna dla noclobbera.
Czy
W systemie FreeBSD (który domyślnie nie używa bash) wprowadziłem następujące zmiany: Zakładając, że bash jest instalowany z portów, zmień pierwszą linię na #!/usr/local/bin/bash. I wtedy nazywa się to poprzez dodanie funkcji jak w ostatnim wierszu: fingerprint_keys $@. Zapisałem skrypt jako fingerprints.bash, oznaczając go jako wykonywalny chmod u+x ./fingerprints.bash. Dodatkowo dodałem komentarz do pliku z linkiem do tej odpowiedzi, podobnie jak u góry # solution from "Will" on SO http://serverfault.com/a/615892/126742. Nazwij to tak ./fingerprints.bash ~/.ssh/authorized_keys.
derekv
1
@derekv: bardziej przenośną metodą jest użycie następującego hashbangu:, #!/usr/bin/env bashponieważ ścieżka do envjest bardzo przenośna i każe envwykonać Bash, o którym wie.
0xC0000022L,
7

One-liner oparty na sztuczce / dev / stdin z odpowiedzi ℝaphink i man xargs → PRZYKŁADY :

egrep '^[^#]' ~/.ssh/authorized_keys | xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<"%"'
akavel
źródło
Działa to świetnie, a biorąc pod uwagę, że jest to jednowierszowy, można go łatwo użyć do uruchomienia polecenia za pośrednictwem SSH. Dzięki!
Thibaut Barrère