はじめに
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:Decrypt
kms: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
の情報で盛り上がっている中、お付き合いくださりありがとうございました!
こちらからは以上です。