Cloud9用EC2へのSession Manager越しのSSH接続(ポート転送)

:::note info
目的
- Cloud9環境にTeratermで接続する
- Cloud9環境にVSCodeで接続する
:::

:::note warn
前提条件
- [AWS Cloud9環境のCloudShellでの構築](https://qiita.com/sincere_networker/items/b428f2ad0fe5c7e6ef9c)が完了していること
- IAM Identity Centerのユーザーでログインできること
- AWS CLI のインストール済みであること
- AWS CLI 用の Session Manager プラグインをインストール済みであること
- 検証はWindows上のWSLで確認
:::


# 1) AWS CLIでのSSO認証設定
## 1-1) ブラウザでSSOログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/6a1f3277-5378-f870-e433-363e6dfc06a2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/368dba1b-6b72-3b9a-dcd0-78778e51626f.png)

## 1-2) AWS CLIから認証設定
aws configure ssoで「SSO start URL」と「SSO region」を入力
```bash:コマンド
aws configure sso
```
下記を入力
SSO session name (Recommended):
SSO start URL [None]:
SSO region [None]:
```bash:出力
ser01@WIN-CCVQU8G9E71:~$ aws configure sso
SSO session name (Recommended): Cloud9-Qiita
SSO start URL [None]: https://xxxxxxxxxxxx.awsapps.com/start#
SSO region [None]: ap-northeast-1
SSO registration scopes [sso:account:access]:
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.ap-northeast-1.amazonaws.com/

Then enter the code:

FWPW-KXZC
gio: https://device.sso.ap-northeast-1.amazonaws.com/?user_code=FWPW-KXZC: Operation not supported
```
## 1-3) ブラウザから許可
gioのURLをブラウザで開いて「Confirm and continue」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/16de49bf-8f49-1a02-4dc2-6f0fb0964094.png)

「Allow」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/5794f903-7f82-d6af-eea7-770333ca32aa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/cf443208-c7e2-0581-308f-2245957b0296.png)

## 1-4) AWS CLIから続きを設定
下記を入力
CLI default client Region [None]:
CLI default output format [None]:

```bash:出力
The only AWS account available to you is: 999999999999
Using the account ID 999999999999
The only role available to you is: Qiita
Using the role name "Qiita"
WARNING: your terminal doesn't support cursor position requests (CPR).
CLI default client Region [None]: ap-northeast-1
CLI default output format [None]: json
CLI profile name [Qiita-999999999999]:

To use this profile, specify the profile name using --profile, as shown:

aws s3 ls --profile Qiita-999999999999
```
# 2) AWS CLIでのSSOログイン
## 2-1) AWS CLIからSSOログイン
```bash:コマンド
export AWS_PROFILE=Qiita-999999999999
aws sso login
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ export AWS_PROFILE=Qiita-999999999999
user01@WIN-CCVQU8G9E71:~$ aws sso login
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.ap-northeast-1.amazonaws.com/

Then enter the code:

CWPL-SDKT
gio: https://device.sso.ap-northeast-1.amazonaws.com/?user_code=CWPL-SDKT: Operation not supported
```
## 2-2) ブラウザから許可
gioのURLをブラウザで開いて「Confirm and continue」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/71d03923-6ace-9bd2-eacc-5256b3ab61c2.png)

「Allow」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/5794f903-7f82-d6af-eea7-770333ca32aa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/cf443208-c7e2-0581-308f-2245957b0296.png)

