aws cli をできるだけ安全に行う

# TL;DR
できるだけ安全にAWS リソースを操作する方法を調べました。

| 方法 | 実行マシン | 煩雑さ | ユースケース | 備考 |
|:--|:--|:--|:--|:--|
| Identity Center+awscli v2 | local | 簡単 | cli操作はこれが基本で良い | AWS 近年の推奨 |
| sts + mfa                 | local | 面倒 | Identity Centerを使ってない（IAMユーザーを使用）場合 | MultiFactorAuthPresent を用いたポリシーのアタッチが必要！ |
| aws-mfa                   | local | 少しだけ面倒 | 同上 | サードパーティのツール |
| CloudShell               | Web | 簡単 | 思いつかない… | マネージメントコンソールで触れるコンソール |
| Cloud9                   | EC2 | 簡単 | IDEにこだわりない場合 | 特に初心者は迷ったらこれで良い気がします |
| SSH + SSM | EC2 | めんどう | IDEがVSCodeじゃないと嫌な場合 | 設定が面倒。運用も少しめんどう。鍵ファイルとか **管理できるなら**鍵認証の方が楽？ |
| EC2 Instance Connect | EC2 | 少しだけ面倒 | EC2のちょっとした設定（特に初期） | sg の設定必要 |

他におすすめあったら教えてください...

# はじめに
AWS cli 使うときの「v2使って！！」という警告文が気になったのがきっかけです。
awscliを実行するために IAMユーザーのアクセスキーを発行する事は非推奨なのは周知の事実とは思いますが、ではどうすればよいか　をまとめてみたいと思います。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/security-creds.html#sec-alternatives-to-long-term-access-keys

大きく以下の２つの視点でまとめてみます。

- awscli が使えればよい場合
- 仮想マシン環境(EC2)が欲しい場合

:::note
詳細情報はリンク先を頼り、できるだけ簡単なまとめに努めたいと思います。
:::

# awscli が使えればよい
## awscli v2 + IAM Identity Center
### 概要
- AWS の最近の推奨
- マネージメントコンソールで一時的なID, PW, Token を発行

### 操作方法
- Identity Center でユーザーを作成（割愛）
- Access Portal からログイン 
    - Access keys をクリックすると以下のような認証情報が表示されます
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092759/4a34c177-1220-0dba-bae6-66c40acd3d2d.png)


- クライアント機で以下のコマンドを実行
```bash
aws configure sso

# SSO session name は好きな文字列を、あとはマネージメントコンソールで表示されているものを入力
```

- Web ブラウザで ://device.sso.*** が開く
- コンソールとWebブラウザで表示されているコードが一致していれば Confirm and continue をクリック
- 最後にデフォルト region, output format, profile name を設定

最終行にサンプルスクリプトが表示される（実際にこのようにcliでリソースを操作できる）
```
aws s3 ls --profile AdministratorAccess-********
```

### 資料

https://dev.classmethod.jp/articles/aws-cli-for-iam-identity-center-sso/

https://zenn.dev/akeru/articles/3ac143a8bf933a


## sts + mfa
### 概要
sts を用いて**一時的な認証情報**を発行します。
アクセスキーを使って```aws sts get-session-token``` を実行 -> 一時キーが発行される

- cli コマンドの実行にはこの一時キーを使うことになります
- また、sts を実行する際に mfa による認証を行います

### 前準備
- mfa を強要するカスタマー管理ポリシーを作成してIAM ユーザーに割り当て
    - これをやらないと**元のアクセスキーが有効になってしまい意味がない!!**

<br>
<details><summary>全リソースの全操作に mfa 認証を強制するポリシー例</summary>

```
{
  "Version": "2012-10-17",
  "Statement": [
        {
            "Sid": "MFARestrectionExample",
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}
```
</details>
<br>

