TerraformでAWS IAMポリシーとして設定するJSONはテキストで書くと構文チェックやエディタによる補完などができません。
そこでaws_iam_policy_document
データソースを使うと便利です。
この記事ではaws_iam_policy_document
データソースの使い方について説明します。
基本的な使い方
aws_iam_policy_document
データソースを使用するには、aws_iam_policy_document
リソースを宣言する必要があります。次に、data
ブロックを使用して、aws_iam_policy_document
データソースを定義します。
以下は、S3バケットへの読み取りアクセスを許可するポリシーの例です。
data "aws_iam_policy_document" "s3_read_policy" {
statement {
sid = "AllowRead"
actions = ["s3:GetObject"]
effect = "Allow"
resources = ["arn:aws:s3:::my-bucket/*"]
}
}
上記のコードでは、aws_iam_policy_document
データソースをs3_read_policy
という名前で宣言しています。statement
ブロックは、S3バケットへの読み取りアクセスを許可する1つのステートメントを定義しています。
aws_iam_policy_document
データソースはIAMポリシーのJSONと対応しています。aws_iam_policy_document.s3_read_policy.json
で以下のように評価されます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRead",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
}
]
}
.json
によってIAMポリシーのJSONが得られるので、IAMポリシーのJSON文字列が必要な箇所で利用できます。
resource "aws_iam_policy" "s3_read_policy" {
name = "s3_read_policy"
policy = data.aws_iam_policy_document.s3_read_policy.json # データソースで定義したポリシーを使用
}
aws_iam_policy_documentのstatement以下の要素
sid
sid
はステートメントの一意の識別子を表します。この値は外部から利用しないので必須ではありません。必要であれば人間に分かりやすい名前をつけておくと良いでしょう。
例えば以下のように記述します。
sid = "AllowRead"
JSONに変換すると以下のようになります。
"Sid": "AllowRead"
actions
actions
はステートメントで許可または拒否されるアクションを定義します。
アクションはAWSサービスが提供するAPI呼び出しを表します。
アクションはイルドカード(*)も使用できます。
以下は、S3バケットへの読み取りアクセスを許可するためのactions
の例です。
actions = [
"s3:PutObject",
"s3:GetObject"
]
この例では “s3:PutObject” と “s3:GetObject” を許可または拒否します。
JSONに変換すると以下のようになります。
"Action": [
"s3:PutObject",
"s3:GetObject"
],
effect
effect
はステートメントで許可または拒否されるアクションの効果を定義します。許可のときはAllow
拒否のときはDeny
を指定します。
以下はS3バケットへの読み取りアクセスを許可するためのeffect
の例です。
effect = "Allow"
actions
で指定したactionを許可します。
JSONに変換すると以下のようになります。
"Effect": "Allow"
principals
principals
はステートメントで許可または拒否されるプリンシパルを定義します。
プリンシパルはアクセス許可を要求するAWSアカウント、IAMユーザー、IAMロール、AWSサービス、AWSリソースなどを指します。
principals
はAWS
、Service
、Federated
、CanonicalUser
のいずれかの値を取ります。
例えばAWSアカウントIDを指定する場合はAWS
を使用し、IAMロールを指定する場合はRole
を使用します。
以下は、S3バケットへの読み取りアクセスを許可するためのprincipals
の例です。
principals {
type = "AWS"
identifiers = ["123456789012"]
}
上記コードではアカウントID 123456789012
のAWSアカウントにアクセス許可を与えています。
JSONに変換すると以下のようになります。
"Principal" : {
"AWS": [
"123456789012"
]
}
condition
condition
はステートメントの条件を定義します。actionを許可または拒否するための柔軟な条件を指定できます。
condition
以下の要素は以下の通りです。
- test: 条件の演算子
- variable: 比較される変数
- values: 比較する値
以下はS3のオブジェクトが指定されたプレフィクスとマッチするかどうかをチェックする例です。
condition {
test = "StringLike"
variable = "s3:prefix"
values = ["prefix/*"]
}
上記はprefix/
から始まるパスのオブジェクトのみにアクセスを許可もしくは拒否する例です。
JSONにすると以下になります。
"Condition": {
"StringLike": {
"s3:prefix": ["prefix/*"]
}
}
さまざまな条件の演算子が利用できるようになっており、例えば接続元のIPアドレスでの比較も可能です。
以下はS3バケットへの読み取りアクセスをIPアドレスが192.0.2.0/24
のユーザーに制限する条件の例です。
condition {
test = "IpAddress"
variable = "aws:SourceIp"
values = ["192.0.2.0/24"]
}
上記のコードでは、aws:SourceIp
という変数に192.0.2.0/24
の値を設定し、test
パラメーターにIpAddress
を設定しています。これにより、IPアドレスが192.0.2.0/24
の場合のみアクセスを許可します。
JSONに変換すると以下のようになります。
"Condition": {
"IpAddress": {
"aws:SourceIp": ["192.0.2.0/24"]
}
}
Statementを複数書く方法
複数のステートメントを定義する場合は、statement
ブロックを複数回並べて書きます。
以下は、S3バケットへの読み取りアクセスと書き込みアクセスを許可するポリシーの例です。
data "aws_iam_policy_document" "s3_rw_policy" {
statement {
sid = "AllowRead"
actions = ["s3:GetObject"]
effect = "Allow"
resources = ["arn:aws:s3:::my-bucket/*"]
}
statement {
sid = "AllowWrite"
actions = ["s3:PutObject"]
effect = "Allow"
resources = ["arn:aws:s3:::my-bucket/data/*"]
}
}
上記のコードでは、2つのステートメントを定義しています。
- 1つ目は
my-bucket/
以下にs3:GetObject
アクションに対して読み取りアクセスを許可 - 2つ目は
my-bucket/data/
以下のみs3:PutObject
アクションに対して書き込みアクセスを許可
これで my-bucket/
直下への s3:PutObject
拒否しています。
JSONにすると以下になります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRead",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "AllowWrite",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/data/*"
},
]
}
Conditionを複数書く方法
複数の条件を定義する場合は、condition
ブロックを複数回並べて書きます。
以下はS3バケットへの読み取りアクセスをIPアドレスが192.0.2.0/24
のみに制限し、さらにHTTPSのみのアクセスに制限する例です。
data "aws_iam_policy_document" "s3_read_policy" {
statement {
sid = "AllowRead"
actions = ["s3:GetObject"]
effect = "Allow"
resources = ["arn:aws:s3:::my-bucket/*"]
condition {
test = "IpAddress"
variable = "aws:SourceIp"
values = ["192.0.2.0/24"]
}
condition {
test = "Bool"
variable = "aws:SecureTransport"
values = ["true"]
}
}
}
上記のコードのようにconditionブロックをならべます。
JSONに変換するとCondition以下は以下のようになります。
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"192.0.2.0/24"
]
},
"Bool": {
"aws:SecureTransport": [
"true"
]
}
}
“Principal”: “*” を書く方法
上記で説明したようにprincipals
ブロックは以下の様に書きます。
principals {
type = "AWS"
identifiers = ["123456789012"]
}
JSONは以下のようになります。
"Principal": {
"type": "AWS",
"identifiers": ["123456789012"]
}
上記はPrincipalの値がオブジェクトになっており、type
とidentifiers
は必須なので以下ようなすべてを許可するprincipalsは直接書けません。
"Principal": "*"
このPrincipalを書くにはtype
とidentifiers
に*
を指定します。
principals {
type = "*"
identifiers = ["*"]
}
参考: 【Terraform】“Principal”: “*” を指定する方法
まとめ
この記事では、Terraformのaws_iam_policy_document
データソースの使い方について紹介しました。
IAMポリシーはAWSリソースへのアクセスを管理するために重要なツールです。
aws_iam_policy_document
データソースを使用するとポリシーを定義するためのコードを簡単に記述できます。
Terraformのコードでポリシーを定義することでバージョン管理や変更管理が簡単になりポリシーの適用に関する問題を回避できます。