Do you actually need this?
Probably not. Answer one question: Is the S3 bucket in the same AWS account as the credentials the agent uses?
“The credentials the agent uses” means the account your
access_key_id belongs
to, or the account of the EC2 instance role if the agent runs on EC2 without
keys.
These are two different settings.
bucket_arn: which bucket to read.
arn:aws:s3:::my-logs. Always required in bucket-polling mode.role_arn: an identity to assume.
arn:aws:iam::123456789012:role/AtatusLogReader. Only on this
page’s cross-account setup.What Atatus configures in AWS: nothing
Worth stating plainly, because it differs from most SaaS integrations. The agent runs on your machine and reads your bucket. The role is assumed between two accounts you control, so there is no Atatus AWS account to trust and no Atatus-issued external ID, so you choose both sides. The only thing that reaches Atatus is the log data, authenticated with the license key already inatatus.yml.
How it works
- The agent authenticates with whatever resolves first: the access keys in your config, or the EC2 instance role when there are none.
- Those credentials are used for one call only:
sts:AssumeRole. - AWS returns temporary credentials for the role.
- Every S3 and SQS call is signed with those, and the agent refreshes them before they expire.
Terminology used below
Two accounts, and it matters which is which:
Get both IDs before you start:
atatus-7f3c1b. It is not a secret AWS issues; it is a value you set on both
sides.
Step 1: Read policy (bucket account)
What the role is allowed to do. Save asread-policy.json, replacing the bucket
name:
Step 2: Trust policy (bucket account)
Who is allowed to assume the role. This is the piece that is usually wrong when things fail. Save astrust-policy.json and put the agent account ID in
Principal:
:root here does not mean the root user. It means “any
principal in that account that has been granted
sts:AssumeRole”, which is why Step 4 is also required. It is
the normal way to write this.Condition block and leave
external_id out of the agent config too. Setting it on one side only makes the
assume fail.
To restrict further, condition on the session name the agent uses:
Step 3: Create the role (bucket account)
Arn in the output is your role_arn:
Using the AWS console instead
Using the AWS console instead
- IAM → Roles → Create role
- Trusted entity type: AWS account → Another AWS account
- Enter the agent account ID
- Tick Require external ID and enter yours
- Skip permissions for now → name it
AtatusLogReader→ Create role - Open the role → Add permissions → Create inline policy → JSON → paste the read policy from Step 1
- Copy the ARN shown at the top of the role page
Step 4: Allow the assume (agent account)
The role trusts the account; now the identity inside it needs permission. Attach to the IAM user whose access key is in the config, or to the EC2 instance role:Step 5: Verify before touching the agent
Run this on the machine running the agent, with the credentials it will use. It should return a set of temporary credentials:unset those three, so the rest of your session
goes back to your own credentials.
That last command also gives you the real key path for bucket_list_prefix, so
copy it from the output rather than guessing.
Step 6: Configure the agent
Addrole_arn and external_id to the stanza in
/etc/atatus-infra-agent/conf.d/s3.d/s3.yml:
source:
and the prefix:
bucket_list_prefix contains the bucket account ID, because that
is whose logs are in the bucket.
Multiple accounts
One stanza per account, each with its own role. They collect in parallel:Configuration reference
Setting
external_id without role_arn is rejected at startup, because on its own it
would be silently ignored.
Troubleshooting
Errors appear in the agent log at/var/log/atatus-infra-agent/.
In the bucket owner’s CloudTrail, the agent’s assume appears with
roleSessionName: atatus-infra-agent, which makes it easy to tell apart from
anything else using the role.