Setting up AWS Security Agent: Agent Space, IAM Role, and S3 Bucket

You can set up an AWS Security Agent workspace by creating an agent space, provisioning an IAM service role with trust policies for the Security Agent service, configuring an S3 bucket for scan artifacts, and linking them together via the AWS CLI.

The AWS Security Agent requires three linked resources to run penetration tests and code scans: an agent space, an IAM service role, and an S3 bucket. According to the aws/agent-toolkit-for-aws repository, the complete setup workflow is defined in the setup-security-agent skill and maintains minimal local state in a .security-agent/ directory.

Prerequisites

Before running the setup commands, ensure you have:

  • The AWS CLI installed and configured with appropriate IAM permissions
  • Access to the aws securityagent API commands
  • Permissions to create IAM roles, S3 buckets, and Security Agent resources in your AWS account

Core Components Overview

Three resources must exist and be linked for a functional workspace:

  • Agent space: A logical container for scans and penetration tests, created via aws securityagent create-agent-space.
  • IAM service role: Named conventionally as SecurityAgentScanRole, this grants the Security Agent service permissions to read S3 objects and publish CloudWatch logs.
  • S3 bucket: Stores uploaded source archives and scan artifacts, following the naming pattern security-agent-scans-<ACCOUNT>-<REGION>.

Step-by-Step Setup Procedure

Verify Existing Local State

Check for previous configuration to avoid duplicate resource creation:

if [ -f .security-agent/config.json ]; then
  cat .security-agent/config.json
else
  echo "No existing config – starting fresh."
fi

If the file exists, the agent_space_id is reused; otherwise, proceed to create new resources.

Determine Account ID and Region

Derive your AWS account ID and target region. These values are used throughout the setup but are not stored in the local config file to prevent configuration drift:

ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
REGION="${AWS_REGION:-us-east-1}"
echo "Account=$ACCOUNT, Region=$REGION"

Create or Select an Agent Space

List existing spaces or create a new one. The skill does not auto-select when multiple spaces exist:


# List existing spaces

aws securityagent list-agent-spaces

# Create a new space if needed

AGENT_SPACE_ID=$(aws securityagent create-agent-space --name security-scans \
  --query "agentSpaceId" --output text)

Provision the IAM Service Role

Create the SecurityAgentScanRole with a trust policy that allows the Security Agent service to assume the role, scoped to your account:

ROLE_NAME=SecurityAgentScanRole
ROLE_ARN="arn:aws:iam::$ACCOUNT:role/$ROLE_NAME"

if ! aws iam get-role --role-name $ROLE_NAME >/dev/null 2>&1; then
  # Trust policy

  cat > /tmp/sa-trust.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "securityagent.amazonaws.com"},
      "Action": "sts:AssumeRole",
      "Condition": {"StringEquals": {"aws:SourceAccount": "'"${ACCOUNT}"'"}}
    }
  ]
}
EOF

  # Permissions policy

  cat > /tmp/sa-perms.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject","s3:GetObjectVersion","s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::security-agent-scans-${ACCOUNT}-${REGION}",
        "arn:aws:s3:::security-agent-scans-${ACCOUNT}-${REGION}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],
      "Resource": "arn:aws:logs:*:${ACCOUNT}:log-group:/aws/securityagent/*"
    }
  ]
}
EOF

  aws iam create-role --role-name $ROLE_NAME --assume-role-policy-document file:///tmp/sa-trust.json
  aws iam put-role-policy --role-name $ROLE_NAME \
    --policy-name SecurityAgentCodeReviewAccess --policy-document file:///tmp/sa-perms.json
fi

If the role exists but has an outdated trust policy, update it using aws iam update-assume-role-policy.

Configure the S3 Bucket

Create the region-specific bucket with public access blocking and a 30-day lifecycle rule:

BUCKET="security-agent-scans-${ACCOUNT}-${REGION}"

if ! aws s3api head-bucket --bucket "$BUCKET" >/dev/null 2>&1; then
  if [ "$REGION" = "us-east-1" ]; then
    aws s3api create-bucket --bucket "$BUCKET"
  else
    aws s3api create-bucket --bucket "$BUCKET" \
      --create-bucket-configuration LocationConstraint="$REGION"
  fi
fi

aws s3api put-public-access-block --bucket "$BUCKET" \
  --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

cat > /tmp/sa-lifecycle.json <<'EOF'
{
  "Rules": [
    {
      "ID": "AutoDeleteUploads",
      "Status": "Enabled",
      "Filter": {"Prefix": ""},
      "Expiration": {"Days": 30}
    }
  ]
}
EOF

aws s3api put-bucket-lifecycle-configuration --bucket "$BUCKET" \
  --lifecycle-configuration file:///tmp/sa-lifecycle.json

Register Resources with the Agent Space

Link the IAM role and S3 bucket to your agent space. This step is idempotent:

aws securityagent update-agent-space \
  --agent-space-id $AGENT_SPACE_ID \
  --name security-scans \
  --aws-resources iamRoles=[$ROLE_ARN],s3Buckets=[$BUCKET]

Persist Local Configuration

Store the minimal required state in .security-agent/config.json and exclude the directory from version control:

mkdir -p .security-agent
cat > .security-agent/config.json <<EOF
{
  "agent_space_id": "$AGENT_SPACE_ID",
  "region": "$REGION"
}
EOF

echo '*' > .security-agent/.gitignore

Source Code Reference

The complete workflow is documented in the aws/agent-toolkit-for-aws repository:

Summary

  • Agent space: Create via aws securityagent create-agent-space to serve as the logical container for scans.
  • IAM role: Provision SecurityAgentScanRole with trust policies for securityagent.amazonaws.com and permissions for S3 and CloudWatch Logs.
  • S3 bucket: Create a region-specific bucket named security-agent-scans-<ACCOUNT>-<REGION> with public access blocks and lifecycle policies.
  • Local state: Store only the agent_space_id and region in .security-agent/config.json; derive role and bucket names from the account ID to prevent drift.
  • Idempotency: All setup steps can be run multiple times safely without creating duplicate resources.

Frequently Asked Questions

What happens if I delete and recreate the IAM role or S3 bucket?

The AWS Security Agent setup derives the role and bucket names from your AWS account ID rather than storing them in the local .security-agent/config.json file. This design prevents configuration drift; if you recreate resources manually with the same naming convention, the next scan will automatically use the new resources without requiring config updates.

Can I use an existing agent space instead of creating a new one?

Yes. Run aws securityagent list-agent-spaces to view available spaces. If you have existing spaces, capture the agentSpaceId and set the AGENT_SPACE_ID variable accordingly. The setup skill never auto-selects a space when multiple exist, so you must explicitly confirm your choice.

Why does the IAM role need CloudWatch Logs permissions?

The Security Agent service writes scan logs and execution outputs to CloudWatch Logs using the logs:CreateLogGroup, logs:CreateLogStream, and logs:PutLogEvents permissions. This allows you to monitor scan progress and troubleshoot failures through the AWS Management Console or CloudWatch Logs API.

Is the setup process safe to run multiple times?

Yes. Every step in the workflow is idempotent. The IAM role creation checks for existence before proceeding, the S3 bucket creation verifies via head-bucket, and the update-agent-space API call succeeds without duplication if resources are already attached. You can safely rerun the setup script if interrupted or if requirements change.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →