AWS AppSync における特定 API 配下のリソースのみに編集権限を付与する

SCSKの畑です。初投稿です。

現在携わっている複数の案件において、サーバレスアーキテクチャにおける WEB アプリケーション(フロントエンド/バックエンド双方)の構築・開発を行っています。これらの案件において、苦労した点や工夫した点などを中心に記載していく予定です。

アーキテクチャ概要

主にデータベース/ DWH 上のテーブルデータをメンテナンスする WEB アプリケーションを作成しています。案件ごとに差異はありますが、概ね以下のようなアーキテクチャで開発を行っています。下図の場合は、メンテナンス対象の DWH が Redshift となっています。

正直なところ、AWS 上におけるサーバレスアーキテクチャとしては王道というか、特に珍しくない構成だと思いますが。。。

構築・開発中のアプリケーションアーキテクチャ概要図です。

本題

さて、アプリケーション開発の本筋から少し離れたトピックとなるのですが、実際に構築・開発を行うAWS環境がどのように管理・運用されているかというのは案件ごとに異なるところだと思います。今回、お客さん側の組織で主体的に管理されている1つの AWS アカウント環境上で構築する必要があり、使用するサービスの種類、必要なリソースの個数や IAM 権限などについてもある程度明確にした上で申請し、お客さん側に作成等を対応頂く流れとなっていました。また、各種 AWS サービスやリソースの構築・実装についても、 AWS CLI 等は使用できず、全てAWS マネジメントコンソール上から実施する必要がありました。

もちろん、全てをお客さん側で対応頂くというのは色々な観点から現実的ではないので、例えば Lamdba の場合は関数の作成までをお客さん側に実施頂き、ソースコード実装を含む詳細な設定を我々で実施するような棲み分けで権限管理がなされていました。他サービスについても概ね似たような棲み分けで構築を進めることができたのですが、AWS AppSync については一筋縄ではいきませんでした。

ご存じの通り、AWS AppSync における構成単位は API となり、その配下に同 API を構成する各種リソース(スキーマ、データソース、関数など)が紐付いています。つまり、先述したような権限管理の考え方に則ると、APIまでをお客さん側に作成してもらい、配下のリソースについては我々で編集できるような IAM 権限を付与頂くという棲み分けが妥当と考え、お客さんにそのような依頼をしたところ・・

なんとNGをもらってしまいました。詳細を確認した所、対象の IAM 権限(appsync:StartSchemaCreation など)がリソースタイプの指定に対応しておらず、IAM 権限を付与した場合他の API 配下のリソースについても編集可能となってしまうためとのことでした。

なお、本案件についてはお客さんの AWS 環境で Amplify を使用することがポリシー上 NG であったため、自社環境において Amplify を使用して開発したものをお客さん環境に持ち込む、という段取りで進めていました。

そんなバカなことある!?と慌ててドキュメントを確認したところ、確かにそのような記載になっています。(表内のリソースタイプ列に記載がないため、リソースタイプでの許可がサポートされていない)

AWS AppSync のアクション、リソース、および条件キー - サービス認可リファレンス
Word へのアクセスを制御するために IAM ポリシーで使用できるサービス固有のリソースやアクション、条件キーを一覧表示します AWS AppSync。

念のため原著(US版)も確認したのですが同じ内容。うーん、万事休すか。。。

Actions, resources, and condition keys for AWS AppSync - Service Authorization Reference
Lists all of the available service-specific resources, actions, and condition keys that can be used in IAM policies to c...

よって、作成したい各種リソースの詳細な内容をお客さんに伝えて作成頂くように・・と、普通なら引き下がるのですが今回は易々と引き下がれない事情がありました。理由は明白で、API については言うまでもなくアプリケーションの開発領域であるためです。

つまり、アプリケーションのリリースが完了するまでの開発期間はもちろん、リリース後の機能追加なり不具合修正も含めて、API 配下のリソースに変更がある場合はその反映をお客さんにお願いしないといけない、ということになってしまいます。対象となるスキーマのパイプラインや関数の個数も多く、これをそのままお客さんにやってもらう場合にどれくらいの時間・コストが必要かを考えると、いや無理でしょうという結論になりました。

  • そもそも API の実行(appsync:GraphQL)についてはちゃんとリソース指定できるようになっているのに、編集はできないというのはどういうことなのか?
  • AWS の各種サービスにおける権限管理があれだけしっかりとした設計思想の元で作られているのに、API という単位で明確に分割できる AWS AppSync についてそのようなことができないような設計になっているとは思い難い

などと悶々とした結果、自分で試してみないと納得できなくなったので、手元の環境で試してみました。

検証

AWS マネジメントコンソールから AWS AppSync の API 配下のリソースを編集できる IAM ポリシーを、IAM ユーザに付与できるかどうか、というのが検証の内容となります。対象の IAM 権限は複数ありますが、一番分かりやすいところでまずはスキーマを編集できる権限(appsync:StartSchemaCreation)について検証してみることに。

以下検証においてはスクリーンショットに表示されている以外の IAM 権限エラーも複数表示されていましたが、検証目的から外れる内容のものは省略しています。ご了承ください。

まず、確認用の AWS AppSync API 「AppSync-API-test」を作成した上で、スキーマ編集画面をエラーなく開くための以下 IAM ポリシーを付与した IAM ユーザで、AWS マネジメントコンソールからスキーマの編集画面を開いてみます。 

ちなみに、「appsync:ListSourceApiAssociations」についてもドキュメント上はリソース指定に対応していませんでしたが、「appsync:GraphQL」と同じような ARN パスでリソース指定ができたので、他の権限についてもできるのではなかろうかという楽観的予測が芽生えつつありました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "1",
      "Effect": "Allow",
      "Action": [
        "appsync:ListGraphqlApis"
      ],
      "Resource": "*"
    },
    {
      "Sid": "2",
      "Effect": "Allow",
      "Action": [
        "appsync:ListSourceApiAssociations"
      ],
      "Resource": "arn:aws:appsync:${Region}:${Account}:apis/${GraphQLAPIId}/*"
    }
  ]
}

もちろんこの時点では「ロード中」の文字がフォーム内に残ったままになっており権限不足なことは明白ですが、この状態から適当なスキーマ定義を入力してみると、

「appsync:ListResolvers」権限に関するエラー発生時のスクリーンショット

このように「appsync:ListResolvers」権限に関するエラーが発生。最終的にはこの権限も必要になるでしょうが、一旦スルーしてスキーマを保存してみます。

「appsync:StartSchemaCreation」権限に関するエラー発生時のスクリーンショット

すると、狙い通りに「appsync:StartSchemaCreation」権限に関するエラーが発生したので、こちらに対してリソース設定をしてみようということでエラーメッセージの内容を見たところ、リソースの ARN パスが「appsync:ListSourceApiAssociations」のものと少し異なることが判明。よく見ると「appsync:ListResolvers」も同じようなARNパスになっており、以下の通り「/v1/」が追加されているのが分かります。

  • arn:aws:appsync:${Region}:${Account}:apis/${GraphQLAPIId}/<対象リソース名>
  • arn:aws:appsync:${Region}:${Account}:/v1/apis/${GraphQLAPIId}/<対象リソース名>

しかもこの「/v1/」が入ったリソースの ARN パス、ドキュメントに記載がないんですよね・・

Actions, resources, and condition keys for AWS AppSync - Service Authorization Reference
Lists all of the available service-specific resources, actions, and condition keys that can be used in IAM policies to c...

ということで、ちょっときな臭い感じがするものの、普通にこの ARN パスをそのまま設定すれば良いのではないか?と推測して以下のようにポリシーを変更してリトライ。「appsync:GetSchemaCreationStatus」についても必要そうだったので合わせて追加しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "1",
      "Effect": "Allow",
      "Action": [
        "appsync:ListGraphqlApis"
      ],
      "Resource": "*"
    },
    {
      "Sid": "2",
      "Effect": "Allow",
      "Action": [
        "appsync:ListSourceApiAssociations"
      ],
      "Resource": "arn:aws:appsync:${Region}:${Account}:apis/${GraphQLAPIId}/*"
    },
    {
      "Sid": "3",
      "Effect": "Allow",
      "Action": [
        "appsync:StartSchemaCreation",
        "appsync:GetSchemaCreationStatus"
      ],
      "Resource": "arn:aws:appsync:${Region}:${Account}:/v1/apis/${GraphQLAPIId}/*"
    }
  ]
}

スキーマ編集成功時のスクリーンショット

すると、エラーが出力されずにスキーマの保存が完了しました!!

後は必要となりそうな各種 IAM 権限を調べてお客さんに伝えてクローズ!と進めたいところなのですが、ドキュメントに記載されていない内容であるため AWS サポートに裏取り。マニュアルに記載されていない以上は想定されない挙動(≒不具合)の可能性もあり、そのような結論にならないことを願っていたのですが・・

AppSync の StartSchemaCreation アクション等でリソースレベルのアクセス制御が可能となっている事象につきまして、想定された動作であることを確認いたしました。そのため、ご連絡いただきましたようなポリシーにて特定の AppSync API のみスキーマ、リゾルバ、関数を更新いただくことが可能でございます。

ドキュメントやビジュアルエディタ等に本動作が反映されていない点につきましては、製品担当部署にフィードバックを実施いたしました。

ドキュメントについては、本日時点ではまだ反映されていないようでした。

上記回答の通り、無事に想定された動作であることを確認できたので、改めて上記内容及び追加設定頂きたい IAM ポリシーをお客さんに伝えてクローズと相成りました。最後に、実環境に設定した IAM ポリシーを記載しておきます。

  • データソースについてはスキーマやパイプライン、関数などと比較して変更のタイミングが限定的であるため、権限付与しない方針としています。(今考えると付与してしまっても良かった気はしますが・・)
  • AWS マネジメントコンソールからクエリを実行して動作確認を行うことがあるので、それができるように「appsync:GraphQL」権限を追加しています。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "1",
      "Effect": "Allow",
      "Action": [
        "appsync:ListGraphqlApis"
      ],
      "Resource": "*"
    },
    {
      "Sid": "2",
      "Effect": "Allow",
      "Action": [
        "appsync:GraphQL",
        "appsync:ListSourceApiAssociations"
      ],
      "Resource": [
        "arn:aws:appsync:${Region}:${Account}:apis/${GraphQLAPIId}/*"
      ]
    },
    {
      "Sid": "3",
      "Effect": "Allow",
      "Action": [
        "appsync:GetSchemaCreationStatus",
        "appsync:GetResolver",
        "appsync:GetFunction",
        "appsync:GetApiCache",
        "appsync:ListFunctions",
        "appsync:ListResolvers",
        "appsync:ListTypes",
        "appsync:ListDataSources",
        "appsync:ListResolversByFunction",
        "appsync:StartSchemaCreation",
        "appsync:CreateResolver",
        "appsync:UpdateResolver",
        "appsync:DeleteResolver",
        "appsync:CreateFunction",
        "appsync:UpdateFunction",
        "appsync:DeleteFunction",
        "appsync:ListApiKeys"
      ],
      "Resource": [
        "arn:aws:appsync:${Region}:${Account}:/v1/apis/${GraphQLAPIId}/*"
      ]
    }
  ]
}

まとめ

ドキュメントなどの公式情報の内容を抑えておくというのはもちろんですが、実環境での検証も同じくらい大事だということを改めて実感できました。私自身はむしろ後者が先行しがちなのですが、バランスが大事ですね。

本記事のようなシチュエーションに遭遇する機会はそれほど多くないと想像しますが、どなたかの役に立てば幸いです。

タイトルとURLをコピーしました