Skip to content

isopod-cloud/chasm

Repository files navigation

Chasm

NPM Docker Pulls tested with jest

Description

Chasms are what many businesses run into when trying to find the skill-sets and knowledge to navigate between the different cloud provider's environments. This can include APIs, tools, languages, networking architectures, and even having visibility into what subnets you might have in each cloud environment. When what you really want is to be able to get your data from one place to the another that you need... crossing that chasm.

The process of creating IPsec tunnels between virtual private clouds (VPCs) is different in each Cloud Service Provider (CSP), and it can be difficult to automate due to how IP addressing is handled (particularly for inter-cloud connectivity), eventual consistency in the standard CSPs APIs, and some dizzying circular dependencies to navigate through.

Enter Chasm, a tool for bridging the gaps between the clouds for you.

Core functions

  • Report all your VPCs and subnets from your CSPs.
  • Create a mesh IPsec network out of the cloud subnets you select from these CSPs.

Network designs supported

  • Inter-cloud meshing: meshing subnets between two or more distinct clouds i.e. AWS and GCP.

  • Mix of inter and intra-cloud Meshing: meshing subnets between two or more distinct clouds, and more than one subnet within same CSP, where same CSP is under a single account.

Known limitations

No NAT: There is no built in NAT, meaning we can't mesh subnets with overlapping CIDRS.

  • Multi-account, single cloud meshing: We currently do not support situations where you have more than one account associated to a single CSP and want to mesh two or more subnets that are in different CSP accounts (i.e. if you have two AWS accounts with a subnet in account A, and a subnet in account B, these tools do not currently support connectivity between them).

  • Azure cross-subscription meshing: You cannot connect two or more Azure subnets across Azure subscriptions.

  • AWS cross-region meshing: You cannot connect two or more AWS subnets across AWS regions.

  • GCP cross-project meshing: You cannot mesh together two VPCs across GCP projects.

Supported clouds

Quick start

This quickstart will walk you through the process of creating a simple Chasm-powered network: installation, defining the mesh network subnets, deploying the network, and then how to tear it down.

npm

Instructions for the npm quickstart are provided here. Docker may be preferred as you do not need to install pulumi.

Docker

The following instructions are for the docker quickstart. The latest image should be downloaded with:

docker pull isopod/chasm:main

Don't have docker installed? Install Docker Desktop On Mac, Windows, or Linux.

Windows users only - WSL docker quickstart

Windows users should use docker from inside WSL. Follow these quick steps if you use windows.

  1. install a distro:

    wsl --install -d Ubuntu
  2. Ensure the WSL version is 2

    wsl --set-version 2 Ubuntu
  3. Set to default disto

    wsl --set-default Ubuntu
  4. In Docker Desktop, go to Resources, WSL Integration and make sure the checkbox for Enable Integration with my default WSL distro is checked.

  5. Open an Ubuntu WSL prompt (Windows Key+R, then enter WSL, then click Run). Do everything from here like you're on Linux.

More resources if you get stuck: How to use Docker Desktop in WSL, How to install WSL

Installing and configuring cloud CLIs

Before proceeding, follow the guide for installing and configuring cloud CLIs.

Usage

Windows users MUST follow these steps from a WSL2 terminal in the distribution they run Docker from. Link to install WSL

Quick overview of what will be done in the quickstart (more in depth instruction in the following section):

  1. In ./mount/config.json, define the Cloud Accounts that will be used to look up Subnets
  2. Run the find command to list all the subnets that can be meshed
  3. In ./mount/config.json, edit the list of discovered subnets until it contains only the subnets you want to mesh
  4. Run the mesh command to mesh those subnets

Initializing a project directory

First, make a project directory, a mount folder, and change directories into the project folder

mkdir -p chasm/mount/pulumi
mkdir -p chasm/mount/stackWorkDir
cd chasm

Config file

The config file determines:

  1. Which clouds are scraped for subnets (from the "accounts" field)
  2. Which subnets are meshed together (from the "subnets" field within the "VPCs" field for each "account")
    • We do not need to specify "VPCs" in order to run the scrape functionality. It is only used for meshing.

Copy the example config file into ./mount/config.json.

cat << EOF > ./mount/config.json
{
    "accounts": [
        {
            "type": "AwsAccount",
            "id": "arbitrary-unique-id-aws1",
            "region": "YOUR_AWS_REGION"
        },
        {
            "type": "GcpAccount",
            "id": "arbitrary-unique-id-gcp1",
            "project": "YOUR_GCP_PROJECT"
        },
        {
            "type": "AzureAccount",
            "id": "arbitrary-unique-id-az1",
            "subscriptionId": "YOUR_AZURE_SUBSCRIPTION_ID"
        }
    ]
}
EOF

Discovering all VPCs and subnets

  1. Modify ./mount/config.json so that only the cloud accounts you want to scrape are in the "accounts" field

  2. Modify ./mount/config.json so that:

    • For AWS accounts
    • For GCP accounts
      • Set the project field to a PROJECT_ID. You can list them by running:gcloud projects list
    • For Azure accounts
      • Set the subscriptionId field toA subscriptionId. You can list them by running az account subscription list
  3. Scrape all the subnets in the clouds you are logged into with (note this can take a few minutes):

docker run --rm -ti \
    --volume "${PWD}/mount/:/app/mount:rw" \
    --volume "${HOME}/.config/gcloud:/root/.config/gcloud:rw" \
    --volume "${HOME}/.azure/:/root/.azure:rw" \
    --volume "${HOME}/.aws/:/root/.aws/:ro" \
    isopod/chasm:main \
    chasm find

Note: the az cli breaks without read write access to the credential directory.

This will output a json description of all discovered VPCs and subnets to standard out, as well as to a file in ./mount/discovered.json.

