🔑

1PasswordでGoogle Cloud Compute EngineにSSHしてみる

2023/02/14に公開

こんにちは。Google Cloudのカスタマーエンジニアの有賀です。

この記事では1Passwordを使ってGoogle CloudのCompute Engine VM (GCE VM)にSSHしてみます。…と言いつつ、正確には1Passwordを使ってSSHするための秘密鍵を管理してみよう、という内容です。

1PasswordをSSHの鍵管理に使う方法はオフィシャルのドキュメントでも説明されてますし、何番煎じか?っていうくらい似た記事もありますが、ちょっと検索した感じGCE VMの例は見つけられなかったので試してみました。

前提とする環境

GCE VMには主にLinuxとWindowsが選べますますが、ここではLinuxを対象とします。またSSHのクライアント端末としてMac/Linux/Windowsが考えられますが、自分の環境がMacなので、とりあえずMacの話だけします。つまりMacのクライアントからLinuxのサーバーへSSHする例になります。あしからずご了承ください。

あと、GCE VMにSSHで接続できる条件として、VPCのファイアウォールの設定でSSHを許可している必要がありますが、そこは事前に設定ができてる前提とします。(1Passwordとの連携以前に)そもそもGCE VMに接続できないなどのトラブルシューティングには「SSHエラーのトラブルシューティング」のページが参考になると思います。

Google CloudにおけるSSHの鍵管理

そもそもGCE VMへSSHする際のアカウント管理(SSHの鍵管理)には二種類あります。

  • プロジェクト(もしくはVM)のメタデータに登録したSSHの鍵でログインする
  • OS Loginの仕組みで管理されるSSHの鍵でログインする

SSH鍵の登録
SSH鍵の管理

もともとはメタデータを使った方法しかなかったのでそちらが現在でもデフォルトになっていますが、メタデータによる管理はVMへのアクセス権限に差を付けたり、そもそもSSHの鍵管理自体をIAMでコントロールしたりといったことができないので、可能であれば今後はOS Loginを使った管理をしていただくのがよいかと思います

とはいえ、メタデータを使った方法もシンプルで分かりやすいので、本記事ではメタデータによる方法と、OS Loginによる方法の両方を取り上げたいと思います。

SSHのクライアント

単純にGCE VMにSSHするだけでも、実はいくつかの方法があり詳解 Google Compute Engineへの接続という記事に詳しく書きました。

具体的には、ブラウザ上のSSHボタンで接続する方法、Google Cloudのコマンドラインツールであるgcloudコマンドで接続する方法、通常のSSHクライアント/コマンドで接続する方法などがありますが、今回は1Passwordと連携させるのでまずは通常のSSHコマンドと連携させてから、gcloudコマンドとの連携も確認します。

1Passwordでの準備

Google Cloudを触る前に、先に1Password側での準備を済ませます。

ちなみに1Passwordとの連携の仕組みは簡単で、1PasswordがSSHエージェントの役割を果たしてます。

1PasswordのSSHエージェント機能
1PasswordのSSHエージェント機能

では早速設定をします。初めに1Passwordアプリのメニューから「設定… > 開発者」を選びます。「SSHエージェントの設定」をクリックすると…

1Passwordの設定
1Passwordの設定 > 開発者

SSHキー名を表示するか聞かれます。スクリーンショットの日本語が怪しいですが、英語では「Display key names when authorizing connections. (An unencrypted copy of the item title will be stored locally.)」となっており、つまりSSHキー名が平文で保存されるよ、ということです。キー名自体がセンシティブな情報なこともあるかもしれませんが、キー名は表示した方が利便性は高いと思います。(なお、この後の手順に出てくるように、キー名は自分で設定します。)

SSHキー名の表示の選択
SSHキー名の表示の選択

SSHキー名の表示を選択したら設定は終わりです。SSHエージェント用の設定が表示されるのでコピーしておきましょう。

SSHエージェントの設定
SSHエージェントの設定

なお、SSHエージェントの設定はすべて一律です。

~/.ssh/config
Host *
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

こちらをホームディレクトリのSSHの設定ファイル ~/.ssh/config に追加しておきます。(設定ファイルがなければ作成します)

1Passwordの準備ができたので、次にGoogle CloudでSSH鍵を登録します。

メタデータでのSSH鍵管理

初めにメタデータでSSH鍵を管理します。

SSH鍵の登録(メタデータ)

まずはメタデータにSSH鍵(公開鍵)を登録して、それを使ってGCE VMにログインしてみます。実はgcloudコマンドを使うとメタデータへのSSH鍵の登録も自動的におこなってくれるのですが、今回は1Passwordと連携させたいので、手動でSSH鍵を登録するところから始めます。

まずはGoogle CloudのCloud Consoleの左上の三本線メニューから、Compute Engine > Metadataとたどります。次に「SSH KEYS」というタブを選びます。

メタデータのSSH鍵
メタデータのSSH鍵

次に「ADD SSH KEY」ボタンをクリックします。すると、うまくいけば下のスクリーンショットのように1PasswordがSSH鍵の作成をサジェストしてくれます。そこで、この「Create SSH Key...」をクリックすると…


1Passwordと連携

1Passwordが鍵を生成するダイアログになります。SSHキーに名前を付けて(上で表示するか否かを選んだのはこの名前です)、(デフォルトでいいと思いますが)鍵のタイプを選んで「Create & Fill」をクリックすると…

1PasswordでSSH鍵を生成
1PasswordでSSH鍵を生成

自動的に生成したSSH鍵の公開鍵がテキストボックスへ自動的に貼り付けられます。しかし、なぜか「Invalid key」と赤くエラーになってます。

公開鍵を登録したのにエラー
公開鍵を登録したのにエラー

通常SSHの公開鍵はプロトコル 鍵本体 コメントみたいな形式になっていて、コメント部分はオプションだと思いますが、メタデータに登録する場合はこのコメント部分にログインの際のアカウント名(Linuxのアカウント名)を記入するようになっています。

そこでアカウント名(例では「sampleuser」)を末尾に追加しところエラーはなくなりました。最後に「SAVE」ボタンをクリックすると…

アカウント名を追加
アカウント名を追加

無事にSSH鍵が登録できました。

SSH鍵の登録完了
SSH鍵の登録完了

GCE VMへのSSH(メタデータ)

それでは早速GCE VMを作ってログインしてみましょう。GCE VMの作成はCloud Consoleでおこなってもいいですし、gcloudコマンドでおこなっても結構です。(クイックスタートのドキュメントもあります。)

ここではgcloudコマンドでGCE VMを作成します。(gcloudコマンドのインストール方法はこちらのドキュメントを参照のこと。)

$ gcloud compute instances create test-vm-1 \
      --machine-type=e2-micro \
      --zone=asia-northeast1-b
Created [https://www.googleapis.com/compute/v1/projects/agira-tmp-1/zones/asia-northeast1-b/instances/test-vm-1].
NAME       ZONE               MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP   STATUS
test-vm-1  asia-northeast1-b  e2-micro                   10.146.0.13  34.84.201.247 RUNNING

では、ついにSSHコマンドで接続します。SSH鍵の登録のセクションで選んだアカウント名(sampleuser)を指定します。

SSHコマンドを実行して、(はじめての接続なので)続けるかという質問にYesと答えると、スクリーンショットのような1Passwordのダイアログがポップアップします。「アクセスを許可」するとそのままログインが完了します。(Touch IDを使ってれば、Touch IDを触るように促されたりします。)


VMへSSH

テキストでも接続の様子を残しておきます。

$ gcloud compute instances create test-vm-1 \
    --machine-type=e2-micro \
    --zone=asia-northeast1-b
Created [https://www.googleapis.com/compute/v1/projects/agira-tmp-1/zones/asia-northeast1-b/instances/test-vm-1].
NAME       ZONE               MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
test-vm-1  asia-northeast1-b  e2-micro                   10.146.0.13  34.84.201.247  RUNNING

$ ssh sampleuser@34.84.201.247
The authenticity of host '34.84.201.247 (34.84.201.247)' can't be established.
ED25519 key fingerprint is SHA256:xHr4pmWPSbjJF2scMIOIyDodVgSfN7Me0fE8M/7UUCY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '34.84.201.247' (ED25519) to the list of known hosts.
(ここで1Passwordのダイアログがポップアップ)
Linux test-vm-1 5.10.0-19-cloud-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
sampleuser@test-vm-1:~$

gcloudで接続(メタデータ)

SSHコマンドでは無事接続ができたので、gcloudコマンドでの接続も試しておきます。

ただし、すでにgcloudコマンドを使ったことがある場合はそのまま以前の設定でログインできてしまうと思いますので、gcloudコマンドがデフォルトで作成するSSH鍵の名前を変更しておきます。

$ cd ~/.ssh
$ mv google_compute_engine google_compute_engine-
$ mv google_compute_engine.pub google_compute_engine.pub-

これで準備完了です。

gcloudコマンドの場合はVMのIPアドレスの代わりに、VMの名前を指定して接続できます。またSSHコマンドの時と同じく、アカウント名を明示的に指定(sampleuser@)します。

$ gcloud compute ssh sampleuser@test-vm-1 --zone=asia-northeast1-b
WARNING: The private SSH key file for gcloud does not exist.
WARNING: The public SSH key file for gcloud does not exist.
WARNING: You do not have an SSH key for gcloud.
WARNING: SSH keygen will be executed to generate a key.
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):^C

あれ? SSH keygen will be executed to generate a key. とか言ってまた新しいSSH鍵を作ろうとしています。実はこれはgcloudコマンドの仕様で、gcloud compute sshコマンドはSSHエージェントに頼らず自分で作成したSSH鍵をデフォルトで使おうとします。そして、もしデフォルトのSSH鍵ファイルがない場合は、上記のように新規に作成しようとします。

--ssh-key-file=SSH_KEY_FILE というオプションで別のSSH鍵を指定することもできますが、いずれにせよSSHの秘密鍵がファイルとして存在していることが前提になっています。しかし、SSHの秘密鍵は1Passwordの中にあるのでファイルとして指定できません。さてどうしましょう?

実はそのためのオプションとして --plain というオプションが用意されています。ドキュメントによると、This flag is useful if you want to take care of authentication yourself or use specific ssh/scp features. と書かれていて、今回の目的にピッタリな感じなので、早速試してみます。

$ gcloud compute ssh --plain sampleuser@test-vm-1 --zone=asia-northeast1-b
Linux test-vm-1 5.10.0-19-cloud-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Feb  9 09:58:30 2023 from 14.8.16.96
sampleuser@test-vm-1:~$

今度は無事に接続することができました。というわけでSSH鍵の管理に1Password(や他のSSHエージェントベースのナニカ)を使ってる場合に gcloud compute ssh を使う場合は --plain オプションを付けましょう。

OS LoginでのSSH鍵管理

さてここまでメタデータでSSH鍵を管理した場合を見てきましたが、次に本命のOS LoginでのSSH鍵の管理を試してみます。

OS Loginにおけるアカウント名

と、SSH鍵の設定をする前に、OS Loginにおけるアカウント名の話をしたいと思います。

メタデータでのSSH鍵管理のセクションでSSH鍵の登録をする際、SSHの公開鍵のコメント部分にLinuxのアカウント名を書きましたが、OS Loginを使う場合はそのように自由なアカウント名は使わず、デフォルトではGoogle Cloudを利用するのに使っているGoogleアカウントからLinuxアカウント名が生成され、USERNAME_DOMAIN_SUFFIX という形式の形式のアカウント名になります。

具体的には、たとえばGoogleアカウントが seiji@example.com だとすると、OS Loginを使った場合のアカウント名はデフォルトでは seiji_example_com になります。(@._ に置換されます。)

この方法だとアカウント名が長くなりがちですが、gcloudコマンドを使ってログインする場合は以下のように、自動的にアカウント名を補完してSSHをしてくれるので、明示的に指定する必要がなく面倒ではありません。

OS Loginが有効なVMへのgcloudコマンドでの接続
OS Loginが有効なVMへのgcloudコマンドでの接続

一方、1Passwordとgcloudコマンドを連携させるためには上のセクションで見たように --plain というオプションを付ける必要があるのですが、実はこの --plain オプションを付けちゃうと、このアカウント名の補完がおこなわれなくなってしまうのです。その代わり、デフォルトではgcloudコマンドを実行しているPCのアカウント名がそのまま使われます。

OS Loginが有効なVMへの --plain 付きのgcloudコマンドでの接続
OS Loginが有効なVMへの --plain 付きのgcloudコマンドでの接続

上図の例だと結果として gcloud compute ssh --plain を実行すると seiji でログインしようとしますが、GCE VMのアカウント名(seiji_example_com)と違うのでログインに失敗します。

実際の実行結果はこんな感じです。(二行目を見ると seiji というアカウント名でログインしようとしてるのが分かります。)

$ gcloud compute ssh test-vm-1 --plain
seiji@34.84.22.165: Permission denied (publickey).

正しいアカウント名を明示的に指定すればログインできます。

$ gcloud compute ssh seiji_example_com@test-vm-1 --plain
Linux test-vm-1 5.10.0-19-cloud-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64
(中略)
seiji_example_com@test-vm-1:~$

正しいアカウント名を明示的に指定すればログインできるとは言うものの、アカウント名は長めだし、割と面倒です。そこで解決策として考えられるのが、PCのアカウント名とGCE VMのアカウント名(ie. OS Loginのアカウント名)をそろえてしまうことです。

アカウント名をそろえる方法は2つ考えられます。

  1. OS Loginのアカウント名にドメイン名を含まないようにする
  2. OS Loginのアカウント名を任意のアカウント名に変更する

アカウント名からドメイン名を省く

1つ目は上の例のように、Googleアカウント名のアカウント名部分と、PCのアカウント名が同じ場合にのみ使えます。(が、そういう環境は多いんじゃないかと思ってます。)一方、上の注釈に書いたように、異なるドメインで同じアカウント名が使われていた場合に衝突が発生するので、その点は考慮する必要があります。

具体的な方法は比較的簡単で、Google管理コンソールから設定を変更します。メニューの「アプリ > その他のGoogleサービス > Google Cloud Platformの設定」にある「POSIXアカウント設定」の「OS Login APIによって生成されるアカウント名にドメインサフィックスを含める」のチェックを外して設定を保存します。

Google管理コンソールの設定
Google管理コンソールの設定

これでGoogleアカウント seiji@example.com のLinuxアカウント名は seiji になり、PCのアカウント名をそのまま使えます。

アカウント名を任意に変更

一方、Googleアカウント名が ariga@example.com、PCのアカウント名が seiji のような場合には1つ目の方法は使えないので、2つ目の「任意のアカウント名に変更」を試すことになります。

ただ、OS Loginのディレクトリを操作するためのAPIであるDirectory APIにはGUIはおろか、コマンドラインインターフェイスもなく、APIを直接操作する必要があるのでちょっと面倒なんですよね…。

一応APIを試せるページは用意されてるので、今回はそれを使ってみたいと思います。まずはユーザーのリストを見てみます。users.list APIのページで、引数のdomainに使っているGoogleアカウントのドメインを入力して「EXECUTE」を実行します。(権限のあるGoogleアカウントでログインしてから試してください。)

Directory API: users.list
Directory API: users.list

すると下のところに結果が表示されます。

Directory API: users.listの結果
Directory API: users.listの結果

次に実際にアカウント名を変更したいのですが、もしOS Loginを一度も使ってないと、そもそもLinuxのアカウント名自体がディレクトリにできてない可能性が高いので、その場合はいったん次のセクションの「SSH鍵の登録」をおこなってきてください。


SSH鍵の登録ができたらusers.get APIで確認します。(userKey にGoogleアカウント名を入れます。)

Directory API: users.get
Directory API: users.get

出力に以下のような posixAccounts が含まれていたらオッケーです。

users.getのレスポンス
"posixAccounts": [
    {
      "username": "ariga_example_com",
      "uid": "610336879",
      "gid": "610336879",
      "homeDirectory": "/home/ariga_example_com",
      "systemId": "",
      "primary": true,
      "operatingSystemType": "linux"
    }
  ],

ではこの usernamehomeDirectoryusers.update APIで変更します。

userKey にGoogleアカウント名(例の場合 ariga@example.com)、Request bodyには変更したい posixAccounts ブロックを含めます。

Directory API: users.update
Directory API: users.update

usernamehomeDirectory のアカウント名をPCのアカウント名と同じものに変更し、他はそのままにしておきます。

Request bodyに含める内容
{
  "posixAccounts": [
    {
      "username": "seiji",
      "uid": "610336879",
      "gid": "610336879",
      "homeDirectory": "/home/seiji",
      "systemId": "",
      "primary": true,
      "operatingSystemType": "linux"
    }
  ]
}

「EXECUTE」で実行し、200のレスポンスが返ってきたら念の為、再度users.get APIで期待通り変更されているか確認しておきます。

以上でOS Loginディレクトリの変更は完了です。

SSH鍵の登録(OS Login)

(OS Loginのディレクトリの操作のためにすでにSSH鍵を登録していたら、このセクションは飛ばして次へ行きましょう。)

メタデータの場合と違い、OS LoginでのSSH鍵の追加にはCloud Consoleは使えず、gcloudコマンドが必要です。(もちろんAPIやTerraformを使うこともできます。)

gcloudコマンドでSSH鍵をOS Loginのディレクトリに追加するためには、SSHの公開鍵をいったんファイルに保存する必要があります。そこで、メタデータのセクションで(自動的に作られた)SSHの公開鍵を1Passwordからファイルにエクスポートします。1PasswordアプリでSSH鍵を選択して公開鍵のメニューからダウンロードします。

SSHの公開鍵をエクスポート
SSHの公開鍵をエクスポート

Macならばデフォルトで ~/Downloads にダウンロードされます。ファイル名id_ed25519.pub(もしくは実際にダウンロードされたファイル名)を覚えておきましょう。

SSHの公開鍵をエクスポート
SSHの公開鍵をエクスポート

ダウンロードしたSSHの公開鍵を、gcloudコマンドでOS Loginのディレクトリに追加します。

$ gcloud compute os-login ssh-keys add --key-file=id_ed25519.pub
loginProfile:
  name: '116965996597969370277'
  posixAccounts:
  - gid: '610336879'
    homeDirectory: /home/ariga_example_com
    operatingSystemType: LINUX
    primary: true
    uid: '610336879'
    username: ariga_example_com
  sshPublicKeys:
    e7daa9fef3adc518806e4981261275c3ba86516e7cd39c7a6892a02d8f4a4ce3:
      fingerprint: e7daa9fef3adc518806e4981261275c3ba86516e7cd39c7a6892a02d8f4a4ce3
      key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHsm0ivE2G4UYRMF1k3Q5VnIg9T668g8ewpWidLVCdgq
      name: users/ariga@example.com/sshPublicKeys/e7daa9fef3adc518806e4981261275c3ba86516e7cd39c7a6892a02d8f4a4ce3

これでOS LoginのディレクトリへのSSHの公開鍵の登録ができました。

GCE VMへのSSH(OS Login)

では準備ができたので、メタデータの場合と同じようにgcloudコマンドでVMを作成します。今回はOS Loginを有効にするため --metadata enable-oslogin=TRUE を付けます。

$ gcloud compute instances create test-vm-1 \
    --machine-type=e2-micro \
    --zone=asia-northeast1-b \
    --metadata enable-oslogin=TRUE
Created [https://www.googleapis.com/compute/v1/projects/agira-tmp-1/zones/asia-northeast1-b/instances/test-vm-1].
NAME       ZONE               MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP   STATUS
test-vm-1  asia-northeast1-b  e2-micro                   10.146.0.14  34.84.22.165  RUNNING

VMができたらSSHコマンドで接続します。この時使うLinuxのアカウント名は上のセクションでアカウント名をどうしたかしだいになります。

  • 何もしなかった → Googleアカウント名から生成される(eg. ariga_example_com)
  • ドメインサフィックスを付けないように変更した → Googleアカウント名部分 (eg. ariga)
  • 任意のアカウント名に変更した → 変更したアカウント名(eg. seiji)

たとえば3つ目の方法をとったとして試してみると、メタデータでの場合とまったく同じように1Passwordのダイアログがポップアップしてログインが成功します。

$ ssh seiji@34.84.22.165
The authenticity of host '34.84.22.165 (34.84.22.165)' can't be established.
ED25519 key fingerprint is SHA256:fNvYO8dqaa+6nMcfPxX1j0g0ukIE16cPdcRb8tpuVoo.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '34.84.22.165' (ED25519) to the list of known hosts.
(ここで1Passwordのダイアログがポップアップ)
Linux test-vm-1 5.10.0-21-cloud-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64
(後略)
seiji@test-vm-1:~$

gcloudで接続(OS Login)

最後にgcloudコマンドでの接続を試します。といっても「OS Loginにおけるアカウント名」のセクションで仕組みは説明してしまったので、--plain を付ければ1Passwordと連携できることはおわかりかと思います。

PCのアカウント名とLinuxのアカウント名(ie. OS Loginのアカウント名)をそろえた場合は、アカウント名を明示的に指定せずとも gcloud compute ssh test-vm-1 --plain でそのままログインできます。

そろえなかった場合は明示的にアカウント名を指定します。

$ gcloud compute ssh ariga_example_com@test-vm-1 --plain
Linux test-vm-1 5.10.0-21-cloud-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64
(中略)
agira_example_com@test-vm-1:~$

おまけ

外部IPアドレスがないVMへのSSH

ちなみにここまでの例ではいずれもGCE VMに外部IPアドレスがついていましたが、gcloud compute sshコマンドを使うと外部IPアドレスがついてないGCE VMにも簡単にSSHで接続できます。(もちろん1Passwordとも連携できます)

外部IPアドレスがないVMへどうやってSSHできるかの仕組みについては以前書いた下の記事を参照ください。

上の記事にもある通り、外部IPアドレスがないVMにSSHする場合、Identity-Aware Proxy (IAP)というGoogle Cloudが管理するプロキシを経由します。そのためファイアウォールで 35.235.240.0/20 からの接続を許可しておく必要があります。

できたらさっそく外部IPアドレスがないVMを作ってSSHで接続してみましょう。メタデータによる方法でもOS Loginによる方法でも、どちらでもいいですが、オススメのOS Loginの方で試します。「GCE VMへのSSH(OS Login)」のセクションでVMを作った時のコマンドに --no-address を追加して、外部IPアドレスが付かないようにします。

$ gcloud compute instances create test-vm-1 \
    --machine-type=e2-micro \
    --zone=asia-northeast1-b \
    --metadata enable-oslogin=TRUE \
    --no-address
Created [https://www.googleapis.com/compute/v1/projects/agira-tmp-1/zones/asia-northeast1-b/instances/test-vm-1].
NAME       ZONE               MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
test-vm-1  asia-northeast1-b  e2-micro                   10.146.0.18               RUNNING

ご覧の通り「EXTERNAL_IP」のところが空欄になっています。この状態でgcloudコマンドを使って接続してみます。

ここまでで説明した通り、PCのアカウント名のままでよければアカウント名は付けず、異なっている場合は明示的に付けてgcloudコマンドを実行します。--plainも忘れずに。

$ gcloud compute ssh test-vm-1 --plain
External IP address was not found; defaulting to using IAP tunneling.
The authenticity of host 'compute.1752833043515011919 (<no hostip for proxy command>)' can't be established.
ED25519 key fingerprint is SHA256:h+K8x9c3wHDWMjwPJDrDIsodjE/WiVK8rQFc9c6NAPw.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'compute.1752833043515011919' (ED25519) to the list of known hosts.
(ここで1Passwordのダイアログがポップアップ)
Linux test-vm-1 5.10.0-21-cloud-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64
(中略)
agira@test-vm-1:~$

このように外部IPアドレスが付いていても付いていなくても、gcloud compute ssh という同じコマンドでログインできています。出力を見ると External IP address was not found; defaulting to using IAP tunneling. と出ており、外部IPアドレスが付いていないことを検知して、自動的にIAPを使っていることがわかります。

ちなみに外部IPアドレスがあるVMにはじめて接続する場合は The authenticity of host '34.84.22.165 (34.84.22.165)' can't be established. のように、外部IPアドレスとSSHのホスト鍵を対応づけて known_hosts ファイルに保存しています。しかし、外部IPアドレスがない場合はそれができないので、上記 The authenticity of host 'compute.1752833043515011919 (<no hostip for proxy command>)' can't be established. のようにVMのインスタンスIDと紐付けてホスト鍵が保存されています。

$ gcloud compute instances describe test-vm-1 --format="value(id)"
1752833043515011919

$ grep 1752833043515011919 ~/.ssh/known_hosts
compute.1752833043515011919 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICXxovKPJ0lTANrS5wFouakH97LniFD9fXrHBdzm5mh
compute.1752833043515011919 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI67WWPl50c3Eyz8uJFVWGrkhNOAOwmWX47GAQixFM3jcFhQJ6N1OtoLTawXTx0sLQlCI6TpLolV9TEeT899LM4=

--plainによるSSHオプションの変化

gcloudコマンドで --plain オプションを付けるとOS Loginで使うアカウント名を検索してくれなくなる話はしましたが、実はそれ以外にもいくつかSSHのオプションが変化します。gcloud --verbosity=debug compute ssh test-vm-1 のようにデバッグフラグを立てて実行すると --plain を付けない場合と付けた場合とで違いが一目瞭然です。

gcloud compute ssh
DEBUG: Executing command:
  ['/usr/local/bin/ssh',
      '-t',
      '-i', '/Users/seiji/.ssh/google_compute_engine',
      '-o', 'CheckHostIP=no',
      '-o', 'HashKnownHosts=no',
      '-o', 'HostKeyAlias=compute.8256839686434634926',
      '-o', 'IdentitiesOnly=yes',
      '-o', 'StrictHostKeyChecking=yes',
      '-o', 'UserKnownHostsFile=/Users/seiji/.ssh/google_compute_known_hosts',
      'ariga_example_com@34.84.22.165']
gcloud compute ssh --plain
DEBUG: Executing command:
  ['/usr/local/bin/ssh',
      '-t',
      'seiji@34.84.22.165']

個別の説明は省きますが、(--plainを付けない)通常時は、同じIPアドレスで異なるVMが作られるようなクラウド環境で、SSHのホストキーのチェックが毎回エラーにならないよう工夫をしています。同じことを --plain を付けた状態で実現するのは面倒ですが、できなくはないかもしれません。

終わりに

1PasswordでのSSH鍵の管理をちょっと試してみようと思っただけなのに、意外と長くなってしまいました。

SSHコマンドだけを使ってる限りにおいてはSSHの秘密鍵をディスク上に置かなくてよいので安全ですし、さらに1Passwordにログインさえすればどこでも同じ鍵を使い回せるので、1Passwordを信頼できるなら安全でかつ利便性も上がると思います。

一方、gcloudコマンドと併用するためには --plain オプションを付ける必要があり、OS Login利用時のアカウント名の検索がされなくなるとか、いくつか細かい惜しいポイントが出てきてしまいます。もちろん工夫でなんとかなる範囲ではあると思いますが、少し気をつける必要があります。

というわけで、1Passwordをお使いの皆さまは、ぜひGoogle Cloudでもお試しください。

Google Cloud Japan

Discussion