Skip to content

Commit

Permalink
fix: fix issue preventing destroy of vpn routes (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
ocofaigh committed Jul 31, 2023
1 parent 069ccc2 commit c82a2e0
Show file tree
Hide file tree
Showing 38 changed files with 655 additions and 250 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ jobs:
call-terraform-ci-pipeline:
uses: terraform-ibm-modules/common-pipeline-assets/.github/workflows/common-terraform-module-ci-v2.yml@v1.17.0
secrets: inherit
with:
craSCCv2: true
craConfigYamlFile: "cra-config.yaml"
2 changes: 1 addition & 1 deletion .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "go.sum|^.secrets.baseline$",
"lines": null
},
"generated_at": "2023-06-08T12:54:21Z",
"generated_at": "2023-06-09T12:54:21Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down
1 change: 0 additions & 1 deletion Brewfile

This file was deleted.

74 changes: 31 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
<!-- BEGIN MODULE HOOK -->

<!-- Update the title to match the module name and add a description -->
# Client to Site VPN Module
<!-- UPDATE BADGE: Update the link for the following badge-->

[![Stable (With quality checks)](https://img.shields.io/badge/Status-Stable%20(With%20quality%20checks)-green?style=plastic)](https://terraform-ibm-modules.github.io/documentation/#/badge-status)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
[![latest release](https://img.shields.io/github/v/release/terraform-ibm-modules/terraform-ibm-module-template?logo=GitHub&sort=semver)](https://github.com/terraform-ibm-modules/terraform-ibm-client-to-site-vpn/releases/latest)
[![latest release](https://img.shields.io/github/v/release/terraform-ibm-modules/terraform-ibm-client-to-site-vpn?logo=GitHub&sort=semver)](https://github.com/terraform-ibm-modules/terraform-ibm-client-to-site-vpn/releases/latest)
[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

<!-- Remove the content in this H2 heading after completing the steps -->

This module automates the provisioning of a client-to-site VPN in a VPC cluster. For more information, see [About client-to-site VPN servers](https://cloud.ibm.com/docs/vpc?topic=vpc-vpn-client-to-site-overview) in the IBM Cloud docs.

## Network topology
<!-- BEGIN OVERVIEW HOOK -->
## Overview
* [terraform-ibm-client-to-site-vpn](#terraform-ibm-client-to-site-vpn)
* [Examples](./examples)
* [Basic example creating a standalone VPN server](./examples/basic)
* [Client-To-Site VPN add-on for landing zone](./examples/landing-zone)
* [Complete example creating a high availability VPN server](./examples/ha-complete)
* [Contributing](#contributing)

## terraform-ibm-client-to-site-vpn
<!-- END OVERVIEW HOOK -->

### Network topology

The VPN server is deployed in a selected multizone (MZR) region and VPC.

![img.png](docs/client-to-site-vpn-topology.png)

## Considerations
### Considerations

- **Scaling considerations**: The aggregation bandwidth for the stand-alone VPN is 600 Mbps and for the high availability VPN is 1200 Mbps.
- **Client IPv4 address pool**: The client-to-site VPN assigns an IP address to the connecting client from the client IPv4 address pool (CIDR Range). This CIDR range must not overlap with VPC address prefixes.
Expand All @@ -28,7 +35,7 @@ The VPN server is deployed in a selected multizone (MZR) region and VPC.
- **VPN Client authentication**: The client authentication method is required at the time of provisioning of the VPN server. The VPN server supports "username" based authentication. There is no support for the "certificate" based authentication at this point of time.
- **Split tunnel mode**: This module provisions a client-to-site VPN with the split tunnel mode. When the VPN connection is set up, an encrypted tunnel is created over the internet to the VPN server. The split tunnel mode supports sending private traffic that is destined to the VPC inside the VPN tunnel and sending public traffic (internet traffic) outside the VPN tunnel.

## Setting up a client VPN environment and connecting to a VPN server
### Setting up a client VPN environment and connecting to a VPN server

This module has an option to provision access group, policy and users to connect to the VPN when `create_policy` flag is true. Provide list of users needed Client to Site VPN access in the `cts_vpn_access_group_users` variable.

Expand All @@ -40,52 +47,34 @@ Once Client to Site VPN is deployed with access groups, follow these steps:
1. Add users to the access group either in IAM dashboard or by adding users' email id to `var.vpn_client_access_group_users`.
1. Go to https://iam.cloud.ibm.com/identity/passcode to generate the passcode.

### VPN server limitations
#### VPN server limitations

For more information about the current VPN server limitations, see [VPN server limitations](https://cloud.ibm.com/docs/vpc?topic=vpc-vpn-client-vpn-limitations&interface=ui).

## Usage
### Usage

<!-- Add sample usage of the module itself in the following code block -->
```hcl
# Replace "master" with a GIT release version to lock into a specific release
module "client-to-site-vpn" {
source = "terraform-ibm-modules/client-to-site-vpn/ibm"
version = "latest" # Replace "latest" with a release version to lock into a specific release
server_cert_crn = "crn:<...>" # CRN to a server secret or certificate in Secrets Manager
vpn_gateway_name = "example-vpn"
resource_group_id = "65xxxxxxxxxxxxxxxa3fd"
source = "terraform-ibm-modules/client-to-site-vpn/ibm"
version = "XXX" # Replace "XXX" with a release version to lock into a specific release
server_cert_crn = "crn:<...>" # CRN to a server secret or certificate in Secrets Manager
vpn_gateway_name = "example-vpn"
resource_group_id = "65xxxxxxxxxxxxxxxa3fd"
secret_manager_instance_guid = "839fxxxx-xxxx-xxxx-xxxx-xxxxxxx913b9"
subnet_ids = ["0726-ec96c7cd-46f4-4969-9009-7613f8e9e93"] # A list of IDs of subnets dedicated to the VPN in the VPC.
subnet_ids = ["0726-ec96c7cd-46f4-4969-9009-7613f8e9e93"] # A list of IDs of subnets dedicated to the VPN in the VPC.
}
```

## Required IAM access policies
### Required IAM access policies
You need the following permissions to run this module.

<!--
Update these sample permissions, following this format. Replace the sample
Cloud service name and roles with the information in the console at
Manage > Access (IAM) > Access groups > Access policies.
-->

- IAM services
- **VPC Infrastructure** services
- `Editor` platform access
- **No service access**
- **Resource Group** \<your resource group>
- `Viewer` resource group access

For more information about the access you need to run all the GoldenEye modules, see [GoldenEye IAM permissions](https://github.ibm.com/GoldenEye/documentation/blob/master/goldeneye-iam-permissions.md).

<!-- END MODULE HOOK -->
<!-- BEGIN EXAMPLES HOOK -->
## Examples

- [ High-availability mode Client to Site VPN example](examples/highavailability_mode)
- [ Client-To-Site VPN add-on for landing zone](examples/landing-zone)
<!-- END EXAMPLES HOOK -->

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
### Requirements

Expand Down Expand Up @@ -117,16 +106,16 @@ No modules.
| <a name="input_client_auth_methods"></a> [client\_auth\_methods](#input\_client\_auth\_methods) | Client authentication method | `string` | `"username"` | no |
| <a name="input_client_dns_server_ips"></a> [client\_dns\_server\_ips](#input\_client\_dns\_server\_ips) | DNS server addresses that will be provided to VPN clients connected to this VPN server | `list(string)` | `[]` | no |
| <a name="input_client_idle_timeout"></a> [client\_idle\_timeout](#input\_client\_idle\_timeout) | The seconds a VPN client can be idle before this VPN server will disconnect it. Default set to 30m (1800 secs). Specify 0 to prevent the server from disconnecting idle clients. | `number` | `1800` | no |
| <a name="input_client_ip_pool"></a> [client\_ip\_pool](#input\_client\_ip\_pool) | Client IP pool for the VPN | `string` | `"10.0.0.0/20"` | no |
| <a name="input_client_ip_pool"></a> [client\_ip\_pool](#input\_client\_ip\_pool) | The VPN client IPv4 address pool, expressed in CIDR format. The request must not overlap with any existing address prefixes in the VPC or any of the following reserved address ranges: - 127.0.0.0/8 (IPv4 loopback addresses) - 161.26.0.0/16 (IBM services) - 166.8.0.0/14 (Cloud Service Endpoints) - 169.254.0.0/16 (IPv4 link-local addresses) - 224.0.0.0/4 (IPv4 multicast addresses). The prefix length of the client IP address pool's CIDR must be between /9 (8,388,608 addresses) and /22 (1024 addresses). A CIDR block that contains twice the number of IP addresses that are required to enable the maximum number of concurrent connections is recommended. | `string` | `"10.0.0.0/20"` | no |
| <a name="input_create_policy"></a> [create\_policy](#input\_create\_policy) | Set to true to create a new access group (using the value of var.access\_group\_name) with a VPN Client role | `bool` | `true` | no |
| <a name="input_create_s2s_auth_policy"></a> [create\_s2s\_auth\_policy](#input\_create\_s2s\_auth\_policy) | Create IAM Service to Service Authorization to allow communication between all VPN Servers (scoped to the given resource group) and the given Secrets Manager instance. Currently not possible to scope the policy to the exact VPN server ID since the policy is needed before the instance exists as it uses the cert stored in secrets manager during the provisioning process. | `bool` | `true` | no |
| <a name="input_enable_split_tunneling"></a> [enable\_split\_tunneling](#input\_enable\_split\_tunneling) | Enables split tunnel mode for the Client to Site VPN Creation | `bool` | `true` | no |
| <a name="input_resource_group_id"></a> [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group to use when creating the VPC | `string` | n/a | yes |
| <a name="input_enable_split_tunneling"></a> [enable\_split\_tunneling](#input\_enable\_split\_tunneling) | Enables split tunnel mode for the Client to Site VPN server | `bool` | `true` | no |
| <a name="input_resource_group_id"></a> [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group to use when creating the VPN server | `string` | n/a | yes |
| <a name="input_secrets_manager_id"></a> [secrets\_manager\_id](#input\_secrets\_manager\_id) | ID of the Secrets Manager that contains the certificate to use for the VPN, only required when create\_s2s\_auth\_policy is true. | `string` | `null` | no |
| <a name="input_server_cert_crn"></a> [server\_cert\_crn](#input\_server\_cert\_crn) | CRN of a secret in Secrets Manager that contains the certificate to use for the VPN | `string` | n/a | yes |
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | List must have at least 1 subnet ID for standalone VPN and at least 2 subnet IDs for the High Availability mode. | `list(string)` | n/a | yes |
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | List of subnet IDs to provision this VPN server in. List must have at least 1 subnet ID for standalone VPN and at least 2 subnet IDs for the High Availability mode. | `list(string)` | n/a | yes |
| <a name="input_vpn_client_access_group_users"></a> [vpn\_client\_access\_group\_users](#input\_vpn\_client\_access\_group\_users) | List of users to optionally add to the Client to Site VPN Access Group if var.create\_policy is true | `list(string)` | `[]` | no |
| <a name="input_vpn_gateway_name"></a> [vpn\_gateway\_name](#input\_vpn\_gateway\_name) | Name of the VPN | `string` | `"test"` | no |
| <a name="input_vpn_gateway_name"></a> [vpn\_gateway\_name](#input\_vpn\_gateway\_name) | The user-defined name for the VPN server. If unspecified, the name will be a hyphenated list of randomly-selected words. Names must be unique within the VPC the VPN server is serving. | `string` | n/a | yes |
| <a name="input_vpn_server_routes"></a> [vpn\_server\_routes](#input\_vpn\_server\_routes) | Map of server routes to be added to created VPN server. | <pre>map(object({<br> destination = string<br> action = string<br> }))</pre> | `{}` | no |

### Outputs
Expand All @@ -138,7 +127,6 @@ No modules.
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

<!-- BEGIN CONTRIBUTING HOOK -->

<!-- Leave this section as is so that your module has a link to local development environment set up steps for contributors to follow -->
## Contributing

Expand Down
1 change: 0 additions & 1 deletion catalogValidationValues.json.template

This file was deleted.

5 changes: 5 additions & 0 deletions cra-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# More info about this file at https://github.com/terraform-ibm-modules/common-pipeline-assets/blob/main/.github/workflows/terraform-test-pipeline.md#cra-config-yaml
version: "v1"
CRA_TARGETS:
- CRA_TARGET: "examples/ha-complete" # Target directory for CRA scan. If not provided, the CRA Scan will not be run.
CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json`
3 changes: 3 additions & 0 deletions cra-tf-validate-ignore-rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"scc_rules": []
}
12 changes: 12 additions & 0 deletions examples/basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Basic example creating a standalone VPN server

Requirements:
- An existing Secrets Manager instance configured with the private cert engine
- A Certificate Template in the Secrets Manager instance to use for private cert creation.

This example will:
- Create a new resource group if one is not passed in.
- Create a new secret group in the Secrets Manager instance provided.
- Create a new private cert and place it in a secret in the newly created secret group.
- Create a new VPC in the resource group and region provided.
- Create a standalone VPN server
99 changes: 99 additions & 0 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
########################################################################################################################
# Resource Group
########################################################################################################################

module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.0.6"
# if an existing resource group is not set (null) create a new one using prefix
resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null
existing_resource_group_name = var.resource_group
}

########################################################################################################################
## Generate Private Cert using Secrets Manager
########################################################################################################################

# Create a secret group to place the certificate in
module "secrets_manager_group" {
source = "terraform-ibm-modules/secrets-manager-secret-group/ibm"
version = "1.0.0"
region = var.secrets_manager_region
secrets_manager_guid = var.secrets_manager_guid
secret_group_name = "${var.prefix}-certs"
secret_group_description = "A secret group to store private certs"
providers = {
ibm = ibm.ibm-sm
}
}

# Create the private cert
module "secrets_manager_private_certificate" {
source = "terraform-ibm-modules/secrets-manager-private-cert/ibm"
version = "1.0.1"
cert_name = "${var.prefix}-cts-vpn-private-cert"
cert_description = "an example private cert"
cert_template = var.certificate_template_name
cert_secrets_group_id = module.secrets_manager_group.secret_group_id
cert_common_name = "example.com"
secrets_manager_guid = var.secrets_manager_guid
secrets_manager_region = var.secrets_manager_region
providers = {
ibm = ibm.ibm-sm
}
}

########################################################################################################################
## VPC
########################################################################################################################

# Minimal VPC for illustration purpose: 1 subnet across 1 availability zone
module "basic_vpc" {
source = "terraform-ibm-modules/landing-zone-vpc/ibm"
version = "7.3.1"
resource_group_id = module.resource_group.resource_group_id
region = var.region
name = "vpc"
prefix = var.prefix
tags = var.resource_tags
enable_vpc_flow_logs = false
use_public_gateways = {
zone-1 = false
zone-2 = false
zone-3 = false
}
subnets = {
zone-1 = [
{
name = "subnet-a"
cidr = "10.10.10.0/24"
public_gateway = false
acl_name = "vpc-acl"
}
],
zone-2 = []
zone-3 = []
}
}

data "ibm_is_vpc" "basic_vpc" {
depends_on = [module.basic_vpc] # Explicit "depends_on" here to wait for the full subnet creations
identifier = module.basic_vpc.vpc_id
}

########################################################################################################################
## VPN
########################################################################################################################

module "vpn" {
source = "../.."
server_cert_crn = module.secrets_manager_private_certificate.secret_crn
vpn_gateway_name = "${var.prefix}-c2s-vpn"
resource_group_id = module.resource_group.resource_group_id
subnet_ids = slice([for subnet in data.ibm_is_vpc.basic_vpc.subnets : subnet["id"]], 0, 1)
create_policy = var.create_policy
vpn_client_access_group_users = var.vpn_client_access_group_users
access_group_name = "${var.prefix}-access-group"
secrets_manager_id = var.secrets_manager_guid
vpn_server_routes = var.vpn_server_routes
}
File renamed without changes.
10 changes: 10 additions & 0 deletions examples/basic/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.secrets_manager_region
alias = "ibm-sm"
}

provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
}
70 changes: 70 additions & 0 deletions examples/basic/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
variable "ibmcloud_api_key" {
type = string
description = "API key that is associated with the account to use."
sensitive = true
}

variable "region" {
type = string
description = "Region to provision all resources created by this example."
default = "us-south"
}

variable "prefix" {
type = string
description = "Prefix to append to all resources created by this example"
default = "tf-ibm"
}

variable "resource_group" {
type = string
description = "Name of the resource group to use for this example. If not set, a resource group is created."
default = null
}

variable "resource_tags" {
type = list(string)
description = "Optional list of tags to add to the created resources."
default = []
}

variable "secrets_manager_guid" {
type = string
description = "Existing Secrets Manager GUID. The existing Secret Manager instance must have private certificate engine configured."
}

variable "secrets_manager_region" {
type = string
description = "The region in which the Secrets Manager instance exists."
}

variable "certificate_template_name" {
type = string
description = "Name of an existing Certificate Template in the Secrets Manager instance to use for private cert creation."
}

variable "create_policy" {
description = "Set to true to create a new access group (using the value of var.access_group_name) with a VPN Client role"
type = bool
default = true
}

variable "vpn_client_access_group_users" {
description = "List of users in the Client to Site VPN Access Group"
type = list(string)
default = []
}

variable "vpn_server_routes" {
type = map(object({
destination = string
action = string
}))
description = "Map of server routes to be added to created VPN server."
default = {
"vpc-10" = {
destination = "10.0.0.0/8"
action = "deliver"
}
}
}
Loading

0 comments on commit c82a2e0

Please sign in to comment.