-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Elastio terraform deployment automation example
- Loading branch information
Showing
4 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Elastio terraform deployment | ||
|
||
This project presents an example of how you may automate the deployment of the Elastio stack in your AWS account. | ||
|
||
## Obtain a personal access token (PAT) | ||
|
||
First of all, you'll need a secret PAT token to authenticate your Elastio installation with the Elastio Portal. You can generate one by following the steps below. | ||
|
||
1. Open the [Elastio Portal](https://login.elastio.com/) in your web browser. | ||
2. Click on the profile button at the top right corner of the page. | ||
3. Go to the `API access` tab. | ||
4. Click on `Add New Access Token`. | ||
5. Enter the name for the token, for example `Elastio deployment`. | ||
6. Select the scope `Sources: Write` for the token. | ||
7. Click on `Generate Token`. | ||
8. Copy the generated token. | ||
9. *Optional step.* Save the token in a secure place like 1Password or any other secret management system of your choice. This way you won't lose it. | ||
|
||
## Add Elastio to your Terraform | ||
|
||
There is a terraform module under the `module` directory. It deploys all the necessary resources for Elastio to operate. It includes the following: | ||
|
||
- AWS Cloudformation stack named `elastio-account-level-stack`, which is deployed once per AWS account and contains the required IAM resources | ||
- Elastio Cloud Connector stack deployed by Elastio Portal via a REST API call. It contains Lambda functions, DynamoDB databases, S3 buckets, AWS Batch compute environments and other non-IAM resources. | ||
- *Optional.* A NAT provisioning stack that deploys NAT gateways in the private subnets where Elastio scan job workers run. This is necessary only if you deploy Elastio into private subnets that don't have outbound Internet access already. Alternatively you can deploy your own NAT gateway if you want to. | ||
|
||
Add this terraform module to your terraform project add specify the necessary input variables. Here you'll need to pass the PAT token you [generated earlier](#obtain-a-personal-access-token-pat), specify your Elastio tenant name and the list of regions with VPC/subnet configurations where you want to deploy Elastio. | ||
|
||
Here is an example usage of the module | ||
|
||
```tf | ||
provider "aws" {} | ||
provider "http" {} | ||
module "elastio" { | ||
source = "../module" | ||
elastio_pat = "{pat_token_from_elastio_portal}" | ||
elastio_tenant = "mycompany.app.elastio.com" | ||
elastio_cloud_connectors = [ | ||
{ | ||
region = "us-east-2" | ||
vpc_id = "vpc-0001" | ||
subnet_ids = [ | ||
"subnet-0001", | ||
"subnet-0002" | ||
] | ||
}, | ||
{ | ||
region = "us-east-1" | ||
vpc_id = "vpc-0002" | ||
subnet_ids = [ | ||
"subnet-0003", | ||
"subnet-0004", | ||
] | ||
} | ||
] | ||
# This input is optional. Here you can specify the version of the NAT provisioning stack. | ||
# If you don't need it, just omit this input variable. | ||
elastio_nat_provision_stack = "v4" | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
locals { | ||
elastio_endpoint = "https://${var.elastio_tenant}/public-api/v1" | ||
headers = { | ||
Authorization = "Bearer ${var.elastio_pat}" | ||
} | ||
} | ||
|
||
data "http" "cloudformation_template" { | ||
url = "${local.elastio_endpoint}/cloudformation-template" | ||
request_headers = local.headers | ||
|
||
retry { | ||
attempts = 10 | ||
max_delay_ms = 10000 | ||
} | ||
|
||
lifecycle { | ||
postcondition { | ||
condition = self.status_code >= 200 && self.status_code < 300 | ||
error_message = "Status code invalid" | ||
} | ||
} | ||
} | ||
|
||
resource "aws_cloudformation_stack" "elastio_account_level_stack" { | ||
name = "elastio-account-level-stack" | ||
template_url = data.http.cloudformation_template.response_body | ||
tags = { | ||
"elastio:resource" = "true" | ||
} | ||
capabilities = ["CAPABILITY_NAMED_IAM"] | ||
} | ||
|
||
resource "aws_cloudformation_stack" "elastio_nat_provision_stack" { | ||
count = var.elastio_nat_provision_stack == null ? 0 : 1 | ||
|
||
name = "elastio-nat-provision-lambda" | ||
template_url = join( | ||
"/", | ||
[ | ||
"https://elastio-prod-artifacts-us-east-2.s3.us-east-2.amazonaws.com", | ||
"contrib/elastio-nat-provision-lambda/${var.elastio_nat_provision_stack}", | ||
"cloudformation-lambda.yaml" | ||
] | ||
) | ||
tags = { | ||
"elastio:resource" = "true" | ||
} | ||
capabilities = ["CAPABILITY_IAM"] | ||
} | ||
|
||
data "aws_caller_identity" "current" {} | ||
|
||
locals { | ||
elastio_cloud_connector_deploy_requests = [ | ||
for connector in var.elastio_cloud_connectors : merge( | ||
connector, | ||
{ account_id = data.aws_caller_identity.current.account_id }, | ||
) | ||
] | ||
} | ||
|
||
resource "terraform_data" "elastio_cloud_connector" { | ||
for_each = { | ||
for request in local.elastio_cloud_connector_deploy_requests : | ||
request.region => request | ||
} | ||
|
||
input = each.value | ||
triggers_replace = each.value | ||
|
||
provisioner "local-exec" { | ||
command = <<CMD | ||
curl "$elastio_endpoint/deploy-cloud-connector" \ | ||
--location \ | ||
--fail-with-body \ | ||
--show-error \ | ||
--retry-all-errors \ | ||
--retry 5 \ | ||
-X POST \ | ||
-H "Authorization: Bearer $elastio_pat" \ | ||
-H "Content-Type: application/json; charset=utf-8" \ | ||
-d "$request_body" | ||
CMD | ||
|
||
environment = { | ||
elastio_endpoint = local.elastio_endpoint | ||
request_body = jsonencode(self.input) | ||
|
||
// Using nonsensitive() to workaround the problem that the script's | ||
// output is entirely suppressed: https://github.com/hashicorp/terraform/issues/27154 | ||
elastio_pat = nonsensitive(var.elastio_pat) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
terraform { | ||
required_providers { | ||
http = { | ||
source = "hashicorp/http" | ||
version = "3.4.4" | ||
} | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = "5.61.0" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
variable "elastio_pat" { | ||
description = "Personal Access Token generated by the Elastio Portal" | ||
sensitive = true | ||
type = string | ||
nullable = false | ||
} | ||
|
||
variable "elastio_tenant" { | ||
description = "Name of your Elastio tenant. For example `mycompany.app.elastio.com`" | ||
type = string | ||
nullable = false | ||
} | ||
|
||
variable "elastio_cloud_connectors" { | ||
description = "List Cloud Connectors to deploy" | ||
type = list(object({ | ||
region = string | ||
vpc_id = string | ||
subnet_ids = list(string) | ||
})) | ||
nullable = false | ||
default = [] | ||
} | ||
|
||
variable "elastio_nat_provision_stack" { | ||
description = <<DESCR | ||
Specifies the version of Elastio NAT provision stack to deploy (e.g. `v4`). | ||
This is a Cloudformation stack that provisions automatically provisions | ||
NAT Gateways in your VPC when Elastio worker instances run to provide them | ||
with the outbound Internet access when Elastio is deployed in private subnets. | ||
If you don't need this stack (e.g. you already have NAT gateways in your VPC | ||
or you deploy into public subnets) you can omit this parameter. The default | ||
value of `null` means there won't be any NAT provision stack deployed. | ||
The source code of this stack can be found here: | ||
https://github.com/elastio/contrib/tree/master/elastio-nat-provision-lambda | ||
DESCR | ||
type = string | ||
nullable = true | ||
default = null | ||
} |