Skip to main content

Amazon Connect - Operata Integration Updates - Terraform Deployment Guide

How to deploy your Operata AWS integration stacks using Terraform

Written by Hamish Keay

Deploying with Terraform

This guide covers deploying the full suite of Operata Cloud Collector v3 stacks using Terraform.

Operata publishes pre-synthesized Terraform JSON files (.tf.json).

You download one file per stack, set a handful of variables, and run terraform apply. No CDK, npm, or other build tooling is needed - only Terraform and AWS credentials.

What you need to know before starting:

  • ⏱ Each stack takes approximately 5-15 minutes to deploy.

  • πŸ“¦ Terraform state is stored locally by default. For team environments, configure a remote backend (e.g. S3) before deploying.

  • πŸ”‘ Keep your Operata API key out of version control - pass it inline or store it in a secrets manager.


Prerequisites

Requirement

Notes

Terraform

v1.8.x or later - install guide

AWS credentials

In the target account, with permission to create IAM, Lambda, Kinesis, EventBridge, Secrets Manager, and CloudWatch Logs resources - and (for clrules) CloudFormation and Amazon Connect rule resources

Operata Group ID

How to find your Operata Group ID

Operata API key

Terraform .tf.json file(s)

Downloaded from the Operata S3 bucket for your environment (see below)


Available stacks

Stack

Description

Filename pattern

Contact Trace Records (CTR)

Ingests CTR data from your Amazon Connect Kinesis stream

cloud-collector-v3-contact-trace-records-<TAG>.tf.json

Contact Trace Records - VPC

VPC variant of CTR

cloud-collector-v3-contact-trace-records-vpc-<TAG>.tf.json

Contact Lens Data (CLD)

Ingests Contact Lens output from S3.

cloud-collector-v3-contact-lens-data-<TAG>.tf.json

Contact Lens Data - VPC

VPC variant of CLD

cloud-collector-v3-contact-lens-data-vpc-<TAG>.tf.json

Contact Flow Logs (CFL)

Ingests contact flow logs from CloudWatch

cloud-collector-v3-contact-flow-logs-<TAG>.tf.json

Contact Flow Logs - VPC

VPC variant of CFL

cloud-collector-v3-contact-flow-logs-vpc-<TAG>.tf.json

Lex V2 Logs

Ingests Lex V2 conversation logs from CloudWatch

cloud-collector-v3-lexv2-logs-<TAG>.tf.json

Lex V2 Logs - VPC

VPC variant of Lex V2 Logs

cloud-collector-v3-lexv2-logs-vpc-<TAG>.tf.json

Contact Lens Rules (clrules)

Creates the Amazon Connect rules that emit operata_* Contact Lens events.

cloud-collector-v3-contact-lens-rules-<TAG>.tf.json

VPC variants: Choose the VPC variant only if your AWS account requires Lambda functions to run inside a VPC. VPC variants require two additional variables: a VPC ID and a list of private subnet IDs.

Stacks are independent and can be deployed in any combination.


How to deploy each stack

Each section below contains a complete, ready-to-run deploy block and destroy block. Substitute <bucket>, <env>, and <TAG> plus any stack-specific values before running.
​
For production, <bucket> is operata-customer-assets and <env> is prod. <TAG> is the release version.


1. Contact Trace Records (CTR)

Deploy:

shell

mkdir -p ~/operata/ctr-<env> cd ~/operata/ctr-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-trace-records-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                     = "ap-southeast-2" operata_group_id               = "<your-operata-group-id>" operata_api_key                = "<your-operata-api-key>" ctr_kinesis_stream_arn         = "arn:aws:kinesis:ap-southeast-2:111111111111:stream/..." connect_instance_friendly_name = "Prod" agent_data_s3_bucket_name      = ["", ""] EOF terraform init terraform apply

agent_data_s3_bucket_name expects a two-element list in the format ["bucket-name", "prefix/"]. If you have an agent data S3 bucket set up, enter those values. Otherwise leave it as ["", ""].

Destroy:

shell

terraform destroy

CTR - VPC variant:

shell

mkdir -p ~/operata/ctr-vpc-<env> cd ~/operata/ctr-vpc-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-trace-records-vpc-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                            = "ap-southeast-2" operata_group_id                      = "<your-operata-group-id>" operata_api_key                       = "<your-operata-api-key>" ctr_kinesis_stream_arn                = "arn:aws:kinesis:ap-southeast-2:111111111111:stream/..." connect_instance_friendly_name        = "Prod" agent_data_s3_bucket_name             = ["", ""] enrichment_lambda_vpc_id              = "vpc-0123456789abcdef0" enrichment_lambda_vpc_private_subnets = ["subnet-aaaa", "subnet-bbbb"] EOF terraform init terraform apply

