When we started working on TerraHub CLI, our initial goal was to automate terraform execution and allow customer to trigger runs in self-service mode, as part of their existing GitHub and Jenkins pipelines. As any self respected engineering team working on automation, we added relevant test cases to make the process reliable and sustainable. Very proud of our accomplishment!
But… Due to lack of knowledge or experience — and without casting any blame on anyone, especially customer — our effort was fruitless and came kind of unnoticed, which was a little bit of disappointment to our team. Nevertheless, this experience helped us learn that visual representation of our work, even though was almost nothing from our point of view, was highly regarded and deeply appreciated by the customer. That was the starting point and the real birth story of TerraHub.io — the DevOps Hub for Terraform.
We have already made an introduction to TerraHub.io. In this article I would like to focus on under-the-hood aspects of this ecosystem, which consists of:
- TerraHub CLI (hosted by https://github.com/TerraHubCorp/terrahub)
- TerraHub API (hosted by https://www.terrahub.io)
- TerraHub GUI (hosted by https://console.terrahub.io)
Learning from previous lessons, we wanted to make it easier for customers to understand and visualize our work. Therefore we came up with below 3D architecture diagram in order to attempt showing each component in action:
Deciding on Serverless Architecture
Our experience includes every major computing service on AWS: from VM-based EC2 and EB, to container-based ECS and Fargate, and up to serverless-based Lambda and Glue. And we always strive to go extra mile and do more with less. Therefore, choosing serverless architecture for TerraHub.io wasn’t even a debate, but rather an unanimous agreement that we don’t want to use something else.
Members of our team are constantly contributing to open source projects (e.g. https://github.com/MitocGroup/deep-framework). We believe it helps us all to learn by solving real world problems and sharing solutions with others, as well as being open to learn from others and become better.
TerraHub CLI is one of those reusable solutions that we wanted to share with devops community. The problem — Automated Workflow for Terraform — is surprisingly common and requires decent effort to customize for specific needs. Fast forward, we ended up with a fully blown management tool that:
- Manages AWS, Google Cloud, Microsoft Azure and others in one place
- Manages VM-based, Containers, Serverless and others using one workflow
- Manages ALL cloud resources securely in customer’s private networks
- Manages ALL terraform executions in one system using one CI & CD process
TerraHub CLI is developed in Node.js and is published on npmjs.com. The implementation of this tool can be broken down into 4 major components:
- Core Source (reference: https://github.com/TerraHubCorp/terrahub/tree/master/src)
- Commands (reference: https://github.com/TerraHubCorp/terrahub/tree/master/src/commands)
- Helpers (reference: https://github.com/TerraHubCorp/terrahub/tree/master/src/helpers)
- Templates (reference: https://github.com/TerraHubCorp/terrahub/tree/master/src/templates)
Every script is logically interpreted and seamlessly executed under unified umbrella of terrahub command line interface, or thub alias. All dependencies and associated metadata are defined in package.json.
Unfortunately, we were not able to solve all terraform limitations via solo TerraHub CLI. Specifically, if I would like to share my terraform environment with Vlad, I would need to share with him all my credentials and replicate my security setup on his computer, as well as consistently configure and deploy my cloud environment on his laptop. To be clear, this is possible, but it’s a lot of unnecessary work to fit into TerraHub CLI.
In order to avoid this hassle, as well as save valuable time and big chunk of computing resources on both my computer and Vlad’s laptop, we engaged the value and the beauty of the cloud. We have built a reusable collection of TerraHub APIs (at the time of writing, API docs are still work in progress).
TerraHub API is using RESTful architecture to GET, POST, PUT and DELETE data via HTTP requests (+TLS, obviously). We have built it using Node.js and have organized everything in several categories, each category corresponding to associated provider of service (or services):
- TerraHub Management (prefixed by https://api.terrahub.io/v1/thub/*)
- GitHub Management (prefixed by https://api.terrahub.io/v1/github/*)
- AWS Management (prefixed by https://api.terrahub.io/v1/aws/*)
VERY IMPORTANT: Although TerraHub Management APIs and AWS Management APIs are deployed in the same AWS account, TerraHub API can provision and deploy AWS resources in the same AWS account (or multiple accounts), as well as in different ones. This architecture allows us to use cloud native services and manage AWS resources similar to managing Google Cloud resources or Microsoft Azure resources, as well as GitHub or BitBucket, etc. If external service is available over HTTP, TerraHub API will be able to integrate with it bidirectionally.
NOTE: I will intentionally skip describing TerraHub API architecture here because I need TerraHub GUI context, which is described next.
The most important value that we’re adding to existing ecosystem is TerraHub GUI — also known as TerraHub Console — the Graphical User Interface that simplifies and visualizes operations around terraform management. This is the main reason why TerraHub.io is the DevOps Hub for Terraform.
TerraHub Console is built using Vue.js and is packaged using Webpack. The codebase and related assets are deployed as static hosting files on Amazon S3 and exposed to global CDN via Amazon CloudFront. Amazon Route53 works as global DNS that routes www.terrahub.io and console.terrahub.io.
Requests that are coming to TerraHub API on api.terrahub.io first hit Amazon API Gateway. This service is integrated with Amazon Cognito and AWS Lambda authorizer to protect unauthorized use of service.
TerraHub Console authenticates with TerraHub API using JSON Web Token, also known as JWT. Next, JWT is validated by AWS Lambda authorizer function and is checked against IAM policy in Amazon Cognito if user is authorized to perform operation. On success, validated request is further forwarded to integrated AWS Lambda function for computing.
TerraHub CLI authenticated with TerraHub API using THUB token. Next, THUB is validated by AWS Lambda authorizer function. On success, validated THUB is exchanged on valid JWT and, similar to above process, is checked against IAM policy in Amazon Cognito. On success, validated request is further forwarded to integrated AWS Lambda function for computing.
Does it work? Below picture says everything. See for yourself: