こんにちは、SCSKでAWSの内製化支援『テクニカルエスコートサービス』を担当している貝塚です。
前記事では、EC2への接続記録を必ず取得するという観点から、
- Session Managerのログ記録
- Fleet ManagerのRDP録画
- ネットワーク経由の従来型ログイン
を考慮する必要があることを説明し、1. Session Managerのログ記録 について設定方法等を解説しました。
本記事では 2. Fleet ManagerのRDP録画設定方法について解説します。
RDP接続記録の設定
RDP接続記録とは
Fleet Manager Remote Desktopを使用したRDP接続を画面録画し、S3バケットに保存する機能です。GUI操作の証跡を動画として残すことができます。
RDP接続記録を有効化するには、Just-in-time(JIT)ノードアクセスを有効化する必要があります。JITノードアクセスは、動的で時間制限付きのアクセス制御を提供する機能で、承認ポリシーベースのアクセス管理を実現します。
Just-in-time ノードアクセスの概要
Just-in-time(JIT)ノードアクセスは、以下の特徴を持つアクセス制御機能です。
- 動的なアクセス制御:アクセス要求時に承認ポリシーを評価
- 時間制限付きアクセス:一定時間後に自動的にアクセス権限が失効
- 承認ポリシーベース:Cedar言語(Amazonが開発したオープンソースのポリシー言語)で記述された承認ポリシーで制御
- RDP接続記録の前提条件:RDP接続記録機能を有効化するために必須
JITノードアクセスを有効化することで、RDP接続記録機能が利用可能になります。
Quick Setupの初回セットアップ
JITノードアクセスを有効化する前に、Quick Setupの初回セットアップを実行する必要があります。
この記事では単一アカウント環境の場合のみを説明しています。Organizations環境には対応していないのでご注意ください。
quicksetup-init.sh スクリプト(本記事で使用したスクリプトは、記事の最後に掲載しています)を実行します。
bash quicksetup-init.sh --profile default --region ap-northeast-1
–profileにはAWS CLIを実行するプロファイル名を指定します。
このスクリプトは、CloudFormation StackSets用のIAMロール2件を作成します。
- AWS-QuickSetup-StackSet-Local-AdministrationRole
- AWS-QuickSetup-StackSet-Local-ExecutionRole
JIT有効化の手順
Quick Setupの初回セットアップ完了後、 enable-jit-node-access.sh スクリプトを実行してJITノードアクセスを有効化します。
bash enable-jit-node-access.sh --profile default --region ap-northeast-1
–profileにはAWS CLIを実行するプロファイル名を指定します。
このスクリプトは以下の処理を実行します。
1. Configuration Managerを作成
2. JITノードアクセスを有効化
3. ホームリージョン、ターゲットアカウント、ターゲットリージョンを設定
スクリプト実行後、Configuration ManagerのステータスがSUCCEEDEDになることを確認してください。
RDP接続記録の設定
JITノードアクセスの有効化後、 configure-rdp-recording.sh スクリプトを実行してRDP接続記録を設定します。
bash configure-rdp-recording.sh --profile default --region ap-northeast-1 --stack-name my-session-manager-stack
–profileにはAWS CLIを実行するプロファイル名、–stack-name2には 前の記事の「AWS CloudFormationでの設定」のところで作成したスタック名 を指定します。
このスクリプトは以下の処理を実行します。
1. CloudFormationスタックからKMSキーARNとS3バケット名を取得
2. ssm-guiconnect update-connection-recording-preferences APIを使用してRDP接続記録を設定
設定完了後、以下のコマンドで設定内容を確認できます。
aws ssm-guiconnect get-connection-recording-preferences --region ap-northeast-1
承認ポリシーの作成
JITノードアクセスでは、Cedar言語で記述された承認ポリシーによってアクセス制御を行います。承認ポリシーの作成にはSystems Manager統合エクスペリエンスの有効化が必要です。Systems Managerコンソールを開き、画面上部に「新しいエクスペリエンスを有効にする」バナーが表示されている場合はクリックして有効化してください。
有効化後、承認ポリシーの作成はAWSマネジメントコンソールから実施します。
1. Systems Manager >ジャストインタイムノードアクセス に移動
2. 承認ポリシー タブを選択
3. 自動承認ポリシーを作成 をクリック
4. ポリシーステートメントを入力
5. 自動承認ポリシーを公開 ボタンをクリック
自動承認ポリシーによるアクセスの有効期間は1時間で、変更できません。また、AWSアカウントとリージョンごとに1つの自動承認ポリシーのみ作成可能です。
以下は、特定のタグを持つノードへのアクセスを自動承認するポリシーステートメントの例です。
permit (
principal,
action == AWS::SSM::Action::"getTokenForInstanceAccess",
resource
)
when {
resource.hasTag("Project") &&
resource.getTag("Project") == "windows-ec2-private"
};
permitステートメントの各要素は以下の通りです。
- principal: アクセスを要求するユーザー。”principal,” と書くとすべてのユーザーが対象になる。’principal in AWS::IdentityStore::Group::”グループID”,’ と書くと特定のIAM Identity Centerグループに限定できる
- action: JITノードアクセスでは常に AWS::SSM::Action::”getTokenForInstanceAccess”
- resource: アクセス対象のノード
- when句: 自動承認の条件。resource.hasTag()やresource.getTag()でノードのタグを評価できる
設計上の留意点
1. KMSキーの要件
RDP録画の暗号化に使用するKMSキーには、以下の要件があります。
- 対称キー(Symmetric key)であること
- 暗号化と復号化(Encrypt and decrypt)用途であること
- 必須タグ: SystemsManagerJustInTimeNodeAccessManaged: true
このタグがないと、RDP接続記録の設定時にエラーが発生します。
2. S3バケットポリシー
RDP録画ファイルを保存するS3バケットのバケットポリシーには、ssm-guiconnect.amazonaws.com サービスプリンシパルが、RDP録画ファイルをS3バケットに書き込むための権限(PutObject)が必要です。
{
"Sid": "ConnectionRecording",
"Effect": "Allow",
"Principal": {
"Service": ["ssm-guiconnect.amazonaws.com"]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Condition": {
"StringEquals": {
"aws:SourceAccount": "account-id"
}
}
}
aws:SourceAccount条件により、特定のAWSアカウントからのアクセスのみを許可します。
3. IAMロールの権限
RDP接続を開始するユーザーには、以下の権限が必要です。(IAMロール作成は、本記事・前記事のCloudFormationテンプレートやスクリプトには含まれていません)
- ssm-guiconnect:StartConnection
-
ssm-guiconnect:CancelConnection
-
ssm-guiconnect:GetConnection
- kms:CreateGrant
RDP接続とRDP録画の確認
ここまで完了していれば、RDP録画の準備はできています。Fleet Managerを使ってEC2インスタンスに接続(テストインスタンスが必要な場合は 前の記事 でCloudFormationを使って作成したEC2インスタンスを使用)してください。
リモートデスクトップ画面の上部に表示されている設定タブをクリックし、「S3への接続を記録」が有効になっていること、S3バケット に録画保存先のS3名が表示されることを確認してください。
リモートデスクトップ接続を終了すると、指定されたS3バケットに録画データが置かれていることを確認できるはずです。
まとめ
RDP録画有効化手順についてまとめました。
次の記事では、ネットワークの面から検討・考察を行います。
スクリプト類
本記事に出てきたスクリプト類を掲載します。
quicksetup-init.sh
#!/bin/bash
# Quick Setup 初回セットアップスクリプト
# このスクリプトは、AWS Systems Manager Quick Setupの初回セットアップを
# AWS CLIを使用してプログラマティックに実行します。
#
# 使用方法:
# 単一アカウント環境: bash scripts/quicksetup-init.sh
# Organizations環境: bash scripts/quicksetup-init.sh --enable-organizations
set -e
# 設定
REGION="ap-northeast-1"
PROFILE=""
ENABLE_ORGANIZATIONS=false
# コマンドライン引数の解析
while [[ $# -gt 0 ]]; do
case $1 in
--profile)
PROFILE="$2"
shift 2
;;
--enable-organizations)
ENABLE_ORGANIZATIONS=true
shift
;;
--region)
REGION="$2"
shift 2
;;
*)
echo "不明なオプション: $1"
echo "使用方法: $0 [--profile PROFILE] [--enable-organizations] [--region REGION]"
exit 1
;;
esac
done
# プロファイルオプションの設定
PROFILE_OPT=""
if [ -n "${PROFILE}" ]; then
PROFILE_OPT="--profile ${PROFILE}"
fi
ACCOUNT_ID=$(aws sts get-caller-identity ${PROFILE_OPT} --query Account --output text)
echo "=========================================="
echo "Quick Setup 初回セットアップスクリプト"
echo "=========================================="
echo "アカウントID: ${ACCOUNT_ID}"
echo "リージョン: ${REGION}"
echo "Organizations統合: ${ENABLE_ORGANIZATIONS}"
echo ""
# Organizations統合の有効化(オプション)
if [ "${ENABLE_ORGANIZATIONS}" = true ]; then
echo "Organizations統合を有効化します..."
echo ""
# ステップ1: CloudFormationの信頼アクセスを有効化
echo "ステップ1: CloudFormationの信頼アクセスを有効化中..."
if aws cloudformation activate-organizations-access ${PROFILE_OPT} --region "${REGION}" 2>&1 | grep -q "already activated"; then
echo " 既に有効化されています"
else
echo " 有効化しました"
fi
echo ""
# ステップ2: Systems ManagerとOrganizationsの統合を有効化
echo "ステップ2: Systems ManagerとOrganizationsの統合を有効化中..."
if aws organizations enable-aws-service-access ${PROFILE_OPT} --service-principal ssm.amazonaws.com 2>&1 | grep -q "already enabled"; then
echo " 既に有効化されています"
else
echo " 有効化しました"
fi
echo ""
else
echo "単一アカウントモードで実行します(Organizations統合はスキップ)"
echo ""
fi
# ステップ3: Explorer用のIAMロールを作成(単一アカウント環境では不要)
if [ "${ENABLE_ORGANIZATIONS}" = true ]; then
echo "ステップ3: Explorer用のIAMロールを作成中..."
else
echo "ステップ3: Explorer用のIAMロールを作成中(単一アカウント環境ではスキップ)..."
fi
if [ "${ENABLE_ORGANIZATIONS}" = true ]; then
EXPLORER_ROLE_NAME="AWS-QuickSetup-SSM-RoleForEnablingExplorer"
if aws iam get-role ${PROFILE_OPT} --role-name "${EXPLORER_ROLE_NAME}" --region "${REGION}" >/dev/null 2>&1; then
echo " ${EXPLORER_ROLE_NAME}: 既に存在します"
else
aws iam create-role \
${PROFILE_OPT} \
--role-name "${EXPLORER_ROLE_NAME}" \
--assume-role-policy-document file://scripts/quicksetup-init/explorer-role-trust-policy.json \
--region "${REGION}" >/dev/null
echo " ${EXPLORER_ROLE_NAME}: 作成しました"
fi
fi
echo ""
# ステップ4: Quick Setupサービス設定を更新
echo "ステップ4: Quick Setupサービス設定を更新中..."
aws ssm update-service-setting \
${PROFILE_OPT} \
--setting-id "arn:aws:ssm:${REGION}:${ACCOUNT_ID}:servicesetting/ssm/opsitem/ssm-patchmanager" \
--setting-value "Enabled" \
--region "${REGION}" 2>&1 | grep -q "." || echo " 設定を更新しました"
echo ""
# ステップ5: CloudFormation StackSets用のIAMロールを作成
echo "ステップ5: CloudFormation StackSets用のIAMロールを作成中..."
# Administration Role
ADMIN_ROLE_NAME="AWS-QuickSetup-StackSet-Local-AdministrationRole"
if aws iam get-role ${PROFILE_OPT} --role-name "${ADMIN_ROLE_NAME}" --region "${REGION}" >/dev/null 2>&1; then
echo " ${ADMIN_ROLE_NAME}: 既に存在します"
else
aws iam create-role \
${PROFILE_OPT} \
--role-name "${ADMIN_ROLE_NAME}" \
--assume-role-policy-document file://scripts/quicksetup-init/administration-role-trust-policy.json \
--region "${REGION}" >/dev/null
aws iam attach-role-policy \
${PROFILE_OPT} \
--role-name "${ADMIN_ROLE_NAME}" \
--policy-arn "arn:aws:iam::aws:policy/AdministratorAccess" \
--region "${REGION}"
echo " ${ADMIN_ROLE_NAME}: 作成しました"
echo " IAMの整合性を待機中(10秒)..."
sleep 10
fi
# Execution Role用のTrust Policyを動的に生成
EXEC_ROLE_NAME="AWS-QuickSetup-StackSet-Local-ExecutionRole"
EXEC_TRUST_POLICY=$(cat </dev/null 2>&1; then
echo " ${EXEC_ROLE_NAME}: 既に存在します"
else
echo "${EXEC_TRUST_POLICY}" > execution-role-trust-policy.json
aws iam create-role \
${PROFILE_OPT} \
--role-name "${EXEC_ROLE_NAME}" \
--assume-role-policy-document file:///execution-role-trust-policy.json \
--region "${REGION}" >/dev/null
aws iam attach-role-policy \
${PROFILE_OPT} \
--role-name "${EXEC_ROLE_NAME}" \
--policy-arn "arn:aws:iam::aws:policy/AdministratorAccess" \
--region "${REGION}"
rm /execution-role-trust-policy.json
echo " ${EXEC_ROLE_NAME}: 作成しました"
fi
echo ""
echo "=========================================="
echo "Quick Setup 初回セットアップが完了しました"
echo "=========================================="
echo ""
echo "作成されたリソース:"
if [ "${ENABLE_ORGANIZATIONS}" = true ]; then
echo " - IAMロール: ${EXPLORER_ROLE_NAME}"
fi
echo " - IAMロール: ${ADMIN_ROLE_NAME}"
echo " - IAMロール: ${EXEC_ROLE_NAME}"
echo ""
echo "次のステップ:"
echo " 1. JIT有効化スクリプトを実行: bash enable-jit-node-access.sh"
echo ""
enable-jit-node-access.sh
#!/bin/bash
# Just-in-time Node Access有効化スクリプト
# このスクリプトは、AWS Systems Manager Quick SetupのAPIを使用して
# Just-in-time (JIT) ノードアクセスを有効化します。
set -e
# 設定
REGION="ap-northeast-1"
PROFILE=""
# コマンドライン引数の解析
while [[ $# -gt 0 ]]; do
case $1 in
--profile)
PROFILE="$2"
shift 2
;;
--region)
REGION="$2"
shift 2
;;
*)
echo "不明なオプション: $1"
echo "使用方法: $0 [--profile PROFILE] [--region REGION]"
exit 1
;;
esac
done
# プロファイルオプションの設定
PROFILE_OPT=""
if [ -n "${PROFILE}" ]; then
PROFILE_OPT="--profile ${PROFILE}"
fi
ACCOUNT_ID=$(aws sts get-caller-identity ${PROFILE_OPT} --query Account --output text)
CONFIG_MANAGER_NAME="JITNodeAccess-${ACCOUNT_ID}"
S3_BUCKET_NAME="windows-ec2-private-session-logs-${ACCOUNT_ID}"
KMS_KEY_ALIAS="alias/windows-ec2-private-rdp-recording-key"
echo "=========================================="
echo "Just-in-time Node Access 有効化スクリプト"
echo "=========================================="
echo "アカウントID: ${ACCOUNT_ID}"
echo "リージョン: ${REGION}"
echo "S3バケット: ${S3_BUCKET_NAME}"
echo "KMSキーエイリアス: ${KMS_KEY_ALIAS}"
echo ""
# KMSキーIDを取得
echo "KMSキーIDを取得中..."
KMS_KEY_ID=$(aws kms describe-key ${PROFILE_OPT} --key-id "${KMS_KEY_ALIAS}" --region "${REGION}" --query 'KeyMetadata.KeyId' --output text)
echo "KMSキーID: ${KMS_KEY_ID}"
echo ""
# 必要なIAMロールが存在するか確認
echo "必要なIAMロールを確認中..."
ADMIN_ROLE_NAME="AWS-QuickSetup-StackSet-Local-AdministrationRole"
EXEC_ROLE_NAME="AWS-QuickSetup-StackSet-Local-ExecutionRole"
# Administration Roleの存在確認
if aws iam get-role ${PROFILE_OPT} --role-name "${ADMIN_ROLE_NAME}" --region "${REGION}" >/dev/null 2>&1; then
echo " ${ADMIN_ROLE_NAME}: 存在します"
else
echo " ${ADMIN_ROLE_NAME}: 存在しません。作成が必要です。"
echo ""
echo "エラー: 必要なIAMロールが存在しません。"
echo "Quick Setupを使用する前に、以下のロールを作成する必要があります:"
echo " - ${ADMIN_ROLE_NAME}"
echo " - ${EXEC_ROLE_NAME}"
echo ""
echo "これらのロールは、AWS Systems Manager Quick Setupの初回セットアップ時に自動作成されます。"
echo "Systems Managerコンソールから「Quick Setup」を開き、初回セットアップを完了してください。"
exit 1
fi
# Execution Roleの存在確認
if aws iam get-role ${PROFILE_OPT} --role-name "${EXEC_ROLE_NAME}" --region "${REGION}" >/dev/null 2>&1; then
echo " ${EXEC_ROLE_NAME}: 存在します"
else
echo " ${EXEC_ROLE_NAME}: 存在しません。作成が必要です。"
echo ""
echo "エラー: 必要なIAMロールが存在しません。"
exit 1
fi
ADMIN_ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/${ADMIN_ROLE_NAME}"
echo ""
# Configuration Definitionの作成
echo "Configuration Definitionを作成中..."
CONFIG_DEF=$(cat <<EOF
{
"Type": "AWSQuickSetupType-JITNA",
"LocalDeploymentAdministrationRoleArn": "${ADMIN_ROLE_ARN}",
"LocalDeploymentExecutionRoleName": "${EXEC_ROLE_NAME}",
"Parameters": {
"HomeRegion": "${REGION}",
"TargetAccounts": "${ACCOUNT_ID}",
"TargetRegions": "${REGION}"
}
}
EOF
)
echo "Configuration Definition:"
echo "${CONFIG_DEF}" | jq .
echo ""
# Configuration Managerの作成
echo "Configuration Managerを作成中..."
set +e
RESPONSE=$(aws ssm-quicksetup create-configuration-manager \
${PROFILE_OPT} \
--name "${CONFIG_MANAGER_NAME}" \
--description "Just-in-time Node Access configuration for Windows EC2 instances" \
--configuration-definitions "${CONFIG_DEF}" \
--region "${REGION}" \
--output json 2>&1)
EXIT_CODE=$?
set -e
echo "終了コード: ${EXIT_CODE}"
echo "レスポンス:"
echo "${RESPONSE}"
echo ""
if [ ${EXIT_CODE} -eq 0 ]; then
echo "成功: Configuration Managerが作成されました"
MANAGER_ARN=$(echo "${RESPONSE}" | jq -r '.ManagerArn')
echo "Manager ARN: ${MANAGER_ARN}"
else
echo "エラー: Configuration Managerの作成に失敗しました"
exit 1
fi
echo ""
echo "=========================================="
echo "Just-in-time Node Access の有効化が完了しました"
echo "=========================================="
echo ""
echo "次のステップ:"
echo "1. Systems Manager コンソールで設定を確認"
echo "2. 承認ポリシーを作成(自動承認または手動承認)"
echo "3. EC2インスタンスへのアクセスをテスト"
echo ""
configure-rdp-recording.sh
#!/bin/bash
# RDP接続記録設定スクリプト(オプトインログ記録機能用)
# このスクリプトは、Fleet Manager RDP接続の記録設定を行います
# 新しいスタック(windows-ec2-private-vpc-opt-in)用
set -e
# 設定
REGION="ap-northeast-1"
STACK_NAME="windows-ec2-private-vpc-opt-in"
PROFILE=""
# コマンドライン引数の解析
while [[ $# -gt 0 ]]; do
case $1 in
--profile)
PROFILE="$2"
shift 2
;;
--region)
REGION="$2"
shift 2
;;
--stack-name)
STACK_NAME="$2"
shift 2
;;
*)
echo "不明なオプション: $1"
echo "使用方法: $0 [--profile PROFILE] [--region REGION] [--stack-name STACK_NAME]"
exit 1
;;
esac
done
# プロファイルオプションの設定
PROFILE_OPT=""
if [ -n "${PROFILE}" ]; then
PROFILE_OPT="--profile ${PROFILE}"
fi
echo "=========================================="
echo "RDP接続記録設定スクリプト(オプトインログ記録機能用)"
echo "=========================================="
echo "スタック名: ${STACK_NAME}"
echo "リージョン: ${REGION}"
echo ""
# CloudFormationスタックから情報を取得
echo "CloudFormationスタックから情報を取得中..."
ACCOUNT_ID=$(aws sts get-caller-identity ${PROFILE_OPT} --query Account --output text)
KMS_KEY_ARN=$(aws cloudformation describe-stacks \
${PROFILE_OPT} \
--stack-name "${STACK_NAME}" \
--region "${REGION}" \
--query 'Stacks[0].Outputs[?OutputKey==`RDPRecordingKMSKeyArn`].OutputValue' \
--output text)
S3_BUCKET_NAME=$(aws cloudformation describe-stacks \
${PROFILE_OPT} \
--stack-name "${STACK_NAME}" \
--region "${REGION}" \
--query 'Stacks[0].Outputs[?OutputKey==`SessionLogsBucketName`].OutputValue' \
--output text)
echo "アカウントID: ${ACCOUNT_ID}"
echo "S3バケット: ${S3_BUCKET_NAME}"
echo "KMSキーARN: ${KMS_KEY_ARN}"
echo ""
# 値の検証
if [ -z "${KMS_KEY_ARN}" ] || [ -z "${S3_BUCKET_NAME}" ]; then
echo "エラー: CloudFormationスタックから必要な情報を取得できませんでした"
echo "スタック名が正しいか確認してください: ${STACK_NAME}"
exit 1
fi
# 既存の設定を確認
echo "既存のRDP接続記録設定を確認中..."
set +e
EXISTING_PREFS=$(aws ssm-guiconnect get-connection-recording-preferences \
${PROFILE_OPT} \
--region "${REGION}" \
--no-cli-pager 2>&1)
EXIT_CODE=$?
set -e
if [ ${EXIT_CODE} -eq 0 ]; then
echo "既存の設定が見つかりました:"
echo "${EXISTING_PREFS}" | jq .
echo ""
echo "既存の設定を上書きしますか? (y/N)"
read -r RESPONSE
if [[ ! "${RESPONSE}" =~ ^[Yy]$ ]]; then
echo "処理を中止しました"
exit 0
fi
echo ""
fi
# RDP接続記録設定を更新
echo "RDP接続記録設定を更新中..."
# JSONペイロードを作成
PAYLOAD=$(cat <&1)
EXIT_CODE=$?
if [ ${EXIT_CODE} -eq 0 ]; then
echo "成功: RDP接続記録設定が更新されました"
echo "${RESPONSE}" | jq .
else
echo "エラー: RDP接続記録設定の更新に失敗しました"
echo "${RESPONSE}"
exit 1
fi
echo ""
echo "=========================================="
echo "RDP接続記録設定が完了しました"
echo "=========================================="
echo ""
echo "設定内容:"
echo " - S3バケット: ${S3_BUCKET_NAME}"
echo " - KMSキー: ${KMS_KEY_ARN}"
echo ""
echo "次のステップ:"
echo " 1. Fleet Manager > Managed nodes に移動"
echo " 2. 対象のEC2インスタンスを選択"
echo " 3. Node actions > Connect > Remote Desktop を選択"
echo " 4. RDP接続をテスト"
echo " 5. 接続終了後、S3バケットに記録が保存されることを確認"
echo ""
echo "S3バケット内の記録を確認:"
echo " aws s3 ls s3://${S3_BUCKET_NAME}/ --recursive --region ${REGION}"
echo ""




