A generic AWS CLI executor Lambda that lets Elastic Agent Builder agents investigate AWS resources by composing and running CLI commands. The Lambda uses the AWS SecurityAudit managed policy (read-only) and validates every command against a configurable allowlist before execution.
- How it works
- What gets deployed
- Lambda input and output
- Security
- Project structure
- Deployment
- Configuration
- Future extension points
Agent Builder --> Workflow (execute-aws-cli) --> Lambda (aws-cli-executor) --> AWS APIs
- An Agent Builder agent decides it needs AWS data and composes an AWS CLI command.
- The agent invokes a workflow tool, which triggers the "Execute AWS CLI Command" workflow.
- The workflow calls the Lambda via the
aws_lambdaconnector. - The Lambda validates the command, runs it, and returns structured JSON.
- The workflow passes the response back to the agent.
| Component | Description |
|---|---|
| Lambda function | aws-cli-executor -- container image with AWS CLI v2 |
| ECR repository | Hosts the Lambda container image |
| IAM role | aws-cli-executor-role with SecurityAudit + AWSLambdaBasicExecutionRole |
| Elastic Workflow | Wraps the Lambda invocation with inputs/outputs |
| Agent Builder tool | Registers the workflow as a tool agents can call |
| Agent | An "AWS Investigator" agent wired to the tool |
Input:
{
"command": "aws ec2 describe-instances --instance-ids i-abc123 --output json",
"profile": "default"
}Output:
{
"status": "success",
"command": "aws ec2 describe-instances --instance-ids i-abc123 --output json",
"exit_code": 0,
"stdout": "{...}",
"stderr": "",
"truncated": false,
"execution_time_ms": 1234
}The Lambda has multiple layers of protection:
- SecurityAudit IAM policy -- the real perimeter. Even if command validation were bypassed, the Lambda can only perform read-only operations. No S3 data access, no DynamoDB reads, no secret retrieval.
- Action prefix allowlist -- only
describe,list,get,show,check,lookup,head,wait,help, andlsare allowed by default. Configurable via theALLOWED_COMMAND_PREFIXESenvironment variable. - Blocked flags --
--endpoint-url,--cli-input-json,--cli-input-yaml, and--debugare rejected to prevent credential redirect, payload bypass, and information leakage. - File protocol blocking --
file://andfileb://are blocked to prevent local file exfiltration from the Lambda filesystem. - Shell injection protection -- shell operators (
&&,||,;, backticks,$(),${}, redirects) are blocked. Commands run viasubprocess.runwithout a shell, so metacharacters have no effect even if they slip through. - Global-flag-aware parsing -- the command parser uses
shlex.split()tokenization and understands AWS CLI global flags, making it resistant to flag-ordering tricks. - Output truncation -- responses exceeding 5 MB are truncated with a
truncated: trueflag.
aws-cli-agent-tool/
├── README.md
├── lambda/
│ ├── handler.py # Lambda handler
│ ├── utils.py # Response helpers (ok/error)
│ ├── Dockerfile # Container image with AWS CLI v2
│ └── tests/
│ └── test_handler.py # 60 unit tests
├── terraform/
│ ├── main.tf # Provider config
│ ├── variables.tf # Configurable parameters
│ ├── iam.tf # IAM role + SecurityAudit policy
│ ├── lambda.tf # ECR + Docker build + Lambda function
│ └── outputs.tf # Function name, ARN, account ID
├── workflows/
│ └── execute-aws-cli.yaml # Elastic Workflow wrapping the Lambda
└── agent/
└── tool-config.json # Agent Builder tool definition (reference)
- AWS CLI v2 with configured credentials
- Terraform >= 1.0
- Docker
- An Elastic deployment (ECH or Serverless) with:
- Workflows enabled (
Stack Management > Advanced Settings > workflows:ui:enabled) - An AWS Lambda connector configured (you will need its connector ID)
- A GenAI connector for Agent Builder (e.g. Bedrock, OpenAI, or Gemini)
- Workflows enabled (
cd terraform/
terraform init
terraform applyThis creates the ECR repository, builds and pushes the Docker image, and deploys the Lambda function with the SecurityAudit IAM policy.
Open workflows/execute-aws-cli.yaml and replace the placeholder YOUR_LAMBDA_CONNECTOR_ID with the ID of your AWS Lambda connector from Kibana. You can find this under Stack Management > Connectors.
curl -X POST "https://YOUR_KIBANA_URL/api/workflows/workflow" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d "$(jq -n --arg yaml "$(cat workflows/execute-aws-cli.yaml)" '{yaml: $yaml}')"Note the id from the response. You will need it in the next step.
curl -X POST "https://YOUR_KIBANA_URL/api/agent_builder/tools" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"id": "aws-cli-executor",
"type": "workflow",
"description": "Execute read-only AWS CLI commands for investigating AWS resources. Pass a full AWS CLI command string as the command input (e.g. aws ec2 describe-instances --instance-ids i-abc123 --output json). The tool runs the command via a Lambda function with the SecurityAudit policy (read-only access across all AWS services). Only read operations are allowed: describe, list, get, show, check, lookup, ls. Write operations are blocked. Tips: (1) Always include --output json for structured results. (2) Use --query to filter large responses with JMESPath syntax. (3) Run aws sts get-caller-identity to see which account you are in. (4) If output is truncated, narrow the query with more specific filters or --max-items. Optional profile input selects a named AWS CLI profile for cross-account access.",
"configuration": {
"workflow_id": "YOUR_WORKFLOW_ID"
}
}'Replace YOUR_WORKFLOW_ID with the workflow ID from Step 3.
curl -X POST "https://YOUR_KIBANA_URL/api/agent_builder/agents" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"id": "aws-investigator",
"name": "AWS Investigator",
"description": "Investigates AWS resources and infrastructure using CLI commands.",
"configuration": {
"instructions": "You are an AWS infrastructure investigator. When asked about AWS resources, compose appropriate AWS CLI commands and use the aws-cli-executor tool to run them. Always use --output json for structured results. Start by identifying which AWS account you are in with aws sts get-caller-identity. For large result sets, use --query (JMESPath) to filter. When investigating security incidents, gather context from multiple services (EC2, IAM, CloudTrail, VPC). If a command returns truncated output, refine your query with more specific filters. Present findings clearly with key details highlighted.",
"tools": [
{
"tool_ids": ["aws-cli-executor"]
}
]
}
}'Open Agent Builder in Kibana, select the "AWS Investigator" agent, and ask:
"What EC2 instances are running in this account?"
The agent should compose an aws ec2 describe-instances command, invoke the tool, and return a summary of your instances.
| Variable | Default | Description |
|---|---|---|
ALLOWED_COMMAND_PREFIXES |
(empty = built-in defaults) | Comma-separated list of allowed CLI action prefixes |
function_name |
aws-cli-executor |
Lambda function name |
lambda_timeout |
30 |
Lambda timeout in seconds |
lambda_memory |
256 |
Lambda memory in MB |
region |
us-east-2 |
AWS region |
- Cross-account profiles -- bake
~/.aws/configinto the Lambda with named profiles for multi-account assume-role - CloudFormation StackSets -- org-wide deployment of audit roles in target accounts
- Multi-CSP -- same pattern for GCP (Cloud Run +
gcloud) and Azure (Azure Functions +az)