## 2-3) AWS CLIでログイン成功を確認
```bash:出力
Successfully logged into Start URL: https://xxxxxxxxxxxx.awsapps.com/start#
```
# 3) Cloud9用EC2 起動
## 3-1) (変数設定)Cloud9環境ID取得
```bash:コマンド
ENVIRONMENTID=$( \
  aws cloud9 list-environments \
    --region ap-northeast-1 \
    --query environmentIds \
    --output text \
) \
&& echo ${ENVIRONMENTID}
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ ENVIRONMENTID=$( \
  aws cloud9 list-environments \
    --region ap-northeast-1 \
    --query environmentIds \
    --output text \
) \
&& echo ${ENVIRONMENTID}
380f64aa02f84b6cac181d60e37be990
```
## 3-2) (変数設定)EC2インスタンスID取得
```bash:コマンド
EC2_INSTANCE_ID=$( \
  aws ec2 describe-instances \
    --filters "Name=tag-key,Values=aws:cloud9:environment" "Name=tag-value,Values=${ENVIRONMENTID}" \
    --query "Reservations[].Instances[].InstanceId" \
    --output text \
) \
&& echo ${EC2_INSTANCE_ID}
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ EC2_INSTANCE_ID=$( \
  aws ec2 describe-instances \
    --filters "Name=tag-key,Values=aws:cloud9:environment" "Name=tag-value,Values=${ENVIRONMENTID}" \
    --query "Reservations[].Instances[].InstanceId" \
    --output text \
) \
&& echo ${EC2_INSTANCE_ID}
i-08fe65eeaa97d379e
```
## 3-3) EC2インスタンス起動
```bash:コマンド
aws ec2 start-instances \
  --instance-ids ${EC2_INSTANCE_ID}
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ec2 start-instances \
  --instance-ids ${EC2_INSTANCE_ID}
{
    "StartingInstances": [
        {
            "CurrentState": {
                "Code": 0,
                "Name": "pending"
            },
            "InstanceId": "i-08fe65eeaa97d379e",
            "PreviousState": {
                "Code": 80,
                "Name": "stopped"
            }
        }
    ]
}
```
## 3-4) EC2インスタンス起動確認
```bash:コマンド
aws ec2 describe-instance-status \
  --instance-ids ${EC2_INSTANCE_ID}
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ec2 describe-instance-status \
  --instance-ids ${EC2_INSTANCE_ID}
{
    "InstanceStatuses": [
        {
            "AvailabilityZone": "ap-northeast-1c",
            "InstanceId": "i-08fe65eeaa97d379e",
            "InstanceState": {
                "Code": 16,
                "Name": "running"
            },
            "InstanceStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            },
            "SystemStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            }
        }
    ]
}
```


# 4) EC2 キーペア準備
## 4-1) EC2 キーペアを作成
```bash:コマンド
aws ec2 create-key-pair \
  --key-name MyKeyPair \
  --query 'KeyMaterial' \
  --output text \
> MyKeyPair.pem
```
※出力されたpemファイルはSSHログイン時に使用
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ec2 create-key-pair \
  --key-name MyKeyPair \
  --query 'KeyMaterial' \
  --output text \
> MyKeyPair.pem
```
## 4-2) pemファイルをダウンロード
```bash:コマンド
cp -p MyKeyPair.pem /mnt/c/Users/user01/Downloads/
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ cp -p MyKeyPair.pem /mnt/c/Users/user01/Downloads/
user01@WIN-CCVQU8G9E71:~$ 
```
## 4-3) 共通鍵を確認
```bash:コマンド
aws ec2 describe-key-pairs \
  --key-names MyKeyPair \
  --include-public-key \
  --query 'KeyPairs[].PublicKey' \
  --output text
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ec2 describe-key-pairs \
  --key-names MyKeyPair \
  --include-public-key \
  --query 'KeyPairs[].PublicKey' \
  --output text
ssh-rsa 省略
```
## 4-4) AWSCloud9SSMAccessRole(EC2ロール)にAmazonEC2ReadOnlyAccessをアタッチ
```bash:コマンド
aws iam attach-role-policy \
  --role-name AWSCloud9SSMAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws iam attach-role-policy \
  --role-name AWSCloud9SSMAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
```
## 4-5) EC2インスタンス Session Manager接続
```bash:コマンド
aws ssm start-session \
  --target ${EC2_INSTANCE_ID}
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ssm start-session \
  --target ${EC2_INSTANCE_ID}

Starting session with SessionId: test-user-20240211-0920d56908b0afb32
sh-5.2$ 
```
## 4-6) (変数設定)公開鍵
```bash:コマンド
PUBLIC_KEY=$( \
  aws ec2 describe-key-pairs \
    --key-names MyKeyPair \
    --include-public-key \
    --query 'KeyPairs[].PublicKey' \
    --output text \
) \
&& echo ${PUBLIC_KEY}
```
```bash:出力
sh-5.2$ PUBLIC_KEY=$( \
  aws ec2 describe-key-pairs \
    --key-names MyKeyPair \
    --include-public-key \
    --query 'KeyPairs[].PublicKey' \
    --output text \
) \
&& echo ${PUBLIC_KEY}
ssh-rsa 省略
```
## 4-7) EC2インスタンスに公開鍵の追記
```bash:コマンド
sudo sh -c "echo ${PUBLIC_KEY} >> /home/ec2-user/.ssh/authorized_keys"
```
```bash:出力
sh-5.2$ sudo sh -c "echo ${PUBLIC_KEY} >> /home/ec2-user/.ssh/authorized_keys"
sh-5.2$ 
```
## 4-8) EC2インスタンス Session Manager切断
```bash:コマンド
exit
```
```bash:出力
sh-5.2$ exit
exit


