aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
81 stars 71 forks source link

`backend.data.resources.graphqlApi.modes` is empty even when modes are defined #2644

Open kwwendt opened 1 week ago

kwwendt commented 1 week ago

Environment information

System:
  OS: macOS 14.4.1
  CPU: (8) x64 Apple M1
  Memory: 39.98 MB / 16.00 GB
  Shell: /bin/bash
Binaries:
  Node: 20.14.0 - ~/.nvm/versions/node/v20.14.0/bin/node
  Yarn: 1.22.19 - /usr/local/bin/yarn
  npm: 10.7.0 - ~/.nvm/versions/node/v20.14.0/bin/npm
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 1.0.3
  @aws-amplify/backend-cli: 1.0.4
  aws-amplify: 6.3.7
  aws-cdk: 2.146.0
  aws-cdk-lib: 2.146.0
  typescript: 5.4.5
AWS environment variables:
  AWS_PROFILE = kwwendt+mne-Admin
  AWS_DEFAULT_REGION = us-west-2
  AWS_STS_REGIONAL_ENDPOINTS = regional
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables

Data packages

cms-app@0.0.0 /Project
├─┬ @aws-amplify/backend-cli@1.0.4
│ └─┬ @aws-amplify/schema-generator@1.0.0
│   └── @aws-amplify/graphql-schema-generator@0.8.6
└─┬ @aws-amplify/backend@1.0.3
  └─┬ @aws-amplify/backend-data@1.0.2
    └── @aws-amplify/data-construct@1.8.5

Description

const backend = defineBackend({
  auth,
  data
});

console.log(backend.data.resources.graphqlApi.modes); // prints an empty array []

The modes attribute is empty even though IAM is included by default and my API also has AMAZON_COGNITO_USER_POOLS added as an auth mode.

Root cause (most likely): in construct-export.ts Code link reference, the authorization modes aren't passed into the fromGraphqlApiAttributes method. Further investigation shows that the CDK implementation of that method sets modes to an empty array if the attribute isn't passed as part of the method CDK code reference.

Recommendation: modify the construct-export.ts file to pull in the L2 construct vs importing it from the L1 construct OR explicitly pass the other attributes for the fromGraphqlApiAttributes method.

Impact: Without this, I am unable to use the Amazon EventBridge AppSync target L2 construct. That construct checks for IAM as an included auth mode and fails when I pass backend.data.resources.graphqlApi to the construct. Example code below to reproduce.

import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import { Rule, RuleTargetInput, EventField } from "aws-cdk-lib/aws-events";
import { AppSync } from "aws-cdk-lib/aws-events-targets";

const backend = defineBackend({
  auth,
  data
});

const processingStack = backend.createStack("AssetProcessingStack");

const tagsUpdated = new Rule(processingStack, 'TagsUpdated', {
  eventPattern: {
      source: ['events'],
      detailType: ['TagsIdentified'],
      detail: {
          id: [{ "exists": true }]
      }
  }
});

tagsUpdated.addTarget(new AppSync(backend.data.resources.graphqlApi, {
  graphQLOperation: "mutation UpdateAsset($input: AssetInput!) { updateAsset(input: $input) { id tags } }",
  variables: RuleTargetInput.fromObject({
      "input": {
          "id": EventField.fromPath("$.detail.id"),
          "tags": EventField.fromPath("$.detail.tags")
      }
  })
}));
AnilMaktala commented 1 week ago

Hey @kwwendt, thanks for raising this. Have you tried backend.data.resources.cfnResources.cfnGraphqlApi.authenticationType to retrieve the auth mode?

kwwendt commented 1 week ago

Hey @AnilMaktala - it's not a matter of needing access to auth modes but being able to reference the graphqlApi object in another CDK construct like this which checks if the modes attribute contains IAM in order to provision AppSync as a target for EventBridge.

Subset of code pulled from above:

const tagsUpdated = new Rule(processingStack, 'TagsUpdated', {
  eventPattern: {
      source: ['events'],
      detailType: ['TagsIdentified'],
      detail: {
          id: [{ "exists": true }]
      }
  }
});

tagsUpdated.addTarget(new AppSync(backend.data.resources.graphqlApi, {
  graphQLOperation: "mutation UpdateAsset($input: AssetInput!) { updateAsset(input: $input) { id tags } }",
  variables: RuleTargetInput.fromObject({
      "input": {
          "id": EventField.fromPath("$.detail.id"),
          "tags": EventField.fromPath("$.detail.tags")
      }
  })
}));

Location in the CDK code where it checks for IAM in the IGraphqlApi resource type.

chrisbonifacio commented 4 days ago

Marking this is as a bug as I was able to reproduce it consistently as well. The modes should not be an empty array if there are auth modes configured on defineData.