EC2 Instance Connect でのインスタンス接続ユーザーについて調べてみた

2019.07.02

 

こんにちは 園部です。

先日、SSH でのインスタンス接続をIAM でコントロールが出来る EC2 Instance Connect がリリースされました。

利用方法やユースケースは、弊社メンバーも記事にしてくれています!

本記事では、接続ユーザー部分を追っていきたいと思います。

前提情報

EC2 Instance Connect(以降、EIC) における接続ユーザーとは、対象インスタンスへSSHを行う際のOSユーザーとなります。 例: ec2-user, ubuntu, root, ssm-user

EIC では、IAM で接続ユーザーを指定することが出来ます。

Condition 部分の "ec2:osuser" で指定します。

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "ec2-instance-connect:SendSSHPublicKey",
"Resource": "arn:aws:ec2:region:account-id:instance/i-instance-id",
"Condition": {
"StringEquals": {
"ec2:osuser": "ami-username"
}
}
}]
}

今回は、このIAM 接続ユーザー指定部分を従来のSSH設定ファイルとともに追ってみたいと思います。

  • sshd_config(長いので、有効な部分だけ抜粋)
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/libexec/openssh/sftp-server
AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f
AuthorizedKeysCommandUser ec2-instance-connect

やってみた

検証パターン

  • 指定なし(No.1)
  • AMIデフォルトユーザー指定(No.2)
  • 任意作成ユーザー指定(No.3)
  • SSH 設定ファイルで AllowUsers との関係(No.4)

事前準備

EC2起動

パブリックサブネットに、AmazonLinux2(ami-00d101850e971728d)を一台起動します。

IAMポリシー作成

IAM > ポリシー > ポリシーの作成 を選択

まずは接続ユーザーを指定しないパターンを入力します。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2-instance-connect:SendSSHPublicKey",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
}

ポリシーの確認 > 名前を入力 > ポリシーの作成 を選択

IAMユーザー作成

先ほど、作成したIAM ポリシーをアタッチしたIAM ユーザーを作成します。

検証パターン: No.1

EIC で接続

今回は、mssh を利用してコマンドラインから接続します。 (msshについては、 弊社メンバーのブログ: EC2 Instance Connect CLIでEC2インスタンスへのSFTPもできます をご参照ください)

  • ec2-user で接続
$ mssh ec2-user@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-192-168-1-250 ~]$
  • root で接続
$ mssh root@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[root@ip-192-168-1-250 ~]#
  • 作業用ユーザーで接続(事前にeic-blogユーザーを作成)
# useradd eic-blog
# exit
$ mssh eic-blog@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[eic-blog@ip-192-168-1-250 ~]$

AmazonLinux2 のデフォルトでは root でのSSH接続は不可ですが、EICでは接続が可能です。新しく作成したユーザーもユーザーを作成しただけで接続が可能です。

以前からの SSH クライアントでの接続方法では不可なため、認識漏れで意図せずrootでの接続を許可していたという状況にならないように注意が必要です。

検証パターン: No.2

先ほど、作成したポリシーで ec2-user を指定します。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2-instance-connect:SendSSHPublicKey",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:osuser": "ec2-user"
}
}
},
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
}

EIC で接続

  • ec2-user で接続
$ mssh ec2-user@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-192-168-1-250 ~]$
  • root で接続
$ mssh root@i-046a3746dc6012f1c
Error while pushing the public key:
An error occurred (AccessDeniedException) when calling the SendSSHPublicKey operation: User: arn:aws:iam::アカウントID:user/temp-eic is not authorized to perform: ec2-instance-connect:SendSSHPublicKey on resource: arn:aws:ec2:ap-northeast-1:アカウントID:instance/i-046a3746dc6012f1c
  • 作業用ユーザーで接続
$ mssh eic-blog@i-046a3746dc6012f1c
Error while pushing the public key:
An error occurred (AccessDeniedException) when calling the SendSSHPublicKey operation: User: arn:aws:iam::アカウントID:user/temp-eic is not authorized to perform: ec2-instance-connect:SendSSHPublicKey on resource: arn:aws:ec2:ap-northeast-1:アカウントID:instance/i-046a3746dc6012f1c

EICを利用しない従来のSSHクライアントでの接続方法と同じ状況が出来ました。

検証パターン: No.3

今度は、先ほど作成した eic-blog を指定します。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2-instance-connect:SendSSHPublicKey",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:osuser": "eic-blog"
}
}
},
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
}

