0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

今さらながら、AWS の Service-Linked Role(SLR)を初めて知りました。
このロールが陰ながら支えてくれていたことに、感謝しています。
一方で先日、このロールの影響でエラーが出ました。
同じ轍を踏んでほしくないと思い、記事にしました。

概要

  • SLR は、サービスの権限を利用者に壊させない仕組みです。その分、消えにくい性質があります。
  • 本番の apply が、regional NAT Gateway の作成で 403 になりました。
  • 足りなかったのは、SLR を作る IAM の権限でした。
  • ステージ環境で通ったのは、コンソール操作で SLR がすでに作られていたからでした。
  • Terraform を実行するデプロイロールに、SLR の作成権限を足して解決しました。

事象: ステージ環境で通った terraform apply が、本番で 403 になった

前提の構成

あるプロジェクトの本番デプロイでの話です。

使用しているバージョンは次のとおりです。

ツール バージョン
Terraform 1.15
hashicorp/aws 6.47.0

新しく作るリソースに、regional NAT Gateway が含まれていました。
regional NAT Gateway の詳細は、AWS 公式ドキュメントを参照してください。
Terraform では、availability_mode に regional を指定します。
この引数は、hashicorp/aws 6.24.0 で追加されました。

# Terraform AWS provider のドキュメントの例(auto mode)
resource "aws_nat_gateway" "example" {
  vpc_id            = aws_vpc.example.id
  availability_mode = "regional"
}

出たエラー

本番で apply を流すと、次のエラーで止まりました。

Error: creating EC2 NAT Gateway: operation error EC2: CreateNatGateway,
https response error StatusCode: 403, RequestID: XXXXXXXXXX,
api error UnauthorizedOperation: Account XXXXXXXXXX is not authorized
to create service-linked role for regional NAT Gateways.

「service-linked role を作成する権限が無いです」とのことでした。
Service-Linked Role(SLR)ってなんだ?
ステージ環境ではちゃんと動いたのになぜ?
ということで調べました。

Service-Linked Role(SLR)とは

SLR は、AWS のサービスが自分で使う IAM ロールです。

SLR は、サービスを初めて使うときに作られます。

今回は、regional NAT Gateway の作成時に、AWS が SLR を自動で作ろうとします。
その SLR が AWSServiceRoleForNATGateway です。

この SLR を作るには、iam:CreateServiceLinkedRole の権限が必要でした。
権限が要るのは、API を呼ぶ IAM ロールで、今回では Terraform の apply を実行するロール (デプロイロール)です。

SLR が必要なのは NAT Gateway だけではない

SLR を使うサービスは、ほかにもたくさんあります。
たとえば、次のようなものです。

サービス SLR の名前
Elastic Load Balancing AWSServiceRoleForElasticLoadBalancing
EC2 Auto Scaling AWSServiceRoleForAutoScaling
Amazon RDS AWSServiceRoleForRDS
Amazon ECS AWSServiceRoleForECS

SLR を使うサービスの一覧は、IAM と連携する AWS のサービスで確認できます。
表の「Service-linked roles」列が「Yes」のものが対象です。

なぜ SLR という仕組みが必要なのか

regional NAT Gateway は、裏で API を呼ぶ

regional NAT Gateway は、作ったあとも自分で動きます。
AWS のドキュメントによると、SLR で次のことをします。

  • 負荷に応じて Elastic IP を割り当て、自動でスケールする
  • 指定された既存の Elastic IP を付け外しする
  • ネットワークインターフェースを調べ、新しい AZ へ自動で広がる

どれも、自分のアカウントの中で API を呼ぶ操作です。
API を呼ぶには、IAM の権限を持った主体が要ります。
その主体が SLR です。

SLR は、サービスが持ち主のロール

SLR は、普通の IAM ロールとは扱いが違います。

項目 SLR 自分で作るサービスロール
権限を決めるのは AWS のサービス 自分
引き受けられるのは そのサービスだけ 信頼ポリシー次第
権限の編集 できない(説明文のみ可) できる
削除 関連リソースを消すまでできない いつでもできる

NAT Gateway の SLR の中身は次のとおりです。

  • 名前: AWSServiceRoleForNATGateway
  • 引き受けられるのは ec2-nat-gateway.amazonaws.com だけ
  • 権限は AWSNATGatewayServiceRolePolicy で定義済み

無ければどうなるか

サービスに権限を渡すには、自分でロールを作ることになります。
信頼ポリシー・権限ポリシーも、自分で書きます。

自分で作ったロールは自分で壊せます。
権限を削りすぎたり、誤って消したりできます。
すると regional NAT Gateway は、動いている最中にスケールできなくなると考えられます。

