グローバルIP無しのセキュアなリモート開発環境を構築 by VSCode Remote Development x GCP x IAP

10 min read読了の目安(約9300字

目次

  1. これは何
  2. やってみた履歴
  3. 手順詳細

1. これは何

今回は「グローバルIPアドレスを持たないセキュアなGCE環境」と「VSCode Remote Development」を組み合わせて、グローバルIP経由しないリモート開発環境を実現する方法を記載しています。

VSCode Remote Development、もしくはGoogle IAP単体記事は見つけましたが、両方を組み合わせた記事が無かったので忘備録として記録しておきます。

最後に詳細な手順を記載していますので、経緯飛ばして手順を知りたい方は 手順詳細 から読んでください

Identity-Aware Proxyとは

Google Cloud のIAP(Identity-Aware Proxy)ってご存知ですか?
既存のWEBサービスに対して認証機能を挟むことができる仕組みです。その機能の中に TCP 転送での IAP の使用 というものがあります。公式文章には以下の記述があります。

IAP TCP 転送を使用して、パブリック IP アドレスを持たない、またはインターネット経由の直接アクセスを許可しない VM インスタンスへの管理者権限を有効にする方法

簡単にいうと、グローバルIP不要でGCEにSSH/RDPできたりする便利なやつです。
今回はこれを用いて、グローバルIP無しに接続出来るGCE(Compute Engine)環境を作成します。

VSCode Remote Development (以下 VSCode RD)とは

ここで細かい説明するまでも無いですね。
分からない方はGoogle先生に聞いてください。丁寧に教えてくれます。

2. やったみた履歴

GCE x VSCode RD を組み合わせてみる

VSCode+RemoteDevelopment+GCEでリモート開発環境を構築する に素晴らしい手順が記載されています。僕も参考にこれで試しました。

ただこれだとGCEにグローバルIPが付与されるのと、Firewallを開けないといけないので、もう少しセキュアにできないかなぁ。と思いました。

Google IAPとは

TCP 転送での IAP の使用 に記載されている通り、 パブリック IP アドレス を持たなくても以下のコマンドだけでGCEにSSHすることができます。
ref: SSH 接続のトンネリング

$ gcloud compute ssh INSTANCE_NAME

素晴らしいですね。でもこれだとコマンド実行しないといけないです。VSCode RD は .ssh/config を使うこともできるので、何とか .ssh/config を生成したいです。

gcloud compute config-ssh

ありました。素晴らしい。 gcloud compute config-ssh.ssh/config を生成してくれるみたいです。

通常、GCEにパブリックIPが付与されている環境ならこんな感じで出ます。しかし、、、

$ gcloud compute config-ssh --project xxxxx
You should now be able to use ssh/scp with your instances.
For example, try running:

  $ ssh instance-1.us-central1-a.xxxxx
  
$ cat ~/.ssh/config
# Google Compute Engine Section
#
# The following has been auto-generated by "gcloud compute config-ssh"
# to make accessing your Google Compute Engine virtual machines easier.
#
# To remove this blob, run:
#
#   gcloud compute config-ssh --remove
#
# You can also manually remove this blob by deleting everything from
# here until the comment that contains the string "End of Google Compute
# Engine Section".
#
# You should not hand-edit this section, unless you are deleting it.
#
Host instance-1.us-central1-a.xxxxx
    HostName 11.22.33.44
    IdentityFile /Users/shogo.muranushi/.ssh/google_compute_engine
    UserKnownHostsFile=/Users/shogo.muranushi/.ssh/google_compute_known_hosts
    HostKeyAlias=compute.132145986798693947
    IdentitiesOnly=yes
    CheckHostIP=no

# End of Google Compute Engine Section

GCEにパブリックIPが付与されていない環境の場合は以下の通りになります。

$ gcloud compute config-ssh --project xxxxx
WARNING: No host aliases were added to your SSH configs because instances have no public IP.

because instances have no public IP ...。パブリックIPが無いと生成してくれないだと...? 悲しみ。

gcloud compute ssh --dry-run

さてどうするか。と色々調べると gcloud compute sshdry-run があり、SSHコマンドを生成してくれることがわかりました。そこで gcloud compute ssh でラップされた生のSSHコマンドを生成します。(以下はマスクしているので漏れても問題ありません)

$ gcloud compute ssh iap-test --tunnel-through-iap --dry-run
No zone specified. Using zone [asia-northeast1-b] for instance: [iap-test].
/usr/bin/ssh -t -i /Users/shogo.muranushi/.ssh/google_compute_engine -o CheckHostIP=no -o HostKeyAlias=compute.214545646547654334 -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/Users/shogo.muranushi/.ssh/google_compute_known_hosts -o ProxyCommand /Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-b --verbosity=warning -o ProxyUseFdpass=no shogo.muranushi@compute.214545646547654334

よっしゃ。これを VSCode の Remote-SSH: Add New SSH host に追加すれば .ssh/config を生成してくれるぞ。ということで、そのまま突っ込んでも Argument missing for option ProxyCommand というエラーが表示され登録できません。

そのため ProxyCommand を修正します。 ProxyCommand の後に =" を加えて、最終部分に " で閉じるだけです。

# from
ProxyCommand /Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-b --verbosity=warning

# To
ProxyCommand="/Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-b --verbosity=warning"

合わせてコマンド冒頭の /usr/bin/sshssh に変えておきます。

修正後の全文としては以下になります。

ssh -t -i /Users/shogo.muranushi/.ssh/google_compute_engine -o CheckHostIP=no -o HostKeyAlias=compute.214545646547654334 -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/Users/shogo.muranushi/.ssh/google_compute_known_hosts -o ProxyCommand="/Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-b --verbosity=warning" -o ProxyUseFdpass=no shogo.muranushi@compute.214545646547654334

VSCode上にSSHコマンドを登録して完成

これを VSCode で Shift-Command-P を押して、 Remote-SSH: Add New SSH host を探して 上のSSHコマンドを入れれば、IAP経由で接続する .ssh/config を生成してくれ、VSCodeにも登録してくれます。

これで VSCode Remote Development x GCP x IAP の環境が完成しました。

3. 手順詳細

さて、これらの再現性を高めるために手順を記録しておきます。

  1. VSCode をインストール

    1. 公式からインストールしましょう
  2. VSCode Remote Development をインストール

    1. 特に難しいことはありませんのでMarketplaceのリンクを載せておきます。
  3. GCE起動

    1. GCPのプロジェクトを作る
    2. gcloud(CLI)のインストール
    3. GCEのサービスを有効にする
      • 新規プロジェクトやまだGCEが有効化されていない場合は以下のコマンドで有効化ください
      $ gcloud services enable compute.googleapis.com
      
    4. GCEのインスタンスを作る
      • VSCodeのリモート環境用のGCEを起動します。パラメータは必要に応じて置き換えてください。実行すると外部IPアドレス(EXTERNAL_IP)の無いGCEが立ち上がってきます
        $ gcloud compute instances create iap-test \
        --zone=asia-northeast1-a \
        --image-family=ubuntu-2004-lts \
        --image-project=ubuntu-os-cloud \
        --boot-disk-size=10GB \
        --boot-disk-type=pd-ssd \
        --machine-type=n1-standard-1 \
        --no-address
        Created [https://www.googleapis.com/compute/v1/projects/xxxxx/zones/asia-northeast1-a/instances/iap-test].
        NAME      ZONE               MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
        iap-test  asia-northeast1-a  n1-standard-1               10.146.0.4                RUNNING
        
  4. SSHコマンドの生成

    1. dry-runでSSHコマンドを生成します
      $ gcloud compute ssh iap-test --tunnel-through-iap --dry-run
      No zone specified. Using zone [asia-northeast1-a] for instance: [iap-test].
      /usr/bin/ssh -t -i /Users/shogo.muranushi/.ssh/google_compute_engine -o CheckHostIP=no -o HostKeyAlias=compute.21093710293709127 -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/Users/shogo.muranushi/.ssh/google_compute_known_hosts -o ProxyCommand /Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-a --verbosity=warning -o ProxyUseFdpass=no shogo.muranushi@compute.21093710293709127
      
    2. 出力結果の修正(ProxyCommandとsshの記述修正)します
      ssh -t -i /Users/shogo.muranushi/.ssh/google_compute_engine -o CheckHostIP=no -o HostKeyAlias=compute.21093710293709127 -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/Users/shogo.muranushi/.ssh/google_compute_known_hosts -o ProxyCommand="/Users/shogo.muranushi/.pyenv/versions/3.8.2/bin/python3 -S /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py compute start-iap-tunnel iap-test %p --listen-on-stdin --project=xxxxx --zone=asia-northeast1-a --verbosity=warning" -o ProxyUseFdpass=no shogo.muranushi@compute.21093710293709127
      
  5. VSCodeに登録

    1. VSCodeで Shift-Command-P を押して、 Remote-SSH: Add New SSH host を選択します
    2. SSHコマンドを貼り付けます
    3. 左サイドバーからコンピューターのマークを選択し、今回追加された「compute.xxxx」を右クリックし、 Current Window か New Window のいずれかを選択します
    4. すると画面左下に 緑のバーが出てSSH接続ができている状態になり、Terminalでコマンドを打つとGCE側の結果が表示されます。 Let's coding!!
  6. 完了
    以下のコマンドでGCEを起動・停止できるので必要に応じてご利用ください。

    # 停止
    gcloud compute instances stop iap-test
    
    # 起動
    gcloud compute instances start iap-test
    
  7. Apendix
    PortFoward も出来るのでアプリの動作確認も問題無し

https://www.youtube.com/watch?v=6ndUhaPjDEw

Happy coding!