Exiting session with sessionId: test-user-20240211-0920d56908b0afb32.

user01@WIN-CCVQU8G9E71:~$ 
```
## 4-9) AWSCloud9SSMAccessRole(EC2ロール)からAmazonEC2ReadOnlyAccessをデタッチ
```bash:コマンド
aws iam detach-role-policy \
  --role-name AWSCloud9SSMAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws iam detach-role-policy \
  --role-name AWSCloud9SSMAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
user01@WIN-CCVQU8G9E71:~$ 
```

# 5) Cloud9環境へのSession Manager経由のSSH(ポートフォワード)開始
```bash:コマンド
aws ssm start-session \
    --target ${EC2_INSTANCE_ID} \
    --document-name AWS-StartPortForwardingSession \
    --parameters '{"portNumber":["22"], "localPortNumber":["56789"]}'
```
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ssm start-session \
    --target ${EC2_INSTANCE_ID} \
    --document-name AWS-StartPortForwardingSession \
    --parameters '{"portNumber":["22"], "localPortNumber":["56789"]}'

Starting session with SessionId: test-user-20240211-0c0e42a473d29c052
Port 56789 opened for sessionId test-user-20240211-0c0e42a473d29c052.
Waiting for connections...
```
# 6) TeraTremからEC2へのSSH接続確認
ホスト: localhost
TCPポート#(P): 56789
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/2fe62e28-852d-db8e-30e5-f3fa2c72b481.png)
セキュリティ警告が表示された場合は続行ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/39d253ea-f3cb-aca6-89bc-0e6975ae1d6f.png)
ユーザ名(N): ec2-user
秘密鍵(K): pemファイルを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/49be55db-986b-b2f4-90e9-250e9d418ce3.png)
ログイン成功後 exitで切断
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/6f65b86d-6f9f-784e-9660-25ee6b5903b1.png)

# 7) VSCodeからEC2へのSSH接続確認
## 7-1) SSH設定
```bash:コマンド
mkdir ~/.ssh
chmod 700 ~/.ssh
mv MyKeyPair.pem ~/.ssh/
chmod 600 ~/.ssh/MyKeyPair.pem 
```
## 7-2) configファイル作成
```bash:コマンド
cat << EOF > ~/.ssh/config
Host cloud9
    HostName localhost
    Port 56789
    User ec2-user
    IdentityFile ~/.ssh/MyKeyPair.pem
EOF
```
## 7-3) ssh接続
```bash:コマンド
ssh cloud9
```
exitで接続終了
```bash:出力
user01@WIN-CCVQU8G9E71:~$ ssh cloud9
The authenticity of host '[localhost]:56789 ([127.0.0.1]:56789)' can't be established.
ED25519 key fingerprint is SHA256:EUPaXfmX6Yub6UtLSa/cUsCwJsBU9ak5rlrLeABPZXU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:56789' (ED25519) to the list of known hosts.

A newer release of "Amazon Linux" is available.
  Version 2023.3.20240205:
Run "/usr/bin/dnf check-release-update" for full release and version update info
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Mon Feb 12 06:02:53 2024 from 127.0.0.1
:~ $ exit
```

# 8) Cloud9環境へのsession manager経由のSSH(ポートフォワード)切断
Ctrl + c で終了
```bash:出力
user01@WIN-CCVQU8G9E71:~$ aws ssm start-session \
    --target ${EC2_INSTANCE_ID} \
    --document-name AWS-StartPortForwardingSession \
    --parameters '{"portNumber":["22"], "localPortNumber":["56789"]}'

Starting session with SessionId: test-user-20240211-0c0e42a473d29c052
Port 56789 opened for sessionId test-user-20240211-0c0e42a473d29c052.
Waiting for connections...

Connection accepted for session [test-user-20240211-0c0e42a473d29c052]
^CTerminate signal received, exiting.


Exiting session with sessionId: test-user-20240211-0c0e42a473d29c052.
```
# 参考
[セッションを開始する - AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-sessions-start.html#sessions-start-port-forwarding)