> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ankra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS Credentials

> Connect AWS to Ankra with an IAM role created by a CloudFormation stack, or with access keys - read-only for cost estimates and inventory, or with provisioning permissions to create EKS clusters.

AWS credentials let Ankra estimate the infrastructure cost of your clusters, sync cloud inventory, and provision [Amazon EKS](/guides/eks-clusters). There are two access levels, and you choose which one to grant:

* **Read-only** - cost estimates, pricing data, and cluster discovery only. Ankra never provisions or modifies AWS resources.
* **EKS provisioning** - everything read-only does, plus creating and managing EKS clusters.

There are also two ways to connect. The **IAM role** method (recommended) launches a one-click CloudFormation stack that creates a role Ankra assumes with short-lived credentials, secured by a unique external ID - no long-lived keys to store or rotate. The **access keys** method stores an access key ID and secret for an IAM user - simpler to set up, but you own key rotation, and the access level is whatever the user's IAM policy allows.

The credential is validated when you save it: the IAM role method performs a real `sts:AssumeRole` call against your role, and access keys are checked with a read-only `sts:GetCallerIdentity` call - so a role that can't be assumed or a key AWS rejects is refused immediately.

## What Ankra Accesses

For cost estimation and inventory, Ankra calls these AWS APIs, all read-only:

| Service       | Actions                                                                                                                                           | Why it's used                                                                                                       |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Pricing       | `pricing:GetProducts`, `pricing:DescribeServices`                                                                                                 | Read the public price catalog to estimate node costs                                                                |
| Cost Explorer | `ce:GetCostAndUsage`, `ce:GetCostForecast`                                                                                                        | Read your account's actual spend and forecast                                                                       |
| EC2           | `ec2:DescribeInstanceTypes`, `ec2:DescribeInstanceTypeOfferings`, `ec2:DescribeAvailabilityZones`, `ec2:DescribeRegions`, `ec2:DescribeInstances` | Read instance-type specs (vCPU and memory), region and zone availability, and running instances to price your nodes |
| EKS           | `eks:ListClusters`, `eks:DescribeCluster`                                                                                                         | Discover the EKS clusters in your account                                                                           |
| STS           | `sts:GetCallerIdentity`                                                                                                                           | Verify the credential works (the **Test connection** check)                                                         |

Provisioning EKS additionally uses:

| Service | Actions                                                                                                                                                                                                                                    | Why it's used                                                                                                                                           |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| EKS     | `eks:*`                                                                                                                                                                                                                                    | Create, upgrade, scale, and delete EKS clusters and managed node groups                                                                                 |
| EC2     | `ec2:Describe*`                                                                                                                                                                                                                            | Discover default-VPC subnets and spot price history when creating clusters. Ankra never creates or modifies EC2 resources - node groups are EKS-managed |
| IAM     | `iam:CreateRole`, `iam:DeleteRole`, `iam:AttachRolePolicy`, `iam:DetachRolePolicy`, `iam:PutRolePolicy`, `iam:DeleteRolePolicy`, `iam:GetRole`, `iam:GetRolePolicy`, `iam:ListRolePolicies`, `iam:ListAttachedRolePolicies`, `iam:TagRole` | Manage the two IAM roles Ankra creates per cluster (`ankra-eks-cluster-<name>` and `ankra-eks-node-<name>`) - restricted to roles named `ankra-eks-*`   |
| IAM     | `iam:PassRole`                                                                                                                                                                                                                             | Attach the `ankra-eks-*` roles to the EKS control plane and to node-group instances - only passable to `eks.amazonaws.com` and `ec2.amazonaws.com`      |
| IAM     | `iam:CreateServiceLinkedRole`                                                                                                                                                                                                              | Let EKS auto-create its service-linked roles on first use in an account - restricted to the EKS, EKS node group, and Auto Scaling services              |

The IAM permissions are deliberately narrow: role management applies only to roles named `ankra-eks-*` (the ones Ankra itself creates), and `iam:PassRole` is conditioned so those roles can only be passed to EKS and EC2. Ankra cannot touch any other IAM role in your account.

