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

> Easily set up your AWS Security Agent workspace. Learn to create agent spaces, configure IAM roles, and set up S3 buckets for scan artifacts using the AWS CLI.

- Repository: [Amazon Web Services/agent-toolkit-for-aws](https://github.com/aws/agent-toolkit-for-aws)
- Tags: how-to-guide
- Published: 2026-07-01

---

**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:

```bash
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:

```bash
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:

```bash

# 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:

```bash
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:

```bash
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:

```bash
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`](https://github.com/aws/agent-toolkit-for-aws/blob/main/.security-agent/config.json) and exclude the directory from version control:

```bash
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:

- **Skill definition**: [`plugins/aws-agents-for-devsecops/skills/setup-security-agent/SKILL.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/plugins/aws-agents-for-devsecops/skills/setup-security-agent/SKILL.md) contains the declarative workflow and safety rules.
- **CLI wrapper**: [`plugins/aws-agents-for-devsecops/commands/setup-security-agent.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/plugins/aws-agents-for-devsecops/commands/setup-security-agent.md) exposes the setup command to agents.

## 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`](https://github.com/aws/agent-toolkit-for-aws/blob/main/.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`](https://github.com/aws/agent-toolkit-for-aws/blob/main/.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.