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(rds): add grant method for Data API #10748

Merged
merged 35 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
80bc323
feat(module): add clusterArn property to IServerlessCluster
asterikx Oct 6, 2020
2736838
feat(rds): add clusterArn property to IServerlessCluster
asterikx Oct 6, 2020
90b8728
Merge branch 'serverlesscluster-resource-arn-prop' of github.com:aste…
asterikx Oct 6, 2020
dd20726
Merge branch 'serverlesscluster-resource-arn-prop' of github.com:aste…
asterikx Oct 6, 2020
d5b2c90
Merge branch 'serverlesscluster-resource-arn-prop' of github.com:aste…
asterikx Oct 6, 2020
e288ee1
revert yarn.lock
asterikx Oct 6, 2020
dbd394c
add grantDataApi method
asterikx Oct 6, 2020
4ed21d5
feat(rds): add grantDataApi method
asterikx Oct 6, 2020
0208ab3
feat(rds): add grantDataApi method
asterikx Oct 6, 2020
0a8822b
Merge github.com:aws/aws-cdk into grant-data-api
asterikx Oct 6, 2020
08af548
fix typos in the docs and add link to data api actions
asterikx Oct 7, 2020
10614a2
Merge branch 'master' into grant-data-api
asterikx Oct 7, 2020
63b8adf
grant only rds-data permissions
asterikx Oct 7, 2020
a61c1e2
use explicit actions instead of wildcard in rds-data statement
asterikx Oct 8, 2020
53cb6d5
move secret to ServerlessClusterBase and grant secret read
asterikx Oct 8, 2020
42980bf
add test for imported clusters with user provided secret
asterikx Oct 8, 2020
7743fbb
check http endpoint is enabled when granting data api access
asterikx Oct 8, 2020
9046d19
rename grant method to grantDataApiAccess
asterikx Oct 8, 2020
15c2694
Merge branch 'master' into grant-data-api
asterikx Oct 8, 2020
b3f721d
Merge branch 'master' into grant-data-api
asterikx Oct 10, 2020
9fd133e
enable http endpoint when granting data api access
asterikx Oct 13, 2020
08f8b36
rename enableHttpEndpoint to enableDataApi
asterikx Oct 14, 2020
cf450b2
Merge branch 'grant-data-api' of github.com:asterikx/aws-cdk into gra…
asterikx Oct 14, 2020
47e2b30
Merge branch 'master' into grant-data-api
asterikx Oct 14, 2020
108a222
add changes to Data API in readme
asterikx Oct 14, 2020
4dae9b1
grant wildcard resource (no resource-level permissions available)
asterikx Oct 15, 2020
bbc629f
show vpc creation in readme example
asterikx Oct 15, 2020
98de6e4
Merge branch 'master' into grant-data-api
asterikx Oct 19, 2020
50f78cb
Merge branch 'master' into grant-data-api
asterikx Nov 4, 2020
bac137b
use wildcard grant
asterikx Nov 4, 2020
c87a07c
Merge branch 'grant-data-api' of github.com:asterikx/aws-cdk into gra…
asterikx Nov 4, 2020
e187da9
fix failing tests
asterikx Nov 4, 2020
08a25c1
rename grantDataApi to grantDataApiAccess
asterikx Nov 4, 2020
088567c
Merge branch 'master' into grant-data-api
njlynch Nov 5, 2020
5ab5ef7
Merge branch 'master' into grant-data-api
mergify[bot] Nov 5, 2020
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
45 changes: 40 additions & 5 deletions packages/@aws-cdk/aws-rds/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ See also [@aws-cdk/aws-secretsmanager](https://github.com/aws/aws-cdk/blob/maste
### IAM Authentication

You can also authenticate to a database instance using AWS Identity and Access Management (IAM) database authentication;
See https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html for more information
See <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html> for more information
and a list of supported versions and limitations.

The following example shows enabling IAM authentication for a database instance and granting connection access to an IAM role.
Expand All @@ -245,12 +245,12 @@ instance.grantConnect(role); // Grant the role connection access to the DB.
```

**Note**: In addition to the setup above, a database user will need to be created to support IAM auth.
See https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.DBAccounts.html for setup instructions.
See <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.DBAccounts.html> for setup instructions.

### Kerberos Authentication

You can also authenticate using Kerberos to a database instance using AWS Managed Microsoft AD for authentication;
See https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/kerberos-authentication.html for more information
See <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/kerberos-authentication.html> for more information
and a list of supported versions and limitations.

The following example shows enabling domain support for a database instance and creating an IAM role to access
Expand All @@ -274,7 +274,7 @@ const instance = new rds.DatabaseInstance(stack, 'Instance', {
**Note**: In addition to the setup above, you need to make sure that the database instance has network connectivity
to the domain controllers. This includes enabling cross-VPC traffic if in a different VPC and setting up the
appropriate security groups/network ACL to allow traffic between the database instance and domain controllers.
Once configured, see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/kerberos-authentication.html for details
Once configured, see <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/kerberos-authentication.html> for details
on configuring users for each available database engine.

### Metrics
Expand Down Expand Up @@ -412,7 +412,7 @@ in the cloud without managing any database instances.

The following example initializes an Aurora Serverless PostgreSql cluster.
Aurora Serverless clusters can specify scaling properties which will be used to
automatically scale the database cluster seamlessly based on the workload.
automatically scale the database cluster seamlessly based on the workload.

```ts
import * as ec2 from '@aws-cdk/aws-ec2';
Expand All @@ -431,7 +431,9 @@ const cluster = new rds.ServerlessCluster(this, 'AnotherCluster', {
}
});
```

Aurora Serverless Clusters do not support the following features:

* Loading data from an Amazon S3 bucket
* Saving data to an Amazon S3 bucket
* Invoking an AWS Lambda function with an Aurora MySQL native function
Expand All @@ -448,3 +450,36 @@ Aurora Serverless Clusters do not support the following features:
Read more about the [limitations of Aurora Serverless](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html#aurora-serverless.limitations)

Learn more about using Amazon Aurora Serverless by reading the [documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html)

#### Data API

You can access your Aurora Serverless DB cluster using the built-in Data API. The Data API doesn't require a persistent connection to the DB cluster. Instead, it provides a secure HTTP endpoint and integration with AWS SDKs.

The following example shows granting Data API access to a Lamba function.

```ts
import * as lambda from '@aws-cdk/aws-lambda';
import * as rds from '@aws-cdk/aws-rds';

const cluster = new rds.ServerlessCluster(this, 'AnotherCluster', {
engine: rds.DatabaseClusterEngine.AURORA_MYSQL,
vpc,
asterikx marked this conversation as resolved.
Show resolved Hide resolved
enableHttpEndpoint: true,
});

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
environment: {
CLUTSER_ARN: cluster.clusterArn,
asterikx marked this conversation as resolved.
Show resolved Hide resolved
SECRET_ARN: cluster.secret.secretArn,
},
});
db.grantDataApi(fn)
asterikx marked this conversation as resolved.
Show resolved Hide resolved
db.secret.grantRead(fn)
asterikx marked this conversation as resolved.
Show resolved Hide resolved
```

**Note**: To invoke the Data API, the resource will need to read the secret associated with the cluster.

To learn more about using the Data API, see the [documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html).
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-rds/lib/perms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const DATA_API_ACTIONS = [
asterikx marked this conversation as resolved.
Show resolved Hide resolved
'secretsmanager:CreateSecret',
'secretsmanager:ListSecrets',
'secretsmanager:GetRandomPassword',
'tag:GetResources',
'rds-data:BatchExecuteStatement',
'rds-data:BeginTransaction',
'rds-data:CommitTransaction',
'rds-data:ExecuteStatement',
'rds-data:RollbackTransaction',
];
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import * as kms from '@aws-cdk/aws-kms';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import { Resource, Duration, Token, Annotations, RemovalPolicy, IResource, Stack } from '@aws-cdk/core';
Expand All @@ -7,6 +8,7 @@ import { IClusterEngine } from './cluster-engine';
import { DatabaseSecret } from './database-secret';
import { Endpoint } from './endpoint';
import { IParameterGroup } from './parameter-group';
import { DATA_API_ACTIONS } from './perms';
import { applyRemovalPolicy, defaultDeletionProtection, DEFAULT_PASSWORD_EXCLUDE_CHARS } from './private/util';
import { Credentials, RotationMultiUserOptions, RotationSingleUserOptions } from './props';
import { CfnDBCluster } from './rds.generated';
Expand Down Expand Up @@ -39,6 +41,13 @@ export interface IServerlessCluster extends IResource, ec2.IConnectable, secrets
* @attribute ReadEndpointAddress
*/
readonly clusterReadEndpoint: Endpoint;

/**
* Grant the given identity to access to the Data API
*
* @param grantee The principal to grant access to
*/
grantDataApi(grantee: iam.IGrantable): iam.Grant
}
/**
* Properties to configure an Aurora Serverless Cluster
Expand Down Expand Up @@ -299,6 +308,21 @@ abstract class ServerlessClusterBase extends Resource implements IServerlessClus
});
}

/**
* Grant the given identity to access to the Data API
*
* @param grantee The principal to grant access to
*/
public grantDataApi(grantee: iam.IGrantable): iam.Grant {
njlynch marked this conversation as resolved.
Show resolved Hide resolved
const ret = iam.Grant.addToPrincipal({
grantee,
actions: DATA_API_ACTIONS,
resourceArns: [this.clusterArn],
njlynch marked this conversation as resolved.
Show resolved Hide resolved
scope: this,
});
return ret;
}

/**
* Renders the secret attachment target specifications.
*/
Expand Down
61 changes: 61 additions & 0 deletions packages/@aws-cdk/aws-rds/test/test.serverless-cluster.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ABSENT, expect, haveResource, haveResourceLike, ResourcePart, SynthUtils } from '@aws-cdk/assert';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import * as kms from '@aws-cdk/aws-kms';
import * as cdk from '@aws-cdk/core';
import { Test } from 'nodeunit';
Expand Down Expand Up @@ -648,6 +649,66 @@ export = {
});
test.done();
},

'grants: data api access'(test: Test) {
// GIVEN
const stack = testStack();
const user = new iam.User(stack, 'User');
const vpc = ec2.Vpc.fromLookup(stack, 'VPC', { isDefault: true });
const cluster = new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_MYSQL,
vpc,
});

// WHEN
cluster.grantDataApi(user);

// THEN
expect(stack).to(haveResource('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: [
'secretsmanager:CreateSecret',
'secretsmanager:ListSecrets',
'secretsmanager:GetRandomPassword',
'tag:GetResources',
'rds-data:BatchExecuteStatement',
'rds-data:BeginTransaction',
'rds-data:CommitTransaction',
'rds-data:ExecuteStatement',
'rds-data:RollbackTransaction',
],
Effect: 'Allow',
Resource: {
'Fn::Join': [
'',
[
'arn:',
{
Ref: 'AWS::Partition',
},
':rds:us-test-1:12345:cluster:',
{
Ref: 'DatabaseB269D8BB',
},
],
],
},
},
],
Version: '2012-10-17',
},
PolicyName: 'UserDefaultPolicy1F97781E',
Users: [
{
Ref: 'User00B015A1',
},
],
}));

test.done();
},
};

function testStack() {
Expand Down