Note: The OpenVPN tools offer partial Ubuntu 20.04 support, but have not been tested fully for compatibility with other Gruntwork modules. For the release notes, checkout this PR that adds support for Ubuntu 20.04. For issues or contributions, please follow the Contributions section of this README, or simply raise a Github issue.
WARNING: Launch Configurations:Launch configurations are being phased out in favor of Launch Templates. Before upgrading to the latest release please be sure to test and plan any changes to infrastructure that may be impacted. Launch templates are being introduced in PR #229
Architecture Overview
Server
The openvpn-server module will deploy a single server into an Auto Scaling Group (ASG) for redundancy
purposes. Should the server fail, a new server will be automatically provisioned by the ASG. Upon initial boot, the
init-openvpn module will establish a new public key infrastructure (PKI), including
a Certificate Authority (CA), server certificate and a certificate revocation list. These assets will then be backed up
to an S3 bucket and encrypted for protection should a server failure occur.
In a failure scenario, when a replacement server is started by the ASG, the PKI will be automatically restored from the
S3 bucket ensuring the previously-issued client certificates will continue to function.
Client Certificate Requests
Users who are members of the proper IAM group will use the openvpn-admin utility to request
a new certificate. Behind the scenes, this certificate request will be sent to the server via an SQS queue, will be signed by
the server and an OpenVPN client configuration file (.ovpn) with the certificates embedded will be written to disk on the
requestor's workstation. This .ovpn file can then be imported into any number of popular OpenVPN clients.
Client Certificate Revocations
Users who are members of the proper IAM group will be allowed to use the same openvpn-admin
utility to revoke an existing user's certificate. Behind the scenes, the revocation requests will be sent to the server
via an SQS queue, the certificate will be revoked and a confirmation will be sent to back to the requestor's workstation.
List Client Certificates
Users who are members of the proper IAM group will be allowed to use the same openvpn-admin
utility to getting a list of valid certificate. Behind the scenes, the list requests will be sent to the server
via an SQS queue, the list of valid certificates will be sent to back to the requestor's workstation.
Usage with multiple AWS accounts
If your IAM users are defined in one AWS account (e.g., security account) and the OpenVPN server is deployed in another
account (e.g., the dev or prod account), then in order for users to be able to request or revoke OpenVPN certificates,
they will need access to the SQS queues in the account with the OpenVPN server. When deploying the openvpn-server
module, you can specify the ARNs of the AWS account where IAM users are defined using the
external_account_arns parameter, and the module will create two IAM roles—one for users and one for admins—that can be
assumed by users in those accounts to get access to the SQS queues. See the how to switch between accounts
documentation
for instructions on assuming IAM roles in other AWS accounts.
Connecting to multiple VPNs
Your VPN users may have problems connecting to multiple VPNs at the same time, unless you follow these best practices:
Make sure that your VPC CIDRs do not overlap.
Make sure that your VPN subnet CIDRs do not overlap. For example, use 172.16.1.0 for Dev, 172.16.2.0 for Prod,
and so on.
Make sure that your openvpn-server module's user-data/user-data.sh includes --search-domain "${search_domain}"
in its arguments to init-openvpn, and pass the appropriate search domain in to the user data template object.
See the example here for details.
Use Viscosity rather than Tunnelblick.
Tunnelblick does not support setting DNS nameservers when connecting to multiple VPNs at the same time,
and suffers from a bug that clobbers the state of your
internet connection if you ever connect to more than one VPN at a time.
How to use this repo (for learning and testing)?
⚠️ The following steps are recommended only for learning and testing purposes. If you need to setup OpenVPN and use this module for a production environment, or anything other than learning and testing purposes, please refer to our Service Catalog and the Production use section below.
On Tunnelblick, and most OpenVPN clients, you should be able to choose full or split tunnel mode (see what this is here).
This module should be configured to use split tunnel mode in favour of directing only the relevant traffic to your OpenVPN Server and hence VPC. This is the default option that might help you save on the costs of running the OpenVPN server.
In short, split tunnel mode will enable you to only direct certain traffic to your OpenVPN server, and leave the rest as is through the public Internet, and full tunnel mode means all your traffic is getting routed through the VPN server. If you've opted in for the latter, your machine will show you a different than the usual public IP address. You can Check what your IP is here..
Try getting a list of valid certificates as an OpenVPN admin
See the examples folder for sample code to build the openvpn-admin binary, a packer template to build an AMI and Terraform code to launch everything necessary to run OpenVPN in your AWS environment.
You can follow the openvpn-host or openvpn-host-duo example to deploy a ready-made OpenVPN host into your AWS infrastructure. These examples are best for learning and experimenting on non-production environments.
At Gruntwork, we've taken the thousands of hours we spent building infrastructure on AWS and
condensed all that experience and code into pre-built packages or modules. Each module is a battle-tested,
best-practices definition of a piece of infrastructure, such as a VPC, ECS cluster, or an Auto Scaling Group. Modules
are versioned using Semantic Versioning to allow Gruntwork clients to keep up to date with the
latest infrastructure best practices in a systematic way.
To use a module in your Terraform templates, create a module resource and set its source field to the Git URL of
this repo. You should also set the ref parameter so you're fixed to a specific version of this repo, as the main
branch may have backwards incompatible changes (see module
sources).
For example, to use v1.0.0 of the openvpn module, you would add the following:
module"openvpn-server" {
source = "git::git@github.com:gruntwork-io/module-openvpn.git//modules/openvpn-server?ref=v1.0.0"// set the parameters for the OpenVPN module
}
Note: the double slash (//) is intentional and required. It's part of Terraform's Git syntax (see module
sources).
See the module's documentation and vars.tf file for all the parameters you can set. Run terraform get -update to
pull the latest version of this module from this repo before runnin gthe standard terraform plan and
terraform apply commands.
Using scripts & binaries
You can install the scripts and binaries in the modules folder of any repo using the Gruntwork
Installer. For example, if the scripts you want to install are
in the modules/mongodb-scripts folder of the https://github.com/gruntwork-io/terraform-aws-mongodb repo, you could install them
as follows:
See the docs for each script & binary for detailed instructions on how to use them.
Developing a module
Versioning
We are following the principles of Semantic Versioning. During initial development, the major
version is to 0 (e.g., 0.x.y), which indicates the code does not yet have a stable API. Once we hit 1.0.0, we will
follow these rules:
Increment the patch version for backwards-compatible bug fixes (e.g., v1.0.8 -> v1.0.9).
Increment the minor version for new features that are backwards-compatible (e.g., v1.0.8 -> v1.1.0).
Increment the major version for any backwards-incompatible changes (e.g. v1.0.8 -> v2.0.0).
The version is defined using Git tags. Use GitHub to create a release, which will have the effect of adding a git tag.
Checkout this PR that adds support for Ubuntu 20.04
Update the conditional logic in the init-vpn & install-vpnbin/install.sh scripts to allow the required OS distro. Other modules may also need updating.
Update the packer example to have a configuration for the new OS build
Use Packer to create a new AMI.
Apply some of the example terraform code (e.g. openvpn-host).
SSH into the EC2 instance and see if there's any error logs - e.g. in the user-data log.
Test by requesting a new certificate from the server.
License
Please see LICENSE.txt for details on how the code in this repo is licensed.
ToDo
Convert to CIDR format for parameters
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"8cb66764d1e661c0de1108136b13f86c742a2185"},{"name":"post-upgrade-test-results.sh","path":".circleci/post-upgrade-test-results.sh","sha":"a4867e8fbdc334b7a90259568ee41ea577fbe764"},{"name":"set-upgrade-test-vars.sh","path":".circleci/set-upgrade-test-vars.sh","sha":"55fa38af236effd7fe855b62cb05186a381e5d6b"}]},{"name":".github","children":[{"name":"ISSUE_TEMPLATE","children":[{"name":"bug_report.md","path":".github/ISSUE_TEMPLATE/bug_report.md","sha":"d2e87e27c601e423865ed660ec697082470ca60f"},{"name":"feature_request.md","path":".github/ISSUE_TEMPLATE/feature_request.md","sha":"023a33099be2336476930c96e17ff1ba5dc55348"}]},{"name":"pull_request_template.md","path":".github/pull_request_template.md","sha":"6b100e40e323b5b07f40ed30616277c51c9f4b9e"}]},{"name":".gitignore","path":".gitignore","sha":"f9a6db7495ce4ee92aeada5e54697ecbc86eb89c"},{"name":".patcher","children":[{"name":"config.yaml","path":".patcher/config.yaml","sha":"2eefb5b855c4c2e4a9cf9fcb47a8d63dafe4de52"},{"name":"patches","children":[{"name":"aws-provider-4.x-2","children":[{"name":"bump_provider_3.75.1.sh","path":".patcher/patches/aws-provider-4.x-2/bump_provider_3.75.1.sh","sha":"539cffdeb53bfcdf3f9dea8e67d60b4d6b434428"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/aws-provider-4.x-2/create_script_for_terraform_init.sh","sha":"5a7355f52a3be6dcaa64fd3ef72fc14c30c35c8b"},{"name":"patch.yaml","path":".patcher/patches/aws-provider-4.x-2/patch.yaml","sha":"510b47e16c3e5dd84ace3260cb6a8c75f4015198"}]},{"name":"aws-provider-4.x","children":[{"name":"bump_provider_3.75.0.sh","path":".patcher/patches/aws-provider-4.x/bump_provider_3.75.0.sh","sha":"7a3efe13136cca239fed10ac79a8235db63b46c7"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/aws-provider-4.x/create_script_for_terraform_init.sh","sha":"c03c62ed4beb78e42ef6d3f3dbc3709eb27dafc3"},{"name":"patch.yaml","path":".patcher/patches/aws-provider-4.x/patch.yaml","sha":"cfbec2e13759e88d6324a4c310f989ca056157f1"}]},{"name":"disable-ebs-optimization","children":[{"name":"patch.yaml","path":".patcher/patches/disable-ebs-optimization/patch.yaml","sha":"75099c388c675cf342b9eac7e837a6c86ac8ccdc"}]},{"name":"iam-inline-policies","children":[{"name":"patch.yaml","path":".patcher/patches/iam-inline-policies/patch.yaml","sha":"360cb48539c3db8f40459a617ae3d2a3059da0a4"}]},{"name":"terraform-1.1-upgrade","children":[{"name":"bump_required_version.sh","path":".patcher/patches/terraform-1.1-upgrade/bump_required_version.sh","sha":"bb7bf58588214e9e09ed0128603234705d30a671"},{"name":"patch.yaml","path":".patcher/patches/terraform-1.1-upgrade/patch.yaml","sha":"151598d0d058c97f47066847e8426c4eabb1a6dc"}]}]}]},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"ef4c514168a04923df9033bb2ea77801b035eef5"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"3bc8a8c8ee6e939522f988c5407a5d62b2d4ac26"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"5ae97660cb6e3a07b61c971f1a25edf402e90f53"},{"name":"README.md","path":"README.md","sha":"8ec8852c1b89d97e42933c9556b611fac5d903e6","toggled":true},{"name":"examples","children":[{"name":"openvpn-host-duo","children":[{"name":"README.md","path":"examples/openvpn-host-duo/README.md","sha":"1a3065f058745f0f03fd74844ac4e872d52538de"},{"name":"main.tf","path":"examples/openvpn-host-duo/main.tf","sha":"69f3b99c4bd748394c93ed978888e6b5f5d08703"},{"name":"outputs.tf","path":"examples/openvpn-host-duo/outputs.tf","sha":"f527145f657a5a99d32c301c591f461f2230e3b9"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/openvpn-host-duo/user-data/user-data.sh","sha":"e1c6767746aa06d4562d267a4abd1223af970845"}]},{"name":"vars.tf","path":"examples/openvpn-host-duo/vars.tf","sha":"d43f199006f6ad686f73f7bce6b805269711aa73"}]},{"name":"openvpn-host","children":[{"name":"README.md","path":"examples/openvpn-host/README.md","sha":"677a151d20ac0d4267035548a85eb91d0f746aab"},{"name":"main.tf","path":"examples/openvpn-host/main.tf","sha":"f4241f13919df55e3ced280557eafc4ca8f39035"},{"name":"outputs.tf","path":"examples/openvpn-host/outputs.tf","sha":"f527145f657a5a99d32c301c591f461f2230e3b9"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/openvpn-host/user-data/user-data.sh","sha":"8d4f915eb25429792e47b7cedeb557093808dba6"}]},{"name":"vars.tf","path":"examples/openvpn-host/vars.tf","sha":"3ab726d7faf42a62c8ae0a8808cbf61190390737"}]},{"name":"packer-duo","children":[{"name":"README.md","path":"examples/packer-duo/README.md","sha":"d1fd05f3adaf4b6f14f625301dcb61cddc15339c"},{"name":"build.json","path":"examples/packer-duo/build.json","sha":"36ce23a888c904142c233880ff7da653a96d4430"}]},{"name":"packer","children":[{"name":"README.md","path":"examples/packer/README.md","sha":"343d485bc6605ff2eb9739f0e9efff1c73a4e390"},{"name":"build.json","path":"examples/packer/build.json","sha":"1637e4a7ada3473baf9515b510ab05d891ed6112"}]}]},{"name":"modules","children":[{"name":"backup-openvpn-pki","children":[{"name":"README.md","path":"modules/backup-openvpn-pki/README.md","sha":"d271084a97e3ea953afb0e9e690fac951bb6be6d"},{"name":"bin","children":[{"name":"backup-openvpn-pki","path":"modules/backup-openvpn-pki/bin/backup-openvpn-pki","sha":"e4333a5f7faded6b0e6367165f02789f5ccc83a4"}]},{"name":"install.sh","path":"modules/backup-openvpn-pki/install.sh","sha":"af225b1dcd43eaab802a9e8040b3d39e25dd46a0"}]},{"name":"init-openvpn","children":[{"name":"README.md","path":"modules/init-openvpn/README.md","sha":"3a55b2c92611085870730ea15d589723b31dc775"},{"name":"bin","children":[{"name":"init-openvpn","path":"modules/init-openvpn/bin/init-openvpn","sha":"6446e18cb12aa1f21cf565905a5e8fbdbabf98d9"}]},{"name":"install.sh","path":"modules/init-openvpn/install.sh","sha":"9a41f990f62b2a9b526edfa813075cff277e1312"}]},{"name":"install-openvpn","children":[{"name":"README.md","path":"modules/install-openvpn/README.md","sha":"6073ab56f3a3ca0a69ca949a8a1e6086d7797709"},{"name":"bin","children":[{"name":"install-openvpn","path":"modules/install-openvpn/bin/install-openvpn","sha":"ab1adf006d22bcb7e79f1dfa7f36be1c14d42961"}]},{"name":"files","children":[{"name":"before.rules","path":"modules/install-openvpn/files/before.rules","sha":"e9f11106dda0d258910a36d88b3cac05c0d85146"},{"name":"openvpn-client.ovpn","path":"modules/install-openvpn/files/openvpn-client.ovpn","sha":"3fe8af5d74c724399d2b2acaaac3e5d07889912f"},{"name":"ufw-default","path":"modules/install-openvpn/files/ufw-default","sha":"ff5e7f69b1f65a2760579d4aa7575b278273e56b"},{"name":"vars.local","path":"modules/install-openvpn/files/vars.local","sha":"b19ce7da2758a7792a05d7563201127f8b1542c9"}]},{"name":"install.sh","path":"modules/install-openvpn/install.sh","sha":"65c8ed227131e94e7db76f47093f05b953950d07"},{"name":"scripts","children":[{"name":"generate-wrapper.sh","path":"modules/install-openvpn/scripts/generate-wrapper.sh","sha":"34d49724be9c3555a886d3cf00cf9cdbcb2a43bf"},{"name":"revoke-wrapper.sh","path":"modules/install-openvpn/scripts/revoke-wrapper.sh","sha":"d158a871cdd70cfed92418b6618d81c6bef08bd7"}]}]},{"name":"openvpn-admin","children":[{"name":".dockerignore","path":"modules/openvpn-admin/.dockerignore","sha":"a725465aee245635a2bd129af54858ed32c84cb8"},{"name":"Dockerfile","path":"modules/openvpn-admin/Dockerfile","sha":"d8b2de7aeb782a31932157e3a4fb183333da4259"},{"name":"README.md","path":"modules/openvpn-admin/README.md","sha":"4a95e9a04a81c965c23b706bc99717d462ab0ca1"},{"name":"_ci","children":[{"name":"build-and-test.sh","path":"modules/openvpn-admin/_ci/build-and-test.sh","sha":"7b57f49d2a5cbce5f3e833c6e3dac767a90a92fa"},{"name":"test.sh","path":"modules/openvpn-admin/_ci/test.sh","sha":"ba48b9b10f31ca3f2e41ee3ce85e04d6ae289657"}]},{"name":"docker-compose.yml","path":"modules/openvpn-admin/docker-compose.yml","sha":"9a1c04848275d1a302063301d55b811aa0d666ed"},{"name":"go.mod","path":"modules/openvpn-admin/go.mod","sha":"1b1ff11c09a4ce6f241bbe25d603fef42d876c5c"},{"name":"go.sum","path":"modules/openvpn-admin/go.sum","sha":"937b7f96570f7130e5d7d69a8d6b03a1e0480e52"},{"name":"openvpn-request-flow-diagram.svg","path":"modules/openvpn-admin/openvpn-request-flow-diagram.svg","sha":"4c170df3fd6cf76d4c8e0bed7e1f2dbd98c08942"},{"name":"openvpn-revoke-flow-diagram.png","path":"modules/openvpn-admin/openvpn-revoke-flow-diagram.png","sha":"ccf48d05e3a492188900dfe73ea2fbc4eb3a3e29"},{"name":"scripts","children":[{"name":"build-linux-binary.sh","path":"modules/openvpn-admin/scripts/build-linux-binary.sh","sha":"732b01317a4f02bb7fb89d9be043c8d2d217a53a"},{"name":"run.sh","path":"modules/openvpn-admin/scripts/run.sh","sha":"bbcb7f9bdf8578561226954669cdb3e886093fcb"}]},{"name":"src","children":[{"name":"aws","children":[{"name":"iam","children":[{"name":"helper.go","path":"modules/openvpn-admin/src/aws/iam/helper.go","sha":"640b32ed9e02deab698ce60e80021d2881fb6297"}]},{"name":"imds","children":[{"name":"helper.go","path":"modules/openvpn-admin/src/aws/imds/helper.go","sha":"61ca786434b7ca1f8758a305e8f12f4e6ca12717"}]},{"name":"sqs","children":[{"name":"helper.go","path":"modules/openvpn-admin/src/aws/sqs/helper.go","sha":"866028cf594dd298253e660a1a31be817f0c8a04"},{"name":"queue.go","path":"modules/openvpn-admin/src/aws/sqs/queue.go","sha":"53b9c517bad2d88eed92d80f94870cde47af252a"}]}]},{"name":"cli","children":[{"name":"app.go","path":"modules/openvpn-admin/src/cli/app.go","sha":"0023ca64cba4e5df87432c6c098e2a0b6b803f81"},{"name":"commands","children":[{"name":"common","children":[{"name":"create.go","path":"modules/openvpn-admin/src/cli/commands/common/create.go","sha":"08ae181c113f08ae025bbf5f2d1a001aa207409e"},{"name":"list.go","path":"modules/openvpn-admin/src/cli/commands/common/list.go","sha":"68d1d9187440ec242cd24996c3e9787846232aa0"},{"name":"revoke.go","path":"modules/openvpn-admin/src/cli/commands/common/revoke.go","sha":"4e6905837543dc86a4cd09a8cbad4c62cbd6b5d7"}]},{"name":"list","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/list/action.go","sha":"a0172bef13e160136599532b7180f0498d40c8bc"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/list/command.go","sha":"5359a90dc353d11cb68ff308cc3f31d4c6c3c505"}]},{"name":"process-list","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/process-list/action.go","sha":"2497633bc47f42191269faf5040d9277aa582e9b"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/process-list/command.go","sha":"3b1e06d89f8e03f6230e72019840f1e85c42057a"}]},{"name":"process-requests","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/process-requests/action.go","sha":"92b6e2d55dee3a6d1e666efac0fc47c704bd4c08"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/process-requests/command.go","sha":"cb35bf252e02f57921bb265bc2ab35ff71358e59"}]},{"name":"process-revokes","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/process-revokes/action.go","sha":"40a9f75d1c9d9094418ccc9f7a4f5744c903c825"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/process-revokes/command.go","sha":"cd9dd70ca3878378cd6a8008b2f41edd20a64dba"}]},{"name":"request","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/request/action.go","sha":"550fefaf973985f7c79b7393d402dee601316dcf"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/request/command.go","sha":"ce353e2df43a6f7453dbe7ca4d2e14ab86517b7f"}]},{"name":"revoke","children":[{"name":"action.go","path":"modules/openvpn-admin/src/cli/commands/revoke/action.go","sha":"27afcd6ab06ace2b61ee27722d577d021adb86b0"},{"name":"command.go","path":"modules/openvpn-admin/src/cli/commands/revoke/command.go","sha":"28c1cee87599561371807a3ead35515c67376a8c"}]}]},{"name":"flags","children":[{"name":"errors.go","path":"modules/openvpn-admin/src/cli/flags/errors.go","sha":"64a7faa0c60b4d3591a2d91c3fea1f6504563066"},{"name":"flags.go","path":"modules/openvpn-admin/src/cli/flags/flags.go","sha":"c3129587514a57d7f7204cb6348014f5322667b3"},{"name":"helper.go","path":"modules/openvpn-admin/src/cli/flags/helper.go","sha":"8854d71d77a40c9f54024bc10dd738290d146fd2"}]}]},{"name":"log","children":[{"name":"exported.go","path":"modules/openvpn-admin/src/log/exported.go","sha":"fb6fedf429497cb6a2691f8b34d08d11b741be0e"},{"name":"formatter.go","path":"modules/openvpn-admin/src/log/formatter.go","sha":"ba905fe7e6ba33c50d9fffcfc0b22ad1bf568ca2"},{"name":"logger.go","path":"modules/openvpn-admin/src/log/logger.go","sha":"8a9765385ddbaa47ea6f830b393834900a68a305"}]},{"name":"main.go","path":"modules/openvpn-admin/src/main.go","sha":"8e6768c4a977519c712795e0de209a850f126dbc"},{"name":"network","children":[{"name":"mtu.go","path":"modules/openvpn-admin/src/network/mtu.go","sha":"eb4e42b45283d0f906414700ce9848495b62adaa"},{"name":"mtu_test.go","path":"modules/openvpn-admin/src/network/mtu_test.go","sha":"575f98be286e3e061d68666aed50f7fce2fdc0dd"},{"name":"ping_darwin.go","path":"modules/openvpn-admin/src/network/ping_darwin.go","sha":"c3d2c4d16e41bc96b29b16bf8099e8129c134a5d"},{"name":"ping_linux.go","path":"modules/openvpn-admin/src/network/ping_linux.go","sha":"076ec2ce8819056bfcdd71505dd5eb6c014fc7ce"},{"name":"ping_windows.go","path":"modules/openvpn-admin/src/network/ping_windows.go","sha":"92e5459631d4ab94d0918406a290b30b45718dfd"}]},{"name":"openvpn-admin","path":"modules/openvpn-admin/src/openvpn-admin","sha":"64a2930768b6d97f5820b7f3c5f24cb56cfab579"},{"name":"openvpn","children":[{"name":"db.go","path":"modules/openvpn-admin/src/openvpn/db.go","sha":"72984b37dec212d9855fa8cf189d924d0f36060e"},{"name":"profile.go","path":"modules/openvpn-admin/src/openvpn/profile.go","sha":"b2629f5f7efd1bf44a3732a0d865dd75cc753f02"},{"name":"profile_test.go","path":"modules/openvpn-admin/src/openvpn/profile_test.go","sha":"b21f08b07e77d0564a0975d6bb96b0a23013b5e1"},{"name":"testdata","children":[{"name":"etc-openvpn-index.txt","path":"modules/openvpn-admin/src/openvpn/testdata/etc-openvpn-index.txt","sha":"c58e8a79de5b25f271a997fdc9c8ff43835dcced"}]},{"name":"util.go","path":"modules/openvpn-admin/src/openvpn/util.go","sha":"39eeb332fa825667f0c0e51c9e997a15995fcb12"}]},{"name":"shell","children":[{"name":"cmd.go","path":"modules/openvpn-admin/src/shell/cmd.go","sha":"2213dcd1b78f6f4cf4cb684ca50495cb9cb0f5bd"},{"name":"cmd_test.go","path":"modules/openvpn-admin/src/shell/cmd_test.go","sha":"e8503476253b21f03fa75f1dbd8a8c046b72311b"}]}]}]},{"name":"openvpn-server","children":[{"name":"README.md","path":"modules/openvpn-server/README.md","sha":"87b5f1fe56a78b2310fd3a0232d68da34ba0ab07"},{"name":"main.tf","path":"modules/openvpn-server/main.tf","sha":"af041fddce7eb019becdb8ede4f684d5b4fa24a9"},{"name":"outputs.tf","path":"modules/openvpn-server/outputs.tf","sha":"e8603a2fca1aaf0629c90323e1638bbe2898cf81"},{"name":"vars.tf","path":"modules/openvpn-server/vars.tf","sha":"ea7b1d831a002c406bcb2c3affe228c7f73834f1"}]},{"name":"start-openvpn-admin","children":[{"name":"README.md","path":"modules/start-openvpn-admin/README.md","sha":"0c9902a49939a60e80a57fa0f39bfbb50eafd40a"},{"name":"bin","children":[{"name":"run-process-lists","path":"modules/start-openvpn-admin/bin/run-process-lists","sha":"39a46d5e65063bc53d64b311dd1619d6c7215471"},{"name":"run-process-requests","path":"modules/start-openvpn-admin/bin/run-process-requests","sha":"b17582ec08c2f947114409f8423e1ec6a54aea77"},{"name":"run-process-revokes","path":"modules/start-openvpn-admin/bin/run-process-revokes","sha":"48c363ab23fd311d775e8a306ff927ec9371dc22"}]},{"name":"install.sh","path":"modules/start-openvpn-admin/install.sh","sha":"60322825cdd2c070f068577da31a8fff0992df80"}]}]},{"name":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","path":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","sha":"ae586c0fe830819580e1009d41a9074f16e65bed"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"0b09878429ef9ed0b43b812a3947ba8e1264d107"},{"name":"go.mod","path":"test/go.mod","sha":"7f5d4aafd56f29429596727e9967721216aaa052"},{"name":"go.sum","path":"test/go.sum","sha":"4aa2f6ffdab978874596226f0a807db7a532a131"},{"name":"local-test","children":[{"name":"docker-compose.yml","path":"test/local-test/docker-compose.yml","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"}]},{"name":"openvpn_test.go","path":"test/openvpn_test.go","sha":"5aad9c1e63b411b7d6de5ebe16d8e463f57ca3ee"},{"name":"test_helpers.go","path":"test/test_helpers.go","sha":"f250a2ee29e5c55a8fb97359083a565846575fad"},{"name":"upgrades","children":[{"name":"upgrade_test.go","path":"test/upgrades/upgrade_test.go","sha":"45439270e11feb53a18c951ae3b8503d55ab753d"}]},{"name":"validation","children":[{"name":"validate_all_modules_and_examples_test.go","path":"test/validation/validate_all_modules_and_examples_test.go","sha":"33d73c385b64c4fc870033e99427e683c31dc45a"}]}]}]},"detailsContent":"<p><img src=\"https://img.shields.io/badge/tf-%3E%3D1.1.0-blue.svg\" alt=\"Terraform Version\" class=\"preview__body--diagram\"></p>\n<h1 class=\"preview__body--title\" id=\"open-vpn-package-infrastructure-package\">Open VPN Package Infrastructure Package</h1><div class=\"preview__body--border\"></div><p>This repo contains modules for running a production-ready OpenVPN server and managing OpenVPN user accounts. The modules are:</p>\n<ul>\n<li><a href=\"/repos/v0.27.4/package-openvpn/modules/init-openvpn\" class=\"preview__body--description--blue\">init-openvpn</a> - initializes the public key infrastructure (PKI) via OpenSSL for use by OpenVPN. Designed to be run via user-data on boot</li>\n<li><a href=\"/repos/v0.27.4/package-openvpn/modules/install-openvpn\" class=\"preview__body--description--blue\">install-openvpn</a> - Scripts to install the OpenVPN image in a packer-generated AMI</li>\n<li><a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-admin\" class=\"preview__body--description--blue\">openvpn-admin</a> - A command-line utility to request, revoke certificates and getting a list valid certificates and to process those requests</li>\n<li><a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-server\" class=\"preview__body--description--blue\">openvpn-server</a> - Terraform templates that deploy OpenVPN</li>\n<li><a href=\"/repos/v0.27.4/package-openvpn/modules/start-openvpn-admin\" class=\"preview__body--description--blue\">start-openvpn-admin</a> - Scripts to start <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-admin\" class=\"preview__body--description--blue\">openvpn-admin</a> on the <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-server\" class=\"preview__body--description--blue\">openvpn-server</a> in order to process certificate requests and revocations</li>\n</ul>\n<p><strong>Note:</strong> The OpenVPN tools offer partial Ubuntu 20.04 support, but have not been tested fully for compatibility with other Gruntwork modules. For the release notes, <em>checkout <a href=\"/repos/terraform-aws-openvpn\" class=\"preview__body--description--blue\">this PR</a> that adds support for Ubuntu 20.04</em>. For issues or contributions, please follow the Contributions section of this README, or simply raise a Github issue.</p>\n<p><strong>WARNING: Launch Configurations:</strong> <a href=\"https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html\" class=\"preview__body--description--blue\" target=\"_blank\">Launch configurations</a> are being phased out in favor of <a href=\"https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-templates.html\" class=\"preview__body--description--blue\" target=\"_blank\">Launch Templates</a>. Before upgrading to the latest release please be sure to test and plan any changes to infrastructure that may be impacted. Launch templates are being introduced in <a href=\"/repos/terraform-aws-openvpn\" class=\"preview__body--description--blue\">PR #229</a></p>\n<h2 class=\"preview__body--subtitle\" id=\"architecture-overview\">Architecture Overview</h2>\n<h4 id=\"server\">Server</h4>\n<p>The <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-server\" class=\"preview__body--description--blue\">openvpn-server</a> module will deploy a single server into an Auto Scaling Group (ASG) for redundancy\npurposes. Should the server fail, a new server will be automatically provisioned by the ASG. Upon initial boot, the\n<a href=\"/repos/v0.27.4/package-openvpn/modules/init-openvpn\" class=\"preview__body--description--blue\">init-openvpn</a> module will establish a new public key infrastructure (PKI), including\na Certificate Authority (CA), server certificate and a certificate revocation list. These assets will then be backed up\nto an S3 bucket and encrypted for protection should a server failure occur.</p>\n<p>In a failure scenario, when a replacement server is started by the ASG, the PKI will be automatically restored from the\nS3 bucket ensuring the previously-issued client certificates will continue to function.</p>\n<h4 id=\"client-certificate-requests\">Client Certificate Requests</h4>\n<p>Users who are members of the proper IAM group will use the <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-admin\" class=\"preview__body--description--blue\">openvpn-admin</a> utility to request\na new certificate. Behind the scenes, this certificate request will be sent to the server via an SQS queue, will be signed by\nthe server and an OpenVPN client configuration file (.ovpn) with the certificates embedded will be written to disk on the\nrequestor's workstation. This <code>.ovpn</code> file can then be imported into any number of popular OpenVPN clients.</p>\n<h4 id=\"client-certificate-revocations\">Client Certificate Revocations</h4>\n<p>Users who are members of the proper IAM group will be allowed to use the same <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-admin\" class=\"preview__body--description--blue\">openvpn-admin</a>\nutility to revoke an existing user's certificate. Behind the scenes, the revocation requests will be sent to the server\nvia an SQS queue, the certificate will be revoked and a confirmation will be sent to back to the requestor's workstation.</p>\n<h4 id=\"list-client-certificates\">List Client Certificates</h4>\n<p>Users who are members of the proper IAM group will be allowed to use the same <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-admin\" class=\"preview__body--description--blue\">openvpn-admin</a>\nutility to getting a list of valid certificate. Behind the scenes, the list requests will be sent to the server\nvia an SQS queue, the list of valid certificates will be sent to back to the requestor's workstation.</p>\n<h4 id=\"usage-with-multiple-aws-accounts\">Usage with multiple AWS accounts</h4>\n<p>If your IAM users are defined in one AWS account (e.g., security account) and the OpenVPN server is deployed in another\naccount (e.g., the dev or prod account), then in order for users to be able to request or revoke OpenVPN certificates,\nthey will need access to the SQS queues in the account with the OpenVPN server. When deploying the <a href=\"/repos/v0.27.4/package-openvpn/modules/openvpn-server\" class=\"preview__body--description--blue\">openvpn-server\nmodule</a>, you can specify the ARNs of the AWS account where IAM users are defined using the\n<code>external_account_arns</code> parameter, and the module will create two IAM roles—one for users and one for admins—that can be\nassumed by users in those accounts to get access to the SQS queues. See the <a href=\"/repos/terraform-aws-security/modules/cross-account-iam-roles#how-to-switch-between-accounts\" class=\"preview__body--description--blue\">how to switch between accounts\ndocumentation</a>\nfor instructions on assuming IAM roles in other AWS accounts.</p>\n<h4 id=\"connecting-to-multiple-vp-ns\">Connecting to multiple VPNs</h4>\n<p>Your VPN users may have problems connecting to multiple VPNs at the same time, unless you follow these best practices:</p>\n<ol>\n<li>Make sure that your VPC CIDRs do not overlap.</li>\n<li>Make sure that your VPN subnet CIDRs do not overlap. For example, use <code>172.16.1.0</code> for Dev, <code>172.16.2.0</code> for Prod,\nand so on.</li>\n<li>Make sure that your <code>openvpn-server</code> module's <code>user-data/user-data.sh</code> includes <code>--search-domain "${search_domain}"</code>\nin its arguments to <code>init-openvpn</code>, and pass the appropriate search domain in to the user data template object.\nSee the <a href=\"/repos/v0.27.4/package-openvpn/examples/openvpn-host\" class=\"preview__body--description--blue\">example here</a> for details.</li>\n<li>Use <a href=\"https://www.sparklabs.com/viscosity/\" class=\"preview__body--description--blue\" target=\"_blank\">Viscosity</a> rather than <a href=\"https://tunnelblick.net/\" class=\"preview__body--description--blue\" target=\"_blank\">Tunnelblick</a>.\nTunnelblick does not support setting DNS nameservers when connecting to multiple VPNs at the same time,\nand suffers from <a href=\"https://github.com/Tunnelblick/Tunnelblick/issues/573\" class=\"preview__body--description--blue\" target=\"_blank\">a bug</a> that clobbers the state of your\ninternet connection if you ever connect to more than one VPN at a time.</li>\n</ol>\n<h2 class=\"preview__body--subtitle\" id=\"how-to-use-this-repo-for-learning-and-testing\">How to use this repo (for learning and testing)?</h2>\n<p>⚠️ <strong><em>The following steps are recommended only for learning and testing purposes. If you need to setup OpenVPN and use this module for a production environment, or anything other than learning and testing purposes, please refer to our <a href=\"/repos/terraform-aws-service-catalog\" class=\"preview__body--description--blue\">Service Catalog</a> and the <a href=\"#how-to-use-this-repo-for-production\" class=\"preview__body--description--blue\">Production use section below</a>.</em></strong></p>\n<ol>\n<li><a href=\"/repos/v0.27.4/package-openvpn/examples/packer/README.md#building-an-ami-using-the-packer-templates\" class=\"preview__body--description--blue\">Build the AMI image using <code>Packer</code></a></li>\n<li><a href=\"/repos/v0.27.4/package-openvpn/examples/openvpn-host/README.md#quick-start\" class=\"preview__body--description--blue\">Configure the module & apply using Terraform</a></li>\n<li><a href=\"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups_manage_add-remove-users.html\" class=\"preview__body--description--blue\" target=\"_blank\">Add users & admins to the relevant IAM groups created by the module</a></li>\n<li>Try requesting a certificate<pre>aws-vault exec <Non-<span class=\"hljs-literal\">admin</span>-openvpn-<span class=\"hljs-literal\">user</span>> -- openvpn-<span class=\"hljs-literal\">admin</span> request --username <Non-<span class=\"hljs-literal\">admin</span>-openvpn-<span class=\"hljs-literal\">user</span>> --aws-region <region>\n</pre>\n</li>\n<li>Try using that certficiate to connect to the OpenVPN server and route your local traffic through there\n<ul>\n<li>you could use <a href=\"https://tunnelblick.net/\" class=\"preview__body--description--blue\" target=\"_blank\">Tunnelblick</a> for MacOS based machines, or <a href=\"https://openvpn.net/client-connect-vpn-for-windows/\" class=\"preview__body--description--blue\" target=\"_blank\">OpenVPN Connect for Windows-based machines</a></li>\n<li>On Tunnelblick, and most OpenVPN clients, you should be able to choose <em>full</em> or <em>split</em> tunnel mode (see what this is <a href=\"https://cybernews.com/what-is-vpn/split-tunneling\" class=\"preview__body--description--blue\" target=\"_blank\">here</a>).</li>\n<li>This module should be configured to use split tunnel mode in favour of directing only the relevant traffic to your OpenVPN Server and hence VPC. This is the default option that might help you save on the costs of running the OpenVPN server.</li>\n<li>In short, split tunnel mode will enable you to only direct certain traffic to your OpenVPN server, and leave the rest as is through the public Internet, and full tunnel mode means all your traffic is getting routed through the VPN server. If you've opted in for the latter, your machine will show you a different than the usual public IP address. You can <a href=\"https://checkip.amazonaws.com/\" class=\"preview__body--description--blue\" target=\"_blank\">Check what your IP is here.</a>.</li>\n</ul>\n</li>\n<li>Try getting a list of valid certificates as an OpenVPN admin<pre>aws-vault <span class=\"hljs-built_in\">exec</span> <<span class=\"hljs-built_in\">Admin</span>-openvpn-user> -- openvpn-<span class=\"hljs-built_in\">admin</span> <span class=\"hljs-built_in\">list</span> --aws-region <region>\n</pre>\n</li>\n<li>Try revoking a certificate as an OpenVPN admin<pre>aws-vault exec <Admin-openvpn-<span class=\"hljs-literal\">user</span>> -- openvpn-<span class=\"hljs-literal\">admin</span> revoke --username <Non-<span class=\"hljs-literal\">admin</span>-openvpn-<span class=\"hljs-literal\">user</span>> --aws-region <region>\n</pre>\n</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"examples\">Examples</h3>\n<p>See the <a href=\"/repos/v0.27.4/package-openvpn/examples\" class=\"preview__body--description--blue\">examples</a> folder for sample code to build the <code>openvpn-admin</code> binary, a packer template to build an AMI and Terraform code to launch everything necessary to run OpenVPN in your AWS environment.</p>\n<p>You can follow the <a href=\"/repos/v0.27.4/package-openvpn/examples/openvpn-host\" class=\"preview__body--description--blue\">openvpn-host</a> or <a href=\"/repos/v0.27.4/package-openvpn/examples/openvpn-host-duo\" class=\"preview__body--description--blue\">openvpn-host-duo</a> example to deploy a ready-made OpenVPN host into your AWS infrastructure. These examples are best for learning and experimenting on non-production environments.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-to-use-this-repo-for-production\">How to use this repo (for production)?</h2>\n<p>We recommend that for a production environment you use the example from our Gruntwork AWS Service Catalog: <a href=\"/repos/terraform-aws-service-catalog/examples/for-production/infrastructure-live/stage/us-west-2/stage/networking/openvpn-server\" class=\"preview__body--description--blue\">examples/for-production/[...]/networking/openvpn-server</a>.</p>\n<p>If you'd prefer to use the module code from the Service catalog instead of the example, please see <a href=\"/repos/terraform-aws-service-catalog/modules/mgmt/openvpn-server\" class=\"preview__body--description--blue\">terraform-aws-service-catalog/.../modules/mgmt/openvpn-server</a>.</p>\n<h2 class=\"preview__body--subtitle\" id=\"what-is-a-module\">What is a module?</h2>\n<p>At <a href=\"http://www.gruntwork.io\" class=\"preview__body--description--blue\" target=\"_blank\">Gruntwork</a>, we've taken the thousands of hours we spent building infrastructure on AWS and\ncondensed all that experience and code into pre-built <strong>packages</strong> or <strong>modules</strong>. Each module is a battle-tested,\nbest-practices definition of a piece of infrastructure, such as a VPC, ECS cluster, or an Auto Scaling Group. Modules\nare versioned using <a href=\"http://semver.org/\" class=\"preview__body--description--blue\" target=\"_blank\">Semantic Versioning</a> to allow Gruntwork clients to keep up to date with the\nlatest infrastructure best practices in a systematic way.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-use-a-module\">How do you use a module?</h2>\n<p>Most of our modules contain either:</p>\n<ol>\n<li><a href=\"https://www.terraform.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform</a> code</li>\n<li>Scripts & binaries</li>\n</ol>\n<h4 id=\"using-a-terraform-module\">Using a Terraform Module</h4>\n<p>To use a module in your Terraform templates, create a <code>module</code> resource and set its <code>source</code> field to the Git URL of\nthis repo. You should also set the <code>ref</code> parameter so you're fixed to a specific version of this repo, as the <code>main</code>\nbranch may have backwards incompatible changes (see <a href=\"https://www.terraform.io/docs/modules/sources.html\" class=\"preview__body--description--blue\" target=\"_blank\">module\nsources</a>).</p>\n<p>For example, to use <code>v1.0.0</code> of the openvpn module, you would add the following:</p>\n<pre><span class=\"hljs-keyword\">module</span> <span class=\"hljs-string\">\"openvpn-server\"</span> {\n source = <span class=\"hljs-string\">\"git::git@github.com:gruntwork-io/module-openvpn.git//modules/openvpn-server?ref=v1.0.0\"</span>\n\n <span class=\"hljs-comment\">// set the parameters for the OpenVPN module</span>\n}\n</pre>\n<p><em>Note: the double slash (<code>//</code>) is intentional and required. It's part of Terraform's Git syntax (see <a href=\"https://www.terraform.io/docs/modules/sources.html\" class=\"preview__body--description--blue\" target=\"_blank\">module\nsources</a>).</em></p>\n<p>See the module's documentation and <code>vars.tf</code> file for all the parameters you can set. Run <code>terraform get -update</code> to\npull the latest version of this module from this repo before runnin gthe standard <code>terraform plan</code> and\n<code>terraform apply</code> commands.</p>\n<h4 id=\"using-scripts-binaries\">Using scripts & binaries</h4>\n<p>You can install the scripts and binaries in the <code>modules</code> folder of any repo using the <a href=\"/repos/gruntwork-installer\" class=\"preview__body--description--blue\">Gruntwork\nInstaller</a>. For example, if the scripts you want to install are\nin the <code>modules/mongodb-scripts</code> folder of the https://github.com/gruntwork-io/terraform-aws-mongodb repo, you could install them\nas follows:</p>\n<pre><span class=\"hljs-string\">gruntwork-install </span><span class=\"hljs-built_in\">--module-name</span> <span class=\"hljs-string\">\"init-openvpn\"</span> <span class=\"hljs-built_in\">--repo</span> <span class=\"hljs-string\">\"https://github.com/gruntwork-io/terraform-aws-openvpn\"</span> <span class=\"hljs-built_in\">--tag</span> <span class=\"hljs-string\">\"0.0.1\"</span>\n</pre>\n<p>See the docs for each script & binary for detailed instructions on how to use them.</p>\n<h2 class=\"preview__body--subtitle\" id=\"developing-a-module\">Developing a module</h2>\n<h4 id=\"versioning\">Versioning</h4>\n<p>We are following the principles of <a href=\"http://semver.org/\" class=\"preview__body--description--blue\" target=\"_blank\">Semantic Versioning</a>. During initial development, the major\nversion is to 0 (e.g., <code>0.x.y</code>), which indicates the code does not yet have a stable API. Once we hit <code>1.0.0</code>, we will\nfollow these rules:</p>\n<ol>\n<li>Increment the patch version for backwards-compatible bug fixes (e.g., <code>v1.0.8 -> v1.0.9</code>).</li>\n<li>Increment the minor version for new features that are backwards-compatible (e.g., <code>v1.0.8 -> v1.1.0</code>).</li>\n<li>Increment the major version for any backwards-incompatible changes (e.g. <code>v1.0.8 -> v2.0.0</code>).</li>\n</ol>\n<p>The version is defined using Git tags. Use GitHub to create a release, which will have the effect of adding a git tag.</p>\n<h4 id=\"tests\">Tests</h4>\n<p>See the <a href=\"/repos/v0.27.4/package-openvpn/test\" class=\"preview__body--description--blue\">test</a> folder for details.</p>\n<h2 class=\"preview__body--subtitle\" id=\"contributions\">Contributions</h2>\n<h4 id=\"adding-support-for-a-new-os-distribution\">Adding support for a new OS distribution</h4>\n<p><em>Checkout <a href=\"/repos/terraform-aws-openvpn\" class=\"preview__body--description--blue\">this PR</a> that adds support for Ubuntu 20.04</em></p>\n<ol>\n<li>Update the conditional logic in the <code>init-vpn</code> & <code>install-vpn</code> <code>bin/install.sh</code> scripts to allow the required OS distro. Other modules may also need updating.</li>\n<li>Update the packer example to have a configuration for the new OS build</li>\n<li>Use Packer to create a new AMI.</li>\n<li>Apply some of the example terraform code (e.g. <code>openvpn-host</code>).</li>\n<li>SSH into the EC2 instance and see if there's any error logs - e.g. in the <code>user-data</code> log.</li>\n<li>Test by requesting a new certificate from the server.</li>\n</ol>\n<h2 class=\"preview__body--subtitle\" id=\"license\">License</h2>\n<p>Please see <a href=\"/repos/v0.27.4/package-openvpn/LICENSE.txt\" class=\"preview__body--description--blue\">LICENSE.txt</a> for details on how the code in this repo is licensed.</p>\n<h2 class=\"preview__body--subtitle\" id=\"to-do\">ToDo</h2>\n<ol>\n<li>Convert to CIDR format for parameters</li>\n</ol>\n","repoName":"package-openvpn","repoRef":"v0.27.4","serviceDescriptor":{"serviceName":"OpenVPN","serviceRepoName":"package-openvpn","serviceRepoOrg":"gruntwork-io","cloudProviders":["aws"],"description":"Deploy an OpenVPN server. Supports auto healing, public key infrastructure (PKI), cert backup, and managing user accounts using IAM groups.","imageUrl":"openvpn.png","licenseType":"subscriber","technologies":["Terraform","Bash","Go"],"compliance":[],"tags":[""]},"serviceCategoryName":"Client VPN access","fileName":"README.md","filePath":"","title":"Repo Browser: OpenVPN","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}