This is a guest post by Clément Contini, Cloud System Administrator for cloud.ca. cloud.ca is a HashiCorp technology partner and provides Canadian regional cloud infrastructure for companies who have data sovereignty requirements. cloud.ca works as a standalone IaaS platform, or can be part of a hybrid or multi-cloud solution.
The cloud.ca team has developed a purpose-built provider for HashiCorp Terraform, making it possible to automate infrastructure deployments on the cloud.ca platform. Terraform is one of the numerous open-source tools for infrastructure management available from HashiCorp. It provides a DevOps-friendly approach to deploying complex IaaS environments, enabling increased agility and flexibility, particularly when it involves re-use of existing deployment architectures. You can download the cloud.ca provider here: https://github.com/cloud-ca/terraform-provider-cloudca.
Apache CloudStack serves as the underlying orchestration platform for cloud.ca. While it has a generic Terraform provider (which we wrote about here), we knew we could provide more value for our users by developing our own. This custom provider is more aligned with the design of our platform and specific deployment options, meaning users can automate cloud.ca-specific capabilities via their Terraform configuration. For example, we simplify the use of CloudStack projects, a parameter that otherwise needs to be provided repeatedly when using the generic CloudStack provider. As an additional benefit, a single user can have access to manage multiple environments in an organization via Terraform, using the same credentials, if cloud.ca permissions allow it.
Another aspect that the cloud.ca provider covers that cannot be done with the generic CloudStack provider is the ability to control the “management” layer using the “environment” resource. You can specify the details of the role-based access control for each user in the Terraform configuration and/or even create new environments.
Let’s take a look at a real configuration made for the cloud.ca provider, available in the following repository: https://github.com/cloud-ca/blog_post_cloudca_terraform_provider. This configuration will create an environment and a VPC with 3 networks. One network will be used for the front-end machines, one for the back-end machines and the last one for a utility machine.
All available variables are gathered in a file called “variables.tf” and represent all the customization that can be applied on the configuration. Here is an excerpt of the file:
# Provider credentials
variable "api_key" {}
# General variables
variable "is_production" {}
variable "frontend_count" {}
variable "backend_count" {}
# Environment
variable "service_code" {}
variable "organization_code" {}
variable "environment_name" {}
variable "environment_description" {
default = "Environment for %s workloads"
}
variable "admin" {
type = "list"
}
variable "read_only" {
type = "list"
}
variable "database_ports" {
default = [ 3306 ]
}
variable "web_ports" {
default = [ 80, 443 ]
}
To begin to use this configuration, create a file “terraform.tfvars” with all the variables that don’t have a default in “variables.tf”. This might be things such as API keys, a list of users the organization wants to add to the environment, a list of required attributes specified in a README file, or variables to override. An example of this might be if you want to open port 8080 instead of 80 and 443, just add this to “terraform.tfvars”
web_ports = [ 8080 ]
And to specify role accesses:
admin_role = [ "clement", "mike" ]
read_only_role = [ ]
Now take a look at “main.tf”. It configures a “cloudca_environment” which takes a list of users in “admin_role” and “read_only_role”. These roles have to be specified in the “terraform.tfvars” file (no default is provided, you need to use the users from your own organization).
resource "cloudca_environment" "default" {
service_code = "${var.service_code}"
organization_code = "${var.organization_code}"
name = "${var.environment_name}"
description = "${format("${var.environment_description}", "${var.environment_name}")}"
admin_role = ["${var.admin}"]
read_only_role = ["${var.read_only}"]
}
This also means that if you have several similar environments, let’s say a production environment and a development environment, you can use the same configuration for both of them and just change the variables “admin” and “read_only” to the appropriate values to limit the access to the production environment but enable full access on the development one.
One of the required variables in “terraform.tfvars” is the boolean “is_production”. When set to true, the ACL rules are stricter:
For example, the following piece of code handles ACL rules creation for the database network:
resource "cloudca_network_acl_rule" "db_allow_in_ports" {
environment_id = "${cloudca_environment.default.id}"
count = "${var.is_production ? var.frontend_count * length(var.database_ports) : 1}"
rule_number = "${10 + count.index + 1}"
action = "Allow"
protocol = "TCP"
start_port = "${element(var.database_ports, count.index % length(var.database_ports))}"
end_port = "${element(var.database_ports, count.index % length(var.database_ports))}"
cidr = "${var.is_production ?
"${element(cloudca_instance.web_instance.*.private_ip, count.index)}/32" : "0.0.0.0/0" }"
traffic_type = "Ingress"
network_acl_id = "${cloudca_network_acl.db_acl.id}"
}
Depending if the environment is for production or not, the CIDR of the ACL will be different: open to 0.0.0.0/0 for the development environment, extracted from the instances of the web network for production. The ports are also configurable and are selected from the list provided as variables.
The cloud.ca Terraform provider directly leverages built-in features of the platform, such as the activity log. Any action performed while using the cloud.ca Terraform provider will show up in the activity view. If you deploy the example configuration, you will see the different actions as they are performed:
We are continuously improving and developing the cloud.ca Terraform provider. An upcoming near-term roadmap item will provide the ability to export a Terraform configuration from an existing cloud.ca environment. This way, if the environment had been built manually but the user wants to reproduce it easily (in terms of infrastructure layout), it would be possible to simply press a button, get the Terraform configuration, and use it to create a similar environment.
In conclusion, we think Terraform is an excellent tool to use with cloud.ca:
HashiCorp Terraform is a product to provision any infrastructure for any application. Terraform provides infrastructure as code, cloud platform management, and self-service infrastructure. To learn more about HashiCorp Terraform visit https://www.hashicorp.com/products/terraform/.
A recap of HashiCorp infrastructure and security news and developments from Google Cloud Next, from scaling infrastructure as code to fighting secrets sprawl and more.
New in Terraform 1.8: Provider-defined functions let users extend Terraform with custom capabilities. Plus, refactoring can now be done across resource types.
See usage examples of Terraform 1.8's new launch-day provider-defined functions for AWS, Google Cloud, and Kubernetes.