SSHの鍵管理は、セキュリティと利便性のトレードオフがある悩ましい問題です。AWSなど他サービスのアカウントが絡んでくるとなおさらです。今回はそんな悩みを、 AWS Systems Manager ( 旧称 SSM ) を使って、シンプルかつよりセキュアにしたお話をしたいと思います。
はじめに
こんにちは。エンジニアの小川です。SSHの鍵管理はみなさんどのようにされているでしょうか?一般的には1ユーザーにつき、1つの秘密鍵 / 公開鍵のペアが常かと思います。ただ、この管理は厳密にしようとすると非常に悩ましい問題です。
キッチハイクではAWS Systems Managerが提供するSession Managerを使うことで、その悩みにひとつ道筋をつけることができました。今回はその導入によって、問題がどのように解決されたのか、導入手順も交えながらご紹介したいと思います。
注記 : AWS Systems Manager は、以前は Amazon Simple Systems Manager ( SSM ) および Amazon EC2 Systems Manager ( SSM ) と呼ばれていました。
SSH鍵管理に関する2つの悩み
1. 鍵管理のコスト
SSHの鍵管理は悩ましい問題である、と書きましたが、それは端的に言えばセキュリティと可用性のトレードオフの問題です。
踏み台サーバー経由で各サーバーに接続するのは定番の方法ですがいくつかのバリエーションがあります。 接続ユーザーごとに公開鍵を登録する、それに加えてユーザごとにアカウントを作るなどです。
セキュリティを強固にしようとするならば、踏み台サーバーにユーザーごとのアカウントを作ることとなります。どのユーザーがどこのサーバーに接続したかが分かるようになり、あとからログを追いやすくなります。
ただ、その一方で管理作業は複雑になってきます。新しく接続する必要のあるユーザーが増えると、公開鍵の登録だけでなく、ユーザーの作成などの作業が発生して、管理コストが上がっていきます。
さらに管理のミスをするリスクも増えます。サーバーに接続する必要がなくなっても、サーバーに配置した公開鍵や、ユーザーの削除が漏れていて、意図しないSSH接続ができてしまうようなケースです。
2. AWSのIAMユーザー管理とSSHの鍵管理で同じような管理作業が発生する
もうひとつ、AWSを使っている場合は、SSH管理に加えて同じような領域、同じような単位の管理作業が増えることになります。
AWSを使っている場合は、開発に新規メンバーが入ってきたら、インフラ関連の作業として、SSH鍵の設定とIAMユーザーの新規作成はセットになっていることが多いのではないでしょうか。
同じインフラ作業の領域ながら、AWSのIAMユーザーとSSHの鍵の管理は別々となります。もしメンバーが開発から離れた場合、IAMユーザーの削除も必要ですし、SSHの鍵の無効化処理も別に必要となります。
こうなってくると、IAMでSSHに接続するユーザーの管理もできたら楽でいいな・・・と思ってきますね。
AWS Systems Manager Session Manager
そんな悩みを解決するのがAWS Systems Manager Session Manager(以下 Session Manager)です。 AWS Systems Manager は、以前は SSM ( Amazon Simple Systems Manager ) と呼ばれていました。
Session ManagerはAWS Systems Managerの機能のひとつで、ブラウザシェルやCLIからEC2インスタンスにアクセスする機能を提供してくれます。
Session Managerのメリット
このSession Managerを使うことで以下のようなメリットがあります。
- SSHポートを開けずに済む
- 踏み台サーバが不要になる
- サーバーへのアクセス権限をIAMで管理できる
- CloudTrail、CloudWatchLogsでログを取れる
SSHポートを開かずに済む
- Session ManagerではSession ManagerエンドポイントへのアクセスとなるのでSSHのポートを開ける必要がなくなります。
踏み台サーバが不要になる
- Session Managerを使うと対象のインスタンスがプライベートサブネットにあっても直接接続ができます(Private Linkの設定が別途必要)。
IAMポリシーでインスタンスへのアクセス制御を一元管理化できる
- SSHでのアクセスではなくなるので、SSH鍵管理が不要となります。 IAMポリシーで対象サーバーへのアクセスを一元管理することができます。
CloudTrail、CloudWatchLogsでログを取れる
- 別途の転送設定をしなくても接続のログをCloudTrail、CloudWatchLogsで取ることができます。どのサーバーにどのユーザーが接続したかが分かります。
Session ManagerでSSHトンネリング
すばらしいですね!上記のメリットだけ聞くと、Session Managerに全面移行したくなります。ですが、Session Managerには以下の制限があります。
- ファイル転送ができない
- ポート転送ができない
なので、ふだんSSH(ないしはSCP)でやれていることの完全代替とはなりません。特にファイル転送ができないとなるといろいろと困るのではないでしょうか。
ではSession Managerを使いつつ、この制限を迂回できる手段はないのでしょうか・・・?
その手段が、2019年からサポートされたSession ManagerでのSSHトンネリングです。
セッションマネージャーが SSH と SCP のトンネリングサポートを開始
この機能を使うことで、SSH鍵管理から完全脱却とはいきませんが・・・、セキュリティを担保しつつ、より管理を楽にすることができます。
キッチハイクでもこの方式を採用することで、運用を楽にすることができるようになりました。以降では具体的な導入方法と実際に導入してみての所感について書いていきたいと思います。
Session Managerの設定
まずはSession Managerの設定です。
1. EC2インスタンス側の設定
Session Managerを使用するには、対象のEC2インスタンスにSSM Agentがインストールされている必要があります。Amazon Linux2であればデフォルトでインストールがされているので楽です。 SSHトンネリングの機能を使うにはバージョン 2.3.672.0 以上がインストールされている必要があるので予め確認をしてください。
次に、対象のEC2インスタンスにIAMロールをアタッチする必要があります。
この設定には高速セットアップを使うと非常に楽です。EC2インスタンスに対し、Systems Manager用のIAMロールをよしなにアタッチしてくれます。
AWS Systems Manager 高速セットアップ - AWS Systems Manager
マネージドインスタンスに対象のインスタンスが表示されていれば設定は完了です。
なお、EC2インスタンスに既に別のIAMロールをアタッチ済みの場合はこのセットアップでは上手くいかないのでご注意ください。既存のIAMロールに追加で権限を付与する必要があります。
一覧に出てこない場合のトラブルシューティングはこちらの資料が参考になります。
2. IAMユーザーへのポリシーアタッチ
つづいて、サーバーに接続するユーザー向けにIAMポリシーをアタッチします。
のクイックスタートデフォルト IAM ポリシー - AWS Systems Manager
ステップ 8: (オプション) を通じて SSH 接続を有効にする - AWS Systems Manager
上記を参照に以下のようなIAMポリシーを作成して、IAMユーザー(or グループ)にアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:StartSession" ], "Resource": [ "arn:aws:ec2:region:987654321098:instance/i-02573cafcfEXAMPLE", "arn:aws:ssm:region:account-id:document/SSM-SessionManagerRunShell", "arn:aws:ssm:*:*:document/AWS-StartSSHSession" ], "Condition": { "BoolIfExists": { "ssm:SessionDocumentAccessCheck": "true" } } }, { "Effect": "Allow", "Action": [ "ssm:DescribeSessions", "ssm:GetConnectionStatus", "ssm:DescribeInstanceProperties", "ec2:DescribeInstances" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ssm:TerminateSession" ], "Resource": [ "arn:aws:ssm:*:*:session/${aws:username}-*" ] }, { "Effect": "Allow", "Action": [ "kms:GenerateDataKey" ], "Resource": "key-name" } ] }
3. クライアントの設定
最後にクライアント側の設定です。以下ではmacOS前提で書いていきます。
AWS CLIがインストールされていない場合は、AWS CLIをインストールします。Homebrewがお手軽です。
$ brew install awscli
プラスして、Session Manager用のプラグインをインストールします。
$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
つづいてSSH接続の設定をします。 ~/.ssh/config
に以下の設定を追記します
host i-* mi-* ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
以上でクライアントの設定は完了です。SSHでサーバーに接続してみましょう。 以下のようにIPではなくインスタンスIDな点だけを除けば、接続方法は同じです。
$ ssh -i ~/.ssh/key ec2-user@i-xxxxxxxxxxxxxx
導入後の実運用について
一言でいえば、既存のSSH運用の体験を損なわずに、アクセス管理をIAM側に寄せて、SSH鍵の管理をシンプルにすることができました。
具体的には、メンバーが抜けることがあっても、IAMユーザーを削除するだけで済むようになりました。
SSH鍵管理を完全になくすには至りませんでしたが、IAMとSSH鍵の2つの組み合わせでアクセスを管理するようになったため、SSH鍵の管理を個人単位でなくしても、アクセス制御ができるようになりました。
現在、キッチハイクではSSH鍵の管理単位をサーバーの環境ごとにしています。これにより、メンバーの出入りごとのSSH鍵の設定および削除作業の手間を減らすことができました。(ただし、念の為SSH鍵の定期的な入れ替えは必要かと思います)
また、ログについてもCloudTrailでログが流れてくるので、以前と遜色なく使えています。もともと、SSHのログをCloudWatchLogsへログ転送していたため、ロググループとフォーマットが変わっただけでほぼそのまま移行ができました。どのユーザーがどのサーバーに接続したかもログに出力されるので管理観点からもメリットがあります。
まとめ
以上、Session ManagerとSSHの組み合わせによるインスタンスの接続管理について述べてきました。まとめると以下となります。
- Session Managerを使うことでインスタンスの接続管理をIAMに一元管理できる
- Session ManagerのSSHトンネリングを使うことで、SSH機能をそのままに代替できる
- 結果、インスタンスの接続管理を大幅にシンプルにすることができた
AWSを使われているのであれば、SSH鍵管理の悩みを低減してくれる方法かと思います。本記事が参考になれば幸いです。
参考資料
最後に導入時に参考にさせていただいた記事の一覧です。こちらも是非ご覧いただければと思います。
- 踏み台サーバの鍵(公開鍵・秘密鍵)の管理方法について比較してみた|スクショはつらいよ
- セッションマネージャー越しにSSHアクセスすると何が嬉しいのか | DevelopersIO
- AWS Session ManagerのSSH接続を導入した事例紹介 - WonderPlanet Developers’ Blog
- Session Manager で SSH/SCPをトンネリングしてEC2に接続する - Qiita
特に最初の記事は、SSH鍵管理のパターンが整理されていてSession Managerのメリットがとてもわかり易いです。
We're Hiring
キッチハイクでは、AWSが得意なエンジニアを募集中です!