Views:
By default, Container Security automatically patches ECS Fargate task definitions at runtime using a Lambda function. Automatic patching can be disabled to allow manual configuration of task definitions with the required security containers and settings.

Prerequisites

  • An Amazon ECS Fargate cluster connected to TrendAI Vision One™.
  • Runtime security enabled for the ECS cluster in the TrendAI Vision One™ console.
  • IAM permissions to create and modify ECS task definitions and IAM roles.
  • An ECS task execution role with permissions to pull container images and write to CloudWatch Logs.
Note
Note
If the execution role does not have the logs:CreateLogGroup permission, pre-create the CloudWatch log group before deploying the task definition (as shown in the Terraform example in Step 3).

Step 1: Disable automatic patching

For existing deployments
In the AWS Lambda console, update the environment variable DISABLE with value true to the trendmicro-container-security-ecs-taskdef-patcher function to prevent automatic patching of task definitions.
For new AWS account deployments
Before deploying the Container Security stack from the TrendAI Vision One™ console, modify the CloudFormation template to set the EnableAutomatedFargatePatching parameter default value to false, then deploy the stack using the modified template.

Step 2: Get current container image versions

Container image versions should match the version specified in the Container Security deployment template. The latest CloudFormation template can be downloaded from the TrendAI Vision One™ console. The corresponding version can also be obtained from the deployed template.
Locate the following default values in the template:
  • CloudPdigVersion
  • CloudScoutVersion
  • CloudFalcoVersion

Step 3: Create or update task definition

The manual patching process requires several specific configurations to ensure Container Security works correctly. The Terraform example below contains all required settings.
Configuration requirements
The following configurations are required:
  • PID mode (task): Allows security containers to monitor application processes across the entire task.
  • Shared volume (trendmicro-component): Enables init containers to copy binaries that the Runtime security container executes.
  • SYS_PTRACE capability: Required for both application and security containers to enable process tracing and security monitoring.
  • Container dependencies: Ensures security containers start before the application and in the correct sequence.
  • Health checks: Confirms security components are running before marking the task as healthy.
  • IAM permissions: Allows security containers to retrieve authentication tokens from AWS Secrets Manager and SSM Parameter Store, and report security events.
TrendAI Vision One™ endpoint configuration
Replace the <VISION_ONE_ENDPOINT> value in the Terraform code to match the TrendAI Vision One™ region:
Region
Endpoint URL
Americas
https://api.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
Europe
https://api.eu.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
Japan
https://api.xdr.trendmicro.co.jp/external/v2/direct/vcs/external/vcs
Australia
https://api.au.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
India
https://api.in.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
Singapore
https://api.sg.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
Middle East and Africa
https://api.mea.xdr.trendmicro.com/external/v2/direct/vcs/external/vcs
Terraform example
# Data sources to get current AWS region and account ID
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}

# Variables
variable "log_group" {
  description = "CloudWatch log group name for ECS containers"
  type        = string
  default     = "/ecs/your-task-definition-family-name"
}

variable "cluster_name" {
  description = "Name of your existing ECS cluster"
  type        = string
  default     = "your-cluster-name"
}

variable "execution_role_arn" {
  description = "ARN of the existing ECS task execution role"
  type        = string
}

# Pre-create CloudWatch log group
resource "aws_cloudwatch_log_group" "ecs_logs" {
  name              = var.log_group
  retention_in_days = 7

  tags = {
    Name        = "ECS Task Logs"
    ManagedBy   = "Terraform"
    Application = "Vision One Container Security"
  }
}

