This Terraform configuration mirrors the CDK get-started example, providing an equivalent Infrastructure as Code setup for deploying AWS DevOps Agent resources.
AWS DevOps Agent helps you monitor and manage your AWS infrastructure using AI-powered insights. This configuration automates the setup described in the getting started guide.
- Terraform >= 1.0
- AWS CLI configured with appropriate permissions
- One AWS account for the monitoring (primary) account
- (Optional) A second AWS account for cross-account monitoring
This guide is divided into three parts:
- Part 1 — Deploy an agent space with an operator app and an AWS association in your monitoring account. After completing this part, the agent can monitor issues in that account.
- Part 2 (Optional) — Add a source AWS association for a service account and deploy a cross-account IAM role plus an echo Lambda into that account.
- Part 3 (Optional) — Register third-party services (Dynatrace, ServiceNow, Splunk, New Relic, GitLab, PagerDuty) and associate them with the agent space.
| Resource | Name | Purpose |
|---|---|---|
| Agent Space | Configurable | Central agent space with operator app |
| IAM Role | DevOpsAgentRole-AgentSpace-* | Assumed by the agent to monitor the account. Uses AIDevOpsAgentAccessPolicy managed policy. |
| IAM Role | DevOpsAgentRole-WebappAdmin-* | Operator app role. Uses AIDevOpsOperatorAppAccessPolicy managed policy. |
| Association | AWS (monitor) | Links the monitoring account |
| Association | AWS (source) | Links the service account (optional) |
| Resource | Name | Purpose |
|---|---|---|
| IAM Role | DevOpsAgentRole-SecondaryAccount-TF | Cross-account role trusted by the Agent Space. Uses AIDevOpsAgentAccessPolicy managed policy. |
| Lambda | echo-service-tf | Example service |
Each integration you enable creates a service registration plus an association with the agent space:
| Resource | Service type | Auth |
|---|---|---|
| Dynatrace | dynatrace |
OAuth client credentials |
| ServiceNow | servicenow |
OAuth client credentials |
| Splunk | mcpserversplunk |
Bearer token |
| New Relic | mcpservernewrelic |
API key |
| GitLab | gitlab |
Access token |
| PagerDuty | pagerduty |
OAuth client credentials |
Datadog is not included. Connecting Datadog requires interactive user OAuth authorization (browser login + consent) per the Datadog connection guide, which Terraform cannot automate. Register Datadog manually through the Capability Providers page in the console.
-
Clone and configure
git clone <this-repo> cd sample-aws-devops-agent-terraform cp terraform.tfvars.example terraform.tfvars
-
Edit
terraform.tfvarswith your agent space name and description. -
Deploy
./deploy.sh
Or manually:
terraform init terraform plan terraform apply
-
Record the outputs — note the
agent_space_arnvalue for Part 2. -
Verify
./post-deploy.sh
-
Set the service account ID in
terraform.tfvars:service_account_id = "<YOUR_SERVICE_ACCOUNT_ID>"
-
Set the agent space ARN from Part 1 output:
agent_space_arn = "arn:aws:aidevops:us-east-1:<MONITORING_ACCOUNT_ID>:agentspace/<SPACE_ID>"
-
Configure the
aws.serviceprovider inmain.tfwith credentials for the service account. You can use either a named profile or an assume role:Using a profile:
provider "aws" { alias = "service" region = var.aws_region profile = "your-service-account-profile" }
Or using assume role:
provider "aws" { alias = "service" region = var.aws_region assume_role { role_arn = "arn:aws:iam::<SERVICE_ACCOUNT_ID>:role/OrganizationAccountAccessRole" } }
-
Deploy again:
terraform apply
-
Test the echo service:
aws lambda invoke \ --function-name echo-service-tf \ --payload '{"test": "hello world"}' \ --profile service \ --region us-east-1 \ response.json cat response.json
Third-party integrations are configured through the integrations variable. Because these resources reference the agent space directly, they can be deployed in the same terraform apply as Part 1 (no separate phase or agent space ID wiring is required, unlike the CDK IntegrationsStack).
-
Add an
integrationsblock toterraform.tfvars, populating only the services you want. Seeterraform.tfvars.examplefor the full shape. For example:integrations = { dynatrace = { account_urn = "<DYNATRACE_ACCOUNT_URN>" client_id = "<DYNATRACE_CLIENT_ID>" client_name = "<DYNATRACE_CLIENT_NAME>" client_secret = "<DYNATRACE_CLIENT_SECRET>" env_id = "<DYNATRACE_ENVIRONMENT_ID>" resources = ["<DYNATRACE_RESOURCE_1>"] } }
ServiceNow gotcha: always set
instance_idexplicitly (the short instance name, e.g."ven04972"— not the fullinstance_url). Ifinstance_idis omitted, the association falls back toinstance_url, which the DevOps Agent API rejects with a400 GeneralServiceException: instanceId '<url>' does not match the registered ServiceNow instance. -
Apply:
terraform apply
-
Review the outputs —
integration_service_idsandintegration_association_idsmap each enabled service to its registered IDs.
Security: the
integrationsvariable is markedsensitive, so its values are redacted from plan/apply output. Do not commit real credentials toterraform.tfvars. For production, source secrets from AWS Secrets Manager or SSM Parameter Store (e.g. viadatasources) rather than plaintext.
| Variable | Description | Default |
|---|---|---|
aws_region |
AWS region for deployment | us-east-1 |
agent_space_name |
Name for the Agent Space | MyAgentSpace |
agent_space_description |
Description for the Agent Space | AgentSpace for monitoring my application |
service_account_id |
Service account ID for cross-account monitoring | "" |
agent_space_arn |
Agent Space ARN (required for Part 2) | "" |
name_postfix |
Postfix for IAM role names | "" |
tags |
Tags for all resources | See variables.tf |
integrations |
Optional third-party integrations (Dynatrace, ServiceNow, Splunk, New Relic, GitLab, PagerDuty). Datadog must be connected manually — see note above. Sensitive. | {} |
- IAM propagation delays: The configuration includes a 30-second
time_sleepbetween IAM role creation and Agent Space creation. The DevOps Agent service validates the operator role's trust policy during Agent Space creation, and this can fail if IAM hasn't fully propagated. If you still see trust policy errors, wait a minute and runterraform applyagain — the IAM roles will already exist and the apply will pick up where it left off. - ServiceNow
instanceId does not matcherror: Setinstance_idexplicitly in theservice_nowintegration block to the short instance name (e.g."ven04972"), not the fullinstance_url. See the note in Part 3 above. - Dynatrace association
status: invalid: Ifterraform applysucceeds but the resulting association reportsstatus = "invalid"(visible viaaws devops-agent get-associationor the console), this indicates Dynatrace rejected the OAuth client credentials — double-checkclient_id,client_secret, andaccount_urnagainst the Dynatrace account, rather than a Terraform configuration issue.
Destroy in reverse order if you deployed Part 2:
./cleanup.shOr manually:
terraform destroyThis project is licensed under the MIT License - see the LICENSE file for details.
For production deployments, store integration credentials in AWS Secrets Manager
instead of plaintext tfvars. The secrets-manager.tf file provides a
Dynatrace example:
# terraform.tfvars
dynatrace_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:devops-agent/dynatrace-AbCdEf"
dynatrace_account_urn = "urn:dtaccount:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
dynatrace_env_id = "abc12345"
dynatrace_resources = ["HOST-123"] # optionalThe secret should be a JSON object:
{"client_id": "dt0s02.X", "client_name": "my-client", "client_secret": "dt0s02.X.secret"}If both var.integrations.dynatrace and dynatrace_secret_arn are set,
integrations.tf takes precedence and the Secrets Manager path is skipped.