LoginSignup
3
2

More than 1 year has passed since last update.

Session Manager をローカルから利用するときに、セキュアな環境にするときの考慮点

Posted at

はじめに

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 を作成します。

image-20221228185555613.png

 

上記の 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 になっているはずです。

いつ、どんなコマンドを実行して、どんな結果だったのかを後から追いやすくなります。このログを有効活用すると、後から操作履歴を追いやすくなります。

image-20221229130804539.png

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 を作成したあとに、

image-20221229131752379.png

 

IAM User や Group などに、そのポリシーを紐づけます。

image-20221229131840990.png

 

すると、該当の 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 を作成します。

image-20221229135206565.png

 

Document の名前と、Type を選びます。

image-20221229135831409.png

 

次の 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 を押します。

image-20221229135908746.png

 

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

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2