Overview
The provided CloudFormation templates create two IAM roles and their policies when you onboard an AWS account:
Managed policies:
aviatrix-assume-role-policyattaches toaviatrix-role-ec2and grantssts:AssumeRoleonaviatrix-*, plus marketplace metering ands3:GetBucketLocation.aviatrix-app-policyattaches toaviatrix-role-appand grants the full permission set described in The Application Permission Policy.
aviatrix-role-ec2, assumes aviatrix-role-app
(cross-account for managed accounts), and then performs AWS API calls. The
Controller does the bulk of the AWS work; a gateway needs very few runtime
permissions, though not zero (see
Gateway Logging to CloudWatch). Earlier
releases required broader gateway permissions, and Aviatrix has progressively
reduced that runtime dependency to improve security posture.
Keep the
aviatrix-app-policy action set consistent across the primary
account and every secondary account, especially if you maintain it manually
(see Custom and Scoped Permission
Policies). The roles themselves vary
slightly by account: the trust relationship on aviatrix-role-app differs
between the primary and secondary accounts by default, and differs further if
you harden it (see Trust Relationships
(Default) and Hardening the Trust
Policy).The Two IAM Roles in Detail
aviatrix-role-ec2 (Instance Role)
This role trusts only the EC2 service so it can act as an instance profile:aviatrix-assume-role-policy permission policy, as shipped:
aviatrix-role-app (Application Role)
The trust policy on this role controls which principal may assume it. Scoping that trust to the Controller’s instance role is Aviatrix’s primary hardening recommendation (see Hardening the Trust Policy). The permission policy attached to this role isaviatrix-app-policy.
Trust Relationships (Default)
The primary access account is the first account added to the Controller. If the Controller needs to build connectivity in an AWS account other than its own, you create a secondary access account, which requires IAM roles, policies, and a trust relationship back to the primary account. By default, the CloudFormation templates configureaviatrix-role-app to trust
account root (:root):
- Primary (Controller) account: trusts its own
:root. - Secondary (gateway) account (
aviatrix-secondary-account-iam.json, withOtherAccountNumberset to the Controller account): trusts both its own:rootand the Controller account’s:root:
:root means any suitably permissioned identity in the account can
assume the application role, including the gateway instance role
(aviatrix-role-ec2), which is allowed to assume aviatrix-*. That default is
reasonable for a dedicated-account deployment. For cleaner isolation between the
Controller and its gateways, scope this trust to the Controller’s role instead.
This is Aviatrix’s recommended best practice (see
Hardening the Trust Policy).
Inspect the current trust on any account:
The Application Permission Policy
The defaultaviatrix-app-policy for the latest software version is published
at
IAM_access_policy_for_CloudN.txt.
Both the CloudFormation and Terraform onboarding paths reference this file as
the default, and it is the reference for the current permission set. It is a
generic template built for broad compatibility. Aviatrix ships it as the default
but designed it to be customized: scope and harden it (see
Custom and Scoped Permission Policies)
to fit your environment.
Gateway Logging to CloudWatch
When you enable CloudWatch logging, the gateway itself ships its logs, and this does not useaviatrix-role-app. The gateway’s CloudWatch agent assumes a
dedicated CloudWatch role (the CloudWatch Log role ARN you configure,
cw_role_arn) using the gateway’s instance role, and the posting permissions
(logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents) live on
that role instead. Two consequences follow:
- Trust-pinning and policy-scoping of
aviatrix-role-app(see Hardening the Trust Policy and Custom and Scoped Permission Policies) do not affect CloudWatch logging. - The gateway instance role (
aviatrix-role-ec2) must retainsts:AssumeRoleto the CloudWatch role. The defaultaviatrix-*assume policy covers anaviatrix-named CloudWatch role; if you tighten the gateway role’s assume policy below that, also allow the CloudWatch role ARN.
Auditing and Updating Policies
Aviatrix audits each onboarded account and can update its policy from either CoPilot or the Controller.Prerequisites
- An AWS access account already onboarded to the Controller.
- Admin access to CoPilot or the Aviatrix Controller.
From CoPilot
1
Open the Cloud Account page
Go to Cloud Resources > Cloud Account.
2
Select the accounts to audit or update
Select the checkboxes for the AWS accounts you want to audit, or the
accounts with IAM policies you want to update. You can select multiple
AWS accounts.
3
Run the action
Click the Actions menu and select Audit or Update IAM
Policy. You can also run an audit from the More
menu.

