Skip to content

Commit

Permalink
feat(neptune): introduce cluster grant method for granular actions
Browse files Browse the repository at this point in the history
  • Loading branch information
humanzz committed Sep 7, 2022
1 parent b0ba52e commit 6fddb0c
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 7 deletions.
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-neptune/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ const cluster = new neptune.DatabaseCluster(this, 'Cluster', {
iamAuthentication: true, // Optional - will be automatically set if you call grantConnect().
});
const role = new iam.Role(this, 'DBRole', { assumedBy: new iam.AccountPrincipal(this.account) });
cluster.grantConnect(role); // Grant the role connection access to the DB.
// Use one of the following statements to grant the role the necessary permissions
cluster.grantConnect(role); // Grant the role neptune-db:* access to the DB
cluster.grant(role, 'neptune-db:ReadDataViaQuery', 'neptune-db:WriteDataViaQuery'); // Grant the role the specified actions to the DB
```

## Customizing parameters
Expand Down
19 changes: 16 additions & 3 deletions packages/@aws-cdk/aws-neptune/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ export interface IDatabaseCluster extends IResource, ec2.IConnectable {
*/
readonly clusterReadEndpoint: Endpoint;

/**
* Grant the given identity the specified actions
* @param grantee the identity to be granted the actions
* @param actions the data-access actions
*
* @see https://docs.aws.amazon.com/neptune/latest/userguide/iam-dp-actions.html
*/
grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant;

/**
* Grant the given identity connection access to the database.
*/
Expand Down Expand Up @@ -360,15 +369,15 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC

protected abstract enableIamAuthentication?: boolean;

public grantConnect(grantee: iam.IGrantable): iam.Grant {
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
if (this.enableIamAuthentication === false) {
throw new Error('Cannot grant connect when IAM authentication is disabled');
throw new Error('Cannot grant when IAM authentication is disabled');
}

this.enableIamAuthentication = true;
return iam.Grant.addToPrincipal({
grantee,
actions: ['neptune-db:*'],
actions,
resourceArns: [
[
'arn',
Expand All @@ -381,6 +390,10 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC
],
});
}

public grantConnect(grantee: iam.IGrantable): iam.Grant {
return this.grant(grantee, 'neptune-db:*');
}
}

/**
Expand Down
80 changes: 77 additions & 3 deletions packages/@aws-cdk/aws-neptune/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ describe('DatabaseCluster', () => {
});
});

test('createGrant - creates IAM policy and enables IAM auth', () => {
test('grantConnect - enables IAM auth and grants neptune-db:* to the grantee', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');
Expand Down Expand Up @@ -528,7 +528,7 @@ describe('DatabaseCluster', () => {
});
});

test('createGrant - throws if IAM auth disabled', () => {
test('grantConnect - throws if IAM auth disabled', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');
Expand All @@ -544,7 +544,81 @@ describe('DatabaseCluster', () => {
});

// THEN
expect(() => { cluster.grantConnect(role); }).toThrow(/Cannot grant connect when IAM authentication is disabled/);
expect(() => { cluster.grantConnect(role); }).toThrow(/Cannot grant when IAM authentication is disabled/);
});

test('grant - enables IAM auth and grants specified actions to the grantee', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');

// WHEN
const cluster = new DatabaseCluster(stack, 'Cluster', {
vpc,
instanceType: InstanceType.R5_LARGE,
});
const role = new iam.Role(stack, 'DBRole', {
assumedBy: new iam.AccountPrincipal(stack.account),
});
cluster.grant(role, 'neptune-db:ReadDataViaQuery', 'neptune-db:WriteDataViaQuery');

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', {
IamAuthEnabled: true,
});
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [{
Effect: 'Allow',
Action: ['neptune-db:ReadDataViaQuery', 'neptune-db:WriteDataViaQuery'],
Resource: {
'Fn::Join': [
'', [
'arn:', {
Ref: 'AWS::Partition',
},
':neptune-db:',
{
Ref: 'AWS::Region',
},
':',
{
Ref: 'AWS::AccountId',
},
':',
{
'Fn::GetAtt': [
'ClusterEB0386A7',
'ClusterResourceId',
],
},
'/*',
],
],
},
}],
Version: '2012-10-17',
},
});
});

test('grant - throws if IAM auth disabled', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');

// WHEN
const cluster = new DatabaseCluster(stack, 'Cluster', {
vpc,
instanceType: InstanceType.R5_LARGE,
iamAuthentication: false,
});
const role = new iam.Role(stack, 'DBRole', {
assumedBy: new iam.AccountPrincipal(stack.account),
});

// THEN
expect(() => { cluster.grant(role, 'neptune-db:ReadDataViaQuery', 'neptune-db:WriteDataViaQuery'); }).toThrow(/Cannot grant when IAM authentication is disabled/);
});

test('autoMinorVersionUpgrade is enabled when configured', () => {
Expand Down

0 comments on commit 6fddb0c

Please sign in to comment.