2. Contact Lens Data (CLD)

Deploy:

shell

mkdir -p ~/operata/cld-<env> cd ~/operata/cld-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-lens-data-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                       = "ap-southeast-2" operata_group_id                 = "<your-operata-group-id>" operata_api_key                  = "<your-operata-api-key>" contact_lens_data_s3_bucket_name = "<your-contact-lens-bucket>" EOF terraform init terraform apply

Destroy:

shell

terraform destroy

CLD - VPC variant:

shell

mkdir -p ~/operata/cld-vpc-<env> cd ~/operata/cld-vpc-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-lens-data-vpc-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                                       = "ap-southeast-2" operata_group_id                                 = "<your-operata-group-id>" operata_api_key                                  = "<your-operata-api-key>" contact_lens_data_s3_bucket_name                 = "<your-contact-lens-bucket>" s3_kinesis_integrator_lambda_vpc_id              = "vpc-0123456789abcdef0" s3_kinesis_integrator_lambda_vpc_private_subnets = ["subnet-aaaa", "subnet-bbbb"] EOF terraform init terraform apply

3. Contact Flow Logs (CFL)

Deploy:

shell

mkdir -p ~/operata/cfl-<env> cd ~/operata/cfl-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-flow-logs-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                     = "ap-southeast-2" operata_group_id               = "<your-operata-group-id>" operata_api_key                = "<your-operata-api-key>" cf_log_group                   = "/aws/connect/<instance>/ContactFlowLogs" connect_instance_friendly_name = "Prod" EOF terraform init terraform apply

Destroy:

shell

terraform destroy

CFL - VPC variant:

shell

mkdir -p ~/operata/cfl-vpc-<env> cd ~/operata/cfl-vpc-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-flow-logs-vpc-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                             = "ap-southeast-2" operata_group_id                       = "<your-operata-group-id>" operata_api_key                        = "<your-operata-api-key>" cf_log_group                           = "/aws/connect/<instance>/ContactFlowLogs" connect_instance_friendly_name         = "Prod" cfl_decoder_lambda_vpc_id              = "vpc-0123456789abcdef0" cfl_decoder_lambda_vpc_private_subnets = ["subnet-aaaa", "subnet-bbbb"] EOF terraform init terraform apply

4. Lex V2 Logs

Deploy:

shell

mkdir -p ~/operata/lexv2-<env> cd ~/operata/lexv2-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-lexv2-logs-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region         = "ap-southeast-2" operata_group_id   = "<your-operata-group-id>" operata_api_key    = "<your-operata-api-key>" lex_log_group_name = "/aws/lex/<your-bot>/conversation-logs" EOF terraform init terraform apply

Destroy:

shell

terraform destroy

Lex V2 Logs - VPC variant:

shell

mkdir -p ~/operata/lexv2-vpc-<env> cd ~/operata/lexv2-vpc-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-lexv2-logs-vpc-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                                = "ap-southeast-2" operata_group_id                          = "<your-operata-group-id>" operata_api_key                           = "<your-operata-api-key>" lex_log_group_name                        = "/aws/lex/<your-bot>/conversation-logs" lex_enrichment_lambda_vpc_id              = "vpc-0123456789abcdef0" lex_enrichment_lambda_vpc_private_subnets = ["subnet-aaaa", "subnet-bbbb"] EOF terraform init terraform apply

5. Contact Lens Rules (clrules)

clrules creates approximately 50 Amazon Connect rules that publish operata_*-prefixed Contact Lens events.

How it works: this Terraform stack wraps the Operata Contact Lens Rules CloudFormation template via an aws_cloudformation_stack resource. Running terraform apply provisions a nested CloudFormation stack named operata-contact-lens-rules-<env> in your account, which in turn creates the Connect rules.

Deploy:

shell

mkdir -p ~/operata/clrules-<env> cd ~/operata/clrules-<env> curl -O https://<bucket>.s3.amazonaws.com/cloud-collector-v3-contact-lens-rules-<TAG>.tf.json cat > terraform.tfvars <<EOF aws_region                  = "ap-southeast-2" amazon_connect_instance_arn = "arn:aws:connect:ap-southeast-2:111111111111:instance/<your-instance-id>" EOF terraform init terraform apply