With the IAM role method, these are exactly the policies the CloudFormation stack creates - you can review the templates before deploying ([read-only](https://ankra-templates.s3.eu-north-1.amazonaws.com/aws/v1/ankra-cloud-cost-readonly.cfn.yaml), [provisioning](https://ankra-templates.s3.eu-north-1.amazonaws.com/aws/v1/ankra-provisioning.cfn.yaml)). The role's trust policy only allows Ankra's AWS principal to assume it, and only when the request carries your external ID, with sessions capped at one hour - Ankra never stores AWS keys for a role credential. With access keys, you attach equivalent policies to an IAM user yourself - the **Access keys** tab below includes ready-made policy JSON for both levels.

## Creating an AWS Credential

Pick the tab that matches what you want the credential to do. Each flow is complete - follow one from top to bottom. The two IAM-role flows are identical except for which CloudFormation template you launch.

<Tabs>
  <Tab title="Read-only (cost and inventory)">
    Creates a role (`AnkraCloudCostReadOnly` by default) with the read-only actions from [What Ankra Accesses](#what-ankra-accesses). Ankra can price your nodes, read your spend, and discover clusters, but cannot create or change anything.

    You will move between two browser tabs - the Ankra credential dialog and the AWS CloudFormation console - and need an AWS account where you may create CloudFormation stacks and IAM roles (for example `AdministratorAccess`, or CloudFormation plus IAM write permissions). The whole flow takes about five minutes.

    <Steps>
      <Step title="Start the wizard in Ankra">
        Go to **Credentials** → **Add** → **AWS** and pick **Read-only (cost & inventory)**. Enter a credential name.

        The dialog shows your unique **external ID** (it starts with `ankra-`). This ID ties the role to your organisation and is pre-filled in the stack you are about to launch - you don't need to copy it anywhere.

        <Warning>
          Keep this dialog open until you finish. A fresh external ID is generated each time you open the wizard - if you close it and start again after creating the stack, the new ID won't match your stack and the connection will fail. See [troubleshooting](#troubleshooting-aws-credentials) if this happens.
        </Warning>
      </Step>

      <Step title="Launch the CloudFormation stack">
        Click **Launch CloudFormation stack**. This opens the AWS console's quick-create page in a new tab, with everything pre-filled: the template, the stack name (`AnkraCloudCostReadOnly`), your external ID, and the Ankra principal that will assume the role.

        1. If prompted, sign in to the AWS account you want to connect.
        2. Leave the `ExternalId` and `AnkraPrincipalArn` parameters unchanged. You can rename the stack or role if your organisation requires it.
        3. Tick **I acknowledge that AWS CloudFormation might create IAM resources with custom names** at the bottom of the page.
        4. Click **Create stack**.
      </Step>

      <Step title="Wait for CREATE_COMPLETE">
        The stack creates a single IAM role and nothing else, and usually finishes in under a minute. Wait until the stack status shows `CREATE_COMPLETE` (use the refresh button on the stack page).
      </Step>

      <Step title="Copy the Role ARN from the Outputs tab">
        On the stack page, open the **Outputs** tab and copy the value of the `RoleArn` output. It looks like:

        ```
        arn:aws:iam::<account-id>:role/AnkraCloudCostReadOnly
        ```

        If you don't see an Outputs tab, the stack hasn't finished creating yet, or you are looking at a different stack.
      </Step>

      <Step title="Add to Ankra (UI)">
        Back in the Ankra dialog, paste the ARN into **Role ARN**. Set the **Default region** to the region you want Ankra to use for cost data.

        Click **Test connection** - Ankra performs a real `sts:AssumeRole` call against your new role, and on success you'll see "AWS role assumed successfully". Then click **Connect AWS account** to save. The credential now appears in your credentials list and is used automatically for cost and inventory sync.
      </Step>
    </Steps>
  </Tab>

  <Tab title="EKS provisioning">
    Creates a role (`AnkraProvisioning` by default) that can manage [EKS clusters](/guides/eks-clusters) and the `ankra-eks-*` IAM roles Ankra creates for them, plus all the read-only actions - so a single provisioning credential also powers cost estimates and inventory.

    You will move between two browser tabs - the Ankra credential dialog and the AWS CloudFormation console - and need an AWS account where you may create CloudFormation stacks and IAM roles (for example `AdministratorAccess`, or CloudFormation plus IAM write permissions). The whole flow takes about five minutes.

    <Steps>
      <Step title="Start the wizard in Ankra">
        Go to **Credentials** → **Add** → **AWS** and pick **Provisioning (EKS clusters)**. Enter a credential name.

        The dialog shows your unique **external ID** (it starts with `ankra-`). This ID ties the role to your organisation and is pre-filled in the stack you are about to launch - you don't need to copy it anywhere.

        <Warning>
          Keep this dialog open until you finish. A fresh external ID is generated each time you open the wizard - if you close it and start again after creating the stack, the new ID won't match your stack and the connection will fail. See [troubleshooting](#troubleshooting-aws-credentials) if this happens.
        </Warning>
      </Step>

      <Step title="Launch the CloudFormation stack">
        Click **Launch CloudFormation stack**. This opens the AWS console's quick-create page in a new tab, with everything pre-filled: the template, the stack name (`AnkraProvisioning`), your external ID, and the Ankra principal that will assume the role.

        1. If prompted, sign in to the AWS account you want to connect.
        2. Leave the `ExternalId` and `AnkraPrincipalArn` parameters unchanged. You can rename the stack or role if your organisation requires it, and set the optional `PermissionsBoundaryArn` parameter if your organisation requires a permissions boundary on new roles.
        3. Tick **I acknowledge that AWS CloudFormation might create IAM resources with custom names** at the bottom of the page.
        4. Click **Create stack**.
      </Step>

      <Step title="Wait for CREATE_COMPLETE">
        The stack creates a single IAM role and nothing else, and usually finishes in under a minute. Wait until the stack status shows `CREATE_COMPLETE` (use the refresh button on the stack page).
      </Step>

      <Step title="Copy the Role ARN from the Outputs tab">
        On the stack page, open the **Outputs** tab and copy the value of the `RoleArn` output. It looks like:

        ```
        arn:aws:iam::<account-id>:role/AnkraProvisioning
        ```

        If you don't see an Outputs tab, the stack hasn't finished creating yet, or you are looking at a different stack.
      </Step>

      <Step title="Add to Ankra (UI)">
        Back in the Ankra dialog, paste the ARN into **Role ARN**. Set the **Default region** to the region you want Ankra to use for cost data and as the default for new EKS clusters.

        Click **Test connection** - Ankra performs a real `sts:AssumeRole` call against your new role, and on success you'll see "AWS role assumed successfully". Then click **Connect AWS account** to save.
      </Step>

      <Step title="Create your first EKS cluster">
        With the credential saved, follow [Amazon EKS](/guides/eks-clusters) to provision a cluster from the portal, CLI, or API.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Access keys">
    Stores an access key ID and secret for an IAM user. What the credential can do is determined entirely by the user's IAM policy - attach the read-only policy for cost and inventory, or the provisioning policy to also create EKS clusters.

    <Steps>
      <Step title="Create a least-privilege IAM policy">
        In AWS IAM, create a policy with exactly the permissions Ankra uses - these mirror the CloudFormation templates from the IAM-role method.

        For cost and inventory only:

        ```json Read-only policy theme={null}
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "PricingAndInventory",
              "Effect": "Allow",
              "Action": [
                "pricing:GetProducts",
                "pricing:DescribeServices",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeInstanceTypeOfferings",
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeRegions",
                "ec2:DescribeInstances"
              ],
              "Resource": "*"
            },
            {
              "Sid": "CostExplorer",
              "Effect": "Allow",
              "Action": ["ce:GetCostAndUsage", "ce:GetCostForecast"],
              "Resource": "*"
            },
            {
              "Sid": "ClusterDiscovery",
              "Effect": "Allow",
              "Action": [
                "eks:ListClusters",
                "eks:DescribeCluster",
                "sts:GetCallerIdentity"
              ],
              "Resource": "*"
            }
          ]
        }
        ```

        To also provision EKS clusters, use this instead (a superset of the read-only policy):

        ```json Provisioning policy theme={null}
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "EksLifecycle",
              "Effect": "Allow",
              "Action": "eks:*",
              "Resource": "*"
            },
            {
              "Sid": "Ec2Read",
              "Effect": "Allow",
              "Action": "ec2:Describe*",
              "Resource": "*"
            },
            {
              "Sid": "PricingAndCostRead",
              "Effect": "Allow",
              "Action": [
                "pricing:GetProducts",
                "pricing:DescribeServices",
                "ce:GetCostAndUsage",
                "ce:GetCostForecast",
                "sts:GetCallerIdentity"
              ],
              "Resource": "*"
            },
            {
              "Sid": "IamForEksRoles",
              "Effect": "Allow",
              "Action": [
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:AttachRolePolicy",
                "iam:DetachRolePolicy",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "iam:ListRolePolicies",
                "iam:ListAttachedRolePolicies",
                "iam:TagRole"
              ],
              "Resource": "arn:aws:iam::*:role/ankra-eks-*"
            },
            {
              "Sid": "IamServiceLinkedRoles",
              "Effect": "Allow",
              "Action": "iam:CreateServiceLinkedRole",
              "Resource": "arn:aws:iam::*:role/aws-service-role/*",
              "Condition": {
                "StringEquals": {
                  "iam:AWSServiceName": [
                    "eks.amazonaws.com",
                    "eks-nodegroup.amazonaws.com",
                    "autoscaling.amazonaws.com"
                  ]
                }
              }
            },
            {
              "Sid": "IamPassRole",
              "Effect": "Allow",
              "Action": "iam:PassRole",
              "Resource": "arn:aws:iam::*:role/ankra-eks-*",
              "Condition": {
                "StringEquals": {
                  "iam:PassedToService": [
                    "eks.amazonaws.com",
                    "ec2.amazonaws.com"
                  ]
                }
              }
            }
          ]
        }
        ```

        If you prefer AWS-managed policies over least privilege, the read-only level is roughly covered by `ReadOnlyAccess` plus `Billing` - but the explicit policies above grant only what Ankra actually calls.
      </Step>

      <Step title="Create an IAM user and access key">
        1. In AWS IAM, create a user (or pick an existing one) and attach the policy from the previous step.
        2. Open the user → **Security credentials** → **Create access key**, and choose a use case such as **Third-party service**.
        3. Copy the access key ID and secret access key - the secret is shown only once.
      </Step>

      <Step title="Add to Ankra (UI)">
        Go to **Credentials** → **Add** → **AWS** → **Access keys**, then provide:

        * **Name**: a unique identifier for the credential
        * **Access key ID** and **Secret access key**: the values from the previous step

        When you save, Ankra verifies the keys with a read-only `sts:GetCallerIdentity` call.
      </Step>
    </Steps>

    <Note>
      Use the IAM role method where you can - it avoids storing long-lived secrets, and access is revocable on the AWS side by deleting the CloudFormation stack. With access keys, you own rotation: rotate the key in IAM and update the credential in Ankra.
    </Note>
  </Tab>
</Tabs>

<Note>
  Already added a read-only credential and want to provision EKS? The access level of an IAM-role credential is fixed when it is created and there is no edit flow. Run the **EKS provisioning** tab again under a new credential name, then delete the old read-only credential in Ankra and its CloudFormation stack in AWS.
</Note>

## Revoking Access

For an IAM-role credential, delete the CloudFormation stack in AWS - this deletes the role, and no further access is possible. For an access-keys credential, deactivate or delete the access key in IAM. Then delete the credential in Ankra.

<Warning>
  Revoking on the AWS side while the credential is still in use breaks cost sync and, at the provisioning level, Ankra's ability to manage your EKS clusters. Delete or replace the Ankra credential first if clusters depend on it.
</Warning>

## Troubleshooting AWS Credentials

The table below covers the **Test connection** result in the Ankra UI:

| Test connection result                                                                 | Cause                                                                                                                                      | Solution                                                                                                                                                      |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AWS denied the role assumption. Check the role trust policy and external ID.           | The stack hasn't finished, the external ID doesn't match, the ARN is wrong or points to a nonexistent role, or the trust policy was edited | Wait for `CREATE_COMPLETE`; verify you copied the `RoleArn` value from the stack's **Outputs** tab (not the stack ARN); for an external ID mismatch see below |
| AWS rejected the supplied credentials.                                                 | The access key is deactivated or deleted, or the secret was mistyped                                                                       | Check the key is active in IAM, or create a new access key and re-paste both values                                                                           |
| Could not reach the AWS STS endpoint.                                                  | Network or connectivity issue, or an invalid default region                                                                                | Check the **Default region** is a valid AWS region and retry                                                                                                  |
| Could not validate the AWS credentials. Check the access key id and secret access key. | Shown on save when validation fails - for either connection method, all causes collapse to this one message                                | Click **Test connection** to get the specific message, then use the rows above                                                                                |
| An AWS credential with this name already exists.                                       | Credential names are unique per organisation                                                                                               | Pick a different name, or delete the old credential first if you are replacing it                                                                             |

**External ID mismatch** is the most common cause of a denied role assumption: a fresh external ID is generated each time the wizard opens, so if you closed and reopened the Ankra dialog after launching the stack, the stack carries an old ID. Fix it in AWS: on the stack page choose **Update** → **Use existing template**, replace the `ExternalId` parameter with the ID currently shown in the Ankra dialog, and update the stack. Alternatively, delete the stack and relaunch it from the current dialog. Note that AWS reports a nonexistent role as the same access-denied error, so double-check the ARN too.

**Test connection** only verifies that the role can be assumed (or that the keys are valid) - it does not inspect the attached permissions. If the credential saves fine but cost data stays empty, inventory doesn't appear, or EKS cluster creation fails with `AccessDenied`, the role or user is missing actions from the tables in [What Ankra Accesses](#what-ankra-accesses). For a stack-created role that usually means the template was modified - update the stack back to the published template. For an access-keys user, re-check the policy against the JSON in the **Access keys** tab.
