Skip to content

Commit

Permalink
feat(rds): add grantDataApi method
Browse files Browse the repository at this point in the history
  • Loading branch information
asterikx committed Oct 6, 2020
1 parent e288ee1 commit 4ed21d5
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 5 deletions.
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,
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,
SECRET_ARN: cluster.secret.secretArn,
},
});
db.grantDataApi(fn)
db.secret.grantRead(fn)
```
**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 = [
'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 {
const ret = iam.Grant.addToPrincipal({
grantee,
actions: DATA_API_ACTIONS,
resourceArns: [this.clusterArn],
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, haveOutput, 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 @@ -652,6 +653,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

0 comments on commit 4ed21d5

Please sign in to comment.