aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.81k stars 821 forks source link

Custom Key Fails to Adhere to Unique Constraints #7414

Closed mm-git closed 3 years ago

mm-git commented 3 years ago

Before opening, please confirm:

JavaScript Framework

Vue

Amplify APIs

GraphQL API

Amplify Categories

api

Environment information

``` System: OS: Windows 10 10.0.19042 CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz Memory: 1.97 GB / 15.62 GB Binaries: Node: 14.16.1 - C:\Program Files\nodejs\node.EXE npm: 7.12.0 - C:\Program Files\nodejs\npm.CMD Browsers: Chrome: 90.0.4430.212 Edge: Spartan (44.19041.964.0), Chromium (90.0.818.66) Internet Explorer: 11.0.19041.1 npmPackages: @fortawesome/fontawesome-svg-core: ^1.2.35 => 1.2.35 @fortawesome/free-regular-svg-icons: ^5.15.3 => 5.15.3 @fortawesome/free-solid-svg-icons: ^5.15.3 => 5.15.3 @fortawesome/vue-fontawesome: ^3.0.0-3 => 3.0.0-3 @types/uuid: ^8.3.0 => 8.3.0 @types/validator: ^13.1.3 => 13.1.3 @typescript-eslint/eslint-plugin: ^4.18.0 => 4.22.1 @typescript-eslint/parser: ^4.18.0 => 4.22.1 @vee-validate/rules: ^4.1.20 => 4.1.20 @vue/cli-plugin-babel: ~4.5.0 => 4.5.13 @vue/cli-plugin-eslint: ~4.5.0 => 4.5.13 @vue/cli-plugin-pwa: ~4.5.0 => 4.5.13 @vue/cli-plugin-router: ~4.5.0 => 4.5.13 @vue/cli-plugin-typescript: ~4.5.0 => 4.5.13 @vue/cli-plugin-vuex: ~4.5.0 => 4.5.13 @vue/cli-service: ~4.5.0 => 4.5.13 @vue/compiler-sfc: ^3.0.0 => 3.0.11 @vue/eslint-config-standard: ^5.1.2 => 5.1.2 @vue/eslint-config-typescript: ^7.0.0 => 7.0.0 animate.css: ^4.1.1 => 4.1.1 aws-amplify: ^3.4.0 => 3.4.0 axios: ^0.21.1 => 0.21.1 blob-util: ^2.0.2 => 2.0.2 core-js: ^3.6.5 => 3.12.1 (2.6.12) dayjs: ^1.10.4 => 1.10.4 direct-vuex: ^0.12.1 => 0.12.1 eslint: ^6.7.2 => 6.8.0 eslint-plugin-import: ^2.20.2 => 2.22.1 eslint-plugin-node: ^11.1.0 => 11.1.0 eslint-plugin-promise: ^4.2.1 => 4.3.1 eslint-plugin-standard: ^4.0.0 => 4.1.0 eslint-plugin-vue: ^7.0.0 => 7.9.0 memo-parser: 0.2.1 node-sass: ^4.12.0 => 4.14.1 register-service-worker: ^1.7.1 => 1.7.2 sass-loader: ^8.0.2 => 8.0.2 svg-path-bounds: ^1.0.2 => 1.0.2 typescript: ~4.1.5 => 4.1.5 uuid: ^3.4.0 => 3.4.0 (3.3.2) validator: ^13.6.0 => 13.6.0 vue: ^3.0.0 => 3.0.11 vue-awesome-example: 2.0.0 vue-router: ^4.0.0-0 => 4.0.6 vue3-mq: ^2.3.1 => 2.3.1 vuex: ^4.0.0-0 => 4.0.0 vuex-persistedstate: * => 4.0.0-beta.3 npmGlobalPackages: @aws-amplify/cli: 4.51.2 @ionic/cli: 6.14.1 @vue/cli-init: 4.5.13 @vue/cli: 4.5.13 coffeescript: 2.5.1 cordova: 10.0.0 dotenv-cli: 4.0.0 eslint: 7.26.0 eslit: 6.0.0 exp: 57.2.1 expo-cli: 4.4.7 graphql-schema-utilities: 1.1.3 gulp: 4.0.2 ionic: 5.4.16 live-server: 1.2.1 mocha: 8.4.0 node-gyp: 8.0.0 node-ts: 5.1.1 npm: 7.12.0 production: 0.0.2 react-native-cli: 2.0.1 serverless-create-global-dynamodb-table: 3.1.1 serverless-dynamodb-autoscaling: 0.6.2 serverless: 2.43.0 to-ico-cli: 1.0.0 ts-node: 9.1.1 typescript: 4.2.3 vue-next: 0.0.1 webpack-cli: 4.7.0 webpack: 5.36.2 windows-build-tools: 5.2.2 wscat: 4.0.1 ```

Describe the bug

I defined a model like this.

type XXX
  @model
  @auth(
    rules:[
      { allow: owner, operations: [create, update, delete] }
    ]
  )
{
  id: ID!
  owner: String
}

It works fine. At first Owner A create a record on a XXX table. If owner B create a record with same id, it cause error 400.

But, I defined a model with custom primary key, it doesn't work.

type XXX
  @model
  @auth(
    rules:[
      { allow: owner, operations: [create, update, delete] }
    ]
  )
  @key(fields: ["customId"])
{
  customId: ID!
  owner: String
}

Even though owner B create a record with same customId created by ownerA, it will be no error. In addition, after create operation by owner B, owner value is still owner A, but _version changed to 2.

Expected behavior

Even if model have a custom primary keys, It should be prevented creating a record with same id created by other owner.

Reproduction steps

  1. define some model with custom primary key
  2. create a record by owner A on the model.
  3. create record with same id created by owner A. It will be OK result.
mm-git commented 3 years ago

The OK result of the create operation by owner B, it includes owner A's owner field. It means, owner B can know owner A's id. It may be a security risk?

medelman17 commented 3 years ago

@mm-git -- We'll investigate in short order. Thanks for raising.

josefaidt commented 3 years ago

Hey @mm-git :wave: thanks for raising this! In order to filter items that are created by the owner when we execute a list operation for example, we need to add read to the operations in our @auth rules like so:

 @auth(
    rules:[
      { allow: owner, operations: [read, create, update, delete] }
    ]
  )

if this is the case, then owners are only allowed to see what they've created, but are able to create an item using an existing custom key. Owners are not allowed to update or delete records owned by other owners, though. Given the current setup without read noted in the allowed operations all items from all owners can be returned.

I've raised this issue to the team to take a further look at!

/cc team: I'm also seeing custom keys being added to listXXX operations. With the schema:

type Todo
  @model
  @auth(rules: [{ allow: owner, operations: [read, create, update, delete] }])
  @key(fields: ["customId"]) {
  customId: ID!
  name: String!
  owner: String
}

we see the following in the built schema:

type Query {
  getTodo(customId: ID!): Todo
  listTodos(customId: ID, filter: ModelTodoFilterInput, limit: Int, nextToken: String, sortDirection: ModelSortDirection): ModelTodoConnection
}

however this is not the case when not using custom keys.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.