SSM セッションマネージャーでサーバー上の操作ログを取得

SSMセッションマネージャーを使ってサーバーメンテナンス操作ログを徹底的に記録してみます。
2019.08.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな吉井 亮です。

AWS 上の EC2 に対してリモートでメンテナンスする際に
監査の要件でサーバー上の操作ログを取得しければならないシステムは数多いと思います。

今回はセッションマネージャーを使って
サーバーメンテナンス操作ログを徹底的に記録してみます。

前提

以下のような前提を置きました。

  • リモートからのメンテナンスは必ず踏み台サーバーを経由する
  • 踏み台サーバーへはセッションマネージャー経由でログインする
  • SSH ポートは開放しない
  • 踏み台サーバーへのアクセス許可は IAM で管理
  • 踏み台サーバーは Amazon Linux 2
  • ログインはメール通知
  • ログイン後の操作ログは S3 へ保管

準備

リモートメンテナンスを行うクライアント PC に
AWS CLISession Manager Plugin をインストールします。

インストール方法は最新情報を確認し、最新バージョンをインストールするようお願いします。

Windows に AWS CLI をインストールする
Windows に Session Manager Plugin をインストールする

macOS に AWS CLI をインストールする
macOS で Session Manager Plugin をインストールおよびアンインストールする

AWS CLI

インストールが完了したら CLI の初期設定を行います。

$ aws  configure
AWS Access Key ID []: ご自身の IAM ユーザーのアクセスキーを入力
AWS Secret Access Key []: ご自身の IAM ユーザーのシークレットアクセスキーを入力
Default region name []: ap-northeast-1 と入力
Default output format []: そのままエンター

環境設定

SNS

セッションマネージャー経由のログインをメールで通知するための設定を行います。
管理者権限、または、SNS 操作権限を持った IAM ユーザーで以下コマンドを実行します。

※your-topic は任意の名称に置き換えてください。

$ aws sns create-topic --name your-topic --attributes DisplayName=SessionManager
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:your-topic"
}

TopicArn が結果として出力されるのでメモしておきます。

作成したトピックをサブスクライブします。
※ --topic-arn は上でメモしたものを指定ください。
※ your-mail-address は任意のメールアドレスに置き換えてください。

$ aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:123456789012:your-topic --protocol email --notification-endpoint your-mail-address

「AWS Notification - Subscription Confirmation」という件名のメールが届きます。
内容を確認して Confirm してください。

CloudWatch Events

セッションマネージャー経由のログインを通知するために
CloudWatch Events を使います。
管理者権限、または、CloudWatch Events 操作権限を持った IAM ユーザーで以下コマンドを実行します。

$ aws events put-rule --name "StartSession" --event-pattern "{\"source\":[\"aws.ssm\"],\"detail-type\":[\"AWS API Call via CloudTrail\"],\"detail\":{\"eventSource\":[\"ssm.amazonaws.com\"],\"eventName\":[\"StartSession\",\"ResumeSession\"]}}"

$ aws events put-targets --rule StartSession --target "Id"="1","Arn"="arn:aws:sns:ap-northeast-1:880749116261:session-notification"

インスタンスプロファイルの作成

踏み台サーバー用のインスタンスプロファイルを作成します。
管理者権限、または、IAM 及び EC2 操作権限を持った IAM ユーザーで以下コマンドを実行します。

ロールの作成

以下の JSON ファイルを作成します。
ファイル名は例で assumerole.json にしています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
            "ssm.amazonaws.com",
            "ec2.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ロールを作成します。
※ EC2SSMRole は任意のロール名に置き換えてください。

$ aws iam create-role --role-name EC2SSMRole --assume-role-policy-document file://assumerole.json
$ aws iam create-instance-profile --instance-profile-name EC2SSMRole
$ aws iam add-role-to-instance-profile --role-name EC2SSMRole --instance-profile-name EC2SSMRole

S3アクセス用ポリシーの作成

2020.4.10更新 
公開した当時は AmazonEC2RoleforSSM というやや強めのサービスロールを使っていました。このサービスロールは現在では使えません。それに対応するため手順を修正しました。

