🦶
AWS CDKでセッションマネージャーから接続できる踏み台サーバーを定義する
備忘録
結論
import { Construct } from "constructs";
import { Stack, StackProps, aws_ec2 as ec2 } from "aws-cdk-lib";
export class HogeStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, "VPC", {
subnetConfiguration: [
{
cidrMask: 24,
name: "isolated",
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
],
});
// 踏み台インスタンスのセキュリティグループ
const bastionHostSG = new ec2.SecurityGroup(this, "BastionHostSG", {
vpc,
allowAllOutbound: true,
});
// 踏み台インスタンス
new ec2.BastionHostLinux(this, "BastionHost", {
vpc,
subnetSelection: {
subnetGroupName: "isolated",
},
securityGroup: bastionHostSG,
});
// VPCエンドポイントのセキュリティグループ
const endpointSG = new ec2.SecurityGroup(this, "EndpointSG", {
vpc,
allowAllOutbound: true,
});
// 必須のVPCエンドポイント
vpc.addInterfaceEndpoint("SSMEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.SSM,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("SSMMessagesEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.SSM_MESSAGES,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("EC2MessagesEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.EC2_MESSAGES,
securityGroups: [endpointSG],
});
// 場合によって必要なVPCエンドポイント
vpc.addInterfaceEndpoint("KMSEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.KMS,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("LogsEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
securityGroups: [endpointSG],
});
vpc.addGatewayEndpoint("S3Endpoint", {
service: ec2.GatewayVpcEndpointAwsService.S3,
subnets: [
{
subnetGroupName: "isolated",
},
],
});
// 踏み台インスタンスからVPCエンドポイントへのhttpsを許可
endpointSG.addIngressRule(
ec2.Peer.securityGroupId(bastionHostSG.securityGroupId),
ec2.Port.tcp(443),
"https from bastion host",
false
);
}
}
説明
踏み台サーバー用EC2インスタンスの定義
aws_cdk_lib/aws_ec2
のBastionHostLinuxを使う。
// 踏み台インスタンス
new ec2.BastionHostLinux(this, "BastionHost", {
vpc,
subnetSelection: {
subnetGroupName: "isolated",
},
securityGroup: bastionHostSG,
});
OSは最新のAmazon Linux 2。インスタンスタイプのデフォルトは't3.nano'
なので、適宜変更する。
AWS Systems Managerのセッションマネージャーから接続することを推奨しているので、実行ロールにはそれが可能な権限が最初から付与されている。
セッションマネージャーから接続するためのVPCエンドポイントの設定
ステップ 1: Session Manager の前提条件を満たす - AWS Systems Manager
上記の記事の「エンドポイントへの接続」に記載されている以下3つのVPCエンドポイントは必須。
- ssm.region.amazonaws.com
- ssmmessages.region.amazonaws.com
- ec2messages.region.amazonaws.com
// 必須のVPCエンドポイント
vpc.addInterfaceEndpoint("SSMEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.SSM,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("SSMMessagesEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.SSM_MESSAGES,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("EC2MessagesEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.EC2_MESSAGES,
securityGroups: [endpointSG],
});
以下は場合によって必要。
- KMS, Cloudwatch Logs
- 参考記事: Systems Manager を使用したインターネットアクセスなしでのプライベート EC2 インスタンスの管理
- KMSはセッションマネージャーでKMSによる暗号化を指定している場合に必要
- Cloudwatch logsはセッションマネージャーでログ出力を有効にしている場合に必要
- S3
- 踏み台に何かしらデータを持ち込んだり、yumでパッケージをインストールするなどの場合に必要
- (他にも必要なケースがあるかも)
// 場合によって必要なVPCエンドポイント
vpc.addInterfaceEndpoint("KMSEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.KMS,
securityGroups: [endpointSG],
});
vpc.addInterfaceEndpoint("LogsEndpoint", {
service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
securityGroups: [endpointSG],
});
vpc.addGatewayEndpoint("S3Endpoint", {
service: ec2.GatewayVpcEndpointAwsService.S3,
subnets: [
{
subnetGroupName: "isolated",
},
],
});
あとは、踏み台から設定したVPCエンドポイントに対してhttps(TCP 443番)を許可する。
// 踏み台インスタンスからVPCエンドポイントへのhttpsを許可
endpointSG.addIngressRule(
ec2.Peer.securityGroupId(bastionHostSG.securityGroupId),
ec2.Port.tcp(443),
"https from bastion host",
false
);
Discussion