如何获取.ssh / authorized_keys(2)文件的所有指纹


39

有没有一种简单的方法来获取在.ssh / authorized_keys ||中输入的所有指纹的列表。.ssh / authorized_keys2文件?

ssh-keygen -l -f .ssh/authorized_keys 

只返回第一行/条目/公钥的指纹

用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"
        )
    }
}'

但是我没有找到更简单的方法或ssh命令吗?


为了可靠地执行此操作,您必须考虑authorized_keys文件中的options字段,该文件ssh-keygen位于。我正在寻找一种可靠的方法来解析它,但是这个答案涵盖了我能想到的最好的方法。
starfry

Answers:


45

这是另一种使用纯bash的临时文件,其中没有临时文件:

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

您可以轻松地使其成为您的函数.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}"
}

并调用:

$ fingerprints .ssh/authorized_keys

1
很好@Raphink,谢谢。添加了code.childno.de/marcel/changeset/afdce0dd ;)注意:ssh-keygen -l -f /dev/stdin似乎无法在Mac上运行。尽管如此,它与服务器无关,但与gnaa apple 有关,还是BSD的“问题”出现了/dev/stdin is not a public key file.
childno͡.de

1
从阅读/dev/stdin不是一般的好主意,这是更好地使用-,但由于某种原因ssh-keygen不知道-...
ℝaphink

在Mac上无法使用?
2014年

1
如果键前面带有选项,则此方法不起作用。
starfry

1
@ℝaphink:我希望local file="${1:-$HOME/.ssh/authorized_keys}"允许它不带任何参数地工作,并且默认为普通~/.ssh/authorized_keys文件,并引用< "$file"用作while循环输入的内容。
0xC0000022L

8

这是一种可移植的方式,用于显示给定文件的所有关键指纹,并在Mac和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
}

用法示例:

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 $ 

遗憾的是,但这既不是“更简单”,也不是“更小”,甚至也不是“更智能”,并且除了上面列出的方法外,没有采取其他方法。只是使用更多错误处理程序的脚本;)
childno͡.de2014年

3
哪个更安全,对吗?欢迎您进行编辑,但为什么要投票?我没有提议这是比您更好的解决方案……我觉得一个安全的临时文件更好,并且出于脚本目的需要更多的安全性。另外,以上版本是noclobber安全的。
2014年

对于FreeBSD系统(默认情况下不使用bash),我进行了以下更改:假设从端口安装了bash,请将第一行更改为#!/usr/local/bin/bash。然后,我将其添加为最后一行来调用该函数:fingerprint_keys $@。我将脚本另存为fingerprints.bash,并用标记为可执行chmod u+x ./fingerprints.bash。另外,我在文件顶部添加了注释,并带有指向此答案的链接,就像在顶部附近# solution from "Will" on SO http://serverfault.com/a/615892/126742。这样称呼它./fingerprints.bash ~/.ssh/authorized_keys
derekv 2015年

1
@derekv:更可移植的方法是使用以下hashbang:,#!/usr/bin/env bash因为for的路径env是非常可移植的,并且告诉env执行已知的Bash。
0xC0000022L

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.