The Update IAM Policy option applies only to AWS accounts; if you select
non-AWS cloud accounts when updating policies, Aviatrix skips them during the
update. AWS saves the current policy version and retains up to 5 latest
non-default versions.
From the Aviatrix Controller
1
Open Access Accounts
Select Accounts > Access Accounts from the left-hand menu.
2
Audit the account
Select an AWS account and click Audit near the top of the page. If
the account needs an update, the Account Audit text at the top of the
page reads “[Account Name] is not using the latest IAM policy.”
3
Update the policy
If the account is not using the latest IAM policy, click Update
Policy to update it.
- The permission policy. It compares the attached
aviatrix-app-policyaction set (not resources) against the Controller’s latest. A missing action reports “not using the latest IAM policy — Missing policy list (…)” with statusPass*, and Update Policy adds the missing actions. The audit also requires a managed policy literally namedaviatrix-app-policy; permissions attached inline or under another name report “No policy associated to aviatrix-role-app.” - The trust relationship. The audit also checks the trust, and today it passes only if the account’s own account number appears in the trust principals. This has a side effect on hardening; see the callout under Known Issue: Audit False Positive on Secondary Accounts.
Custom IAM Role Names
If the primary access account uses a custom EC2 IAM role name for the Controller, every secondary IAM-based access account must use an identical EC2 IAM role name. The primary and secondary access accounts must use identical role names when both of the following are true:- The primary access account uses custom IAM roles.
- The secondary account does not use custom gateway IAM roles.
custom-role-app and custom-role-ec2 on a
secondary access account. custom-role-ec2 also exists on the primary account,
because that is where the Controller runs. When you launch a gateway under the
secondary access account, the Controller takes the primary access account’s EC2
role name (custom-role-ec2) and passes it to the API call that creates the
instance. That API call refers to a role on the secondary CSP account, not the
role of the primary account.
Hardening the Trust Policy
Recommended best practice. Scopeaviatrix-role-app’s trust to the
Controller’s instance role instead of :root. This creates clean isolation
between the Controller, which manages the account, and the gateways, and is the
configuration Aviatrix recommends for production:
aviatrix-role-ec2; only that role can. This keeps the control plane
(Controller) and data plane (gateways) cleanly separated.
Hardening behaves differently depending on your topology:
- Gateways in a separate account (recommended): scoping the trust gives clean role isolation. The Controller’s role lives in a different account, and only it can assume the application role.
- Gateways in the Controller account: the gateways share the same instance role you are scoping to, so trust scoping alone does not separate the two. Running the Controller and gateways in separate accounts, the recommended model, gives the cleanest isolation.
aviatrix-role-ec2. A
principal running as the gateway’s own instance role is limited to what that
role allows and cannot assume aviatrix-role-app. ExternalId is a third-party
delegated-access control; scoping the trust to the Controller’s role is the
self-managed equivalent.
Known Issue: Audit False Positive on Secondary Accounts
Why it is safe to ignore: This is a cosmetic false positive. The audit only reads the trust and never reverts it, so the finding has no functional effect. The Controller/primary account is unaffected, because its pinned role lives in that same account. Optional workaround (to show a green audit): Add the account’s ownaviatrix-role-app ARN to the trust alongside the Controller role:
aviatrix-role-app is inert, because only something
already running as that role could match it. It satisfies the audit with no real
impact on your permission scope and does not grant the gateway instance role any
access; the isolation still holds.
Status: A future release will fix this so the Controller-role-pinned trust
passes the audit natively.
Custom and Scoped Permission Policies
Trust scoping isolates the roles; scopingaviatrix-app-policy is a further,
optional layer of least privilege that narrows what the application role can do.
Aviatrix supports customer-customized policies. Scope incrementally and test
each change per feature.
Tier 1 (Highest Impact): Scope the IAM Self-Update Permissions
Policy self-update, scoped to its own ARN. By default,iam:CreatePolicyVersion grants access on Resource: "*", which allows edits
to any managed policy in the account. Scoping it to the role’s own policy is a
recommended tightening and resolves the common scanner finding (for example,
from Wiz) on this permission:
- The Controller’s Audit/Update Policy function requires these permissions to
maintain
aviatrix-app-policy. Without them, the policy no longer updates automatically when a new software version or feature introduces additional permission requirements. - The account audit then reports the policy as out of date. Because a failed audit surfaces as an account health state, external account monitoring can raise false-positive alerts on these accounts even though they operate correctly.
- You maintain the policy externally instead: incorporate any new permission
requirements, published in
IAM_access_policy_for_CloudN.txt, into your customized policy and apply it across the primary account and all secondary accounts.
aviatrix-*:
Keep
iam:CreateServiceLinkedRole on Resource: "*" if present. AWS controls
service-linked-role names (for example, ELB’s), so scoping this action breaks
their creation.aviatrix-role-ec2, creating and attaching its instance profile, and
creating service-linked roles.