以下の JSON ファイルを作成します。
ファイル名は例で ssmlogs3.json にしています。
※ファイル内の your-bucketname はご自身のバケット名に置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::your-bucketname/*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetBucketLocation",
                "s3:GetEncryptionConfiguration",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads"
            ],
            "Resource": "arn:aws:s3:::your-bucketname",
            "Effect": "Allow"
        }
    ]
}

ポリシーを作成します。
※ EC2SSMRole は任意のロール名に置き換えてください。

$ aws iam create-policy --policy-name CustomPolicyssmlogs3 --policy-document file://ssmlogs3.json

上コマンドの標準出力の Arn をコピーします。

作成したポリシーをロールにアタッチします。
※ EC2SSMRole は任意のロール名に置き換えてください。

$ aws iam attach-role-policy --role-name EC2SSMRole --policy-arn 上でコピーしたArn

SSM用ポリシーのアタッチ

作成したロールに AmazonSSMManagedInstanceCore をいう SSM 用ポリシーをアタッチします。

$ aws iam attach-role-policy --role-name EC2SSMRole --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

EC2 インスタンスにインスタンスプロファイルをアタッチ

ロールを EC2 にアタッチします。
※ your-instance-id は対象の EC2 インスタンスに置き換えてください。

$ aws ec2 associate-iam-instance-profile --iam-instance-profile Name=EC2SSMRole --instance-id your-instance-id

S3 バケット

操作ログをテキストファイルで保管する S3 バケットを作成します。
管理者権限、または、S3 操作権限を持った IAM ユーザーで以下コマンドを実行します。
※ your-bucket-name は任意の名称に置き換えてください。

$ aws s3 mb s3://your-bucket-name
$ aws s3api put-bucket-encryption --bucket your-bucket-name --server-side-encryption-configuration "{\"Rules\":[{\"ApplyServerSideEncryptionByDefault\":{\"SSEAlgorithm\":\"AES256\"}}]}"
$ aws s3api put-public-access-block --bucket your-bucket-name --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

セッションマネージャー

この手順はマネジメントコンソールから行います。
セッションマネージャー を開きます。

設定 タブを開き 編集 をクリックします。

今回は以下のように設定します。

項目
Enable Run As support for Linux instances チェックをオフ
Key Management Service (KMS) チェックをオフ
S3 バケット チェックをオン
ログデータの暗号化 チェックをオン
リストからバケット名を選択 前の手順で作成したバケットを選択
S3 キープレフィックス - オプション sessionmanager
CloudWatch ログ チェックをオフ


リモートメンテナンスの開始

準備が整いました。
踏み台サーバーへのログイン許可は IAM で制御します。

セッションマネージャー経由のログインを許可する IAM ユーザー/グループに
以下の IAM ポリシーをアタッチします。

IAM ポリシーの作成

以下の JSON ファイルを作成します。
ファイル名は例で session.json にしています。
※ your-account-id はご自身のアカウントに置き換えてください。
※ your-instance-id はご自身の EC2 インスタンス (踏み台) に置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "0",
            "Effect": "Allow",
            "Action": "ssm:StartSession",
            "Resource": "arn:aws:ec2:ap-northeast-1:your-accont-id:instance/your-instance-id"
        }
    ]
}
$ aws iam create-policy --policy-name ssm-session-policy --policy-document file://session.json

作成したポリシーはセッションマネージャーを許可する IAM ユーザー/グループにアタッチしてください。

接続

それでは踏み台サーバーへログインします。
以下のコマンドを実行します。
※ your-instance-id はご自身の EC2 インスタンス (踏み台) に置き換えてください。

$ aws --profile ssmuser ssm start-session --target your-instance-id

試しに適当なコマンドを実行してみます。

Starting session with SessionId: ssmuser-05b997125a8bfd115
sh-4.2$
sh-4.2$
sh-4.2$ date
Sat Aug 24 06:58:39 UTC 2019
sh-4.2$
sh-4.2$
sh-4.2$ date
Sat Aug 24 06:58:40 UTC 2019
sh-4.2$
sh-4.2$
sh-4.2$
sh-4.2$ exit

メール通知

ログインをメールで通知することにしていました。
受信ボックスを見てみます。

通知が届いています。

S3 バケット内

作成した S3 バケットにテキストファイルが作成されています。

Script started on 2019-08-24 06:58:51+0000
[?1034hsh-4.2# /usr/bin/ssm-session-logger /var/lib/amazon/ssm/i-xxxxxxxxx/sess 
ion/orchestration/ssmuser-05b997125a8bfd115/Standard_Stream/ipcTempFile.log fals 
e
Error occurred fetching the seelog config file path:  open /etc/amazon/ssm/seelog.xml: no such file or directory
Initializing new seelog logger
New Seelog Logger Creation Complete
[?1034hsh-4.2$ 
sh-4.2$ 

sh-4.2$ 

sh-4.2$ date

Sat Aug 24 06:58:39 UTC 2019

sh-4.2$ 

sh-4.2$ 

sh-4.2$ date

Sat Aug 24 06:58:40 UTC 2019

sh-4.2$ 

sh-4.2$ 

sh-4.2$ 

sh-4.2$ exit

exit

sh-4.2# exit
exit

Script done on 2019-08-24 06:59:56+0000

まとめ

踏み台サーバー経由のリモートメンテナンスという観点では
強めの統制をきかせることが出来るのはないでしょうか。

SSH ポートをセキュリティグループで空けなくてよく
接続権限は IAM 管理可能ということで、運用コストは減らせるかもしれません。
ぜひご活用ください。

参考

Amazon CloudWatch Logs を使用して CloudTrail のログファイルをモニタリングする

以上、吉井 亮 がお届けしました。