The apply takes approximately 25 seconds. Rule creation is serialized to respect the Amazon Connect CreateRule API rate limit (2 requests per second).

Verify:

shell

aws connect list-rules \   --region ap-southeast-2 \   --instance-id <your-instance-id> \   --publish-status PUBLISHED \   --query 'RuleSummaryList[?starts_with(Name, `operata_`)] | length(@)' # Expected output: ~50

Destroy:

shell

terraform destroy

clrules creates no AWS Secrets Manager secrets. No force-deletion step is required after destroy.


Upgrading an existing stack

⚠️ If unexpected resources appear in the plan, contact Operata before proceeding.

To apply a newer Operata release to an already-deployed stack:

  1. Download the new <TAG> .tf.json file into the same working directory, replacing the previous file.

  2. Run terraform plan to confirm only the expected resources change (typically the Lambda zip key and a few metadata fields).

  3. Run terraform apply.

State in the working directory tracks resource identity, so the upgrade is in place. The EventBridge pipe, Kinesis stream, and IAM resources are not replaced. For clrules specifically, terraform apply triggers a CloudFormation stack update on the nested operata-contact-lens-rules-<env> stack, which diffs and updates only the changed rules.


Redeploying after a destroy

AWS Secrets Manager schedules secrets for deletion with a 30-day recovery window - they are not removed immediately after terraform destroy. If you attempt terraform apply again before the window expires, the apply will fail with:

InvalidRequestException: You can't create this secret because a secret with this name is already scheduled for deletion.

To unblock an immediate redeploy, force-delete the affected secrets after destroy:

shell

aws secretsmanager delete-secret \   --region ap-southeast-2 \   --secret-id /cloud-collector-v3/<service>/apiToken-<env> \   --force-delete-without-recovery

⚠️ --force-delete-without-recovery permanently removes the secret. Use this only when you intend to recreate it immediately.


Secrets created per stack:

Stack

Secrets

clrules

None

CTR

/cloud-collector-v3/ctr/apiToken-<env>

CLD

/cloud-collector-v3/cld/apiToken-<env>

CFL

/cloud-collector-v3/cfl/apiToken-<env>, /cloud-collector-v3/cfl/redactionPolicyCache-<env>

Lex V2 Logs

/cloud-collector-v3/lex/apiToken-<env>, /cloud-collector-v3/lex/redactionPolicyCache-<env>


How to verify it's working

Place or receive a short test call on your Amazon Connect instance, then check the following.

Allow up to 5 minutes for data to appear. Remember to Close Contact if testing inbound call data.


1. Check API activity

Go to Group Settings β†’ Integrations β†’ API Management and confirm the API key shows a recent Last Used timestamp. This confirms your stack is actively sending data to Operata.
​

2. Check CTR data

Go to Calls and Logs β†’ Details / Summary and confirm the test call appears.
​

3. Check Contact Lens data

Go to Dashboards β†’ Conversational Analytics and confirm data appears. Filter by the test agent name, or sort by most recent call.

If data doesn't appear after 10 minutes, proceed to the troubleshooting steps below.


Troubleshooting

Work through the checklist below before contacting Operata support:
​

EventBridge Pipe fails to create on first apply. This is an IAM eventual-consistency issue. The role and policies are created correctly, but EventBridge performs an upfront access check before IAM has finished propagating. Re-run terraform apply - Terraform leaves the role in place and only retries the pipe.
​

Secret already scheduled for deletion. Force-delete the affected secret(s) via the CLI (see Redeploying after a destroy above), then re-apply.
​

CLD deploys cleanly but no data appears in Operata. The EventBridge Pipe shows RUNNING but no contact-lens summaries appear. Check that Contact Lens is enabled on your Amazon Connect instance and that calls are being processed with Contact Lens analysis turned on.
​

API key shows no recent activity. Check that operata_api_key and operata_group_id in your terraform.tfvars are correct. An incorrect API key causes data to be silently rejected.
​

Terraform inline_policy deprecation warning. Terraform may print a deprecation warning on aws_iam_role.inline_policy. This is a provider-level notice only. The configuration applies cleanly and has no functional impact.


Need help?

If you run into any issues, or aren't sure which stacks or environment applies to your setup, we're here to help.
​

πŸ“§ Email us at help@operata.com
πŸ’¬ Or send a message directly from within the Operata application

Did this answer your question?