resource "aws_ecs_task_definition" "this" {
  family                   = "your-task-definition-family-name"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "512"
  memory                   = "1024"

  # Task role - for runtime permissions (SSM, Secrets Manager, ECS TagResource)
  task_role_arn      = aws_iam_role.container_security_role.arn
  # Execution role - for pulling images and writing logs
  execution_role_arn = var.execution_role_arn

  # Required for Vision One Container Security
  pid_mode = "task"
  volume { name = "trendmicro-component" }

  container_definitions = jsonencode([
    # Your application container
    {
      name             = "your-app"
      image            = "your-app-image:tag"
      essential        = true

      # Application must depend on security container and have SYS_PTRACE capability
      dependsOn        = [{ condition = "START", containerName = "trendmicro-security" }]
      linuxParameters  = { capabilities = { add = ["SYS_PTRACE"] } }
      logConfiguration = {
        logDriver = "awslogs",
        options = {
          "awslogs-group" = var.log_group,
          "awslogs-create-group" = "true",
          "awslogs-region" = data.aws_region.current.id,
          "awslogs-stream-prefix" = "ecs"
        }
      }
    },

    # Vision One Container Security: Init container for PDIG
    {
      name             = "trendmicro-init-pdig"
      image            = "public.ecr.aws/trendmicro/container-security/cloud-pdig:<CloudPdigVersion>"
      essential        = false
      user             = "0"  # Required for FIPS images - runs as root to write to shared volume
      entryPoint       = ["/bin/sh"]
      command          = ["-c", "set -e; attempt=0; until [ $attempt -ge 3 ]; do attempt=$((attempt+1)); if timeout 30 sh -c 'cp -fv /usr/bin/pdig /var/TrendMicro/ && cp -fv /*.sh /var/TrendMicro/'; then exit 0; fi; sleep 2; done; exit 1"]
      mountPoints      = [{ sourceVolume = "trendmicro-component", containerPath = "/var/TrendMicro/" }]
      logConfiguration = {
        logDriver = "awslogs",
        options = {
          "awslogs-group" = var.log_group,
          "awslogs-create-group" = "true",
          "awslogs-region" = data.aws_region.current.id,
          "awslogs-stream-prefix" = "ecs"
        }
      }
    },

    # Vision One Container Security: Init container for Scout
    {
      name             = "trendmicro-init-scout"
      image            = "public.ecr.aws/trendmicro/container-security/cloud-scout:<CloudScoutVersion>"
      essential        = false
      user             = "0"  # Required for FIPS images - runs as root to write to shared volume
      entryPoint       = ["/bin/sh"]
      command          = ["-c", "set -e; attempt=0; until [ $attempt -ge 3 ]; do attempt=$((attempt+1)); if timeout 30 sh -c 'cp -fv /*.sh /var/TrendMicro/ && cp -fv /service /var/TrendMicro/ && cp -fv /ecs_entry /var/TrendMicro/ && cp -fv /MQTT_config.yaml /var/TrendMicro/ && chmod -v 755 /var/TrendMicro/*.sh'; then exit 0; fi; sleep 2; done; exit 1"]
      mountPoints      = [{ sourceVolume = "trendmicro-component", containerPath = "/var/TrendMicro/" }]
      dependsOn        = [{ condition = "SUCCESS", containerName = "trendmicro-init-pdig" }]
      logConfiguration = {
        logDriver = "awslogs",
        options = {
          "awslogs-group" = var.log_group,
          "awslogs-create-group" = "true",
          "awslogs-region" = data.aws_region.current.id,
          "awslogs-stream-prefix" = "ecs"
        }
      }
    },

    # Vision One Container Security: Runtime security container
    {
      name             = "trendmicro-security"
      image            = "public.ecr.aws/trendmicro/container-security/cloud-falco:<CloudFalcoVersion>"
      essential        = false
      user             = "0"  # Required - runs as root for PDIG and Falco operations
      entryPoint       = ["/bin/sh"]
      command          = ["-c", "cp -f /var/TrendMicro/* / && /start_ecs_fargate.sh"]

      # Environment variables - adjust VISION_ONE_ENDPOINT for your region
      environment = [
        { name = "PARAMETER_PREFIX", value = "/V1CS" },
        { name = "SPC_MODE", value = "false" },
        { name = "FILE_INTEGRITY_MONITORING", value = "true" },
        { name = "VISION_ONE_ENDPOINT", value = "<VISION_ONE_ENDPOINT>" },
        { name = "LOG_LEVEL", value = "info" }
      ]

      dependsOn        = [
        { condition = "SUCCESS", containerName = "trendmicro-init-pdig" },
        { condition = "SUCCESS", containerName = "trendmicro-init-scout" }
      ]
      mountPoints      = [{ sourceVolume = "trendmicro-component", containerPath = "/var/TrendMicro/", readOnly = true }]
      linuxParameters  = { capabilities = { add = ["SYS_PTRACE"] } }

      # Health check ensures security components are running properly
      healthCheck = {
        command     = ["CMD-SHELL", "pgrep -f falco >/dev/null && pgrep -f '/service.*grpc-socket-path' >/dev/null || exit 1"]
        interval    = 30
        timeout     = 5
        retries     = 3
        startPeriod = 60
      }
      logConfiguration = {
        logDriver = "awslogs",
        options = {
          "awslogs-group" = var.log_group,
          "awslogs-create-group" = "true",
          "awslogs-region" = data.aws_region.current.id,
          "awslogs-stream-prefix" = "ecs"
        }
      }
    }
  ])
}

# IAM role for the task
resource "aws_iam_role" "container_security_role" {
  name = "container-security-task-role"
  assume_role_policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole",
      Effect = "Allow",
      Principal = { Service = "ecs-tasks.amazonaws.com" }
    }]
  })
}

# IAM policy with required permissions for Vision One Container Security
resource "aws_iam_role_policy" "container_security_role_policy" {
  name = "container-security-task-role-policy"
  role = aws_iam_role.container_security_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = "ssm:GetParameter"
        Resource = "arn:aws:ssm:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:parameter/V1CS/*"
      },
      {
        Effect   = "Allow"
        Action   = "secretsmanager:GetSecretValue"
        Resource = "arn:aws:secretsmanager:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:secret:/V1CS/${var.cluster_name}/AuthToken-*"
      },
      {
        Effect   = "Allow"
        Action   = "ecs:TagResource"
        Resource = "arn:aws:ecs:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:task/*"
      },
      {
        Effect   = "Allow"
        Action   = "sqs:SendMessage",
        Resource = "arn:aws:sqs:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:trendmicro-container-security-*"
      }
    ]
  })
}

Step 4: Deploy and verify

  1. Apply the Terraform configuration:
    terraform plan
    terraform apply
  2. Verify the task definition is created correctly in the AWS ECS console.
  3. Deploy a service using this task definition.
  4. Check CloudWatch Logs to confirm all containers start successfully.
  5. Verify in the TrendAI Vision One™ console that the workload appears and security events are being collected.

Important information

Before uninstalling: When planning to uninstall Container Security, unpatch the task definitions first. This prevents potential application crashes.
Version updates: Container image versions and configuration settings may change between releases. Checking the latest CloudFormation template is recommended for current requirements.
Update process: When updating to a new release, download the latest template, update the task definition with new image versions, test in a non-production environment, then deploy to production.