Skip to content

Commit

Permalink
Migrate to cdk v2 (#180)
Browse files Browse the repository at this point in the history
* Migrate to cdk v2

* 1.0.0-beta.0

* make cdk-lib versioning flexible

* 1.0.0-beta.1

* Update README and use cdk 2.7.0
  • Loading branch information
snowiow authored Jan 13, 2022
1 parent 29bb518 commit 77e4e19
Show file tree
Hide file tree
Showing 26 changed files with 21,987 additions and 5,177 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.d.ts
*.js
13 changes: 13 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": [
"./node_modules/@moia-oss/eslint-prettier-typescript-config/config/eslint.js",
"./node_modules/@moia-oss/eslint-prettier-typescript-config/config/eslint-strict.js"
],
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
"@typescript-eslint/consistent-type-assertions": [2, { "assertionStyle": "as" }]
}
}
12 changes: 6 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: "monthly"
- package-ecosystem: "github-actions"
directory: "/"
interval: 'monthly'
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: "monthly"
interval: 'monthly'
8 changes: 5 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
pull_request:
types:
- opened
- synchronize
- synchronize

jobs:
test:
Expand All @@ -17,9 +17,11 @@ jobs:
node-version: 16
- name: NPM Install
run: npm ci
- name: Format Check
run: npm run format:check
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Build
run: npm run build
- name: Test
run: npm run test
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*.d.ts
node_modules
.jsii