Volume mounts should only be specified for cloud CLIs you have installed on your system. For example, if you only have gcloud CLI installed, you would instead run:

docker run --rm -ti \
    --volume "${PWD}/mount/:/app/mount:rw" \
    --volume "${HOME}/.config/gcloud:/root/.config/gcloud:rw" \
    isopod/chasm:main \
    chasm find

Meshing subnets

*** Note ***: You cannot connect two or more AWS subnets across AWS regions.

  1. Copy only the VPCs and subnets to be added to the mesh network from the output, into the VPCs section for it's account in ./mount/config.json. For example, a complete GCP account with VPCs would look like:
{
	"type": "GcpAccount",
	"id": "arbitrary-unique-id",
	"project": "get from 'gcloud projects list'",
	"vpcs": [
		{
			"id": "xxxxxxxxxxxxxxxxxx",
			"type": "GcpVpc",
			"projectName": "myProject",
			"networkName": "xxxxxxxxxxxxxxxxxx-vpc",
			"subnets": [
				{
					"id": "xxxxxxxxxxxxxxxxxx",
					"cidr": "xxx.xxx.xxx.xxx/xx",
					"type": "GcpSubnet",
					"region": "us-west4"
				}
			]
		}
	]
}

The pre-mesh config file is a more complete example.

Standing up a mesh network

Create the mesh network with:

Be aware that this will create cloud resources which cost money. Make sure you preserve the ./mount/stackWorkDir directory for when you want to tear down in the next step.*

docker run --rm -ti \
    --volume "${PWD}/mount/:/app/mount:rw" \
    --volume "${PWD}/mount/pulumi:/root/.pulumi:rw" \
    --volume "${HOME}/.config/gcloud:/root/.config/gcloud:rw" \
    --volume "${HOME}/.azure/:/root/.azure:rw" \
    --volume "${HOME}/.aws/:/root/.aws/:ro" \
    --env PULUMI_CONFIG_PASSPHRASE="arbitrary-passphrase" \
    isopod/chasm:main \
    chasm mesh -n "my-network" --url file:///app/mount/stack

When prompted, enter a pre shared key (PSK). It must be at least 8 characters. PSKs are used for Internet Key Exchange (IKE) to secure traffic between the two peers while they work on generating random keys to use to talk to each other. Refer to the RFC for more details.

If you run into some trouble, you might find some suggestions under Troubleshooting.

Tearing down a mesh network

Chasm also allows you to tear-down the network you created. This gives you the flexibility to automate bringing up and tearing down the network on demand.

It is important to note that there may be some delay between when the CSPs in delete the network resources, and when the network fully come down. We recommend allowing about 5 minutes buffer time between when you need the network to be up and running if you plan to bring it up shortly after tearing it down.

  1. Destroy the mesh network with:
docker run --rm -ti \
    --volume "${PWD}/mount/:/app/mount:rw" \
    --volume "${PWD}/mount/pulumi:/root/.pulumi:rw" \
    --volume "${HOME}/.config/gcloud:/root/.config/gcloud:rw" \
    --volume "${HOME}/.azure/:/root/.azure:rw" \
    --volume "${HOME}/.aws/:/root/.aws/:ro" \
    --env PULUMI_CONFIG_PASSPHRASE="arbitrary-passphrase" \
    isopod/chasm:main \
    chasm mesh -n "my-network" -D --url file:///app/mount/stack

Roadmap

  • Routing: Currently the deployment will create a fully meshed IPsec tunnel between subnets selected. We will be adding routing between those subnets to automate traffic running across the IPsec tunnel network created. Right now, you'd have to go back and add that manually - something we're looking to update soon.
  • Security groups for the IPsec network for ease in adding security policies
  • Cross-account Cloud Meshing: We'd like to support meshing subnets within one cloud but across different accounts. This requires some work around how we authenticate, so it's not currently implemented.
  • CI/CD: This is particularly tricky in this space due to the security implications of automated testing for tools that operate on cloud resources, therefore we're temporarily handling this manually while we figure out a safe way to do it.

Support

We are excited to hear your feedback and engagement. You can reach us by submitting issues, feedback, questions, and merge requests at our Gitlab Issue tracker. We also encourage you to contact us at [email protected] in the event you identify any security-related bug, so we can look to address it quickly and in a manner that protects our community.

Contributing

Open source projects flourish with vigorous user contributions, and we'd love to have your additions to our project! In order to make it a good experience, we recommend that you read both the Code of Conduct and our contributing guide, then checkout the templates for an MR, which may assist you in successfully submitting your first Merge Request (MR) with us. Prospective code contributors might find the good first issue tag useful.

Visuals

Multi-vpc example

3 VPCs connected together with IPsec VPN connections. The rightmost VPC has a highly available service in 2 distinct subnets.

azure example

A data diagram showcasing the resources created in an Azure VPC to support connections to two distinct external VPCs.

gcp example

A data diagram showcasing the resources created in a GCP VPC to support connections to two distinct external VPCs.

aws example

A data diagram showcasing the resources created in an AWS VPC to support connections to two distinct external VPCs.

Building from source

Check out the instructions at docs/building-from-source.md.

Testing

Unit

You can run unit tests with:

yarn test:unit

Integration

The discovery tests require a config.json to be set up in the base directory of the repository to run. Additonally the tests for each individual cloud will utilize the first account of its type listed in the file. You can run integration tests with:

yarn test:integration

All

You can run all tests with:

yarn test:all

Or:

yarn test

Creating a release

Use the gitlab release feature to create a new semver tag. Creating a new tag will trigger ci to publish both a npm package and docker image.

Licensing

See the LICENSE.txt file for licensing information as it pertains to files in this repository.