Linux
AWS
SSH
EC2
S3

S3に置いた公開鍵でSSH認証したい

なぜ?

  • サーバが増えると、各ユーザの公開鍵を更新するのが大変 (ansibleとか使ってても)1
  • LDAPやDB等を使うにしても、サーバ構築・維持の手間を敬遠
  • DRサイト等の複数拠点に鍵を更新する場合にS3だと楽(aws s3 sync とか)でVPNで繋がっている必要も無い

どうやる?

  • /etc/ssh/sshd_config で AuthorizedKeysCommand を指定する
  • 指定するコマンドは ssh-s3-helper
  • S3バケットを用意して、SSH公開鍵をアップロードしておく

実行環境

  • go 版 (ssh-s3-helper.go)
    • go 1.6.2 で動作確認済み
  • sh 版 (ssh-s3-helper.sh)
    • /bin/sh と、curl または wget で 動作確認済み

Bucketポリシーの設定

{
    "Version": "2012-10-17",
    "Id": "Policy1513788471347",
    "Statement": [
        {
            "Sid": "Stmt1513788469343",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your_s3_bucket/*",
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpc": "your_vpc_id"
                }
            }
        }
    ]
}

ssh-s3-helperの設定

/etc/default/ssh-s3-helper

s3_bucket=your_s3_bucket
s3_region=ap-northeast-1
s3_prefix=ssh/
  • s3_bucket
    • バケット名
  • s3_region
    • リージョン名
  • s3_prefix
    • S3バケットにおけるprefix (不要なら空にする)

/etc/ssh/sshd_config の設定

AuthorizedKeysCommand /usr/local/bin/ssh-s3-helper %u
AuthorizedKeysCommandUser nobody
  • /usr/local/bin/ssh-s3-helper.sh は、以下設定で配置を想定
    • ユーザー root、グループ root
    • パーミッション 555
  • このままの設定をお勧めします

    • AuthorizedKeysCommandUserは root を使う例が見つかったりしますが、不用意に 強すぎる権限を与える必要はないです (%u も止めた方が安心だと思います)
    • nobody か 本用途のために専用アカウントを作るのが良いかと思います
    AuthorizedKeysCommandUser
             Specifies the user under whose account the AuthorizedKeysCommand is run.  It is rec‐
             ommended to use a dedicated user that has no other role on the host than running
             authorized keys commands.  If AuthorizedKeysCommand is specified but
             AuthorizedKeysCommandUser is not, then sshd(8) will refuse to start.
    
    • 「 use a dedicated user that has no other role on the host」とあり、他に役割のないアカウントを指定するのが推奨となっています(man sshd_configより)

補足

  • ssh-s3-helper で 公開鍵が得られなかった場合は、AuthorizedKeysFile (~/.ssh/authorized_keys) が参照されるとのこと

    If a key supplied by AuthorizedKeysCommand does not successfully authenticate and 
    authorize the user then public key authentication continues using the usual 
    AuthorizedKeysFile files.
    
    • man sshd_configより
  • S3が応答しない場合に備えて、~/.ssh/authorized_keys を置いた緊急用アカウントがあった方がよさそう

さらに

  • S3バケットにssh用の公開鍵をせっかく置いたなら...、次のようにするとsudoについてもLDAP等を使った外部認証より、ずっと楽に楽になるのではと妄想中
    • libpam-ssh-agent-auth用のauthorized_keysをS3においた公開鍵から生成
    • sudo の 認証に libpam-ssh-agent-auth を使う
      • この場合、ssh用とは別にsudo用の公開鍵を作る (prefix を sudo/ でアップロードしておく)
      • クライアント側でssh-add するときは -t で lifetime を指定しておく
    • サーバ上のアカウントにはパスワードが無くても、SSH公開鍵でのSSH認証とsudo認証が可能になる
    • libpam-ssh-agent-auth について

  1. SSHしたら負け と言えるほど成熟した環境なら、こんな物すらいらないはずですけども