Skip to main content
Aviatrix uses AWS IAM roles to give the Controller and gateways the permissions they need to build and secure your cloud network. For AWS access accounts, Aviatrix recommends authenticating with IAM roles instead of static access keys. IAM roles avoid long-lived credentials and are the default onboarding method when the Controller runs in AWS. Aviatrix also supports access key and secret authentication, and this method is required when the Controller runs in a different cloud than AWS (for example, Azure or GCP) and manages an AWS account, because no AWS EC2 instance is available to attach an IAM role to. In this case, leave the IAM roles checkbox unmarked when you add the AWS access account, and provide an access key and secret instead. Setting Up Additional Access Accounts for Different Clouds shows the CoPilot and Controller steps for adding an AWS access account. Account with Access Key for AWS China Accounts describes the access-key onboarding method.

Overview

The provided CloudFormation templates create two IAM roles and their policies when you onboard an AWS account: Managed policies:
  • aviatrix-assume-role-policy attaches to aviatrix-role-ec2 and grants sts:AssumeRole on aviatrix-*, plus marketplace metering and s3:GetBucketLocation.
  • aviatrix-app-policy attaches to aviatrix-role-app and grants the full permission set described in The Application Permission Policy.
The Controller runs as 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:
The 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 is aviatrix-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 configure aviatrix-role-app to trust account root (:root):
  • Primary (Controller) account: trusts its own :root.
  • Secondary (gateway) account (aviatrix-secondary-account-iam.json, with OtherAccountNumber set to the Controller account): trusts both its own :root and the Controller account’s :root:
Trusting :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 default aviatrix-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 use aviatrix-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 retain sts:AssumeRole to the CloudWatch role. The default aviatrix-* assume policy covers an aviatrix-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 MoreMore menu iconmenu.
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 audit reports on two independent things:
  • The permission policy. It compares the attached aviatrix-app-policy action set (not resources) against the Controller’s latest. A missing action reports “not using the latest IAM policy — Missing policy list (…)” with status Pass*, and Update Policy adds the missing actions. The audit also requires a managed policy literally named aviatrix-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.
As of version 9.0, the policy audit compares the policy’s action set only, not resource scoping. A customized policy that keeps the same actions while narrowing resources continues to pass the action check and is recognized as customized. When a later version introduces new required actions, the Controller appends them to your customized policy instead of overwriting it, so your customization persists across upgrades.

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.
Example: The Controller uses 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. Scope aviatrix-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:
The Controller continues to assume the role cross-account as its own 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.
With the trust scoped, the Controller continues to build and manage the account normally, because it assumes the role as its own 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

The account audit’s trust check requires the account’s own account number to appear in the trust. After you scope a secondary/gateway account’s trust to the Controller role, the audit reports “does not have a trusted relationship with its own account” for that account.
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 own aviatrix-role-app ARN to the trust alongside the Controller role:
The self-reference to 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; scoping aviatrix-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:
With this scoping, the role can version only its own policy, not others in the account. For the tightest security posture, you can remove these two permissions entirely instead of scoping them. Review these caveats first:
  • 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.
PassRole and instance-profile management, scoped to 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.
These scopings retain everything the Controller needs to launch gateways: passing aviatrix-role-ec2, creating and attaching its instance profile, and creating service-linked roles.