Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(neptune): introduce cluster grant method for granular actions #21926

Merged
merged 7 commits into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 neptune-db:* 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 @@ -271,6 +271,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 @@ -364,15 +373,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 actions as IAM authentication is not enabled');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new Error('Cannot grant actions as IAM authentication is not enabled');
throw new Error('Cannot grant permissions when IAM authentication is not enabled');

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick question here, the README says:

const cluster = new neptune.DatabaseCluster(this, 'Cluster', {
  vpc,
  instanceType: neptune.InstanceType.R5_LARGE,
  iamAuthentication: true, // Optional - will be automatically set if you call grantConnect().
});

It seems that this sort of contradicts that. Can you add a clarifying line that explicitly setting this to false and trying to grant permissions will throw an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh, I found the existing implementation of grantConnect and its side effect of possibly enabling iam auth, and how enabling iamAuth is handled a bit surprising!

https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/aws-neptune/lib/cluster.ts#L368

In terms of the error message, now that I look at it, I think the older version that uses "disabled" actually makes more sense and is more consistent with the implemented behaviour which

  1. Defaults to disabled (I think a cloudformation default rather than a cdk default)
  2. Requires one to explicitly disable iam auth if they don't want it and want grant methods to throw such exceptions

I get that grant enabling iam auth might be a convenience, but it's a bit twisted IMHO!

So, for this PR, how about

  1. change the error message to Cannot grant permissions when IAM authentication is disabled
  2. update the README to say // Optional - will be automatically set if you call grant() or grantConnect()

}

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

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

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"version": "21.0.0",
"files": {
"06bc77521a70e494cf9fb7d601f5111e19745b0ecde4b6ac42b311f1a19f8328": {
"86dda049435a7e62de07d7e302f55c3c286433c9f4736de7c9bee4336473b1c7": {
"source": {
"path": "aws-cdk-neptune-integ.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "06bc77521a70e494cf9fb7d601f5111e19745b0ecde4b6ac42b311f1a19f8328.json",
"objectKey": "86dda049435a7e62de07d7e302f55c3c286433c9f4736de7c9bee4336473b1c7.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,74 @@
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
},
"Role1ABCC5F0": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "sagemaker.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"Description": "AWS Sagemaker notebooks role example for interacting with Neptune Database Cluster"
}
},
"RoleDefaultPolicy5FFB7DAB": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"neptune-db:GetEngineStatus",
"neptune-db:ReadDataViaQuery"
],
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":neptune-db:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Fn::GetAtt": [
"DatabaseB269D8BB",
"ClusterResourceId"
]
},
"/*"
]
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "RoleDefaultPolicy5FFB7DAB",
"Roles": [
{
"Ref": "Role1ABCC5F0"
}
]
}
},
"ParamsA8366201": {
"Type": "AWS::Neptune::DBClusterParameterGroup",
"Properties": {
Expand Down Expand Up @@ -503,6 +571,7 @@
"Ref": "DatabaseSubnets3C9252C9"
},
"EngineVersion": "1.2.0.0",
"IamAuthEnabled": true,
"KmsKeyId": {
"Fn::GetAtt": [
"DbSecurity381C2C15",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"validateOnSynth": false,
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/06bc77521a70e494cf9fb7d601f5111e19745b0ecde4b6ac42b311f1a19f8328.json",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/86dda049435a7e62de07d7e302f55c3c286433c9f4736de7c9bee4336473b1c7.json",
"requiresBootstrapStackVersion": 6,
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
"additionalDependencies": [
Expand Down Expand Up @@ -183,6 +183,18 @@
"data": "DbSecurity381C2C15"
}
],
"/aws-cdk-neptune-integ/Role/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "Role1ABCC5F0"
}
],
"/aws-cdk-neptune-integ/Role/DefaultPolicy/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "RoleDefaultPolicy5FFB7DAB"
}
],
"/aws-cdk-neptune-integ/Params/Resource": [
{
"type": "aws:cdk:logicalId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,110 @@
"version": "0.0.0"
}
},
"Role": {
"id": "Role",
"path": "aws-cdk-neptune-integ/Role",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-neptune-integ/Role/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::IAM::Role",
"aws:cdk:cloudformation:props": {
"assumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "sagemaker.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"description": "AWS Sagemaker notebooks role example for interacting with Neptune Database Cluster"
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.CfnRole",
"version": "0.0.0"
}
},
"DefaultPolicy": {
"id": "DefaultPolicy",
"path": "aws-cdk-neptune-integ/Role/DefaultPolicy",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-neptune-integ/Role/DefaultPolicy/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::IAM::Policy",
"aws:cdk:cloudformation:props": {
"policyDocument": {
"Statement": [
{
"Action": [
"neptune-db:GetEngineStatus",
"neptune-db:ReadDataViaQuery"
],
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":neptune-db:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Fn::GetAtt": [
"DatabaseB269D8BB",
"ClusterResourceId"
]
},
"/*"
]
]
}
}
],
"Version": "2012-10-17"
},
"policyName": "RoleDefaultPolicy5FFB7DAB",
"roles": [
{
"Ref": "Role1ABCC5F0"
}
]
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.CfnPolicy",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.Policy",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.Role",
"version": "0.0.0"
}
},
"Params": {
"id": "Params",
"path": "aws-cdk-neptune-integ/Params",
Expand Down Expand Up @@ -856,6 +960,7 @@
"Ref": "DatabaseSubnets3C9252C9"
},
"engineVersion": "1.2.0.0",
"iamAuthEnabled": true,
"kmsKeyId": {
"Fn::GetAtt": [
"DbSecurity381C2C15",
Expand Down
Loading