いつかまたパタゴニアに

主にソフトウェア開発周りで気づいたことなどをまとめています

EC2にVSCode Serverを構築してセキュアにアクセスしよう!

はじめに

cloud9廃止に伴い、ここ最近はAWS上での開発環境構築に関連した話題がにわかに盛り上がりを見せています。

cloudshell, sagemaker studio code editorなどなどが候補として上がってきていますが、 CDK開発など重厚なビルド処理などを行うような開発では、強力なインスタンス性能を求められる事もあると思います。

そんな状況向けに、EC2インスタンスにVSCode Serverを導入しブラウザからセキュアにアクセスを確立できるような環境構築を模索したので、 内容をまとめておきます。

セットアップ方法

デプロイ

手っ取り早く作成できるよう、CDK Construct(cdk-code-server)として公開しています。

constructs.dev

ここから、AWS CDKを用いてデプロイしてみましょう。

CDK自体のセットアップは公式ドキュメントを参照ください。STEP5まで実行すればOKです。

CDKアプリケーションが構築できたら、cdk-code-serverをインストールしたうえで、Stack定義を以下のように書き換えます。

npm install cdk-code-server
import * as cdk from 'aws-cdk-lib';
import { CodeServer } from 'cdk-code-server';
import { Construct } from 'constructs';

export class CodeServerStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // CodeServerクラスをインスタンス化
    new CodeServer(this, 'CodeServer');
  }
}

デプロイしてみましょう。

$ npx cdk deploy

✨  Synthesis time: 5.39s

CodeServerStack: start: Building 6b82c08c411ad583faa859a28107837b81c3dc67035e3a7bebd7f45fc243e8f0:current_account-current_region
...

// IAMの変更一覧
IAM Statement Changes

// yを入力して続行
Do you wish to deploy these changes (y/n)? y
CodeServerStack: deploying... [1/1]
CodeServerStack: creating CloudFormation changeset...

 ✅  CodeServerStack

✨  Deployment time: 646.04s

✨  Total time: 651.44s

10分程度でデプロイが完了します。

VSCodeアクセス

EC2へ接続

まずはAWS ConsoleのEC2管理コンソールにアクセスし、EIC Endpoint経由でEC2インスタンスに接続します。

以下の画面が表示されればOKです。

EC2コンソール画面

VSCode serverのセットアップ

コンソール上で以下のコマンドを実行し、認証コードをコピーします。

[ec2-user@ip-10-0-0-23 ~]$ code tunnel service install
[2024-06-10 02:10:42] info Using GitHub for authentication, run `code tunnel user login --provider <provider>` option to change this.
To grant access to the server, please log into https://github.com/login/device and use code 3811-9932

次に、ブラウザでhttps://github.com/login/deviceにアクセスし、コードを入力します。

上の例では、「3811-9932」を入力し、「Continue」>「Authorize-Visual-Studio-Code」を実行します。

続いてEC2インスタンスに戻り、再度code tunnelを実行し、表示されたURL https://vscode.dev/tunnel/ip-{privateIp}{region} をブラウザで開きます。

[ec2-user@ip-10-0-0-23 ~]$ code tunnel
*
* Visual Studio Code Server
*
* By using the software, you agree to
* the Visual Studio Code Server License Terms (https://aka.ms/vscode-server-license) and
* the Microsoft Privacy Statement (https://privacy.microsoft.com/en-US/privacystatement).
*
[2024-06-10 02:11:44] info Creating tunnel with the name: ip-10-0-0-23ap-north
[2024-06-10 02:11:44] info Open this link in your browser https://vscode.dev/tunnel/ip-10-0-0-23ap-north

Connected to an existing tunnel process running on this machine.

Open this link in your browser https://vscode.dev/tunnel/ip-10-0-0-23ap-north

VSCodeが開き、"What type of account did you used to start this tunnel? "というプロンプトが表示されますので、GitHubを選択します。

ここでまたGitHubの認証画面が表示された場合、Authorizeを押下してください。

ターミナルを開けば準備完了です!!

VSCodeサーバに接続完了

構成

Public Subnet上のEC2インスタンスにVSCode Serverをインストールし、EC2 Instance Connect(EIC) Endpoint経由で管理通信ができるようにしています。

構成図

ポイント

EC2インスタンスはパブリックサブネット上に設置されていますが、セキュリティグループのインバウンドルールとしてはEIC EndpointからのSSHしか許可されていません。

SecurityGroup

したがって、Internetからインスタンスへの直接通信は不可であり、非常にセキュアな開発環境となっています。

EIC Endpointによる管理通信

EC2 Instance Connect Endpoint (EIC Endpoint)はEC2インスタンスへの管理通信を簡便に行うためのサービスです。

1VPCあたり1つまで設置することができ、以下の条件を満たすことでInternetからEC2インスタンスへのSSH or RDPが行えるようになります。

EIC エンドポイントについては別記事にて利用例を解説しています。 GUIツールによるDBへの管理通信を確立する例も紹介していますので、合わせてご覧ください。

nixieminton.hatenablog.com

VSCode Serverへのアクセス

VSCode ServerにはEIC Endpointを介さずアクセスします。

VScode Serverへのアクセスはhttps://vscode.devを介して行われており、EC2インスタンスとvscode.devの間のトンネルはEC2インスタンス側から通信が行われています。したがって、EC2インスタンス側でアウトバウンドルールを開放しておけば、この接続を確立することができます。

つまり、VSCode Serverへ通信するために別途インバウンドルールを開放する必要はありません。

クライアントがVSCodeではないという違いはありますが、以下の図がイメージとして近いはずです。

vscode

参考: AWS Systems Manager と VS Code Remote SSH を組み合わせて快適なリモート開発環境を作る方法 | DevelopersIO

アクセス権限管理はAWSの手を離れ、すべてGitHubに委任する形となりますが、十二分にセキュアなものだと思います。

(もちろん、GitHub側のログイン設定でMFAは有効化しておきましょう)

また、このVSCode Server - vscode.dev間のトンネル形成はservice化させることが可能です。詳細な手順はコンストラクトのREADMEをご参照ください。

github.com

NodeJSやgitなどのインストール

EC2インスタンスにはVSCodeに加えて、デフォルトでNodeJSやgitが導入されています。

インスタンス起動時にこれらのインストールコマンド群がuserdataを使って自動実行されるようにしています。

こちらも別途CDKコンストラクトとして公開していますので、興味のある方は参考にしてみてください。

github.com

IAM権限

VSCode Server上での全てのAWS APIを叩く処理は、EC2 インスタンスに紐づけられたIAMロールの権限にて行われます。

cdk-code-serverではデフォルトで管理者権限をインスタンスに付与しています。権限を絞りたい場合は、IAMポリシーステートメントを引数として渡せばOKです。

https://constructs.dev/packages/cdk-code-server/v/0.0.7?lang=typescript#usage

設定一覧

CDK上で設定できる項目は以下のとおりです。 インスタンスタイプがそこそこ大きめな点と、ARMアーキテクチャをデフォルトで採用している点にご注意ください!

new CodeServer(this, 'CodeServer', {
  vpc,
  // EC2インスタンスタイプ
  // Default is c7g.2xlarge
  instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
  // CPUアーキテクチャ
  // Default is ec2.AmazonLinuxCpuType.ARM_64
  cpuType: ec2.AmazonLinuxCpuType.X86_64,
  // インスタンスロール用IAMポリシー
  // Default is a policy that has an administrator access
  policy,
  // EBSのボリュームサイズ
  // Default is 30 GB
  volumeSize: 100,
});

FAQ

Q: EC2はプライベートサブネットに設置しないの?

A: セキュリティグループで十分アクセスは絞れているため、パブリックでも問題ないと考えています。プライベートに設置すると、EC2インスタンスからInternetへの通信経路確保のためにNAT Gatewayを設置する必要があり、コスト的にも大きなデメリットとなります。

Q: 管理通信はSSM session managerでも良くないですか?

A: 良いです。パブリックサブネットなので、session manager用のVPC Endpoint作成なども不要ですしね! EIC Endpointを採用した理由は、自分で作ったopen-constructs/aws-cdk-libraryのL2コンストラクトを使いたかっただけです。

Q: vscode.devを介さず、EIC Endpointを使ってVSCode Serverへアクセスもできるんじゃないですか?

A: その通りです。EIC Endpointを経由したトンネル作成を行うことができるので、それを活用すればloclhostとEC2間でトンネル確立が可能です。ただし、EIC Endpointでは宛先ポートが22 or 3389に限られるため、VSCode Serverがlistenするポートを3389に変更する必要があります。

最後に

この環境はCDK conference 2024で開催されたCDK Contribute Workshop向けに作成しました。

また、こちらを参考に自身の書籍向けの開発環境をcloud9から移行されたかたもいらっしゃるみたいです。(とっても嬉しいです)

皆様も是非ご活用いただけると嬉しいです。