Skip to content

Amplify DynamoDB Table's grantReadWriteData does not grant permissions on indexes #3054

@fossamagna

Description

@fossamagna

Environment information

System:
  OS: Linux 6.6 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
  CPU: (8) arm64 unknown
  Memory: 18.46 GB / 23.43 GB
  Shell: /bin/bash
Binaries:
  Node: 22.16.0 - /usr/local/bin/node
  Yarn: 1.22.22 - /usr/local/bin/yarn
  npm: 10.9.2 - /usr/local/bin/npm
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/auth-construct: 1.8.1
  @aws-amplify/backend: 1.16.1
  @aws-amplify/backend-ai: Not Found
  @aws-amplify/backend-auth: 1.7.1
  @aws-amplify/backend-cli: 1.8.0
  @aws-amplify/backend-data: 1.6.1
  @aws-amplify/backend-deployer: 2.1.3
  @aws-amplify/backend-function: 1.14.1
  @aws-amplify/backend-output-storage: 1.3.1
  @aws-amplify/backend-secret: 1.4.0
  @aws-amplify/backend-storage: 1.4.1
  @aws-amplify/cli-core: 2.2.1
  @aws-amplify/client-config: 1.8.0
  @aws-amplify/data-construct: 1.16.3
  @aws-amplify/data-schema: 1.21.0
  @aws-amplify/deployed-backend-client: 1.8.0
  @aws-amplify/form-generator: 1.2.1
  @aws-amplify/model-generator: 1.2.0
  @aws-amplify/platform-core: 1.10.0
  @aws-amplify/plugin-types: 1.11.0
  @aws-amplify/sandbox: 2.1.2
  @aws-amplify/schema-generator: 1.4.0
  @aws-cdk/toolkit-lib: 1.1.1
  aws-amplify: 6.15.3
  aws-cdk-lib: 2.189.1
  typescript: 5.8.3
No AWS environment variables
No CDK environment variables

Describe the bug

Even when granting permissions using table.grantReadWriteData(grantee), access to GSIs created via secondaryIndexes is not granted to the grantee.

Workaround

Instead of calling table.grantReadWriteData directly, use the following function.

function grantReadWriteData(table: ITable, grantee: IGrantable) {
  return table.grantReadWriteData(grantee).combine(
    Grant.addToPrincipal({
      grantee,
      actions: ["dynamodb:Query", "dynamodb:Scan"],
      resourceArns: [`${table.tableArn}/index/*`],
    }),
  );
}

Reproduction steps

  1. Define schema inamplify/data/resource.ts
    export const schema = a.schema({
      Customer: a
        .model({
          name: a.string(),
          phoneNumber: a.phone(),
          accountRepresentativeId: a.id().required(),
        })
        .secondaryIndexes((index) => [index("accountRepresentativeId")])
        .authorization(allow => [allow.publicApiKey()]),
    });
  2. Add amplify/functions/getCustomerByAccountRepresentativeId/resource.ts
    import { defineFunction } from '@aws-amplify/backend';
    export const getCustomerByAccountRepresentativeId = defineFunction({
      name: 'getCustomerByAccountRepresentativeId',
    });
  3. Add amplify/functions/getCustomerByAccountRepresentativeId/handler.ts
    import type { Handler } from 'aws-lambda';
    
    export const handler: Handler = async (event, context) => {
      // Code for accessing a DynamoDB table using GSI goes here
      ...
    };
  4. Lastly, this function needs to be added to your backend.
    import { defineBackend } from '@aws-amplify/backend';
    import { getCustomerByAccountRepresentativeId } from './functions/getCustomerByAccountRepresentativeId/resource';
    
    const backend = defineBackend({
      getCustomerByAccountRepresentativeId
    });
    
    const table = backend.data.resources.tables.Customer;
    table.grantReadWriteData(backend.getCustomerByAccountRepresentativeId);
  5. Run npx ampx sandbox
  6. Permissions are granted for the Customer table, but not for the indexes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions