🎉

AWS入門 - IAM について整理してみる

2021/10/28に公開

AWSを使う必要が出てきたので、色々と試してみる。
ここでは、IAM周りについて整理してみる。

AWS Identity and Access Management

https://aws.amazon.com/jp/iam/

IAMとはAWSの様々なリソースへに対するアクセスを管理するためのもの。
認証(N)と認可(Z)が主な役割。

ID・パスワードやアクセストークン・シークレットキーをもとに認証を行い。
ポリシーをもとに認可を行う。

認証・認可どちらも通過した場合のみ、
指定のリソースへとアクセスしアクションを実行できる。

主な用語

IAMを使う上で重要となる用語を整理してみる。

プリンシパル

IAMの仕組みを使ってAWSのリソースを使う人たち。
人間であることもあれば、アプリケーションであることもある。

リクエスト

リクエストとは、IAMの仕組みを使ってAWSのリソースを使う行為そのもの。
リクエストするためには、次のような情報を含める必要がある。

  • アクション・オペレーション
    • リソースに対して行いたい内容
    • XXXを取得するとか、YYYを登録するとか
  • リソース
    • 対象のAWSリソースに関する情報
  • プリンシパル
    • リクエストする自分自身の情報
  • 環境データ
    • リクエスト時の環境情報
    • IPアドレスとか、時刻とか
  • リソースデータ
    • リソースに関連する情報
    • リクエスト先によって違うんだと思う

認証

いわゆる本人確認。
ID・パスワードやアクセストークン・シークレットキーを元に認証する。

認可

いわゆる権限確認。
プリンシパルのリクエスト内容を元に、指定のリソースに対してアクション・オペレーションを実行できる権限を持っているか確認する。

で、権限を確認する際に突合する情報がポリシー。
ポリシーには、誰が・どこに対して・何をしてよいか、といった情報が記載されている。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html

アクション・オペレーション

リクエストが通った後に、リソースに対して行う内容。
XXXを取得するとか、YYYを登録するとか、そういったやつ。

リソース

アクション・オペレーションを行いたい対象。
S3であったり、EC2であったりする。

IAM ユーザー

AWSアカウントではなく、AWSアカウント内のユーザー。
IAMユーザーには、マネジメントコンソールにアクセスするためのパスワードを設定することができる。
各ユーザーには個別のアクセスキーを作成することも出来るので、人間ではなくアプリケーションが使うこともできる。

ポリシー

認可する内容を記述したもの。
「XXXは、YYYに対して、ZZZしてよい」といった事を記述している。
この情報を元に認可を判断し、OKであればリソースに対してアクション・オペレーションを行える。

JSON ポリシー

基本的にはJSON形式でポリシーは保存されるらしい。
ただし、マネジメントコンソール上では、JSONを意識しなくても済むようになっている。

ポリシーは1つ以上のステートメントで構成されている。
ステートメントが複数あって、
1つのリクエストに対して複数のステートメントが当てはまる場合は、OR判定される。

ステートメントの中身はこういった情報が入っている。

  • Version
    • ポリシーのバージョン
    • "2012-10-17"が最新らしい
  • Statement
    • Sid
      • ステートメントのID
    • Effect
      • "Allow" または "Deny"
      • アクセスを許可するのか、拒否するのか、を指定してる
    • Principal
      • 対象のプリンシパル
    • Action
      • 対象のアクション一覧
      • XXXを取得するとか、YYYを登録するとか、そういったやつ
    • Resource
      • アクションを行う対象のリソース
    • Condition
      • ポリシーが適用される状況
      • 多要素認証が有効であればとか、そういったやつ

e.g.

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "s3:ListBucket",
    "Resource": "arn:aws:s3:::example_bucket"
  }
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "FirstStatement",
      "Effect": "Allow",
      "Action": ["iam:ChangePassword"],
      "Resource": "*"
    },
    {
      "Sid": "SecondStatement",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Sid": "ThirdStatement",
      "Effect": "Allow",
      "Action": [
        "s3:List*",
        "s3:Get*"
      ],
      "Resource": [
        "arn:aws:s3:::confidential-data",
        "arn:aws:s3:::confidential-data/*"
      ],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    }
  ]
}

IAMを使ってリクエストしてみる

IAMユーザーに対し、S3読み込み権限をもったポリシーを付与する。
そして、実際にS3に対してリクエストしてみる。

ポリシー作成

指定のS3バケット内にある、"/images"ディレクトリ内のオブジェクトを読み取れるようにする。

IAMユーザー作成

次に、IAMユーザーを作成する。
アクセスキーでの認証方法を選択し、先程作成したS3用のポリシーを適用する。

IAMユーザーのアクセスキーIDとシークレットアクセスキーはメモしておく。

S3へリクエスト

公式のSDKを使ってS3にリクエストする。

const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');

(async () => {
    const client = new S3Client({
        region: 'ap-northeast-1',
        credentials: {
            accessKeyId: 'XXXXX',
            secretAccessKey: 'YYYYY',
        },
    });
    const res = await client.send(new GetObjectCommand({
        Bucket: 's3-bucket-20211027-ac',
        Key: 'images/building_takoyaki_yatai.png',
    }));
    console.log(res.LastModified);
    console.log(res.ContentLength);
    console.log(res.ContentType);
})();

"/images/*"に対しての読み取りを許可しているので、情報が取得できた。

$ node index.js
2021-10-27T14:29:31.000Z
666159
image/png

今度は、許可していないディレクトリに対して読み取りリクエストしてみる。

const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');

(async () => {
    const client = new S3Client({
        region: 'ap-northeast-1',
        credentials: {
            accessKeyId: 'XXXXX',
            secretAccessKey: 'YYYYY',
        },
    });
    const res = await client.send(new GetObjectCommand({
        Bucket: 's3-bucket-20211027-ac',
        Key: 'files/pose_pien_uruuru_woman.png',
    }));
    console.log(res.LastModified);
    console.log(res.ContentLength);
    console.log(res.ContentType);
})();

期待通り、アクセスを拒否された。

$ node index.js
AccessDenied: Access Denied

まとめ

VPSレスな構成にすればするほど、
IAMによる権限管理が重要になってくるはずなので、
本番では注意して扱いたい部分。

めんどくさい部分ではあるが、
基礎知識は把握しておかないと後で痛い目みるんじゃなかろうか。

その他

Discussion