Skip to content

Repository files navigation

AWS DevOps Agent Terraform Configuration

This Terraform configuration mirrors the CDK get-started example, providing an equivalent Infrastructure as Code setup for deploying AWS DevOps Agent resources.

Overview

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.

Prerequisites

  • 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

What this guide covers

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.

Resources Created

Part 1: Monitoring Account

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)

Part 2: 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

Part 3: Third-Party Integrations (Optional)

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.

Usage

Part 1: Deploy the Agent Space

  1. Clone and configure

    git clone <this-repo>
    cd sample-aws-devops-agent-terraform
    cp terraform.tfvars.example terraform.tfvars
  2. Edit terraform.tfvars with your agent space name and description.

  3. Deploy

    ./deploy.sh

    Or manually:

    terraform init
    terraform plan
    terraform apply
  4. Record the outputs — note the agent_space_arn value for Part 2.

  5. Verify

    ./post-deploy.sh

Part 2 (Optional): Add Cross-Account Monitoring

  1. Set the service account ID in terraform.tfvars:

    service_account_id = "<YOUR_SERVICE_ACCOUNT_ID>"
  2. Set the agent space ARN from Part 1 output:

    agent_space_arn = "arn:aws:aidevops:us-east-1:<MONITORING_ACCOUNT_ID>:agentspace/<SPACE_ID>"
  3. Configure the aws.service provider in main.tf with 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"
      }
    }
  4. Deploy again:

    terraform apply
  5. 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

Part 3 (Optional): Register Third-Party Integrations

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).

  1. Add an integrations block to terraform.tfvars, populating only the services you want. See terraform.tfvars.example for 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_id explicitly (the short instance name, e.g. "ven04972" — not the full instance_url). If instance_id is omitted, the association falls back to instance_url, which the DevOps Agent API rejects with a 400 GeneralServiceException: instanceId '<url>' does not match the registered ServiceNow instance.

  2. Apply:

    terraform apply
  3. Review the outputsintegration_service_ids and integration_association_ids map each enabled service to its registered IDs.

Security: the integrations variable is marked sensitive, so its values are redacted from plan/apply output. Do not commit real credentials to terraform.tfvars. For production, source secrets from AWS Secrets Manager or SSM Parameter Store (e.g. via data sources) rather than plaintext.

Configuration Options

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. {}

Troubleshooting

  • IAM propagation delays: The configuration includes a 30-second time_sleep between 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 run terraform apply again — the IAM roles will already exist and the apply will pick up where it left off.
  • ServiceNow instanceId does not match error: Set instance_id explicitly in the service_now integration block to the short instance name (e.g. "ven04972"), not the full instance_url. See the note in Part 3 above.
  • Dynatrace association status: invalid: If terraform apply succeeds but the resulting association reports status = "invalid" (visible via aws devops-agent get-association or the console), this indicates Dynatrace rejected the OAuth client credentials — double-check client_id, client_secret, and account_urn against the Dynatrace account, rather than a Terraform configuration issue.

Cleanup

Destroy in reverse order if you deployed Part 2:

./cleanup.sh

Or manually:

terraform destroy

License

This project is licensed under the MIT License - see the LICENSE file for details.

Secrets Manager integration (production recommended)

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"]  # optional

The 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.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages