今回は、AWS Systems Manager InventoryによるEC2インスタンスのソフトウェア、設定、ファイル、レジストリ情報の自動収集システムをAWS CDKで実装する方法をまとめました。
はじめに
今回は、AWS Systems Manager Inventoryを使用して、EC2インスタンスのソフトウェア情報、システム設定、インストールされているファイル、Windowsレジストリ情報などを自動収集し、S3バケットに保存するアーキテクチャをAWS CDKで実装していきます。
今回作成するリソース
- S3バケット: SSMインベントリデータの保存先
- バケットポリシー: SSMサービス専用のアクセス権限
- SSM Association: インベントリ収集の自動実行設定
- Resource Data Sync: インベントリデータの一元化と同期
アーキテクチャ概要
AWS CDK ソースコード
S3バケット設定(インベントリ保存)
const ssmInventoryBucket = new s3.Bucket(this, 'SsmInventoryBucket', {
bucketName: `s3b-ssm-inventory-bucket`, // バケット名
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, // パブリックアクセスをすべてブロック
encryption: s3.BucketEncryption.S3_MANAGED, // 暗号化タイプ:SSE-S3
autoDeleteObjects: true, // バケット削除時にオブジェクトも削除 デプロイ成功後にfalseに設定
enforceSSL: true, // SSL/TLS暗号化を強制
lifecycleRules: [ // ライフサイクルルール作成
{
id: 'Expiration Rule 12 Months', // ライフサイクルルール名
expiration: cdk.Duration.days(366), // 1年間保持
}
],
removalPolicy: cdk.RemovalPolicy.DESTROY, // スタック削除時にバケットも削除 デプロイ成功後にRETAINに変更
});
// バケットポリシー追加
ssmInventoryBucket.addToResourcePolicy(new iam.PolicyStatement({ // バケットポリシー追加
sid: 'AWSSSMInventoryWrite', // ステートメントID
effect: iam.Effect.ALLOW, // 許可
actions: [ // 許可するアクション
's3:PutObject' // オブジェクトの配置を許可
],
resources: [ // 対象リソース
`${ssmInventoryBucket.bucketArn}/AWSLogs/${cdk.Stack.of(this).account}/SSM/*`, // SSMログ用パス
ssmInventoryBucket.bucketArn, // バケット自体
],
principals: [new iam.ServicePrincipal('ssm.amazonaws.com')], // SSMサービス
conditions: { // 条件
StringEquals: { // 文字列完全一致
's3:x-amz-acl': 'bucket-owner-full-control', // ACL制御
'aws:SourceAccount': cdk.Stack.of(this).account // 送信元アカウント制限
}
}
}));
ポイント:
- セキュア設計: パブリックアクセス完全ブロック、SSL強制
- 長期保存: コンプライアンス要件に応じた1年間保持
- 暗号化: SSE-S3による自動暗号化
- コスト管理: ライフサイクルポリシーによる自動削除
- 最小権限: SSMサービスのみにPutObject権限を付与
- アカウント制限: 自アカウントからのアクセスのみ許可
- ACL制御: バケット所有者の完全制御を保証
- パス制限: SSM専用パスのみへのアクセス制限
SSM Association設定
const inventoryAssociation = new ssm.CfnAssociation(this, 'InventoryAssociation', {
name: 'AWS-GatherSoftwareInventory', // 実行するSSMドキュメント名
associationName: 'ssm-inventory', // インベントリ名
targets: [{ // ターゲット
key: 'InstanceIds', // 対象キー
values: ['*'] // 対象値
}],
parameters: {
'applications': ['Enabled'], // アプリケーション情報を収集
'awsComponents': ['Enabled'], // AWSコンポーネント情報を収集
'networkConfig': ['Enabled'], // ネットワーク設定情報を収集
'windowsUpdates': ['Enabled'], // Windowsアップデート情報を収集 (Windowsのみ)
'instanceDetailedInformation': ['Enabled'], // インスタンスの詳細情報を収集
'services': ['Enabled'], // サービス設定を収集 (Windowsのみ)
'windowsRoles': ['Enabled'], // Windowsロール設定を収集 (Windowsのみ)
'customInventory': ['Enabled'], // カスタムインベントリデータを収集
'billingInfo': ['Enabled'], // ライセンス含有アプリケーションの課金情報を収集
'files': ['[{"Path":"C:\\Program Files","Pattern":["*.exe"],"Recursive":true}]'], // ファイルを収集
'windowsRegistry': ['[{"Path":"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion","ValueNames":["ProductName"],"Recursive":false}]'], // Windowsレジストリデータを収集
},
scheduleExpression: 'rate(30 minutes)', // インベントリの収集頻度:30分ごと
outputLocation: { // 実行結果出力先指定
s3Location: {
outputS3BucketName: ssmInventoryBucket.bucketName, // インベントリ用のバケットに出力
outputS3KeyPrefix: `AWSLogs/${cdk.Stack.of(this).account}/SSM/Logs` // ディレクトリを作成
}
}
})
ポイント:
- 包括的収集: ソフトウェア、設定、ファイル、レジストリの全面的な情報収集
- 定期実行: 30分間隔での自動収集(要件に応じて調整可能)
- カスタマイズ: ファイルパスやレジストリキーの設定
- 構造化出力: JSON形式での構造化されたデータ保存
Resource Data Sync設定
//resourceデータの同期設定
const resourceDataSync = new ssm.CfnResourceDataSync(this, 'ResourceDataSync', { // リソースデータの同期
syncName: 'resource-data-sync', // 同期名
s3Destination:{
bucketName: ssmInventoryBucket.bucketName, // バケット名
bucketPrefix: `AWSLogs/${cdk.Stack.of(this).account}/SSM/`, // バケットプレフィックス名
bucketRegion: cdk.Stack.of(this).region, // バケットのリージョン:東京リージョン
syncFormat: 'JsonSerDe' // 同期形式:JSON
}
});
// 依存関係の設定
resourceDataSync.node.addDependency(inventoryAssociation); // 先にSSMインベントリ作成
ポイント:
- データ一元化: 複数インスタンスのインベントリデータを統合管理
- 標準形式: JsonSerDe形式による構造化データ
- リージョン対応: マルチリージョン環境での統合管理
- 依存関係: Association作成後の実行を保証
インベントリ収集項目と活用方法
収集項目詳細
カテゴリ | 収集内容 | 用途 |
---|---|---|
Applications | インストール済みソフトウェア一覧 | ライセンス管理、セキュリティ監査 |
AWS Components | AWS CLI、CloudWatch Agent等 | AWS管理ツールの導入状況 |
Network Config | ネットワーク設定情報 | ネットワーク構成管理 |
Windows Updates | 適用済み更新プログラム | パッチ管理、脆弱性対応 |
Instance Details | CPU、メモリ、OS情報 | 資産管理、容量計画 |
Services | Windowsサービス状態 | サービス管理、異常検知 |
Windows Roles | Windowsサーバーロール | 機能構成管理 |
Files | 指定パスのファイル情報 | セキュリティ監査、変更管理 |
Registry | Windowsレジストリ値 | システム設定管理 |
注意点
- Association制限: インスタンス単位で1つのInventory Associationのみ設定可能です
今回実装したコンストラクトファイルまとめ
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
export interface SsmInventoryConstructProps {
}
export class SsmInventoryConstruct extends Construct {
constructor(scope: Construct, id: string, props?: SsmInventoryConstructProps) {
super(scope, id);
//===========================================
// ssmインベントリ用のS3バケット作成
//===========================================
const ssmInventoryBucket = new s3.Bucket(this, 'SsmInventoryBucket', {
bucketName: `s3b-ssm-inventory-bucket`, // バケット名
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, // パブリックアクセスをすべてブロック
encryption: s3.BucketEncryption.S3_MANAGED, // 暗号化タイプ:SSE-S3
autoDeleteObjects: true, // バケット削除時にオブジェクトも削除 デプロイ成功後にfalseに設定
enforceSSL: true, // SSL/TLS暗号化を強制
lifecycleRules: [ // ライフサイクルルール作成
{
id: 'Expiration Rule 12 Months', // ライフサイクルルール名
expiration: cdk.Duration.days(366), // 1年間保持
}
],
removalPolicy: cdk.RemovalPolicy.DESTROY, // スタック削除時にバケットも削除 デプロイ成功後にRETAINに変更
});
// バケットポリシー追加
ssmInventoryBucket.addToResourcePolicy(new iam.PolicyStatement({ // バケットポリシー追加
sid: 'AWSSSMInventoryWrite', // ステートメントID
effect: iam.Effect.ALLOW, // 許可
actions: [ // 許可するアクション
's3:PutObject' // オブジェクトの配置を許可
],
resources: [ // 対象リソース
`${ssmInventoryBucket.bucketArn}/AWSLogs/${cdk.Stack.of(this).account}/SSM/*`, // SSMログ用パス
ssmInventoryBucket.bucketArn, // バケット自体
],
principals: [new iam.ServicePrincipal('ssm.amazonaws.com')], // SSMサービス
conditions: { // 条件
StringEquals: { // 文字列完全一致
's3:x-amz-acl': 'bucket-owner-full-control', // ACL制御
'aws:SourceAccount': cdk.Stack.of(this).account // 送信元アカウント制限
}
}
}));
//===========================================
// SSMインベントリ作成
//===========================================
const inventoryAssociation = new ssm.CfnAssociation(this, 'InventoryAssociation', {
name: 'AWS-GatherSoftwareInventory', // 実行するSSMドキュメント名
associationName: 'ssm-inventory', // インベントリ名
targets: [{ // ターゲット
key: 'InstanceIds', // 対象キー
values: ['*'] // 対象値
}],
parameters: {
'applications': ['Enabled'], // アプリケーション情報を収集
'awsComponents': ['Enabled'], // AWSコンポーネント情報を収集
'networkConfig': ['Enabled'], // ネットワーク設定情報を収集
'windowsUpdates': ['Enabled'], // Windowsアップデート情報を収集 (Windowsのみ)
'instanceDetailedInformation': ['Enabled'], // インスタンスの詳細情報を収集
'services': ['Enabled'], // サービス設定を収集 (Windowsのみ)
'windowsRoles': ['Enabled'], // Windowsロール設定を収集 (Windowsのみ)
'customInventory': ['Enabled'], // カスタムインベントリデータを収集
'billingInfo': ['Enabled'], // ライセンス含有アプリケーションの課金情報を収集
'files': ['[{"Path":"C:\\Program Files","Pattern":["*.exe"],"Recursive":true}]'], // ファイルを収集
'windowsRegistry': ['[{"Path":"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion","ValueNames":["ProductName"],"Recursive":false}]'], // Windowsレジストリデータを収集
},
scheduleExpression: 'rate(30 minutes)', // インベントリの収集頻度:30分ごと
outputLocation: { // 実行結果出力先指定
s3Location: {
outputS3BucketName: ssmInventoryBucket.bucketName, // インベントリ用のバケットに出力
outputS3KeyPrefix: `AWSLogs/${cdk.Stack.of(this).account}/SSM/Logs` // ディレクトリを作成
}
}
})
//resourceデータの同期設定
const resourceDataSync = new ssm.CfnResourceDataSync(this, 'ResourceDataSync', { // リソースデータの同期
syncName: 'resource-data-sync', // 同期名
s3Destination:{
bucketName: ssmInventoryBucket.bucketName, // バケット名
bucketPrefix: `AWSLogs/${cdk.Stack.of(this).account}/SSM/`, // バケットプレフィックス名
bucketRegion: cdk.Stack.of(this).region, // バケットのリージョン:東京リージョン
syncFormat: 'JsonSerDe' // 同期形式:JSON
}
});
}
}
まとめ
今回は、AWS Systems Manager Inventoryを活用した包括的なインベントリ管理システムをAWS CDKで実装しました。
皆さんのお役に立てば幸いです。