未使用の apt キーを識別して削除するにはどうすればよいですか?

未使用の apt キーを識別して削除するにはどうすればよいですか?

通常のインストールでは、PPA 用であろうと他のソース用であろうと、いくつかの apt GPG キーが追加されますが、後で使用されません。

どのキーが実際にどのリポジトリに使用されているかを GUI (ソフトウェア プロパティ) で識別するのは困難です。

どのキーが使用されているかを簡単に識別して、他のすべてのキーを削除する方法はありますか?

私の意見では、これはセキュリティ上、何らかの意味合いがあります。リポジトリの所有者が秘密鍵を紛失し、新しい鍵を使用するようにリポジトリを更新した場合、多くの人が古い (信頼できない) 鍵をインストールしたままになっているのではないでしょうか。

答え1

未使用のキーを削除するのは非常に簡単ですが、キーを追加するときと同様に、どのキーが使用されなくなり、削除できるかを判断するのはユーザーの責任です。

まず、現在持っている apt キーを一覧表示しますsudo apt-key list

不要になったキーを特定したら、 で簡単に削除できますsudo apt-key del KEYID

list コマンドを使用すると、通常、各キーが何であるかを確認できます。特に、ppa からのキーの場合は、通常、uid に「Launchpad PPA for John」などが含まれるため、そのキーが何であるかを確認できます。したがって、ソースからその ppa を削除し、使用しなくなった場合は、安全に削除できます。

特定のキーがどこから来たのかを知るために、Google で簡単に検索する必要がある場合があります。たとえば、mono キーの uid は「Xamarin Public Jenkins」ですが、xamarin を Google で検索すると、そのキーがどこから来たのかがわかります。また、不明な場合は、いつでも bash 履歴に戻って、追加したキーを見つけることができます。

man apt-key詳細情報とその他のコマンドについてはこちらをご覧ください。

答え2

未使用の GPG キーを自動的に識別 (およびオプションで削除) するスクリプトを作成しました。

#!/bin/bash
#------------------------------------
# Script that identifies and optionally removes unused trusted gpg keys.
# These keys are usually added to install software from non-standard repositories (e.g. PPAs)
# TODO:
# - what if source repo is not reachable
# - dunno why but the delete doesn't actually delete keys anymore ¯\_(ツ)_/¯
# - dunno why but slack key gets detected as unused even if slack is on the system ¯\_(ツ)_/¯
#------------------------------------

usage() { 
    echo "Usage: $(basename "$0") [-b] [-d] [-h]" 1>&2
    echo "prints to stdout the unused keys in the format <keyid> <userid>" 1>&2
    echo "-b, backups trusted.gpg and trusted.gpg.d/ appending .bak (requires superuser)" 1>&2
    echo "-d, deletes unused keys (requires superuser)" 1>&2
    echo "-h, shows this help" 1>&2
}

backup=0
delete=0

while getopts ":bdh" o; do
    case "${o}" in
        b)
            backup=1    
            ;;
        d)
            delete=1
            ;;
        h)
            usage
            exit 0
            ;;
        *)
            usage
            exit 1
            ;;
    esac
done
shift $((OPTIND-1))

# create directory in /tmp with random name
tmpdir=$(mktemp -d)
#echo "storing tmp files in $tmpdir" 1>&2

# get list of sources
grep -h ^deb /etc/apt/sources.list /etc/apt/sources.list.d/*.list > "${tmpdir}"/sources

# get list of releases files
# first sed expression removes content between square brackets (such as architecture specifications)
# awk is used to get only the source url and the distro we are using
# the 2 subsequent sed expressions are used piece everything together and generate the url to the Release.gpg file we need
# sort and uniq are used to eliminate duplicate entries
sed -e "s/\[.*\] //" "${tmpdir}/sources" | awk '{print $2" "$3}' | sed -E -e "s/\/? /\/dists\//" | sed -e "s/$/\/Release.gpg/" | sort | uniq > "${tmpdir}"/releases

# for each source, compute the keyid and save it in a file
while read -r url; do
    domain=$(echo $url | awk -F/ '{print $3}')
    #echo "processing ${url}"
    wget -q -T 10 -O "${tmpdir}"/"${domain}"_Release.gpg "$url"
    gpg --list-packets "${tmpdir}"/"${domain}"_Release.gpg | grep "keyid" | grep -Eo "[0-9A-F]{16}" >> "${tmpdir}"/sourcekeyidstemp
done <"${tmpdir}"/releases

# remove duplicate entries
sort "${tmpdir}"/sourcekeyidstemp | uniq > "${tmpdir}"/sourcekeyids

# for each trusted gpg key, extract his keyid and userid
gpg --list-packets /etc/apt/trusted.gpg | grep -A 8 "public key packet" | grep -E "keyid:|user ID" | grep -oE "[0-9A-F]{16}|\".*\""  | awk '{(getline tmp); print $0,tmp}' > "${tmpdir}"/trustedkeys

for f in /etc/apt/trusted.gpg.d/*.gpg; do
    gpg --list-packets "$f" | grep -A 8 "public key packet" | grep -E "keyid:|user ID" | grep -oE "[0-9A-F]{16}|\".*\""  | awk '{(getline tmp); print $0,tmp}' >> "${tmpdir}"/trustedkeys
done

# for each trusted gpg key, check if in use
touch "${tmpdir}"/unusedkeys
while read -r line; do
    keyid=$(echo "$line" | cut -d "\"" -f 1)
    userid=$(echo "$line" | cut -d "\"" -f 2)
    check=$(grep ${keyid} "${tmpdir}"/sourcekeyids)
    if [ -z "$check" ]; then
        echo "${keyid} ${userid}" >> "${tmpdir}"/unusedkeys
    fi 
done <"${tmpdir}"/trustedkeys

# backup gpg keys 
if [ $backup -eq 1 ]; then
    sudo cp /etc/apt/trusted.gpg /etc/apt/trusted.gpg.bak
    sudo cp -r /etc/apt/trusted.gpg.d/ /etc/apt/trusted.gpg.d.bak
fi

# delete unused gpg keys
if [ $delete -eq 1 ]; then
    while read -r line; do
        keyid=$(echo "$line" | cut -d "\"" -f 1)
        sudo apt-key del "$keyid" >/dev/null 
    done <"${tmpdir}"/unusedkeys
    echo "deleted keys:"
fi

# print unused keys
cat "${tmpdir}"/unusedkeys

かなり扱いにくいですが、動作します。バグがある可能性がありますので、自己責任でご使用ください。

スクリプトのワークフローは次のとおりです。

  • オンラインリポジトリからRelease.gpgファイルを取得して、すべてのaptソースのKEYIDを抽出します。
  • すべてのローカルの信頼できるキーの KEYID を抽出します。
  • いくつかの KEYID がローカルに存在し、オンライン ソースから抽出されたものには存在しないかどうかを確認します。それらは未使用のキーです。

編集: リンクを修正しました 編集: リンクを修正するのに疲れたので、ここにコードを貼り付けました

関連情報