SLR は、この「うっかり壊す」を仕組みで防ぎます。

権限は AWS が決めて、利用者は編集できません。
全リージョンの regional NAT Gateway を消すまで、削除もできません。

SLR は「サービスが動き続けるための権限」を、利用者の手から切り離す仕組みです。その代わり、最初に作る瞬間だけは利用者の権限に頼ります。

逆に、SLR が作れないと regional NAT Gateway そのものが作れません。
今回の 403 が、まさにその状態です。

原因: ステージ環境で通った理由

ステージ環境では、リリースリハーサルの前に検証をしていました。
そのとき、コンソールから regional NAT Gateway を一度作っていました。
この操作で、SLR もアカウントに作られていました。

SLR は、一度あれば作り直されません。
リハーサルの時点で、SLR はすでにありました。
そのため、本番と同じロール・ポリシーでもエラーは出ませんでした。

コンソールで NAT Gateway を作った人には、SLR を作る権限がありました。
SLR は、その人の権限で黙って作られます。
手動操作の影響で、デプロイロールの不足を隠していました。

解決策: デプロイロールに SLR の作成権限を足す

デプロイロールに、次の権限を追加しました。

{
  "Sid": "IamCreateNatGatewaySlr",
  "Effect": "Allow",
  "Action": "iam:CreateServiceLinkedRole",
  "Resource": "arn:aws:iam::XXXXXXXXXXXX:role/aws-service-role/ec2-nat-gateway.amazonaws.com/AWSServiceRoleForNATGateway",
  "Condition": {
    "StringLike": {
      "iam:AWSServiceName": "ec2-nat-gateway.amazonaws.com"
    }
  }
}

ポイントは3つです。

  • Action は、"iam:CreateServiceLinkedRole"。"iam:CreateRole" ではないので注意
  • Resource で、作れる SLR を NAT Gateway のものだけに絞る
    • SLR のパスは role/aws-service-role/... になる
  • Condition で、対象のサービス名も NAT Gateway に限る

権限を足したあと、本番の apply は最後まで成功しました。

再発防止

デプロイ前に SLR の有無を確かめる

アカウントに SLR があるかは、次のコマンドで分かります。

aws iam get-role --role-name AWSServiceRoleForNATGateway

無ければ NoSuchEntity のエラーになります。
そのアカウントでは、apply が初めて SLR を作ります。
デプロイロールに作成権限があるかを、先に確認できます。

新しいサービス・機能の初回 apply では SLR を確認する

SLR は、サービスや機能を初めて使うときに作られます。
今回の regional NAT Gateway も、本番では初めて使う機能でした。

そこで、新しいサービス・機能の初回 apply 前に、次を確認します。

  • そのサービス・機能が SLR を使うか
  • 本番アカウントに、その SLR がすでにあるか
  • 無い場合、デプロイロールに作成権限があるか

SLR を Terraform で管理する方法もある

SLR は、aws_iam_service_linked_role で明示的に作れます。

resource "aws_iam_service_linked_role" "nat_gateway" {
  aws_service_name = "ec2-nat-gateway.amazonaws.com"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_nat_gateway" "example" {
  vpc_id            = aws_vpc.example.id
  availability_mode = "regional"

  depends_on = [aws_iam_service_linked_role.nat_gateway]
}

こう書くと、SLR の作成が plan に出ます。
レビューの時点で、SLR が作られると分かります。

ただし、次の点に注意が要ります。

  • 作成権限(iam:CreateServiceLinkedRole)は、引き続き必要
  • SLR がすでにあるアカウントでは、import が要る
  • この SLR はアカウントに1つなので、管理する場所を1か所にする
  • 誤って消さないよう、prevent_destroy を付ける

今回のプロジェクトでは、IAM を Terraform で管理していないため、この方法は使っていません。

自分への問い

この件の前にも、同じ形の見落としがありました。
ステージ環境では運よく成功し、本番で初めて問題が出る形です。

そこで、次の問いを持つことにしました。

この環境は、まっさらな本番と同じ状態か

まとめ: 同じ目に遭わないために

  • EC2 の API が 403 でも、メッセージに service-linked role とあれば IAM の権限を見る
  • SLR を作る権限は、API を呼んだ側に要る。デプロイロールも例外ではない
  • 権限は Resource と Condition で、必要な SLR だけに絞って渡す
  • ステージ環境の成功が、過去の手動操作に影響されていないかを疑う
  • 新しいサービス・機能を初めて apply するときは、SLR が要るかを確認する

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?