.log
tags
dist/
test/__snapshots__/
Expand Down
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@moia-oss/eslint-prettier-typescript-config/config/prettier"
82 changes: 44 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fmoia-oss%2Fbastion-host-forward%2Fbadge&style=flat)](https://actions-badge.atrox.dev/moia-oss/bastion-host-forward/goto)
[![npm version](https://badge.fury.io/js/%40moia-oss%2Fbastion-host-forward.svg)](https://badge.fury.io/js/%40moia-oss%2Fbastion-host-forward)
[![PyPI version](https://badge.fury.io/py/moia-dev.bastion-host-forward.svg)](https://badge.fury.io/py/moia-dev.bastion-host-forward)

# Bastion Host Forward

This is a CDK Library providing custom bastion host constructs for connecting to
Expand All @@ -18,11 +19,26 @@ Currently the following AWS Services are supported:
| Redshift | `BastionHostRedshiftForward` |
| RDS | `BastionHostRDSForward` |

# V1 DISCLAIMER

We introduced v1.0.0 recently, which now relies on v2 of CDK. This introced an
incompability, because they don't offer a L2 Construct for
[Redshift](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_redshift-readme.html)
anymore. This is why we cant offer the `BastionHostRedshiftForward` Construct
anymore. We would need to accept a CFN L1 Construct instead, but we didn't allow
this for the `BastionHostRedisForward` as well. Instead we decided to rename the
`BastionHostRedisForward` to `GenericBastionHostForward`, which needs only the
endpoint address and the port of the data store to be able to forward connections.

With the new `GenericBastionHostForward` you are still able to forward
connections to Redis and Redshift and also every other data store in AWS, which
we don't support specifically so far.

# Technical details

The bastion hosts are extensions of the official `BastionHostLinux` CDK
construct, which allows connecting to the bastion host and from there connect to
the data layer.
the data layer.

These constructs additionally install and configure
[HAProxy](https://www.haproxy.org/) to forward the endpoint of the chosen data
Expand Down Expand Up @@ -66,6 +82,7 @@ pip install moia-dev.bastion-host-forward
```

# Examples

The following section includes some examples in supported languages how the
Bastion Host can be created for different databases.

Expand Down Expand Up @@ -132,30 +149,20 @@ that IPs from within the VPC are able to connect to the RDS Database. This
needs to be set in the RDS's Security Group. Otherwise the Bastion Host can't
connect to the RDS.
## Bastion Host for Redis in Typescript
The instantiation of a BastionHostRedisForward works very similar to the RDS
example, except that you pass a CfnCacheCluster to the BastionHost like this:
```typescript
new BastionHostRedisForward(this, 'RedisBastion', {
elasticacheCluster: cluster,
vpc: vpc,
});
```
## Bastion Host for Redshift
## Bastion Host for a generic data store on AWS (Redis, Redshift etc.)
### Typescript
A minimal example for creating the Redshift Forward Construct, which will be used via
username/password could look like this snippet. It's very similar to the RDS
version. The only difference is that we need a Redshift Cluster object instead
of a RDS DatabaseInstance:
A minimal example for creating the Generic Forward Construct, which will be used
via username/password could look like this snippet. In this case we forward a
connection to a RedShift instance, but this can also be a Redis Node or any
other data store on AWS. Instead of passing the complete L2 construct and
letting the library extract the necessary properties, the client is passing them
directly to the construct:
```typescript
import * as cdk from '@aws-cdk/core';
import { BastionHostRedshiftForward } from '@moia-dev/bastion-host-forward';
import { GenericBastionHostForward } from '@moia-dev/bastion-host-forward';
import { SecurityGroup, Vpc } from '@aws-cdk/aws-ec2';
import { Cluster } from '@aws-cdk/aws-redshift';

Expand All @@ -164,29 +171,26 @@ export class PocRedshiftStack extends cdk.Stack {
super(scope, id, props);

const vpc = Vpc.fromLookup(this, 'MyVpc', {
vpcId: 'vpc-12345678'
vpcId: 'vpc-12345678',
});

const securityGroup = SecurityGroup.fromSecurityGroupId(
this,
'BastionHostSecurityGroup',
'sg-1245678',
{ mutable: false }
);
const securityGroup = SecurityGroup.fromSecurityGroupId(this, 'BastionHostSecurityGroup', 'sg-1245678', {
mutable: false,
});

const redshiftCluster = Cluster.fromClusterAttributes(this, 'RedshiftCluster', {
clusterName: 'myRedshiftClusterName',
clusterEndpointAddress: 'myRedshiftClusterName.abcdefg.eu-central-1.redshift.amazonaws.com',
clusterEndpointPort: 5439,

});

new BastionHostRedshiftForward(this, 'BastionHostRedshiftForward', {
new GenericBastionHostForward(this, 'BastionHostRedshiftForward', {
vpc,
name: 'MyRedshiftBastionHost',
securityGroup,
redshiftCluster
})
name: 'MyRedshiftBastionHost',
address: redshiftCluster.clusterEndpointAddress,
port: redshiftCluster.clusterEndpointPort,
});
}
}
```
Expand All @@ -213,20 +217,21 @@ class PocRedshiftStack(cdk.Stack):
self,
"sec_group", "sg-12345678"
)
redshiftCluster = aws_redshift.Cluster.from_cluster_attributes(
redshift_cluster = aws_redshift.Cluster.from_cluster_attributes(
self,
"cluster",
cluster_name="myRedshiftClusterName",
cluster_endpoint_address="myRedshiftClusterName.abcdefg.eu-central-1.redshift.amazonaws.com",
cluster_endpoint_port=5439
)

bastion_host_forward.BastionHostRedshiftForward(
bastion_host_forward.GenericBastionHostForward(
self,
"bastion-host",
name="my-vastion-host",
name="my-bastion-host",
security_group=security_group,
redshift_cluster=redshiftCluster,
address: redshift_cluster.cluster_endpoint_address,
port: redshift_cluster.cluster_endpoint_port,
vpc=vpc
)
```
Expand Down Expand Up @@ -266,7 +271,7 @@ export class BastionHostPocStack extends cdk.Stack {
);

new BastionHostAuroraServerlessForward(this, 'BastionHost', {
vpc,
vpc,
serverlessCluster,
});
```
Expand Down Expand Up @@ -305,6 +310,7 @@ AWS](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manage
The Session Manager offers a command to forward a specific port. On the Bastion
Host a HAProxy was installed which forwards the connection on the same
port as the specified service. Those are by default:
- RDS MySQL: 3306
- RDS PostgreSQL: 5432
- Redis: 6739
Expand All @@ -328,11 +334,11 @@ same as the RDS Port.
Now you would be able to connect to the RDS as it would run on localhost:5432.
*Note*
_Note_
In the example of a MySQL running in Serverless Aurora, we couldn't connect to
the database using localhost. If you face the same issue, make sure to also try to connect via
the local IP 127.0.0.1.
the local IP 127.0.0.1.
Example with the MySQL CLI:
Expand Down
14 changes: 6 additions & 8 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
module.exports = {
"roots": [
"<rootDir>/test"
],
testMatch: [ '**/*.test.ts'],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
}
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
};
24 changes: 13 additions & 11 deletions lib/aurora-serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@
limitations under the License.
*/

import * as cdk from '@aws-cdk/core';
import * as iam from '@aws-cdk/aws-iam';
import * as rds from '@aws-cdk/aws-rds';
import { Stack, Token } from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import type { IServerlessCluster } from 'aws-cdk-lib/aws-rds';
import type { Construct } from 'constructs';

import { BastionHostForward } from './bastion-host-forward';
import { BastionHostForwardBaseProps } from './bastion-host-forward-base-props';
import type { BastionHostForwardBaseProps } from './bastion-host-forward-base-props';

export interface BastionHostAuroraServerlessForwardProps extends BastionHostForwardBaseProps {
/*
* The Aurora Serverless Cluster where the bastion host should be able to connect to
*/
readonly serverlessCluster: rds.IServerlessCluster;
readonly serverlessCluster: IServerlessCluster;
/*
* The resource identifier of this.serverlessCluster.
* Can be omitted, when not using IAM Authentication.
*
* Is needed for the rds-db:connect permission. This property is currently
* not exported by the rds.ServerlessCluster.
* not exported by the ServerlessCluster.
*/
readonly resourceIdentifier?: string;

Expand All @@ -42,13 +44,13 @@ export interface BastionHostAuroraServerlessForwardProps extends BastionHostForw
* Creates a Bastion Host to forward to an Aurora Serverless Cluster
*/
export class BastionHostAuroraServerlessForward extends BastionHostForward {
constructor(scope: cdk.Construct, id: string, props: BastionHostAuroraServerlessForwardProps) {
constructor(scope: Construct, id: string, props: BastionHostAuroraServerlessForwardProps) {
super(scope, id, {
vpc: props.vpc,
name: props.name,
securityGroup: props.securityGroup,
address: props.serverlessCluster.clusterEndpoint.hostname,
port: cdk.Token.asString(props.serverlessCluster.clusterEndpoint.port),
port: Token.asString(props.serverlessCluster.clusterEndpoint.port),
clientTimeout: props.clientTimeout,
});

Expand All @@ -60,8 +62,8 @@ export class BastionHostAuroraServerlessForward extends BastionHostForward {
resources: [
this.genDbUserArnFromRdsArn(props.resourceIdentifier, props.iamUser),
props.serverlessCluster.clusterArn,
]
})
],
}),
);
}
}
Expand All @@ -70,6 +72,6 @@ export class BastionHostAuroraServerlessForward extends BastionHostForward {
* @returns the resource ARN for the the rds-db:connect action
*/
private genDbUserArnFromRdsArn(dbIdentifier: string, dbUser: string): string {
return `arn:aws:rds-db:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:dbuser:${dbIdentifier}/${dbUser}`;
return `arn:aws:rds-db:${Stack.of(this).region}:${Stack.of(this).account}:dbuser:${dbIdentifier}/${dbUser}`;
}
}
17 changes: 8 additions & 9 deletions lib/bastion-host-forward-base-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@
limitations under the License.
*/

import * as ec2 from '@aws-cdk/aws-ec2';
import type { ISecurityGroup, IVpc } from 'aws-cdk-lib/aws-ec2';

export interface BastionHostForwardBaseProps {

/**
* The Vpc in which to instantiate the Bastion Host
*/
readonly vpc: ec2.IVpc;
readonly vpc: IVpc;

/**
* The name of the bastionHost instance
Expand All @@ -33,12 +32,12 @@ export interface BastionHostForwardBaseProps {
* @default If none is provided a default security group is attached, which
* doesn't allow incoming traffic and allows outbound traffic to everywhere
*/
readonly securityGroup?: ec2.ISecurityGroup;
readonly securityGroup?: ISecurityGroup;

/**
* The HAProxy client timeout in minutes
*
* @default 1
*/
/**
* The HAProxy client timeout in minutes
*
* @default 1
*/
readonly clientTimeout?: number;
}
3 changes: 1 addition & 2 deletions lib/bastion-host-forward-props.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BastionHostForwardBaseProps } from './bastion-host-forward-base-props';
import type { BastionHostForwardBaseProps } from './bastion-host-forward-base-props';

export interface BastionHostForwardProps extends BastionHostForwardBaseProps {
/**
Expand All @@ -11,4 +11,3 @@ export interface BastionHostForwardProps extends BastionHostForwardBaseProps {
*/
readonly port: string;
}

Loading

0 comments on commit 77e4e19

Please sign in to comment.