Skip to content

Instantly share code, notes, and snippets.

@alsmola
Last active March 23, 2026 21:11
Show Gist options
  • Select an option

  • Save alsmola/3ab81be2dca0e1825548346cef3642e8 to your computer and use it in GitHub Desktop.

Select an option

Save alsmola/3ab81be2dca0e1825548346cef3642e8 to your computer and use it in GitHub Desktop.

Verify AWS credentials and trailtool readiness

$ trailtool status
AWS credentials: OK (account XXXXXXXXXXXX)
Ingestor stack: OK (trailtool-ingestor)
Data access: OK

Good, trailtool is ready. Let me check the role for denied events.

Get SandboxPowerUser role details

$ trailtool roles detail SandboxPowerUser --format json
{
  "name": "AWSReservedSSO_SandboxPowerUser_XXXXXXXXXXXXXXXX",
  "account_id": "XXXXXXXXXXXX",
  "total_events": 60,
  "total_denied_events": 11,
  "top_denied_event_names": {
    "cloudtrail.amazonaws.com:LookupEvents": 1,
    "iam.amazonaws.com:GetRole": 3,
    "logs.amazonaws.com:GetLogEvents": 1
  },
  "denied_event_accesses": [
    {
      "service": "cloudtrail.amazonaws.com",
      "event_name": "LookupEvents",
      "count": 1,
      "error_message": "User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/AWSReservedSSO_SandboxPowerUser_XXXXXXXXXXXXXXXX/alex@engseclabs.com is not authorized to perform: cloudtrail:LookupEvents because no identity-based policy allows the cloudtrail:LookupEvents action"
    },
    {
      "service": "logs.amazonaws.com",
      "event_name": "GetLogEvents",
      "count": 1,
      "error_message": "User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/AWSReservedSSO_SandboxPowerUser_XXXXXXXXXXXXXXXX/alex@engseclabs.com is not authorized to perform: logs:GetLogEvents on resource: arn:aws:logs:us-east-1:XXXXXXXXXXXX:log-group:/aws/lambda/trailtool-ingestor:log-stream:2026/03/23/[$LATEST]2aefc3cf2b6e4a0da94ca867e23eb598 because no identity-based policy allows the logs:GetLogEvents action"
    },
    {
      "service": "iam.amazonaws.com",
      "event_name": "GetRole",
      "count": 3,
      "error_message": "User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/AWSReservedSSO_SandboxPowerUser_XXXXXXXXXXXXXXXX/alex@engseclabs.com is not authorized to perform: iam:GetRole on resource: role AWSReservedSSO_SandboxPowerUser_XXXXXXXXXXXXXXXX because no identity-based policy allows the iam:GetRole action"
    }
  ]
}

3 denied actions, all caused by missing identity-based policy permissions. Let me generate a policy that includes them.

Generate policy including denied actions

$ trailtool roles policy SandboxPowerUser --include-denied --explain --format json
{
  "total_actions_used": 37,
  "policy_json": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "cloudtrail:LookupEvents",
          "iam:GetRole",
          "logs:GetLogEvents"
        ],
        "Resource": ["*"]
      }
    ]
  }
}

The generated policy includes the 3 denied actions. Now let me compare against the current Terraform inline policy.

Review current inline policy in main.tf

The current policy has 6 statements. Comparing against the denied actions:

Denied Action Status Fix
cloudtrail:LookupEvents Missing from policy Add to GlobalReadOnly statement (Resource: *)
iam:GetRole Already in HCL but not yet deployed Will be applied with this change
logs:GetLogEvents Missing from policy Add to LogsTrailTool statement (scoped to trailtool log group)

Update inline policy in main.tf — added cloudtrail:LookupEvents to the GlobalReadOnly statement and logs:GetLogEvents to the LogsTrailTool statement, scoped to arn:aws:logs:*:*:log-group:/aws/lambda/trailtool-ingestor:*.

Verify the change with terraform plan

$ terraform plan
...
Terraform will perform the following actions:

  # aws_ssoadmin_permission_set_inline_policy.sandbox_power_user_policy will be updated in-place
  ~ inline_policy = jsonencode(
      ~ {
          ~ Statement = [
              ~ {
                  ~ Action = [
                        "cloudtrail:GetTrailStatus",
                      + "cloudtrail:LookupEvents",
                        ...
                        "health:DescribeEventAggregates",
                      + "iam:GetRole",
                        "kms:Decrypt",
                    ]
                },
              ~ {
                  ~ Action = [
                        "logs:DescribeLogStreams",
                      + "logs:GetLogEvents",
                    ]
                },
            ]
        }
    )

Plan: 0 to add, 1 to change, 0 to destroy.

Plan shows 1 in-place update — the inline policy gains the 3 missing permissions.

Apply the change

$ terraform apply -auto-approve
...
aws_ssoadmin_permission_set_inline_policy.sandbox_power_user_policy: Modifying...
aws_ssoadmin_permission_set_inline_policy.sandbox_power_user_policy: Modifications complete after 6s

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Summary:

  • 3 AccessDenied actions found for SandboxPowerUser via trailtool roles detail
  • 2 permissions added to main.tf:
    • cloudtrail:LookupEvents → GlobalReadOnly statement (Resource: *)
    • logs:GetLogEvents → LogsTrailTool statement (scoped to arn:aws:logs:*:*:log-group:/aws/lambda/trailtool-ingestor:*)
  • 1 permission already in HCL (iam:GetRole) — was pending apply, now deployed
  • terraform plan confirmed a single in-place update; terraform apply succeeded
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment