aws / aws/aws-cdk

aws-redshift-alpha: Race condition when adding table and granting permission in same deployment

Open
#34,200 1 comment 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-redshift bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

When trying to add a new table to a Redshift database AND also grant an existing user permission to that table in the same deployment, the deployment would fail due to the `GRANT` query executing before the table has has been added, leading to `ERROR: relation "new_table" does not exist"`.

### Regression Issue

- [ ] Select this option if this issue appears to be a regression.

### Last Known Working CDK Version

_No response_

### Expected Behavior

New table is created _then_ permission is granted to user.

### Current Behavior

`TablePrivileges` resource update gets initiated _while_ new table is still in `CREATE_IN_PROGRESS`, leading to deployment failure with message:

```
Received response status [FAILED] from custom resource. Message returned: Statement status was FAILED: ERROR: relation "new_table" does not exist
```

### Reproduction Steps

Create cluster with at least one table and user and grant permissions to tables. Deploy this code to CF:

```
const user = new User(this, 'User', {
cluster,
databaseName,
adminUser,
username: 'service_user',
});

const tables = [
new Table(this, 'OldTable', {
tableName: 'existing_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
]

tables.forEach((table) => {
user. addTablePrivileges(table, TableAction.SELECT, TableAction.INSERT);
});
```

Once the previous code finish deployment, add a new table to `tables` list, then attempt to deploy the new change:

```
const user = new User(this, 'User', {
cluster,
databaseName,
adminUser,
username: 'service_user',
});

const tables = [
new Table(this, 'OldTable', {
tableName: 'existing_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
new Table(this, 'NewTable', {
tableName: 'new_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
]

tables.forEach((table) => {
user. addTablePrivileges(table, TableAction.SELECT, TableAction.INSERT);
});
```

Deployment would fail due to race condition between adding new table and granting new permission.

### Possible Solution

Permission grant need to wait for table to finish deployment.

This may be due to dependency chain not being setup correctly. Even though there is a dependency setup between `UserTablePrivileges` and the table, it only seems to be added for the first privilege defined: https://github.com/aws/aws-cdk/blob/v2.190.0/packages/%40aws-cdk/aws-redshift-alpha/lib/user.ts#L117

### Additional Information/Context

_No response_

### CDK CLI Version

cdk: 2.181.0 | aws-redshift-alpha: 2.181.0-alpha.0

### Framework Version

v18.18.2

### Node.js Version

v18.18.2

### OS

MacOS

### Language

TypeScript

### Language Version

TypeScript (5.0.4)

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start in packages/@aws-cdk/aws-redshift-alpha/lib/user.ts around line 117, where the dependency between UserTablePrivileges and the table is configured. Reproduce the deployment with an existing table, then add a new table and its privileges. Done means the new table reaches completion before the grant runs and the deployment no longer fails with the relation-not-found error.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.