AWSAWS CDK

AWS AppSyncでCognito User Pools認証を利用する

「AppSyncでGraphQL簡単に使える」ってことだったので、最近仲良くなろうと頑張ってます。 SaaSとかだとAPIキーではなくCognito User PoolsでAPIの認証かけたいよねってなるので、トライした […]

広告ここから
広告ここまで

「AppSyncでGraphQL簡単に使える」ってことだったので、最近仲良くなろうと頑張ってます。

SaaSとかだとAPIキーではなくCognito User PoolsでAPIの認証かけたいよねってなるので、トライした覚書です。

まとめ

  • GraphQL APIのSettingsでAuthorization typeをCognito UserPoolsに変えればOK
  • defaultActionをDENYにするとスキーマ毎に制御できる
  • マネコンでテストするときにCognito User PoolsのClient IDいるから要注意

AWS CDKでさっさと作る

最近AWS CDKが型定義ファイルとIDEの入力補完でパラメーター書けるので、新しいサービス立ち上げるときによく使ってます。

スタック作ってFailしてRollbackして・・・のループに入る前に、TypeScriptがガンガンバリデートしてくれるので割と助かってます。

ということで簡単なサンプルコード(lib/aws-cdk-stack.ts)

import cdk = require('@aws-cdk/cdk');
import Appsync = require('@aws-cdk/aws-appsync')

export class AwsCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // APIを作る
    const api = new Appsync.CfnGraphQLApi(this, 'GraphQLAPI', {
      authenticationType: 'AMAZON_COGNITO_USER_POOLS',
      name: id,
      userPoolConfig: {
        appIdClientRegex: 'XXXXXXXXX',
        awsRegion: 'us-east-1',
        defaultAction: 'DENY',
        userPoolId: 'us-east-1_XXXXXXx'
      }
    })
    // schemaを定義する(今回は省略)
    const schema = AppSyncSchema.create(this, api)

    // datasourceを定義する(今回は省略)
    const dataSource = AppSyncDatasourcess.create(this, id, api)

    // resolverを定義する(今回は省略)
    const resolvers = AppSyncResolvers.create(this, api)

    // CFNの依存を組む
    resolvers.map((resolver: Appsync.CfnResolver) => {
      resolver.node.addDependency(dataSource);
      resolver.node.addDependency(schema);
    })
  }
}

schema / datasource / resolverも定義しないとですが、そこを書き出すと長いので省略しました。

設定のポイント

設定時のポイントとしては、以下の点があります。

  • 認証方式は1API 1タイプなので、API tokenなどとの併用はできない。
    • schema / resolverとかのコードを共有にして、もう1つAPIつくると良さそう。
  • defaultActionをDENYにした場合、schema毎に許可する設定が必要
  • アプリクライアントも決め打ちしたいなら、appIdClientRegexで指定

複数の認証方式に対応させる

CDKやCloudFormationで複数のAPIを作るのがよいでしょう。

import cdk = require('@aws-cdk/cdk');
import Appsync = require('@aws-cdk/aws-appsync')

export class AwsCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // APIを作る
    const api = new Appsync.CfnGraphQLApi(this, 'GraphQLAPI', {
      authenticationType: 'AMAZON_COGNITO_USER_POOLS',
      name: id,
      userPoolConfig: {
        appIdClientRegex: 'XXXXXXXXX',
        awsRegion: 'us-east-1',
        defaultAction: 'DENY',
        userPoolId: 'us-east-1_XXXXXXx'
      }
    })
    const apiWithKey = new Appsync.CfnGraphQLApi(this, 'GraphQLAPI', {
      authenticationType: 'API_KEY',
      name: id,
    })
      
    new Appsync.CfnApiKey(this, 'apiKey', {
      apiId: apiWithKey.graphQlApiApiId,
    })

    // schemaを定義する(今回は省略)
    const schema = AppSyncSchema.create(this, api)
    const schema1 = AppSyncSchema.create(this, apiWithKey)
    
    // datasourceを定義する(今回は省略)
    const dataSource = AppSyncDatasourcess.create(this, id, api)
    const dataSource1 = AppSyncDatasourcess.create(this, id, apiWithKey)

    // resolverを定義する(今回は省略)
    const resolvers = AppSyncResolvers.create(this, api)
    const resolvers1 = AppSyncResolvers.create(this, apiWithKey)

    // CFNの依存を組む
    resolvers.map((resolver: Appsync.CfnResolver) => {
      resolver.node.addDependency(dataSource);
      resolver.node.addDependency(schema);
    })
    resolvers1.map((resolver: Appsync.CfnResolver) => {
      resolver.node.addDependency(dataSource1);
      resolver.node.addDependency(schema1);
    })
  }
}

schema単位での制御

@aws_authを使うことでschema別に制御できます。ドキュメントをざっと見た範囲では、Cognito User Poolsのgroupで割り振りできる様子です。

type Query {
  getItem(UUID: String!, track_month: Int!): Item
		@aws_auth(cognito_groups: ["admin", "editor", "reader"])
  queryStatistics(
		user_name: String!,
		track_month: Int!,
	): StatisticsConnection
		@aws_auth(cognito_groups: ["admin"])
}

上のサンプルだと、getItemはadmin / editor / readerのいずれかに所属するユーザーがアクセス可能で、queryStatisticsはadminのみアクセスできます。

これとdefaultActionをDENYにする設定を入れることで、ホワイトリスト的に制御できます。ただしすべてのschemaに明示的に設定する必要がありますので、トレードオフであることは要注意です。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts