どうも。小林です。
3度目の投稿にして初めて技術的なことを書こうとしています。
以前書いたAWS認定 セキュリティの対策本にて踏み台サーバ構成の話を書きました。
「インターネットに公開するEC2インスタンスの数は最小にしようね」というお話だったんですが、 今はSSM(AWS Systems Manager)のSession Managerを使えば踏み台サーバがなくとも 直接プライベートサブネット含む各インスタンスのシェル環境を使えるようになってきています。
ということは踏み台サーバへSession Managerで接続するようにすれば、踏み台サーバをインターネットに公開しなくて良いのでは?と思い、 いろいろ考えてみたことを書いておきたいと思います。
なお、計画と検証の記録が主な話で、最初の目論みどおりにはならなかったことをお断りしておきます。
この内容がどなたかの参考になれば幸いです。
そもそもなぜ踏み台サーバが必要なのか
「セキュリティ上必要だから」ではなく、「最初に言ってたとおり、踏み台サーバを使わずSession Managerで直接対象のインスタンスにログインすればいいのでは?」という問いに対する答えです。
主に下記2点をその理由としています。
作業者の環境を統一するため
ネットコムでは同じ案件を担当していても、人によって使っているパソコンのOSが違っていることがあります。
社内標準はWindowsなのですが、業務特性によってmacOSを使う人も。(Linuxはさすがにいないはずですが。)
とはいえ、チームで運用管理をする以上、担当者が同じ環境で作業できるように共通の環境を用意する方がなにかと便利です。作業ログを取得するため
こちらはセキュリティや監査目的です。
ログの取り方は色々あるのですが、作業の起点がわかっていることでログを追うことも容易となるという考えです。
まずは設計
きっかけは踏み台サーバのリプレイスを考えていたところから始まりました。
踏み台サーバを設計するうえでの主な考慮ポイントは以下です。
ログをどうやって取るか
ユーザがどんな作業を行ったのかを後から追えるようにするための全文ログを想定しています。
「後から追う」ということを考えるとユーザごとかつセッションごとに分割して取得できると良さそうです。
現行の踏み台サーバでは専用のアプライアンス製品を介してのアクセスによってログを取っていました。接続経路と接続元制限
当然ながらどこからでも接続できるようにはしたくありません。
オフィスもしくはVPN環境からというように何らかの接続元制限が必要です。
現行の踏み台サーバではファイアウォールによるIP制限をしていました。認証ユーザの管理
踏み台サーバへのログイン認証につかうユーザのことです。
できるだけ管理を楽にしたいところです。
現行の踏み台サーバではOSにユーザを作ってました。
この辺を考えているときに思いついたのが今回冒頭に挙げたSSMのSession Managerでした。
Session Managerとやらを使うと、
- AWSの機能でログが取れて
- IAMで接続元制限ができるし
- IAMのユーザで認証ができるらしい
よし、使ってみるか。と。
ただ、どう動くかは実際に使ってみないとよくわからなかったのでいろいろ試してみることにしました。
Session Managerで接続する踏み台サーバを作ってみよう
これは簡単で、AmazonLinuxのインスタンスを立てればそこにSSMエージェントが入っているので、すぐにSession Managerで接続することができます。
なお今回は接続元はブラウザではなく、AWS CLIを使って接続することを想定しています。
ログはどう出るの?
Session Managerの設定で、S3へログを転送することができます。
ログの内容としては期待どおり操作の全文ログが出たのですが、気になったのがログファイル名。
接続の際のIAMの使い方で違いが出てきます。
踏み台サーバのあるアカウントのIAMユーザ
画像の上段。
こちらだとファイル名から接続したユーザが誰で、更新日時からいつのアクセスかがわかりやすいですね。
踏み台サーバのないアカウントからのスイッチロール
画像の下段。
CLIによるランダムなセッション名がファイル名になるので、誰のアクセスかがわからない…
ファイル名にセッション名が入るのですが、IAMユーザだとセッション名にユーザ名がそのまま入るので上のように見やすくなるのでした。
現環境では基本的にこちらの方式(IAMユーザ管理用アカウントがあって、利用するアカウントにスイッチロールして使う方式)なので、 ログはこちらの形式になるのですが、運用には向いてないですね…
一応補足ですが、.aws/credentials、.aws/configに記載するスイッチロールの設定に role_session_name
を指定することでセッション名を固定化することは可能です。
ただし設定実施は利用者に委ねられるので、運用に向いていないことには変わりません。
接続元制限は?
接続するために利用するIAMポリシーにこんな感じで書きます。
{ "Effect": "Allow", "Action": [ "ssm:StartSession", "ssm:ResumeSession" ], "Resource": [ "踏み台インスタンスのARN" ], "Condition": { "IpAddress": { "aws:SourceIp": [ "許可する接続元IPアドレス" ] } } }
注意点ですが、IAMユーザに直接このIAMポリシーをアタッチする場合、アタッチされたユーザがこのポリシーを変更すると接続元IPアドレス制限を変更できてしまいます。
よって、踏み台接続に使うユーザにはIAMの変更権限を付けないなどの対策をしておく必要があります。
(とはいえ、IAMロールに付ける場合だったり、従来どおりSecurity GroupでIPアドレス制限するときも同様に不用意に設定を変更されないような制限については、いずれにせよどこかで考えておく必要があります。)
認証について
認証はIAMですが、OSで使うユーザはデフォルトで共通のssm-userになります。
なかなか強い権限のあるユーザです。
認証するIAMユーザに「SSMSessionRunAs」というタグを付けてOSのユーザ名を書いておけば別のユーザを指定して使えるのですが、
それだと管理が面倒…
さてどうするか
Session Managerを使って接続する踏み台サーバを作ってみて感じたメリットはこちらです。
踏み台サーバインスタンスのSecurity Group管理が不要
冒頭でこんなことを書きました。
「インターネットに公開するEC2インスタンスの数は最小にしようね」と。
この方法だとIAMで接続元IPアドレスの管理をするので、踏み台サーバインスタンスのSecurity Groupのインバウンドルールには何も入っていません。
つまりインターネットに公開するEC2インスタンスの数を0にすることが可能です。IAM認証が利用できる
IAMの2段階認証やスイッチロールなどを利用して認証ができるのでセキュリティレベルは高いと思います。ログが取りやすい
踏み台サーバのあるアカウントにIAMユーザを作るならログの管理も含めてよさそうに思います。
一方デメリット。
スイッチロールで認証する場合はログ管理に難あり 別アカウントからスイッチロールして利用するならログファイル名がわかりにくくなるので管理に難があります。
ログイン時のユーザがssm-user固定
IAMユーザのタグでも指定できますがそれはそれで管理が面倒…
Session Managerのセッションを通したSSH接続はどうだろう
実はSession Managerの機能としてSSH接続ができるという機能があります。
docs.aws.amazon.com
接続経路はSession Managerの機能を使うのですが、OSへのログインをSSHで行うというイメージです。
メリットとして、
SSHと操作感が同じ
通常のSSH接続と同様のコマンドで接続することができ、SSH鍵認証でログインすることができます。
SCPでのデータ転送も可能です。SSMにセッション履歴が残る
接続履歴がAWSに残ります。
※後述しますが、ログイン後の操作ログは取れません。踏み台サーバインスタンスのSecurity Group管理が不要
Session Managerが接続経路を担うので、Security Groupの22番ポートのインバウンド許可が不要です。ログインユーザの切り替えが楽。
OSログイン認証はSSHなのでSSHコマンドにて指定すれば任意のユーザでログインできます。
ログインは鍵認証なので、セキュリティ面も安心です。
デメリットはこちらです。
操作の全文ログは取れない
この方法ではSSH接続内で行われた操作を記録することはできません。
ログは別の方法で取る必要があります。SSHの鍵管理が必要
ある程度は仕方ないですね。
ただ、Session ManagerのIAM認証+SSH鍵認証になるのでよりセキュリティは強固です。
SSHを使わずにSession Managerのssm-userを使うユーザが現れない?
Session Managerの設定にて「セッションのオペレーティングシステムユーザーを指定する」の
「Linux インスタンスの Run As サポートを有効にする」にチェックを入れて、
「Operating system user name」を空にしておけばユーザ指定をしないSession Manager接続ができなくなります。
こんなエラーが出ます。
An error occurred (BadRequest) when calling the StartSession operation: Invalid RunAs username. Set default username in Session Manager Preferences page.
Session Managerのユーザ指定はIAMユーザの「SSMSessionRunAs」タグで行うので、タグが付いていなければSSHを使ったSession Manager接続しかできなくなります。
逆に言えば、IAMユーザの「SSMSessionRunAs」タグでユーザ指定をすればSession Managerアクセスができるので、SSHを使ったSession Manager接続とユーザ指定したうえでのSession Managerアクセスを併用することができます。
なお、下記のようにIAMポリシーに「ssm:SessionDocumentAccessCheck」を使えば、SSHを使ったSession Manager接続のみを許可することも可能です。
{ "Effect": "Allow", "Action": [ "ssm:StartSession", "ssm:ResumeSession" ], "Resource": [ "arn:aws:ssm:*:*:document/AWS-StartSSHSession", "踏み台インスタンスのARN" ], "Condition": { "IpAddress": { "aws:SourceIp": [ "許可する接続元IPアドレス" ] }, "BoolIfExists": { "ssm:SessionDocumentAccessCheck": "true" } } }
まとめ
Session Managerだけで全ての要件を満たすことはできませんでしたが、インターネットに公開しない踏み台サーバを作成するということは可能でした。
単なる可能/不可能ということだけでなく、運用まで考えて何が良い/足りないという判断をするにはいろいろ触って試すことが大切ですね。