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(ec2): add support for vpn connections #1899

Merged
merged 14 commits into from
Mar 4, 2019
Merged

feat(ec2): add support for vpn connections #1899

merged 14 commits into from
Mar 4, 2019

Conversation

jogold
Copy link
Contributor

@jogold jogold commented Feb 27, 2019

Add support for Site-to-Site VPN connections to VPC networks.

When VPN connections are specified, a VPN gateway is automatically
created and attached to the VPC. By default, routes are propagated on the
route tables associated with the private subnets. Propagation to routes
tables associated with public and/or isolated subnets is supported.

Update VPC context provider to also import vpnGatewayId.

References aws/jsii#231


Pull Request Checklist

  • Testing
    • Unit test added (prefer not to modify an existing test, otherwise, it's probably a breaking change)
    • CLI change?: coordinate update of integration tests with team
    • cdk-init template change?: coordinated update of integration tests with team
  • Docs
    • jsdocs: All public APIs documented
    • README: README and/or documentation topic updated
  • Title and Description
    • Change type: title prefixed with fix, feat will appear in changelog
    • Title: use lower-case and doesn't end with a period
    • Breaking?: last paragraph: "BREAKING CHANGE: <describe what changed + link for details>"
    • Issues: Indicate issues fixed via: "Fixes #xxx" or "Closes #xxx"
  • Sensitive Modules (requires 2 PR approvers)
    • IAM Policy Document (in @aws-cdk/aws-iam)
    • EC2 Security Groups and ACLs (in @aws-cdk/aws-ec2)
    • Grant APIs (only if not based on official documentation with a reference)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.

@jogold jogold requested a review from a team as a code owner February 27, 2019 13:40
Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

Copy: @PaulMaddox


```ts
// Dynamic routing
vpc.newVpnConnection('Dynamic', {
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to addVpnConnection


```ts
const vpc = new ec2.VpcNetwork(stack, 'MyVpc', {
vpnGateway: true
Copy link
Contributor

Choose a reason for hiding this comment

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

allow specifying vpnConnections in props as well via a map from ID to options:

new VpcNetwork(this, 'MyVpc', {
  vpnConnections: {
    dynamic: { ip: '1.2.3.4' }
  }
});

@@ -12,6 +13,12 @@ export interface IVpcSubnet extends IConstruct {
*/
readonly subnetId: string;

/**
* The id of the route table associated with this subnet.
* Not available for an imported subnet.
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this throw for imported subnets?

Copy link
Contributor Author

@jogold jogold Feb 27, 2019

Choose a reason for hiding this comment

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

No, it won't. We need routeTableId in order to propagate routes. The AWS::EC2::VPNGatewayRoutePropagation references it and is created inside the VpcNetwork construct. For imported networks/subnets we just don't need this routeTableId


// Propagate routes on route tables associated with private subnets
const routePropagation = new CfnVPNGatewayRoutePropagation(this, 'RoutePropagation', {
routeTableIds: this.privateSubnets.map(subnet => subnet.routeTableId!),
Copy link
Contributor

Choose a reason for hiding this comment

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

No !s please (it indicates that either the model is wrong or that we need a check with a good error thrown). Seems like routeTableId cannot be undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's indeed a mistake.


constructor(scope: cdk.Construct, id: string, private readonly props: VpcSubnetImportProps) {
super(scope, id);

this.subnetId = props.subnetId;
this.availabilityZone = props.availabilityZone;
this.routeTableId = '';
Copy link
Contributor

Choose a reason for hiding this comment

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

that's fishy

tunnelInsideCidr: string;
}

export interface BaseVpnConnectionProps {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please rename to VpnConnectionOptions (see #1740)

/**
* The IPsec 1 VPN connection type.
*/
export const IPsec1 = 'ipsec.1';
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be an enum maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching to an enum with only one member seems problematic for jsii? See build logs...

Copy link
Contributor

Choose a reason for hiding this comment

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

You are correct: aws/jsii#231

Can you add another member, even a dummy one?

Copy link
Contributor

Choose a reason for hiding this comment

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

And you can add this to the jsii issue and we'll fix once the jsii bug is fixed.

/**
* Indicates whether a VPN gateway should be created and attached to this VPC.
*
* @default false
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this default smarter, so if I define vpn connections on this VPC, it will default to "true", and otherwise to "false". I would expect this to Just Work (TM):

new VpcNetwork(this, 'VPC', {
  vpnConnections: {
    dynamic: { ip: '1.2.3.4' }
  }
});

@eladb
Copy link
Contributor

eladb commented Feb 27, 2019

Hey @jogold great work by the way!

Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

Looks good! I'd like @rix0rrr or @PaulMaddox 's feedback here as well

});
```

To export a VPC that can accept VPN connections, set `vpnGateway` to `true`:
Copy link
Contributor

Choose a reason for hiding this comment

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

"export"?

routePropagation.node.addDependency(attachment);

const vpnConnections = props.vpnConnections || {};
Object.keys(vpnConnections).forEach(cId => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Style: I prefer:

for (const [ id, vpn ] of Object.entries(vpnConnections)) {
  // ...
}

packages/@aws-cdk/aws-ec2/lib/vpn.ts Show resolved Hide resolved
packages/@aws-cdk/aws-ec2/test/integ.vpn.ts Show resolved Hide resolved
@eladb
Copy link
Contributor

eladb commented Feb 27, 2019

@leepa if you have some time to take a quick look, it will be much appreciated.

@eladb
Copy link
Contributor

eladb commented Feb 27, 2019

@jogold 👍

@jogold
Copy link
Contributor Author

jogold commented Feb 27, 2019

Do we need to support an option to propagate routes on isolated subnets? We could have something like:

export enum RoutesPropagationType {
  PrivateOnly,
  PrivateIsolated
}
export interface VpcNetworkProps {
  ...
  /**
   * Where to propagate VPN routes.
   *
   * @default on the route tables associated with the private subnets 
   */
  vpnRoutesPropagation?: RoutesPropagationType
  ...
}

@eladb
Copy link
Contributor

eladb commented Feb 27, 2019

@jogold sounds useful

Copy link
Contributor

@leepa leepa left a comment

Choose a reason for hiding this comment

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

Love this addition - it will make handling VPN connections nicer. There's the case of handing subnet groups rather than being opinionated about only allowing private subnets (so for example, some customers want to just SSH directly to hosts via the VPN connection).


// Propagate routes on route tables associated with private subnets
const routePropagation = new CfnVPNGatewayRoutePropagation(this, 'RoutePropagation', {
routeTableIds: (this.privateSubnets as VpcPrivateSubnet[]).map(subnet => subnet.routeTableId),
Copy link
Contributor

Choose a reason for hiding this comment

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

We should consider allowing an option to allow for subnetgroups to be chosen by the user of this to decide what to propogate - there are reasons you might want to route public (and isolated)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, on it.

* The range of inside IP addresses for the tunnel. Any specified CIDR blocks must be
* unique across all VPN connections that use the same virtual private gateway.
*/
tunnelInsideCidr: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Both things here are independently optional https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-vpnconnection-vpntunneloptionsspecification.html and so one might want to set one and not the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will fix.

/**
* Tunnel options for the VPN connection.
*/
vpnTunnelOptions?: VpnTunnelOption[];
Copy link
Contributor

Choose a reason for hiding this comment

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

Tests don't appear to cover this.

@eladb
Copy link
Contributor

eladb commented Mar 4, 2019

@leepa are you happy with this? Can we merge?

@leepa
Copy link
Contributor

leepa commented Mar 4, 2019

@eladb if the tests are passing, the changes look good!

@eladb
Copy link
Contributor

eladb commented Mar 4, 2019

@jogold may I ask that you write up a nice PR description so we can use as a commit message?

@jogold
Copy link
Contributor Author

jogold commented Mar 4, 2019

@eladb updated description, is this ok?

@eladb eladb merged commit e150648 into aws:master Mar 4, 2019
@eladb
Copy link
Contributor

eladb commented Mar 4, 2019

Perfect. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants