見出し画像

踏み台不要の新機能「EC2 Instance Connect Endpoint」でプライベートEC2に接続する(その2)

こんにちはこぐまです。
AWSの新機能「EC2 Instance Connect Endpoint (EIC Endpoint)」の備忘録となります。今回はその2です。その1はこちら。


ログはどのように出る?

その1で実施した通り「EIC Endpoint」を利用することで、
自前踏み台サーバなし、パブリックIPなし、さらにキーペアなし
で接続することができるようになりました!便利ですね!

「EIC Endpoint」を利用した接続試行については、CloudTrailに記載されます。実際に接続した際、Cloudtrailにはどのように出力されるのかを見てみます。

基本的には、「SendSSHPublicKey」→「OpenTunnel」のアクションが順番で表示されるみたい

実際に接続をしてみて、しばらくしてCloudTrailで確認してみると、
SendSSHPublicKey」と「OpenTunnel」というイベントが記載されています。

イベント名として「SendSSHPublicKey」と「OpenTunnel」が記載されている。

なお、イベントソースは「ec2-instance-connect.amazonaws.com」となっています。イベントソースでフィルタリングするときはこれをキーワードにすると便利かも。以下のようにユーザごとにまとめて表示されます。
この時も必ず「SendSSHPublicKey」と「OpenTunnel」が2組セットで表示されています。(緑の線で分けています。)

「SendSSHPublicKey」とは何か?

正直あっているか自信がないですが、いろんなマニュアルや記事を読み漁り、また実機で確認もしてみて私は以下の理解をしました。もし違っていたらご指摘いただけますと幸いです!

「EIC Endpoint」の前段階のサービスとして、「EIC(EC2 instance Connect)」があります。EICでは、EC2インスタンスはパブリックIPを必要とするという条件がありましたが、接続方法としては今回の「EIC Endpoint」とほぼ同様です。

前回はここで右側を選択しましたが、この左側が「EIC」です。
この表示例ではパブリックIPがないので、利用はできませんが・・

ユーザが「EIC」を使ってEC2インスタンスへのアクセスを試みるとき、まずは「EIC」と「EC2インスタンス」間で疎通ができる必要があります。この時、EICは接続するEC2インスタンスにアクセスするための一時的なキーペアを動的に作成し、その公開鍵をEC2インスタンスのメタデータ内に送るようです。このキーの生存期間は60秒です。この「一時的接続のために作成した公開鍵をEC2インスタンスのメタデータに送る」というアクションが「SendSSHPublicKey」のようです。「EIC Endpoint」ではキーペアが不要・・というのはキーペア自体が本当に不要なわけではなく、実はここで作っている(意識しない)一時的キーペアがあるため、ユーザ管理のキーペアは不要という理解をしました。
マニュアルには「EC2インスタンスのメタデータ内に送り、その有効期限は1分」と書かれていたのですが、実際それが本当に1分で消えるのかどうか興味が湧いて調べてみました。

「SendSSHPublicKey」でプッシュされる一時公開鍵は本当に1分で消える?

インスタンス内のメタデータとあったので、てっきり以下のマニュアルの
「使用可能なパブリックキーのリストを取得する」結果を定期的にモニタリングしていれば、ひょこっと出てきてひょこっと消えるのかなと考えました。

【使用可能なパブリックキーのリストを取得する】
TOKEN=`curl -X PUT "http://169.254.169.xxx/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.xxx/latest/meta-data/public-keys/

 
ちなみにマニュアルコピペだと、一番最初の「TOKEN=」が抜けているのでエラーになります。。

上記コマンドを少し編集して「metacollect.sh」というシェルにして、while文で1秒おきに呼び出しました。

★metacollect.shの中身(dateやsleep,curlの出力を少し変更,sleepも1秒入れる)
[ec2-user@ip-XXXXXXXXX ~]$ cat metacollect.sh
#!/bin/bash
date
TOKEN=`curl -s -X PUT "http://169.254.169.xxx/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" `
curl -s -f -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.xxx/latest/meta-data/public-keys/
sleep 1while文で回す(CTRL+Cで止める)
[ec2-user@ip-XXXXXXXXX ~]$ while true ; do ./metacollect.sh | tee -a result.log ;  done

ところが待てども待てども・・新しい公開鍵がリストに登録されている形跡は見えず・・sleepをusleepにして0.1秒ごとに更新してもダメでした。。

というわけでもう一回マニュアルを見てみると・・・

The SSH daemon uses AuthorizedKeysCommand and AuthorizedKeysCommandUser, which are configured when Instance Connect is installed, to look up the public key from the instance metadata for authentication, and connects you to the instance.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Connect-using-EC2-Instance-Connect.html

どうやら、「AuthorizedKeysCommand 」「AuthorizedKeysCommandUser」というものが関わっている模様。
これは一般的に「/etc/ssh/sshd_config」に記載されているとのことなので見てみました。

バッチリ出てきましたね。

AuthorizedKeysCommand 」の実体は「/opt/aws/bin/eic_run_authorized_keys」にあるようなので見てみます。

こんどは「eic_curl_authorized_keys」を呼び出しています。
timeoutで5秒の時間制限をしていますね。

さらに呼び出されている「eic_curl_authorized_keys」の中身は180行近くありました。正直かなりわけわからない状態でしたが、一つだけヒントそうな場所を見つけました。

# Verify that we have active keys.  Fast-exit if we do not.
keys_status="$(/usr/bin/curl -s -m 1 -H "${IMDS_TOKEN_HEADER}" -o /dev/null -I -w %{http_code} "${IMDS}/managed-ssh-keys/active-keys/${1}/")"

おお!最後のところ、、
「"${IMDS}/managed-ssh-keys/active-keys/${1}/"」
もしかするとこれじゃないか!
${IMDS}という変数は「http://169.254.169.xxx/latest/meta-data/」が入るので、結局見るべき場所は
「http://169.254.169.xxx/latest/meta-data/public_keys」ではなくて
「http://169.254.169.xxx/latest/meta-data/managed-ssh-keys/active-keys・・」
なんだろうな・・と。

そこで「metacollect.sh」を以下のように書き換えて、再度while文で回しながら「EIC Endpoint」からの接続を試みました。

★改良した「metacollect_2.sh」
[ec2-user@ip-XXXXXXXXX  ~]$ cat metacollect_2.sh
#!/bin/bash
date
TOKEN=`curl -s -X PUT "http://169.254.169.xxx/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" `
curl -s -f -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.xxx/latest/meta-data/managed-ssh-keys/active-keys/
sleep 1while文で回す
[ec2-user@ip-XXXXXXXXX ~]$ while true ; do ./metacollect_2.sh | tee -a result.log ;  done

すると・・・

[ec2-user@ip-XXXXXXXXX ~]$ while true ; do ./metacollect_2.sh ; done
Fri Jul 14 12:37:27 UTC 2023
Fri Jul 14 12:37:28 UTC 2023
Fri Jul 14 12:37:29 UTC 2023
Fri Jul 14 12:37:30 UTC 2023
ec2-user Fri Jul 14 12:37:31 UTC 2023
ec2-userFri Jul 14 12:37:32 UTC 2023
ec2-userFri Jul 14 12:37:33 UTC 2023
ec2-userFri Jul 14 12:37:34 UTC 2023
ec2-userFri Jul 14 12:37:35 UTC 2023
ec2-userFri Jul 14 12:37:36 UTC 2023
ec2-userFri Jul 14 12:37:37 UTC 2023
ec2-userFri Jul 14 12:37:38 UTC 2023
ec2-userFri Jul 14 12:37:39 UTC 2023
ec2-userFri Jul 14 12:37:40 UTC 2023

(中略・・・)
ec2-userFri Jul 14 12:38:23 UTC 2023
ec2-userFri Jul 14 12:38:24 UTC 2023
ec2-userFri Jul 14 12:38:25 UTC 2023
ec2-userFri Jul 14 12:38:26 UTC 2023
ec2-userFri Jul 14 12:38:27 UTC 2023
ec2-userFri Jul 14 12:38:28 UTC 2023
ec2-userFri Jul 14 12:38:29 UTC 2023
ec2-userFri Jul 14 12:38:30 UTC 2023

Fri Jul 14 12:38:31 UTC 2023
Fri Jul 14 12:38:32 UTC 2023
Fri Jul 14 12:38:33 UTC 2023
Fri Jul 14 12:38:34 UTC 2023
^C
[ec2-user@ip-XXXXXXXXX ~]$

出てきましたね!「ec2-user」が!
そしてちゃんと1分で消えていることもわかります。
もう少し深堀してみます。
http://169.254.169.xxx/latest/meta-data/managed-ssh-keys/active-keys/のさらに配下に今出てきた「ec2-user」を追加してみます。

★改良した「metacollect_3.sh」(curlのパスの最後に「ec2-user」を追加)
[ec2-user@ip-XXXXXXXXX  ~]$ cat metacollect_3.sh
#!/bin/bash
date
TOKEN=`curl -s -X PUT "http://169.254.169.xxx/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" `
curl -s -f -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.xxx/latest/meta-data/managed-ssh-keys/active-keys/ec2-user
sleep 1

そして、while文で回してみます。

[ec2-user@ip-XXXXXXXXX ~]$ while true ; do ./metacollect_3.sh | tee -a result.log ; done
Fri Jul 14 14:33:44 UTC 2023
Fri Jul 14 14:33:45 UTC 2023
Fri Jul 14 14:33:46 UTC 2023
Fri Jul 14 14:33:47 UTC 2023
#Timestamp =1689345286
#Instance =i-0a3d2c84bcffb603b
#Caller =arn:aws:iam::123456789012:user/eictest-user
#Request =f2e7c3d9-ef92-4b1a-8e50-823e4a3ba085
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOy89hDAbuhN6rj0jRGCZRMEtkaF67mQ/testTestAbc
jwOiIsOM8CaODjYnKOl+kJK16gcAZkV4aycIutv6AjVAepopR8HzLIQTaGJ7zV0nP6sqeDGojhNuLwNooky1Ie73gaNaoJysR2wW+9/9SqBEy35azcxGDvybsr45QfBQdE6O3+oowzQqa249wCjgkcXxxCALHzLKcI4Iec/waZdUaSFxXEsp6xrLxw/n2oA9GBbmqgTNPjncx9k+hCPtXAU/sgMsPM8pKk1+5+jfCKOCeqmpPGwjMtRE8z91dqDX30iqKnSHkfGIL7T8TBHJEhGWGJzo1upQh1+OcAw+RBGHPkZxotOM4c81zKTkM+xzohHd8mfMTipQYBcYdi1z2w==

Fri Jul 14 14:33:48 UTC 2023
#Timestamp =1689345286
#Instance =i-0a3d2c84bcffb603b
#Caller =arn:aws:iam::123456789012:user/eictest-user
#Request =f2e7c3d9-ef92-4b1a-8e50-823e4a3ba085
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOy89hDAbuhN6rj0jRGCZRMEtkaF67mQ/testTestAbc
jwOiIsOM8CaODjYnKOl+kJK16gcAZkV4aycIutv6AjVAepopR8HzLIQTaGJ7zV0nP6sqeDGojhNuLwNooky1Ie73gaNaoJysR2wW+9/9SqBEy35azcxGDvybsr45QfBQdE6O3+oowzQqa249wCjgkcXxxCALHzLKcI4Iec/waZdUaSFxXEsp6xrLxw/n2oA9GBbmqgTNPjncx9k+hCPtXAU/sgMsPM8pKk1+5+jfCKOCeqmpPGwjMtRE8z91dqDX30iqKnSHkfGIL7T8TBHJEhGWGJzo1upQh1+OcAw+RBGHPkZxotOM4c81zKTkM+xzohHd8mfMTipQYBcYdi1z2w==

Fri Jul 14 14:33:49 UTC 2023
#Timestamp =1689345286
#Instance =i-0a3d2c84bcffb603b
#Caller =arn:aws:iam::123456789012:user/eictest-user
#Request =f2e7c3d9-ef92-4b1a-8e50-823e4a3ba085
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOy89hDAbuhN6rj0jRGCZRMEtkaF67mQ/testTestAbc
jwOiIsOM8CaODjYnKOl+kJK16gcAZkV4aycIutv6AjVAepopR8HzLIQTaGJ7zV0nP6sqeDGojhNuLwNooky1Ie73gaNaoJysR2wW+9/9SqBEy35azcxGDvybsr45QfBQdE6O3+oowzQqa249wCjgkcXxxCALHzLKcI4Iec/waZdUaSFxXEsp6xrLxw/n2oA9GBbmqgTNPjn
・・・・・・

ついにプッシュされたと思われる公開鍵が出てきました!

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOy89hDAbuhN6rj0jRGCZRMEtkaF67mQ/testTestAbc

おそらくこれが一時的に作成され、メタデータにプッシュされた公開鍵なのでしょう。ed25519というのは比較的最近出た暗号アルゴリズムということで、私は恥ずかしながらあまり知らなかったです。RSAのようにビット長も長くなく256bit固定だとか。RSAのような素因数分解の困難さではなく、楕円曲線の離散対数・・・云々・・。難しそう。。

そして、CloudTrail側の「SendSSHPublicKey」イベント詳細にもちゃんとこの公開鍵が載っていました。

CloudTrailにてイベントIDも一致していること、および
公開鍵も一致していることが確認できた!

なのでまとめると

1.EICによる接続時は、実はAWSが一時的にキーペアを作成してくれている。ユーザがEC2構成時に設定する必要がないのはそのため。

2.AWSが作る一時的なキーペアは、「SendSSHPublicKey」処理によりインスタンスのメタデータ内に格納される。具体的な場所は「http://169.254.169.xxx/latest/meta-data/managed-ssh-keys/active-keys/」ぽいが、この場所はマニュアルには載っていない・・。

3.上記に格納された一時的な公開鍵は、60秒経つときれいさっぱり消える。それまでに認証を済ませる必要がある。

という感じです!もっとたくさん書きたいことあったけど、思いのほか深くのめりこんでしまったのでまたの機会に!

一点だけわからないのは、公開鍵の次の行に書かれている「jwOiIsOM8CaODjYnKOl+kJK・・・」というプッシュされた内容・・これは何だろう・・。秘密鍵ではなさそう(実際復元しようとしてみたけど無理でした・・もし詳しい方いらっしゃいましたら是非教えて頂きたいです。)

読んで下さってありがとうございました!

この記事が参加している募集

やってみた

この記事が気に入ったらサポートをしてみませんか?