はじめに
AWS Systems Manager Session Manager(以降、Session Manager)とは、AWS Systems Managerの機能の一つで、Amazon EC2 for Linux(以降、EC2)に対してSSHを利用せずに接続できる機能となります。
Session Managerには、セッションロギング機能も提供されており、Session Manager経由で接続したセッションの操作ログを残すことが可能です。
Amazon CloudTrail(以降、CloudTrail)の操作ログはあくまでもSession ManagerからEC2へのセッションの開始/終了などのログしか記録されないので、EC2内での操作も証跡として残したい場合は、Session Managerのセッションロギング機能を有効化するのがよさそうです。
ロギングの有効化設定はマネージメントコンソールやAWS CDK(以降、CDK)などで可能なのですが、CDKの実装方法があまり出回っていないため、本記事でご紹介したいと思います。
前提条件
Session Managerを利用するためには、EC2が以下の条件を満たしている必要があります。
-
SSM Agentのインストール+起動- AWSが提供する
Amazon Linuxはデフォルトで導入済み
- AWSが提供する
- IAMのAWSマネージドポリシー
AmazonSSMManagedInstanceCoreのアタッチ - HTTPS (ポート 443) アウトバウンド・トラフィックの通信許可
*EC2をプライベートサブネットに配置する場合は、NAT Gatewayもしくは以下のVPC Endpointを構築する必要あり
* com.amazonaws.region.ssm
* com.amazonaws.region.ssmmessages
* com.amazonaws.region.ec2messages ※SSM Agentのバージョンが3.3.40.0以降の場合は不要
実装
CDKソースコードの構成図
今回は動作確認用に以下の構成図のAWSリソースを作成します。

CDKソースコード(スタックファイルのみ)
import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import {
Vpc,
IpAddresses,
SubnetType,
SecurityGroup,
Peer,
Port,
Instance,
InstanceType,
InstanceClass,
InstanceSize,
AmazonLinuxImage,
AmazonLinuxGeneration,
} from "aws-cdk-lib/aws-ec2";
import { Bucket } from "aws-cdk-lib/aws-s3";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
import { CfnDocument } from "aws-cdk-lib/aws-ssm";
export class SessionManagerLoggingStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Session Managerログ保管用S3バケット
const bucket = new Bucket(this, "MyBucket");
// EC2向けVPC(パブリックサブネット1つのみ)
const vpc = new Vpc(this, "MyVpc", {
ipAddresses: IpAddresses.cidr("10.0.0.0/16"),
subnetConfiguration: [
{
cidrMask: 24,
name: "public-subnet",
subnetType: SubnetType.PUBLIC,
},
],
maxAzs: 1,
});
// EC2(アウトバウンド通信443のみ許可されたインスタンス)
const securityGroup = new SecurityGroup(this, "MySecurityGroup", {
vpc,
allowAllOutbound: false,
});
securityGroup.addEgressRule(Peer.anyIpv4(), Port.tcp(443));
const instance = new Instance(this, "MyInstance", {
vpcSubnets: {
subnetType: SubnetType.PUBLIC,
},
instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.NANO),
machineImage: new AmazonLinuxImage({
generation: AmazonLinuxGeneration.AMAZON_LINUX_2023,
}),
vpc: vpc,
associatePublicIpAddress: true,
securityGroup: securityGroup,
ssmSessionPermissions: true, // EC2のRoleにAmazonSSMManagedInstanceCoreのPolicyがアタッチされる
});
// セッションログをS3に出力するための権限追加
instance.addToRolePolicy(
new PolicyStatement({
actions: ["s3:GetEncryptionConfiguration", "s3:PutObject"],
resources: [bucket.bucketArn, `${bucket.bucketArn}/*`],
})
);
// Session Managerログ設定(SSMドキュメント)
new CfnDocument(this, "MySessionManagerPreferences", {
name: "SSM-SessionManagerRunShell",
documentType: "Session",
content: {
schemaVersion: "1.0",
description: "Document to hold regional settings for Session Manager",
sessionType: "Standard_Stream",
inputs: {
s3BucketName: bucket.bucketName,
s3EncryptionEnabled: true,
},
},
});
}
}
上記ソースコードを利用して環境をデプロイし、以降の動作確認を実施していきます。
動作確認
- マネージメントコンソールから
EC2にSession Managerで接続