EIC で接続

  • ec2-user で接続
$ mssh ec2-user@i-046a3746dc6012f1c
Error while pushing the public key:
An error occurred (AccessDeniedException) when calling the SendSSHPublicKey operation: User: arn:aws:iam::アカウントID:user/temp-eic is not authorized to perform: ec2-instance-connect:SendSSHPublicKey on resource: arn:aws:ec2:ap-northeast-1:アカウントID:instance/i-046a3746dc6012f1c
  • root で接続
$ mssh root@i-046a3746dc6012f1c
Error while pushing the public key:
An error occurred (AccessDeniedException) when calling the SendSSHPublicKey operation: User: arn:aws:iam::アカウントID:user/temp-eic is not authorized to perform: ec2-instance-connect:SendSSHPublicKey on resource: arn:aws:ec2:ap-northeast-1:アカウントID:instance/i-046a3746dc6012f1c
  • 作業用ユーザーで接続
$ mssh eic-blog@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[eic-blog@ip-192-168-1-250 ~]$

従来の方法と、EICを利用したユーザーを分けて利用することが可能です。

検証パターン: No.4

最後に、IAM はno3のままで、sshd_config に許可ユーザーを設定します。

AllowUsers ec2-user

EIC で接続

  • ec2-user で接続
$ mssh ec2-user@i-046a3746dc6012f1c
Error while pushing the public key:
An error occurred (AccessDeniedException) when calling the SendSSHPublicKey operation: User: arn:aws:iam::アカウントID:user/temp-eic is not authorized to perform: ec2-instance-connect:SendSSHPublicKey on resource: arn:aws:ec2:ap-northeast-1:アカウントID:instance/i-046a3746dc6012f1c
  • 作業用ユーザーで接続
$ mssh eic-blog@i-046a3746dc6012f1c
eic-blog@3.113.248.0: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

IAMで許可していた eic-blog ユーザーも接続が不可となりました。上記の sshd_config に eic-blog を追記して reload します。

AllowUsers ec2-user eic-blog

eic-blogは接続可能となります。

$ mssh eic-blog@i-046a3746dc6012f1c
https://aws.amazon.com/amazon-linux-2/
5 package(s) needed for security, out of 13 available
Run "sudo yum update" to apply all updates.
[eic-blog@ip-192-168-1-250 ~]$

まとめ

EIC がSSHをラッピングしたサービスなので、接続ユーザーをコントロールするには、IAMでもsshd_configでも可能なようです。

複数インスタンス&ユーザーの集中管理を想定するとIAMでの管理の方が適していると思います。

さいごに

なぜこのような動きをするのか?という点ですがこの辺りは、ドキュメントから EIC の仕組みを追うのが早そうです。簡単に抜粋します。

  • EIC をインストールすると以下が準備されます
  • /opt/aws/bin に4つのファイルが作成
  • eic_curl_authorized_keys
  • eic_harvest_hostkeys
  • eic_parse_authorized_keys
  • eic_run_authorized_keys
  • ec2-instance-connect ユーザー&グループが作成
  • /etc/ssh/sshd_config に以下の2行が追加
  • AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f
  • AuthorizedKeysCommandUser ec2-instance-connect

mssh コマンドでは -d でデバック出来ます。ここでは、その情報から処理を追っていきます。

  • ローカルで鍵作成
  • /var/folders/* 配下に秘密鍵が作成(Mac環境)
  • 対象インスタンス情報を取得

EC2InstanceConnect - DEBUG - Successfully got instance information from EC2 API for i-046a3746dc6012f1c

  • 公開鍵のアップロード( SendSSHPublicKey )

EC2InstanceConnect - DEBUG - Successfully pushed the public key to i-046a3746dc6012f1c

  • インスタンス接続

EC2InstanceConnect - DEBUG - Generated command: ssh -i /var/folders/*/tmpqisRpK eic-blog@3.113.248.0

  • AuthorizedKeysCommand による公開鍵の取得

検証時に、rootやeic-blog(ユーザー作成のみ)でもログイン出来たのは、鍵を作成しそれを利用してSSH を行なっているからと考えられます。

EIC を利用する際には接続元の考慮も必要ですが、今まで通り接続ユーザーへの考慮も必要です。留意しながら、利用することでユーザー管理やセキュリティ面での効果が得られるサービスではないかと思います。