Skip to main content

AWS Identity Document

The AWS Identity Document method is for agents running on AWS EC2 instances. The agent fetches its Instance Identity Document (IID) from the EC2 metadata service as a cryptographically signed blob; the Trust Domain Server verifies the signature using AWS public signing keys and confirms the instance is in a running state.

Attributes available for SVID issuance

The following attributes are produced. All have the origin aws_iid.

AttributeAlways emittedDescription
aws_iid.account.idYesAWS account ID of the EC2 instance
aws_iid.ec2.instance.idYesEC2 instance ID
aws_iid.ec2.instance.regionYesAWS region of the instance
aws_iid.ec2.instance.availability_zoneYesAvailability zone
aws_iid.ec2.instance.image_idYesAMI ID
aws_iid.ec2.instance.tag.<TAG_NAME>NoOne attribute per EC2 tag
aws_iid.ec2.security_group.idNoOne attribute per security group ID
aws_iid.ec2.security_group.nameNoOne attribute per security group name
aws_iid.iam.roleNoOne attribute per IAM role (omitted if no instance profile)

Example SPIFFE ID template:

/aws/{{aws_iid.account.id}}/{{aws_iid.ec2.instance.region}}/{{aws_iid.ec2.instance.id}}

How to Deploy

Step 1 — Set Up AWS IAM

The Trust Domain Server needs to assume a role in the agent's AWS account to verify the instance identity and query instance details. Every AWS account where agents will attest must have a role named DefaktoServer that the Trust Domain Server can assume.

Recommended identity pattern:

  • Launch the Trust Domain Server with a role like arn:aws:iam::<servers_account>:role/DefaktoServerHost
  • In each agent account, create a role arn:aws:iam::<agents_account>:role/DefaktoServer with a trust relationship allowing assumption by DefaktoServerHost

Required permissions on the DefaktoServer role in each agent account:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AlwaysRequired",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"iam:GetInstanceProfile"
],
"Resource": "*"
}
]
}

If using eksClusterNames validation, add:

{
"Sid": "EKSClusterValidation",
"Effect": "Allow",
"Action": [
"eks:ListNodegroups",
"eks:DescribeNodegroup",
"autoscaling:DescribeAutoScalingGroups"
],
"Resource": "*"
}

Step 2 — Update cluster configuration

The simplest configuration:

section: AgentAttestation
schema: v1
spec:
policies:
- name: aws_policy
requiredAttestors:
- type: aws_iid

With this setup, agents must be in the same AWS account as the Trust Domain Server (or in accounts explicitly listed in awsAccountsAllowed).

Allow agents from specific additional accounts:

section: AgentAttestation
schema: v1
spec:
policies:
- name: aws_policy
requiredAttestors:
- type: aws_iid
config:
awsAccountsAllowed:
- "111111111111"
- "222222222222"

Allow agents from any account in an AWS Organization:

section: AgentAttestation
schema: v1
spec:
policies:
- name: aws_policy
requiredAttestors:
- type: aws_iid
config:
assumeOrgRoleArns:
- "arn:aws:iam::<management_account>:role/DefaktoServerOrgAccountsList"

The management account role needs organizations:ListAccounts permission and must trust DefaktoServerHost.

Restrict to agents running in specific EKS clusters:

section: AgentAttestation
schema: v1
spec:
policies:
- name: aws_policy
requiredAttestors:
- type: aws_iid
config:
eksClusterNames:
- web-cluster
- data-service-cluster

Apply it using spirlctl:

spirlctl config set cluster --id <cluster-id> attestation-policy.yaml

Or using Terraform:

resource "spirl_cluster_config" "agent_attestation" {
cluster_id = spirl_cluster.my_cluster.id
sections = {
AgentAttestation = <<-YAML
section: AgentAttestation
schema: v1
spec:
policies:
- name: aws_policy
requiredAttestors:
- type: aws_iid
YAML
}
}

Once a configuration document passes validation and is stored, the Defakto control plane syncs it to your Trust Domain Servers automatically. No server or agent restart is required.

Server Configuration Reference

FieldDefaultDescription
awsAccountsAllowedAdditional AWS account IDs permitted beyond the server's own account.
assumeOrgRoleArnsRole ARNs to assume to get a dynamic list of all AWS accounts in those organizations.
eksClusterNamesIf set, agents must be EC2 instances in one of these EKS clusters' node groups.

Step 3 — Configure the Agent

The agent must run on an EC2 instance with access to the instance metadata service.

agent:
auth:
clusterId: c-xxxxxx
attestors:
- type: aws_iid

Step 4 — Verify

Server logs — look for these in order:

  1. "Login started with multi-attestation support" — confirms the agent offered providedMethods: ["aws_iid"]
  2. "Authorization received and verified" — includes agentAttestationAttributes with the instance identity:
    {
    "msg": "Authorization received and verified",
    "agentAttestationAttributes": [
    "aws_iid:aws_iid.account.id=\"123456789012\"",
    "aws_iid:aws_iid.ec2.instance.id=\"i-0abc123def456\"",
    "aws_iid:aws_iid.ec2.instance.region=\"us-east-1\""
    ]
    }
  3. "Connected to agent" — session is fully established

Agent logs — enable debug logging to see "Sending Login" with attestors: ["aws_iid"]. At the default log level, "Connected to server" confirms the session is live.

Metrics — confirm proofs are succeeding:

spirl_attestation_signer.proof{attestor_type="aws_iid",outcome="success"}
spirl_attestation_agent.proof{attestor_type="aws_iid",outcome="success"}

Alert on outcome="failed" to detect IID signature or role assumption failures.

Common errors:

ErrorLikely cause
no cluster policy authorizes the provided attestorsAgent's aws_iid method doesn't match any policy in the cluster's AgentAttestation config
Attestor rejected proof, policy failedTrust Domain Server couldn't assume DefaktoServer role in the agent's account — verify the cross-account IAM trust relationship
Role assumption errors in server logsMissing sts:AssumeRole permission — confirm DefaktoServer exists in the agent's AWS account and trusts the server's identity

Security Considerations

warning

SSRF and replay vulnerability: Any application on the same EC2 instance as the agent can access the IID signature. An attacker with access to the IID signature (via SSRF, a compromised co-hosted application, or a captured network exchange) can replay it from anywhere, indefinitely, as long as the source instance remains running. Because the server caches instance state for up to 3 minutes, there is also a brief window after the instance stops.

Use this method as part of a layered security approach, and prefer combining it with an additional attestation method (such as k8s_token) for environments with strict isolation requirements.

Certificate pinning: The server hardcodes the expected AWS certificates for PKCS#7 signature verification. If AWS rotates these certificates, agents will fail to attest until a new server version with updated pins is deployed.

Response caching: AWS API responses are cached with a default TTL of approximately 3 minutes to minimize API call consumption. Changes to instance state (such as tags or security groups) may not be reflected immediately.

Troubleshooting

The DefaktoServer role must exist in every agent AWS account and be assumable by the Trust Domain Server's identity. The most common configuration issue is a missing or misconfigured sts:AssumeRole permission chain. Check Trust Domain Server logs for detailed role assumption errors when attestation fails.