LoginSignup
2
5

More than 3 years have passed since last update.

Terraform で DynamoDB の Table を作って IAM Policy でアクセス制限

Last updated at Posted at 2019-05-15

やりたいこと

  • Terraform で DynamoDB の Table を作る。
  • 既存のテーブルに読み込みだけが出来る IAM Role を割り当てる。
  • 権限が設定されたかテスト。

Terraform で DynamoDB の Table を作る。

まず AWS ルートユーザや IAM ユーザで aws コマンドが動く事を確認します。

$ export AWS_PROFILE=hoge
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                     hoge           manual    --profile
access_key                  hogehoge shared-credentials-file
secret_key     ********************* shared-credentials-file
    region                 us-west-2      config-file    ~/.aws/config
... 適切な access_key, secret_key, region が表示されると OK。

次のような Terraform file で aws_dynamodb_table を作ります。

dynamodb.tf
resource "aws_dynamodb_table" "music" {
  name           = "Music"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "Artist"
  range_key      = "SongTitle"

  attribute {
    name = "Artist"
    type = "S"
  }

  attribute {
    name = "SongTitle"
    type = "S"
  }
}

初期化

terraform init

設定

terraform apply

これで、DynamoDB へのアクセス » CLI の使用 と同じテーブルが出来ます。

動作確認

$ aws dynamodb put-item --table-name Music --item '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}}'
$ aws dynamodb query --table-name Music --key-condition-expression 'Artist = :a' --expression-attribute-values '{ ":a": {"S": "No One You Know"}}'
{
    "Count": 1,
    "Items": [
        {
            "AlbumTitle": {
                "S": "Somewhat Famous"
            },
            "SongTitle": {
                "S": "Call Me Today"
            },
            "Artist": {
                "S": "No One You Know"
            }
        }
    ],
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

削除

terraform destroy

terraform だと削除が簡単なのが良いですね。

既存のテーブルに Query だけが出来る IAM Policy を作る。

次に、うっかりテーブルを変更してしまわないように、作ったテーブルの Query と GetItem だけが出来る IAM Policy を作ります。

AWS では、テーブル等すべてのリソースに ARN が付きます。DynamoDB のテーブルは以下の ARN で表します。

arn:aws:dynamodb:region:account-id:table/table-name

例えばもしも account-id が 123456789012 で region が us-west-2 なら、上の例は arn:aws:dynamodb:us-west-2:123456789012:table/Music です。terraform で作った ARN は terraform show で確認出来ます。

このテーブルのアクセス権を設定するには Policy 言語 を使います。DynamoDB の例が Amazon DynamoDB でアイデンティティベースのポリシー (IAM ポリシー) を使用する に色々あります。

Policy を Terraform で定義する場合は aws_iam_policy に埋め込む事が出来ます。Music の読み書きを行う Policy は以下のようになります。

resource "aws_iam_policy" "music" {
  name        = "music_policy"
  description = "DynamoDB Music policy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "dynamodb:Query",
        "dynamodb:GetItem"
      ],
      "Effect": "Allow",
      "Resource": "${aws_dynamodb_table.music.arn}"
    }
  ]
}
EOF
}

IAM Role を作る。

作った Policy で制限がかかっているか試すにはいくつか方法があります。ここでは IAM Role を作って自分の IAM User から切り替えて使ってみます。IAM Role を作るには aws_iam_role を使います。assume_role_policy で Role を与える対象 (Principal) を選びます。実用上では Principal に ec2.amazonaws.com 等を選んで特定の AWS サービスに IAM Role を与える事が多いかと思いますが、ここではテストが簡単なように Principal として今まで作業してきた自分の IAM User を設定し、aws cli で Role を切り替えて使うことします。

data "aws_caller_identity" "current" {}

resource "aws_iam_role" "music" {
  name = "music_role"

  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "sts:AssumeRole",
        "Effect": "Allow",
        "Principal": {
          "AWS": "${data.aws_caller_identity.current.arn}"
        }
      }
    ]
  }
  EOF
}

このように aws_iam_roleassume_role_policyaws_iam_policy と同様 Policy 言語で記述します。IAM User を Principal として指定するためには ARN を設定しますが、次のような種類があります。

  • アカウント 123456789012 の任意のユーザ: arn:aws:iam::123456789012:root
  • アカウント 123456789012 のユーザ hoge: arn:aws:iam::123456789012:user/hoge

上の例では Terraform の aws_caller_identity 機能を使って現在のユーザの ARN を取得しているため、実際の ARN をベタ書きする必要がありません。便利。

IAM Policy と IAM Role を関連付ける

これも Terraform だと参照を使えるので非常に簡単です。

resource "aws_iam_role_policy_attachment" "music" {
  role       = "${aws_iam_role.music.name}"
  policy_arn = "${aws_iam_policy.music.arn}"
}

ここまでで Terraform の設定は終わりなので、terraform apply で再度反映させます。

テスト

IAM ロールへの切り替え を参考に作った IAM Role に切り替えてテストしてみます。

もしも現在 AWS_PROFILE=hoge を使っていて、デフォルト region が us-west-2 で、アカウント ID が 123456789012 の場合、~/.aws/config に以下を追記します。
role_arn は terraform show で aws_iam_role.music: の欄に出てくる arn です。

~/.aws/config
...
[profile music]
role_arn = arn:aws:iam::123456789012:role/music_role
source_profile = hoge
region = us-west-2

このように設定すると、music という aws profile で music_role が有効になります。例えば --profile music をつけて DynamoDB にアクセスしてみます。

$ aws dynamodb query --profile music --table-name Music --key-condition-expression 'Artist = :a' --expression-attribute-values '{ ":a": {"S": "No One You Know"}}'
{
    "Count": 1, 
    "Items": [
        {
            "AlbumTitle": {
                "S": "Somewhat Famous"
            }, 
            "SongTitle": {
                "S": "Call Me Today"
            }, 
            "Artist": {
                "S": "No One You Know"
            }
        }
    ], 
    "ScannedCount": 1, 
    "ConsumedCapacity": null
}

のように query は成功しますが、

$ aws dynamodb put-item --profile music --table-name Music --item '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}}'

An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::123456789012:assumed-role/music_role/botocore-session-1557893071 is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-west-2:123456789012:table/Music

のように put-item は目出度くエラーになります。

実際に業務で使う時はこの IAM Role を EC2 とか Kubernetes pod とかに割り当てると、ACCESS_KEY を書かなくても適切な権限を与えられるので便利という物です。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5