Galapagos Tech Blog

株式会社ガラパゴスのメンバーによる技術ブログです。

超久しぶりにインフラ構築したときにやったこと 〜SSM でポートフォワーディング編〜

サービス開発パートナー事業部 Android エンジニアの松下です。最近はストリートファイター 6 を遊んでいます。とても難しい。

弊社ではバックエンド領域も扱う案件も少ないながらに存在していますが、事業部としても個人的にも結構ご無沙汰になっていました。
これを機にインフラ構築を行ったときの備忘録を残したいと思います。 AWS です。

SSM で ssh できるようにする

おじさんがまだ若かった頃、ローカルからデータベースにログインするときには踏み台サーバーに ssh ポートフォワーディングしていたんだよ。という声が聞こえてきそうですが、今どきは 22 番(に限らず ssh できるポート)を公開して晒す、なんてことはしないような気がします。

現代では SSM のセッションマネージャーを使えば IAM ロールやユーザの情報を使って ssh できるようです。

docs.aws.amazon.com

CDK でやってみましょう。

import * as ec2 from "aws-cdk-lib/aws-ec2";
import {InstanceClass, InstanceSize, IVpc, SubnetType} from "aws-cdk-lib/aws-ec2";
import * as cdk from "aws-cdk-lib";

// 踏み台サーバーのセキュリティグループ
const bastionSg = new ec2.SecurityGroup(this, "from-bastion", {
  securityGroupName: "from-bastion",
  vpc: vpc, // どうにか調達する
  allowAllOutbound: true,
});

// 踏み台 EC2
const bastion = new ec2.BastionHostLinux(this, "bastion", {
  vpc: props.vpc,
  instanceName: "bastion",
  instanceType: ec2.InstanceType.of(InstanceClass.T3, InstanceSize.MICRO),
  machineImage: ec2.MachineImage.latestAmazonLinux2023(),
  securityGroup: bastionSg,
  subnetSelection: {
    subnetType: SubnetType.PRIVATE_ISOLATED,
  },
});

const endpointSg = new ec2.SecurityGroup(this, "bastion-endpoint-sg", {
  vpc: props.vpc,
  allowAllOutbound: true,
});

// (1)
vpc.addInterfaceEndpoint("bastion-ssm-endpoint", {
  service: ec2.InterfaceVpcEndpointAwsService.SSM,
  securityGroups: [endpointSg],
});

// (1)
vpc.addInterfaceEndpoint("bastion-ssm-messages-endpoint", {
  service: ec2.InterfaceVpcEndpointAwsService.SSM_MESSAGES,
  securityGroups: [endpointSg],
});

// (1)
vpc.addInterfaceEndpoint("bastion-ec2-messages-endpoint", {
  service: ec2.InterfaceVpcEndpointAwsService.EC2_MESSAGES,
  securityGroups: [endpointSg],
});

// (1)
vpc.addGatewayEndpoint("bastion-s3-gateway", {
  service: ec2.InterfaceVpcEndpointAwsService.S3,
  subnets: [
    {
      subnetType: SubnetType.PRIVATE_ISOLATED,
    }
  ],
});

(2)
endpointSg.addIngressRule(
  ec2.Peer.securityGroupId(bastionSg.securityGroupId),
  ec2.Port.tcp(443),
  "https from bastion host",
  false,
);

new cdk.CfnOutput(this, 'bastion-instance-az', {
  value: bastion.instanceAvailabilityZone,
});

(1) セッションマネージャーを使うときに各種サービスへ接続できるように、色々穴を開けてあげる必要があるようです。
docs.aws.amazon.com

(2) 443 を開けろと言われています。
docs.aws.amazon.com

このあと以下のコマンドでポートフォワーディングが可能になるので、 RDS の中を覗くことが可能になります。

aws ssm start-session --target 踏み台サーバーのインスタンスID \
    --document-name AWS-StartPortForwardingSessionToRemoteHost \
    --parameters '{"host": ["RDSのホスト名"], "portNumber":["DBのポート"],"localPortNumber":["フォワーディングするポート"]}'

所感

昔よくバックエンドエンジニアが「フロントは進化が早すぎてついていけない」と話していたけどインフラもそうなのでは!?と思ってきました。まあ単純に興味関心の差なのだろうし、インフラというより AWS なのかもしれないけれども。

いつもの

弊社ではいっしょに働くアプリエンジニアを募集しています!
ご興味のある方はぜひご応募いただけますと嬉しいです。

hrmos.co