接続後、ログ確認向けにいくつかコマンドを実行して、右上の「終了」ボタンを押下しセッションを終了します。
- アップロードされた
S3ログファイルを確認
セッションを終了するとEC2からS3に対してセッションログが以下のスクショのとおりに出力されています。
- セッションログファイル中身を確認
セッションログをローカルにダウンロードして中身を見てみると以下のようにセッション内で実行したコマンドやその結果が記録されていました。
※ただしなぜか文字化けや不要な改行が含まれています。要因がわかっていません…。MatsuMikan-iskvzqvatbpxd3eynv64u9eqqa.logScript started on 2024-12-15 03:38:33+00:00 [<not executed on terminal>] [?2004hsh-5.2$ [K sh-5.2$ s[Kpwd [?2004l /usr/bin [?2004hsh-5.2$ ua[Kname 0a[K[K-a [?2004l Linux ip-10-0-0-147.ap-northeast-1.compute.internal 6.1.115-126.197.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Nov 5 17:36:57 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux [?2004hsh-5.2$ [7myum info amazon-ssm-agent[27m [C[C[C[C[C[C[C[Cyum info amazon-ssm-agent [?2004l Amazon Linux 2023 repository [=== ] --- B/s | 0 B --:-- ETA Amazon Linux 2023 repository 56% [===========================- ] 55 MB/s | 17 MB 00:00 ETA Amazon Linux 2023 repository 91% [============================================- ] 54 MB/s | 27 MB 00:00 ETA Amazon Linux 2023 repository 35 MB/s | 29 MB 00:00 Amazon Linux 2023 Kernel Livepatch repository [=== ] --- B/s | 0 B --:-- ETA Amazon Linux 2023 Kernel Livepatch repository 54 kB/s | 11 kB 00:00 Installed Packages History database cannot be created, using in-memory database instead: SQLite error on "/var/lib/dnf/history.sqlite": Open failed: unable to open database file Name : [36mamazon-ssm-agent(B[m Version : 3.3.987.0 Release : 1.amzn2023 Architecture : x86_64 Size : 125 M Source : amazon-ssm-agent-3.3.987.0-1.amzn2023.src.rpm Repository : @System Summary : Manage EC2 Instances using SSM APIs URL : http://docs.aws.amazon.com/ssm/latest/APIReference/Welcome.html License : ASL 2.0 Description : This package provides Amazon SSM Agent for managing EC2 Instances using SSM APIs [?2004hsh-5.2$ [K sh-5.2$ [K sh-5.2$ Script done on 2024-12-15 03:38:33+00:00 [COMMAND_EXIT_CODE="0"]
一部の文字化けは残念な感じではありますが、一応EC2内でどのようなコマンドが実行されているかの履歴を取得することができました。
上記ログ内容のとおり、セッションログはコマンド結果がもろにログに記録されます。
特にDBのコマンド(psqlなど)を実行するとそのコマンド結果もログに記録されますので、DBのSELECT結果がログに残ってしまう可能性があります。そういった仕様もご理解の上、セッションログの有効化有無をご検討いただくのがよいでしょう。
※公式のドキュメントには、コマンド実行時に秘匿情報を出力しないようなコマンド例はありますが、Session Managerの機能で特定のコマンド結果を出力しないように制御することはできない(2024/12時点)ので、ヒューマンエラーによりうっかりログ出力される危険性はあります。
トラブルシューティング
CDKのデプロイ時に'SSM-SessionManagerRunShell' already exists.のデプロイエラーが発生する
一度でもマネージメントコンソールからセッションロギング設定を有効化していると、
SSM-SessionManagerRunShellのドキュメントが既に存在しているエラーが発生してしまいます。
❌ SessionManagerLoggingStack failed: Error: The stack named SessionManagerLoggingStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "Resource of type 'AWS::SSM::Document' with identifier 'SSM-SessionManagerRunShell' already exists." (RequestToken: 6ab45d62-c824-bf44-1d0b-dd991baadd2b, HandlerErrorCode: AlreadyExists)
本設定をCDKで管理したい場合は、作成済みのSSM-SessionManagerRunShellドキュメントを削除すればよいのですが、マネージメントコンソール上では削除できないため、AWS CLIでの削除が必要になります。
aws ssm delete-document --name SSM-SessionManagerRunShell
S3-KMSを利用しているS3に送付されない
S3のサーバーサイド暗号化にKMSを指定している場合には、EC2のIAMロールに以下二つのアクションを追加してください。
kms:Decryptkms:GenerateDataKey
補足
CloudTrailで取得できるSession Managerのログ
Session Managerでは主に以下のAPIを用いてEC2にセッションの操作を行いますので、CloudTrailでいつセッションを開始したか、または終了したかのログを追跡することは可能です。
-
StartSession: セッションを開始する -
TerminateSession: セッションを終了する -
ResumeSession: 接続されたセッションに再接続する
▼以下はStartSessionで絞り込んだスクリーンショット

マネージメントコンソールでの設定方法(2024/12時点、スクショのみ)
CDKのソースコードではSSM Documentを新規作成したのですが、マネージメントコンソール上では以下のようにセッションログ設定用の画面が用意されているので、こちらから設定することも可能です。
おまけ:CDK実装で困ったらAmazon Qに頼るもよし
実は、本設定のCDK実装はかなり苦戦しました。
マネージメントコンソール上での設定方法は把握していたものの、本設定がSSM Documentに関連していることに気づくことができず、CDKのリファレンスを探しても本設定方法になかなかたどり着きませんでした。
そんなときにおすすめなのが、Amazon Qで、今回はそちらを頼っていました(笑)。

本設定に限らず、CDKの実装で困ったことがあれば、Amazon Qに頼ってみるのも手ではないでしょうか。
おわりに
ニッチな記事ではございますが、CDKでセッションログの有効化を行いたい方や、セッションログの出力内容について、少しでも知見を共有できれば幸いです。
AWS re:Invent 2024の情報で盛り上がっている中、お付き合いくださりありがとうございました!
こちらからは以上です。
