はじめに
EC2 インスタンスや、Systems Manager で管理しているオンプレミスのマシンにリモートアクセスができる Session Manager という機能があります。従来は踏み台サーバーを使ってリモートアクセスを実現していたことが多かったと思いますが、踏み台サーバー自体に Public IP を持たせている場合はセキュリティ的にちょっときになります。こういった課題感をマネージドサービスで解決するのが、Session Manager という機能です。具体的な使い方はこちらの記事で検証をしました。
ただ、これでもセキュリティ的に気になる点はまだあります。ラップトップに AWS CLI を入れてリモートアクセスする構成を考えたときに、ラップトップに格納するアクセスキー・シークレットキーの取り扱いが気になります。仮に、大きな権限を持たせたアクセスキーが漏洩してしまったときに大変なことになるので、適切な管理が必要です。
この「適切な管理」で対処した方が良いポイントをいくつか整理してみましょう。
AWS が出しているベストプラクティス
まず、AWS がベストプラクティスを Document で公開しています。量が多いですが、それぞれの観点が網羅的に紹介されていて、とても有用なリソースです。この記事で紹介しきれないプラクティスもあるので、ぜひこちらも確認してみてください。
Systems Manager のセキュリティのベストプラクティス
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/security-best-practices.html
AWS アクセスキーを管理するためのベストプラクティス
https://docs.aws.amazon.com/ja_jp/accounts/latest/reference/credentials-access-keys-best-practices.html
IAM でのセキュリティのベストプラクティス
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html
この記事で扱うポイント
上記のベストプラクティスの中で、個人的に重要そうと思ったポイントをいくつか抜粋していきます。紹介しきれないものもあるので、ぜひ上の AWS Document も合わせてご確認ください。
- アクセスキーの取り扱い
- 最小限の権限設定
- MFA の有効化
- ログの有効化
- IP アドレス制限
- コマンド制限
- sudo の制限
- Start-Session の通知
アクセスキーの取り扱い
ラップトップに AWS CLI の実行権限を与えるためのアクセスキーの取り扱いについてです。ベストプラクティスに書いているのですが、そもそもアクセスキーを生成しない方法が紹介されています。アクセスキーを発行することで漏洩する恐れがあるなら、そもそも作らなければいいじゃん、ということですね。SAML で Okta や Azure AD みたいな Identity Provider を使うことで、一時的な権限を生成する方法です。
SAML 認証情報を使って、一時的なユーザー認証情報を取得する方法は次の URL で紹介されています。(ちょっと手間そうだけど・・・。)
また、Okta を使っている場合は、一時的なユーザー認証情報を生成する okta-awscli というツールがあるみたいですね。結構便利そうです。
あと他のプラクティスで紹介されているのが、アクセスキーの定期的な更新や、使っていないアクセスキーの削除などがありました。
アクセスキーのベストプラクティス
https://docs.aws.amazon.com/ja_jp/accounts/latest/reference/credentials-access-keys-best-practices.html
最小限の権限設定
アクセスキーが万が一漏洩したときに、その影響を最小限にするために、最小限の権限設定をするのがお勧めです。いくつかのサンプルが AWS Document で紹介されているので、具体的に方法を見ていきましょう。
IAM Policy で、Session Manager でアクセスする先の Node (仮想マシンのこと) を制限することが出来ます。例えば、次のような IAM Policy を設定します。
- Action で
ssm:StartSession
を指定しており、Session Manager の接続開始のみできる - Resource で
i-04c2e28d623aab574
を指定しており、特定の EC2 Instance に限定して接続ができる
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartSession"
],
"Resource": [
"arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-04c2e28d623aab574"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:TerminateSession",
"ssm:ResumeSession"
],
"Resource": [
"arn:aws:ssm:*:*:session/${aws:username}-*"
]
}
]
}
こんな感じで、IAM Policy を作成します。
上記の IAM Policy を設定した結果、接続を許可しているインスタンスに限定して接続できます。
> aws ssm start-session --target i-04c2e28d623aab574 --profile ssm
Starting session with SessionId: cliuser-sessionmanagertest-0fbe2fd72b3463556
sh-4.2$
sh-4.2$ whoami
ssm-user
sh-4.2$
以下のように、許可していないインスタンスではエラーになります。
> aws ssm start-session --target i-0f7fdbd2425d0cd4a --profile ssm
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/cliuser-sessionmanagertest is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-0f7fdbd2425d0cd4a because no identity-based policy allows the ssm:StartSession action
また、ssm 以外のサービスにはもちろんアクセスできません
> aws s3 ls --profile ssm
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
Session Manager の追加サンプル IAM ポリシー
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-restrict-access-examples.html
MFA の有効化
AWS CLI で MFA を有効化できます。仮にアクセスキーが流出しても MFA を持っていない人はコマンドが実行できないです。また、一時的なアクセスキーが流出した場合でも、デフォルトで 12 時間といった有効期限が設定されているので、一定時間後には使えなくなります。MFA を使ったアクセスキーの保護はかなり有効的な利用だと思います。
内容が多かったため、別の記事の検証内容を掲載します。
ログの有効化
Session Manager では、OS 上で実行したコマンドと、その結果を CloudWatch Logs 等に出力することができます。ログ出力の設定はデフォルトで ON になっているはずです。
いつ、どんなコマンドを実行して、どんな結果だったのかを後から追いやすくなります。このログを有効活用すると、後から操作履歴を追いやすくなります。
IP アドレス制限
IAM Policy の設定の中で、IP アドレス制限を掛けられます。最小限の権限設定と合わせて、IP アドレスの設定を加えることで、よりセキュアな構成が可能です。
次の IAM Policy の例をでは、 NotIpAddress
で書かれている IP アドレス以外は、アクセスを拒否します。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"xx.xx.xx.xx/32"
]
},
"Bool": {"aws:ViaAWSService": "false"}
}
}
}
例えば、次のように IAM Policy を作成したあとに、
IAM User や Group などに、そのポリシーを紐づけます。
すると、該当の IP アドレス以外からは、Session Manager の接続が禁止されました。
> aws ssm start-session --target i-04c2e28d623aab574 --profile ssm
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxx:user/cliuser-sessionmanagertest is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-04c2e28d623aab574 with an explicit deny in an identity-based policy
コマンド制限
Session Manager では、start-session
でリモート接続する以外にも、事前にコマンドを定義する Document を用意することで、コマンドを実行することができます。この機能と一緒に IAM Policy の制限を工夫することで、特定の Document のみ実行を制限させることできます。リモート接続で好きなコマンドを実行することを禁止できます。厳密な環境では、こういった制限をしていくことを検討してもいいかもしれません。
ちょっとやってみましょう。
事前準備として、Systems Manager で Document を作成します。
Document の名前と、Type を選びます。
次の YAML を入力します。これが、事前に定義するコマンドです。
-
commands: "tail -f {{ logpath }}"
と指定しており、tail -f コマンドを実行する -
logpath
の部分は、パラメーターになっていて、実行時に tail 対象のファイルを指定可能 -
allowedPattern
で受け付けるパラメータを正規表現でチェックする
---
schemaVersion: '1.0'
description: Document to view a log file on a Linux instance
sessionType: InteractiveCommands
parameters:
logpath:
type: String
description: The log file path to read.
default: "/var/log/amazon/ssm/amazon-ssm-agent.log"
allowedPattern: "^[a-zA-Z0-9-_/]+(.log)$"
properties:
linux:
commands: "tail -f {{ logpath }}"
runAsElevated: true
こんな感じで入力したら、Create Document を押します。
IAM Policy を次のように変更します。
-
"arn:aws:ssm:ap-northeast-1:xxxx:document/LogTail"
を追加することで、この Document の実行を許可します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartSession"
],
"Resource": [
"arn:aws:ec2:ap-northeast-1:xxxx:instance/i-04c2e28d623aab574",
"arn:aws:ssm:ap-northeast-1:xxxx:document/LogTail"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:TerminateSession",
"ssm:ResumeSession"
],
"Resource": [
"arn:aws:ssm:*:*:session/${aws:username}-*"
]
}
]
}
実際に、Document を使って実行してみましょう。
-
--document-name LogTail
と Document の名前を指定
aws ssm start-session \
--target i-04c2e28d623aab574 \
--document-name LogTail \
--profile ssm
実行例
- Document で指定しているとおり、
"tail -f {{ logpath }}"
のコマンドが実行されている
Starting session with SessionId: cliuser-sessionmanagertest-042c4337bcf51ef77
2022-12-29 05:19:19 INFO [ssm-session-worker] [cliuser-sessionmanagertest-042c4337bcf51ef77] [DataBackend] received plugin config message
2022-12-29 05:19:19 INFO [ssm-agent-worker] [MessageService] [EngineProcessor] [BasicExecuter] [cliuser-sessionmanagertest-042c4337bcf51ef77] master listener started on path: /var/lib/amazon/ssm/i-04c2e28d623aab574/channels/cliuser-sessionmanagertest-042c4337bcf51ef77
2022-12-29 05:19:19 INFO [ssm-session-worker] [cliuser-sessionmanagertest-042c4337bcf51ef77] [DataBackend] {"DocumentInformation":{"DocumentID":"cliuser-sessionmanagerte
別のログを見てみましょう
-
--parameters logpath="/var/log/boot.log" \
と指定しており、他のログファイルを指定
aws ssm start-session \
--target i-04c2e28d623aab574 \
--document-name LogTail \
--parameters logpath="/var/log/boot.log" \
--profile ssm
実行例
Starting session with SessionId: cliuser-sessionmanagertest-0db17cc2b75264163
Dec 29 03:39:06 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:07:40 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:30:20 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:55:16 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 05:20:13 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
しかし、この IAM Policy では、Shell を使ったリモート接続が可能です。
> aws ssm start-session \
--target i-04c2e28d623aab574 \
--profile ssm
Starting session with SessionId: cliuser-sessionmanagertest-0d320f50f4b162dfa
sh-4.2$
このリモート接続を禁止するため、 IAM Policy の変更が必要です。
-
"ssm:SessionDocumentAccessCheck":"true"
を指定することで、Resource
で指定したすべての条件が存在しないとエラーになる。つまり、Document のLogTail
を指定してstart-session
コマンドを実行しないとダメということになり、特定の Document のみが実行できる環境が出来上がる。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartSession"
],
"Resource": [
"arn:aws:ec2:ap-northeast-1:xxxx:instance/i-04c2e28d623aab574",
"arn:aws:ssm:ap-northeast-1:xxxx:document/LogTail"
],
"Condition":{
"BoolIfExists":{
"ssm:SessionDocumentAccessCheck":"true"
}
}
},
{
"Effect": "Allow",
"Action": [
"ssm:TerminateSession",
"ssm:ResumeSession"
],
"Resource": [
"arn:aws:ssm:*:*:session/${aws:username}-*"
]
}
]
}
IAM Policy を変更したあと、想定通りエラーになりました。
> aws ssm start-session \
--target i-04c2e28d623aab574 \
--profile ssm
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxx:user/cliuser-sessionmanagertest is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxx:instance/i-04c2e28d623aab574 because no identity-based policy allows the ssm:StartSession action
Document を指定した接続は、引き続き可能です。
> aws ssm start-session \
--target i-04c2e28d623aab574 \
--document-name LogTail \
--parameters logpath="/var/log/boot.log" \
--profile ssm
Starting session with SessionId: cliuser-sessionmanagertest-068857acd8ebe0559
Dec 29 03:39:06 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:07:40 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:30:20 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 04:55:16 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
Dec 29 05:20:13 ip-192-168-1-149 NET: dhclient: Locked /run/dhclient/resolv.lock
sudo の制限
Session Manager のリモート接続では、Linux では ssm-user
が利用されます。これは、デフォルトで sudo コマンドが利用できるので、root 権限が付与されています。sudoers を編集することで、sudo を禁止できます。詳細は次の Document を参照してみてください。
Start-Session の通知
最後に、Session Manager で start-session
のコマンドを実行したときに、メールや Slack などへ通知ができます。これによって、予期していないタイミングやユーザーによるリモート接続を早期に検知できます。検知できたら、管理者によるセッションの削除や、IAM User の削除などが考えられます。
EventBridge を使ってイベントを拾えるので、そこから SNS だったり Lambda だったりで通知の仕組みが作れます。
参考 URL
Systems Manager のセキュリティのベストプラクティス
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/security-best-practices.html
AWS アクセスキーを管理するためのベストプラクティス
https://docs.aws.amazon.com/ja_jp/accounts/latest/reference/credentials-access-keys-best-practices.html
IAM でのセキュリティのベストプラクティス
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html