- sts で一時的なID, key, Tokenを発行してaws configureや環境変数で指定
```bash
aws sts get-session-token --serial-number {ARN-OF-THE-MFA-DEVICE} --token-code {CODE-FROM-MFA-DEVICE}

{
    "Credentials": {
        "AccessKeyId": "ABC********",
        "SecretAccessKey": "123****",
        "SessionToken": "Fwo*******",
        "Expiration": "2024-01-01T00:00:00Z"
    }
}
```

参考：[aws cli: get-session-token](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/get-session-token.html#synopsis)

### 資料
公式(MultiFactorAuthPresent関連)：

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-multifactorauthpresent

公式(sts関連)：

https://repost.aws/ja/knowledge-center/authenticate-mfa-cli

参考(MultiFactorAuthPresentの注意点)

https://qiita.com/shijimi_san/items/823154d700c35f629172


## aws-mfa
### 概要
上の sts を用いた一時的なトークンによる認証の操作を**楽に**行います。
※AWS公式のツールではないです
[公式github](https://github.com/broamski/aws-mfa)


### 操作方法

ID/key 情報の登録
```
aws configure --profile myuser-long-term
aws configure --profile myuser
```

ログイン
```
aws-mfa --profile myuser
# > mfa コードの入力
# > success! と表示される 
```


#### 補足
基本的にはユーザー名を default(とdefault-long-term) とした方が使いやすいと思います。

#### 資料
参考

https://qiita.com/ogady/items/c17ffe8f7c8e15b15f77

## CloudShell
### 概要
特に説明不要かと思います。Webブラウザ（マネージメントコンソール）で使えるterminal。

公式：https://aws.amazon.com/jp/cli/

### 操作方法
マネージメントコンソールにログイン > サービス検索ウィンドウで CloudShell を検索

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092759/679cb253-fd01-1ce7-a95e-602603d96166.png)


# 仮想マシン(EC2) が必要な場合
## SSM を用いたローカル機からの SSH 接続

### 概要
VSCode を用いたEC2 接続を行う場合に良いように思われます。
が、手順などが結構多く、煩雑です。
- EC2 のセキュリティグループで**22番インバウンドの開放が不要**

### 条件
- EC2 インスタンス作成時にキーペアの作成が必要 
- IAMユーザーのアクセスキーの発行が必要 
- ローカル機にaws cli のインストールが必要

### 方法

- IAM ロールを作成
    - ユースケース：EC2 - EC2 Role for AWS Systems Mnager
    - カスタマー管理ポリシーを作成して付与
        - ポリシーの中身は[公式資料](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-create-iam-instance-profile.html#create-iam-instance-profile-ssn-only)を参考
    - 対象のEC2 のIAMロール（インスタンスプロファイル）をこのロールにする

参考：[公式資料 - ステップ2](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-instance-profile.html)



- EC2 に「SSM Agent(v2.3.672.0 以降)」をインストール
    - インストールの仕方は[公式資料](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ami-preinstalled-agent.html) を参考
    - 補足：この際は Instance Connect などで接続すると良いかも
- ローカル機に「Session Manager プラグイン」をインストール；
    - [公式資料](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)  
- ローカル機の .ssh\config を編集
    - 書き方は非常に特殊です
    - 先にEC2のIDを調べておく
    - ProxyCommand は[公式資料](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html#ssh-connections-enable)（下の方）を参照してください
    （Windows と Linux では書き方が違うようです）

こんな感じになります：
```
Host ec2_over_ssm
  User ec2-user
  ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
  HostName i-1234567890abcdefg
  IdentityFile /path/my-key-pair.pem
  ```

<br>
<details><summary>このセクションの補足情報</summary>
補足１：IAM ロールにAWS管理ポリシー：AmazonSSMManagedInstanceCore を付与という情報がありましたが、なくてもできました。（むしろこれだけでは不足していたようです）ただし、なんとなくもやっとするので、時間があれば追加調査します。  

補足２：SSM Agent は Amazon Linux では最初からインストール済、という情報をどこかで見ましたが、結局インストールしなければSSM のセッションは開始できませんでした。  
</details>


### 個人的な感想
確かにEC2 の22番ポートを開放しなくて良いですが、EC2キーペアはおろかIAM ユーザーのアクセスキーも発行するし、手順は多いし、正直どうなのかな...という気もします。


### トラブルシューティング
####  TargetNotConnected
##### 現象
SSM でセッションを開始する際、以下のメッセージが表示される。
要するにSSM のセッションマネージャーがセッションを開始できていません。
```
when calling the StartSession operation: i-1234567890abcdefg is not connected.
```

##### 原因
原因は色々あるようです。
- EC2 にアタッチしたIAMロールの権限が適切でない
- EC2 に「SSM Agent」がインストールされていない

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-troubleshooting.html


#### UNPROTECTED PRIVATE KEY FILE!
##### 現象
鍵を用いたssh 認証の時にエラーが起こる
```bash
ssh -i /path/my-key-pair.pem username@instance-id
```
##### 対応

鍵ファイルのパーミションは以下である必要がある（それ以上でも以下でもダメ）       
- Linuxの場合は：600(w+r)
- Windowsの場合：SYSTEM、Administrators、自分自身　だけにする
    - 操作
        - 鍵ファイルを右クリック > プロパティ > 「セキュリティ」タブ
詳細設定 > 継承の無効化 > 「継承されたアクセス許可をこのオブジェクトの明示的なアクセス許可に変換」> 適用
        - （アクセス許可）編集：SYSTEM、Administrators、自分自身　だけにする

:::note
独り言；Windows ってどうしてこう分かりにくいんですかね。
設定する際毎回思いますが、こんなの初見で分かるわけないですよね。
:::
 

#### 資料
非常に良い記事です。（ 2024.7月現在　少し古い）
参考：https://blog.serverworks.co.jp/vscode-remote-ssh-via-session-manager

公式（本件の全体的な資料）
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html


## Cloud9
特に説明不要かと思います。
マネージメントコンソールにログインしてCloud9 > 環境を作成

### 特徴
- webブラウザ（マネージメントコンソール）で専用 IDE を開く
- docker, git などの開発ツールがインストール済

## EC2 Instance Connect
### 特徴
- **Public IPv4**を持つインスタンスとの接続
- SSH/RDP接続のためのセキュアな認証・接続サービス
- webブラウザ（マネージメントコンソール）でターミナルを開く

### 前準備

EC2_INSTANCE_CONNECT からの 22番ポートへのインバウンド通信を許可する必要があります。

EC2_INSTANCE_CONNECT の CIDR（アドレス範囲）は以下で確認できます。EC2を配置したリージョンのものを選んでください。

CIDR確認：https://ip-ranges.amazonaws.com/ip-ranges.json  
jqを使って探す例
```bash
curl -s https://ip-ranges.amazonaws.com/ip-ranges.json \
| jq '.prefixes[] | select(.region=="ap-northeast-1" and .service=="EC2_INSTANCE_CONNECT")'
```

リージョンが東京（ap-northeast-1）の場合の例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092759/72b9e3fc-3a16-ccc6-c090-cccb36de479e.png)

### 接続
Management Console：EC2  > ナビゲーションペイン：インスタンス  > インスタンスを選択 > 接続 > ラジオボタンは「EC2 Instance Connect を使用して接続する」のまま > EC2 Instance Connectタブを選択 > ユーザー名を確認 > 接続

公式：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html

### トラブルシューティング
#### Failed to connect to your instance
接続のためには色々条件があるようです。
[公式](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-prerequisites.html)

- セキュリティグループで22番ポートを開放していない場合は解放する（上記参照）



# 資料
## 公式資料：安全にEC2に SSH 接続するには
https://repost.aws/ja/knowledge-center/ec2-ssh-best-practices

## ローカル機で SSM セッションを開始する方法

先にインスタンス IDを確認する
（つかいませんでしたが、備忘録的に）
```
aws ssm start-session --target YOUR_INSTANCE_ID
aws ssm start-session --target i-12345678abcdeg
 ```