お題
ヤクの毛を狩るまでのお話です。
- Network Load Balancer のターゲットとして、Transfer Family で作成した FTPS サーバを指定したい
- 指定するにはIPアドレスが必要
- 残念ながら CDK 標準では、取得できない
- CDK カスタムリソースを利用して AWS SDK を呼び出し、IPアドレスを取得すべし!
コードの断片
CDK スタックまるごとは長すぎるので、関連部分のみです。
FTPS サーバの定義
Transfer family は CDK L1 で作らなくてはいけません。
vpc
変数には、ec2.IVpc
な値が入っていると思ってください。
import * as cdk from "aws-cdk-lib";
import * as cr from "aws-cdk-lib/custom-resources";
// (略)
// FTPサーバ
const server = new cdk.aws_transfer.CfnServer(this, "FtpServer", {
endpointType: "VPC",
endpointDetails: {
// NLB ターゲットにする都合上 subnet ひとつだけ
subnetIds: [vpc.privateSubnets[0].subnetId],
// (略)
},
// (略)
});
プライベートIPアドレスを取得するカスタムリソース
Transfer DescribeServer → EC2 DescribeVpcEndpoints → EC2 DescribeNetworkInterfaces と順番に呼び出し、プライベートIPアドレスを取得しています。
/**
* サーバのIPアドレスを取得
* @param server
*/
private retrieveIpAddressOf(
server: cdk.aws_transfer.CfnServer,
id: string
): string {
// describeServer API を呼び出し
const describeServer = {
service: "Transfer",
action: "describeServer",
parameters: { ServerId: server.attrServerId },
outputPaths: ["Server.EndpointDetails.VpcEndpointId"],
physicalResourceId: cr.PhysicalResourceId.of(id),
};
const serverCr = new cr.AwsCustomResource(this, "DescribeServer", {
onCreate: describeServer,
onUpdate: describeServer,
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
}),
});
const vpcEndpointId = serverCr.getResponseField(
"Server.EndpointDetails.VpcEndpointId"
);
// describeVpcEndpoints API を呼び出し
const desribeVpcEndpoints = {
service: "EC2",
action: "describeVpcEndpoints",
parameters: { VpcEndpointIds: [vpcEndpointId] },
outputPaths: ["VpcEndpoints.0.NetworkInterfaceIds.0"],
physicalResourceId: cr.PhysicalResourceId.of(id),
};
const vpcEndpointCr = new cr.AwsCustomResource(
this,
"DescribeVpcEndpoints",
{
onCreate: desribeVpcEndpoints,
onUpdate: desribeVpcEndpoints,
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
}),
}
);
const networkInterfaceId = vpcEndpointCr.getResponseField(
"VpcEndpoints.0.NetworkInterfaceIds.0"
);
// describeNetworkInterfaces を呼び出し
const describeNetworkInterfaces = {
service: "EC2",
action: "describeNetworkInterfaces",
parameters: { NetworkInterfaceIds: [networkInterfaceId] },
outputPaths: ["NetworkInterfaces.0.PrivateIpAddress"],
physicalResourceId: cr.PhysicalResourceId.of(id),
};
const networkInterfaceCr = new cr.AwsCustomResource(
this,
"DescribeNetworkInterfaces",
{
onCreate: describeNetworkInterfaces,
onUpdate: describeNetworkInterfaces,
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
}),
}
);
return networkInterfaceCr.getResponseField(
"NetworkInterfaces.0.PrivateIpAddress"
);
}
参考リンク
使用するAPIの情報はこちらから拝借しました。感謝!
それぞれAPIの詳細はこちらです。
CDK カスタムリソースのコンストラクタです。
クラスメソッドの記事です。いつもお世話になってます。 ペコリ
ひとりごと
ところで、なんでわざわざ NLB を使うかといいますと、各種サーバ(FTP、WWW)に同じ名前で接続したいからなんだってさー。