AWS IAMポリシーについて考える

# 挨拶

こんにちは！
AdventCalenderに初参加の白"雪姫"です。

私からは以前，[私自身のエンジニアブログとして書いた物](https://kohaku-kageroh.hatenablog.com/entry/20241107/1730943095)を再度まとめて記載させてもらおうと思います。

# 今回のテーマ

タイトルにあるとおり，
**AWSのIAMポリシーについて考える。**
です。

# 要件

下記の通りの要件です。

1. VPC上で起動しているEC2へは，IAMのアクセスキーとシークレットアクセスとSSMを利用して，許可された端末であれば，**どこからでも**接続を行いたい
2. AWSマネジメントコンソールへのログインは出来たとしても，**指定したIPアドレス以外からは接続を拒否したい**
3. AWS CLIは許可された端末から**どこからでも**実行を許可するが，実行が可能な権限は絞りたい

もう，この時点で意味が分かりません。

# AWSのドキュメントを確認する。

AWSには，様々なドキュメントが用意されており，[IAMポリシー](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html)についても有りました。

そこで熟読。

## ポリシーの適用基準について

簡単に書くと，以下の順番で適用され，強く適用されていく

- 明示的拒否
- 条件付き拒否
- 条件付き許可
- 許可のみ

上記をよく覚えておいてください。

## 要件でどれが使えるか考える。

### 要件1
これは，明示的な許可で行けるでしょう。なんなら，IAMユーザからプログラムアクセスを許可してあげれば行ける。
イメージとしては

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1733968557410",
      "Action": "ssm:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
```

こういう感じで行けそうである。

実際には，EC2とIAMユーザに**AmazonSSMManagedInstanceCore**というポリシーを割り当ててます。

![Screenshot 2024-12-12 at 11.04.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553392/22bc1713-44a4-f346-cbc1-c42fa4b5b423.png)

### 要件2

これも一般的に使われている手法で実現が可能です。
**全てを拒否**するポリシーを書きます。
AWSにはConditionという特定の条件下だった場合（もしくは,合致する条件以外の場合)に適用する
という物があります。
そちらを利用する事になります。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1733969377455",
      "Action": "*",
      "Effect": "Deny",
      "Resource": "*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "許可をする接続元IPアドレス"
        }
      }
    }
  ]
}
```

IPアドレスが複数有る場合は以下の様のすれば複数アドレスが登録出来ます。

```json
          "aws:SourceIp": [
              "許可をする接続元IPアドレスA",
              "許可をする接続元IPアドレスB"
              ]
```


これで，接続元IPを絞って**明示的に操作拒否**が出来ます。

### 要件3

これも要件1と同様に「利用可能な物を明示的に書いて許可を行う」ということで解決出来そうです。
例ではEC2の起動・停止・RDSの起動・停止は可能というポリシーにします。


```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1733970190190",
      "Action": [
        "ec2:StartInstances",
        "ec2:StopInstances"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Sid": "Stmt1733970229455",
      "Action": [
        "rds:StartDBCluster",
        "rds:StartDBInstance",
        "rds:StopDBCluster",
        "rds:StopDBInstance"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
```

これを整理して，綺麗にして，ポリシーにをアタッチすれば良いよね。
という考えだったのですが，

実際にやってみて，問題になった事があります。

# 問題点

- 「指定したIPアドレス以外から操作が全てできない」

という問題が発生しました。

さて何が問題だったのでしょうか。

スクロールいただく間に考えてみてください。
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
　
## 答え

この冒頭にIAMのポリシーの適用順序というのを記載致しました。

IAMポリシーで**明示的拒否**が一番強く適用されてしまうため，要件2の拒否した設定が最も強く適用されます。
また，これは実際に適用して初めて分かったことなのですが，
この2番を適用している限りは**他のAllowルールによる許可**を設定しても拒否されてしまいます。

# 解決策

では，どうやって解決するのが一番良いか。
以下の様なルールへ分割いたしました。

1. 明示的な拒否をするのは，削除防止がメインのため，delete系を拒否するポリシーを作成する

記載量が大量になるため，一例でEC2の削除操作を禁止する形で拒否ポリシーを記載します

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1733973226857",
      "Action": [
        "ec2:Delete*"
      ],
      "Effect": "Deny",
      "Resource": "*"
    }
  ]
}
```

Actionのところに有るようにEC2に関するDeleteが着く内容のものは全て拒否する
というポリシーです。
複数必要な場合は，

```json
      "Action": [
        "ec2:Delete*",
        "rds:delete*"
      ]
```

のように書くと複数指定が出来ます。

2. 登録したIPアドレス意外だった場合は，特定の操作のみを有効にするポリシー

これは，ちょっとした応用的な書き方です。
EC2の起動・停止を許可するポリシーだとします。

```json
{
    "version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowIPAddress"
            "Effect": "Deny"
            "NotAction": [
                "ec2:StartInstances",
                "ec2:StopInstances"
                ],
            "Resource": "*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "許可するIPアドレス"
                    ]
                }
            }
        }
    ]
}
```

何してるんだ？っていう話ですが，
数学的な真偽って昔ありましたよね。それを思い浮かべてください。
![Screenshot 2024-12-12 at 12.49.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553392/a8c9bf32-8229-fc0d-6a1b-aea2e0b6078b.png)
イメージはこういった感じです。

この場合は，**「特定のIPアドレスでは無く」かつ「ec2の起動・停止」ではない場合，その操作を拒否する**
というポリシーを記載しています。

図面で言うと
ルール1を拒否してルール2を拒否した場合の偽の拒否のルールを適用する
と言う状態になります。

つまり，「EC2の起動・停止」は許可されますよ。でも他の操作はダメですよ。
というポリシーです。

なお，Denyにしてるので上記になっていますが。Allowにすると
**真の拒否**の部分のみが許可されます。

これにより「要件1」及び「要件3」の基準を満たしながら「要件2」の操作ですが，これに，操作を許可するレベルの権限（AdministratorAccessやPowerUserなど）を付与すれば満たすことになります。

## おまけ

実際は普通はここまですることはあまり一般的とは言えません。
通常であれば，
- 要件2で記載したポリシーを用いてIP制限を実施
- SSOやIAM Identity Center等を用いてポリシーを適用して操作を制限
と言った具合で操作を制限する方がとても楽で有効化と思います。

今回は，SSOやIAM Identity Centerが無い状態で，苦肉の策として悩んだため作っている物なのでこういった方法があるよ
と言うのをご理解頂ければ幸いです。