Skip to main content

IAM Role Setup

To make onboarding even more flexible, nOps now supports integration using an IAM Role-based approach. This method allows customers to grant access using their own IAM policies without deploying a CloudFormation stack.

Prerequisites

To successfully set up the IAM Role integration with nOps, ensure the following:

  • You must have Administrator access to the AWS Management (Payer) account.
  • You must be able to create IAM Policies and IAM Roles.
  • You must have the Cost and Usage Report (CUR) enabled and configured to deliver data to an S3 bucket within your AWS account.
    • The CUR must meet all of the following mandatory criteria:
      • Granularity set to Hourly
      • Overwrite existing report option is enabled
      • Parquet selected as the compression format
      • Schema elements must include both "RESOURCES" and "SPLIT_COST_ALLOCATION_DATA"
  • You will need an External ID which will be provided by nOps.

Onboarding Master Payer with Full Permissions

In order to grant the role the required permissions, we need to create custom Policy(-ies) depending on the access you want to give nOps.

Step 1: Create the Integration Policy

To give nOps full access to ReadOnlyAccess and other services, you only need to create custom integration Policy.

  1. Go to IAM → Policies and click on Create Policy.
  2. Choose the JSON editor and paste the provided JSON.
  3. Click Next, specify a unique Policy Name, and click Create Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cur:DescribeReportDefinitions",
"cur:DeleteReportDefinition",
"cur:PutReportDefinition",
"s3:ListBucket",
"support:CreateCase",
"events:CreateEventBus",
"ce:*"
],
"Resource": "*"
},
{
"Effect": "Deny",
"Action": [
"acm-pca:Describe*",
"acm-pca:Get*",
"acm-pca:List*",
"acm:Describe*",
"acm:Get*",
"acm:List*",
"apigateway:GET",
"appconfig:GetConfiguration*",
"appflow:DescribeConnector*",
"appflow:ListConnector*",
"appstream:DescribeDirectoryConfigs",
"appstream:DescribeUsers",
"appstream:DescribeSessions",
"appsync:Get*",
"appsync:List*",
"athena:Get*",
"athena:List*",
"backup:GetBackupVaultAccessPolicy",
"cassandra:Select",
"chime:Describe*",
"chime:Get*",
"chime:List*",
"cloud9:Describe*",
"cloud9:Get*",
"cloud9:List*",
"clouddirectory:Get*",
"clouddirectory:List*",
"cloudfront:GetCloudFrontOriginAccessIdentity",
"cloudfront:GetFieldLevelEncryption*",
"cloudfront:GetKeyGroupConfig",
"cloudwatch:GetMetricData",
"cloudwatch:GetMetricStream",
"cloudwatch:ListMetricStreams",
"codeartifact:GetAuthorizationToken",
"codeartifact:ReadFromRepository",
"codebuild:BatchGet*",
"codebuild:ListSourceCredentials",
"codecommit:BatchGet*",
"codecommit:Get*",
"codecommit:GitPull",
"codedeploy:BatchGet*",
"codedeploy:Get*",
"codestar:DescribeUserProfile",
"codestar:ListUserProfiles",
"cognito-identity:*",
"cognito-idp:*",
"cognito-sync:*",
"comprehend:Describe*",
"comprehend:List*",
"config:BatchGetAggregateResourceConfig",
"config:BatchGetResourceConfig",
"config:SelectAggregateResourceConfig",
"config:SelectResourceConfig",
"connect:Describe*",
"connect:Get*",
"connect:List*",
"datapipeline:DescribeObjects",
"datapipeline:EvaluateExpression",
"datapipeline:QueryObjects",
"dax:BatchGetItem",
"dax:GetItem",
"dax:Query",
"deepcomposer:Get*",
"deepcomposer:List*",
"devicefarm:GetRemoteAccessSession",
"devicefarm:ListRemoteAccessSessions",
"directconnect:Describe*",
"directconnect:List*",
"discovery:Describe*",
"discovery:Get*",
"discovery:List*",
"dms:Describe*",
"dms:List*",
"ds:Get*",
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:Scan",
"ec2:GetConsoleScreenshot",
"ecr:BatchGetImage",
"ecr:GetAuthorizationToken",
"ecr:GetDownloadUrlForLayer",
"ecr-public:GetAuthorizationToken",
"eks:DescribeIdentityProviderConfig",
"elasticbeanstalk:DescribeConfigurationOptions",
"elasticbeanstalk:DescribeConfigurationSettings",
"es:ESHttpGet*",
"fis:GetExperimentTemplate",
"fms:GetAdminAccount",
"frauddetector:BatchGetVariable",
"frauddetector:Get*",
"gamelift:GetGameSessionLogUrl",
"gamelift:GetInstanceAccess",
"geo:ListDevicePositions",
"glue:GetSecurityConfiguration*",
"glue:SearchTables",
"glue:GetTable*",
"guardduty:GetIPSet",
"guardduty:GetMasterAccount",
"guardduty:GetMembers",
"guardduty:ListMembers",
"guardduty:ListOrganizationAdminAccounts",
"inspector2:GetConfiguration",
"imagebuilder:GetImage",
"iotsitewise:ListAccessPolicies",
"ivs:GetPlaybackKeyPair",
"ivs:GetStreamSession",
"kafka:GetBootstrapBrokers",
"kendra:Query*",
"kinesis:Get*",
"kms:DescribeKey",
"kms:GetPublicKey",
"lex:Get*",
"lambda:GetFunctionConfiguration",
"license-manager:GetGrant",
"license-manager:GetLicense",
"license-manager:ListTokens",
"lightsail:GetBucketAccessKeys",
"lightsail:GetCertificates",
"lightsail:GetContainerImages",
"lightsail:GetKeyPair",
"lightsail:GetRelationalDatabaseLogStreams",
"logs:GetLogEvents",
"logs:StartQuery",
"machinelearning:GetMLModel",
"macie2:GetAdministratorAccount",
"macie2:GetMember",
"macie2:GetMacieSession",
"macie2:SearchResources",
"macie2:GetSensitiveDataOccurrences",
"nimble:GetStreamingSession",
"polly:SynthesizeSpeech",
"proton:GetEnvironmentTemplate",
"proton:GetServiceTemplate",
"proton:ListServiceTemplates",
"proton:ListEnvironmentTemplates",
"qldb:GetBlock",
"qldb:GetDigest",
"rds:Download*",
"rekognition:CompareFaces",
"rekognition:Detect*",
"rekognition:Search*",
"resiliencehub:DescribeAppVersionTemplate",
"resiliencehub:ListRecommendationTemplates",
"robomaker:GetWorldTemplateBody",
"s3-object-lambda:GetObject",
"sagemaker:Search",
"schemas:GetDiscoveredSchema",
"sdb:Get*",
"sdb:Select*",
"secretsmanager:*",
"securityhub:GetFindings",
"securityhub:GetMembers",
"securityhub:ListMembers",
"ses:GetTemplate",
"ses:GetEmailTemplate",
"ses:GetContact",
"ses:GetContactList",
"ses:ListTemplates",
"ses:ListEmailTemplates",
"ses:ListVerifiedEmailAddresses",
"signer:GetSigningProfile",
"signer:ListProfilePermissions",
"signer:ListSigningProfiles",
"sms-voice:DescribeKeywords",
"sms-voice:DescribeOptedOutNumbers",
"sms-voice:DescribePhoneNumbers",
"sms-voice:DescribePools",
"snowball:Describe*",
"sqs:Receive*",
"ssm-contacts:*",
"ssm:DescribeParameters*",
"ssm:GetParameter*",
"sso:Describe*",
"sso:Get*",
"sso:List*",
"storagegateway:DescribeChapCredentials",
"support:DescribeCommunications",
"timestream:ListDatabases",
"timestream:ListTables",
"transcribe:Get*",
"transcribe:List*",
"transfer:Describe*",
"transfer:List*",
"waf-regional:GetChangeToken",
"workmail:DescribeUser",
"workmail:ListUsers"
],
"Resource": "*"
}
]
}

Step 2: Create the System Bucket Policy

To give nOps full access your bucket and reports generated, you need to create custom bucket Policy.

  1. Go to IAM → Policies and click on Create Policy.
  2. Choose the JSON editor and paste the provided JSON.
  3. Click Next, specify a unique Policy Name, and click Create Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketPolicy",
"s3:GetEncryptionConfiguration",
"s3:GetBucketVersioning",
"s3:GetBucketPolicyStatus",
"s3:GetBucketLocation",
"s3:GetBucketAcl",
"s3:GetBucketLogging",
"s3:GetObject",
"s3:PutBucketPolicy",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<example-bucket-name>",
"arn:aws:s3:::<example-bucket-name>/*"
]
}
]
}
note

You should put the name of your bucket configured with CUR in the Policy above.

Step 3: Create the Role

Now we are ready to create an IAM Role.

  1. Go to IAM → Roles, and click Create Role.
  2. Choose Custom trust policy, and paste the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::202279780353:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<generated>"
}
}
}
]
}
note

The ExternalId will be provided by nOps.

Full Permissions

In case of providing full read-only permissions, you should do the following:

  • Attach the AWS managed policy ReadOnlyAccess
  • Attach the custom Integration Policy created earlier
  • Attach the custom System Bucket Policy created earlier

After the role is created, share the following information via the nOps onboarding form:

  • The IAM Role ARN
  • Your S3 bucket name
  • Your CUR export name

Onboarding Master Payer with Minimum Permissions

If you don’t want to provide nOps full permissions, you can create 1–3 policies depending on your usage and attach them to the role.

Platform Permissions (Required)

This basic policy is required for minimum permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling-plans:DescribeScalingPlans",
"autoscaling-plans:GetScalingPlanResourceForecastData",
"autoscaling-plans:DescribeScalingPlanResources",
"autoscaling:DescribePolicies",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeLoadBalancers",
"autoscaling:DescribeScalingActivities",
"autoscaling:DescribeAccountLimits",
"apigateway:GET",
"ce:DescribeCostCategoryDefinition",
"ce:DescribeNotificationSubscription",
"ce:DescribeReport",
"ce:GetAnomalies",
"ce:GetAnomalyMonitors",
"ce:GetAnomalySubscriptions",
"ce:GetApproximateUsageRecords",
"ce:GetCostAndUsage",
"ce:GetCostAndUsageWithResources",
"ce:GetCostCategories",
"ce:GetCostForecast",
"ce:GetDimensionValues",
"ce:GetPreferences",
"ce:GetReservationCoverage",
"ce:GetReservationPurchaseRecommendation",
"ce:GetReservationUtilization",
"ce:GetRightsizingRecommendation",
"ce:GetSavingsPlanPurchaseRecommendationDetails",
"ce:GetSavingsPlansCoverage",
"ce:GetSavingsPlansPurchaseRecommendation",
"ce:GetSavingsPlansUtilization",
"ce:GetSavingsPlansUtilizationDetails",
"ce:GetTags",
"ce:GetUsageForecast",
"ce:ListCostAllocationTagBackfillHistory",
"ce:ListCostAllocationTags",
"ce:ListCostCategoryDefinitions",
"ce:ListSavingsPlansPurchaseRecommendationGeneration",
"ce:ListTagsForResource",
"ce:StartSavingsPlansPurchaseRecommendationGeneration",
"ce:UpdateCostAllocationTagsStatus",
"cloudtrail:DescribeTrails",
"cloudtrail:LookupEvents",
"cloudwatch:GetMetricStatistics",
"compute-optimizer:DescribeRecommendationExportJobs",
"compute-optimizer:GetAutoScalingGroupRecommendations",
"compute-optimizer:GetEBSVolumeRecommendations",
"compute-optimizer:GetEC2InstanceRecommendations",
"compute-optimizer:GetEC2RecommendationProjectedMetrics",
"compute-optimizer:GetECSServiceRecommendationProjectedMetrics",
"compute-optimizer:GetECSServiceRecommendations",
"compute-optimizer:GetEffectiveRecommendationPreferences",
"compute-optimizer:GetEnrollmentStatus",
"compute-optimizer:GetEnrollmentStatusesForOrganization",
"compute-optimizer:GetLambdaFunctionRecommendations",
"compute-optimizer:GetLicenseRecommendations",
"compute-optimizer:GetRDSDatabaseRecommendationProjectedMetrics",
"compute-optimizer:GetRDSDatabaseRecommendations",
"compute-optimizer:GetRecommendationPreferences",
"compute-optimizer:GetRecommendationSummaries",
"config:DescribeConfigurationRecorders",
"consolidatedbilling:GetAccountBillingRole",
"consolidatedbilling:ListLinkedAccounts",
"cost-optimization-hub:GetPreferences",
"cost-optimization-hub:GetRecommendation",
"cost-optimization-hub:ListEnrollmentStatuses",
"cost-optimization-hub:ListRecommendations",
"cost-optimization-hub:ListRecommendationSummaries",
"cost-optimization-hub:UpdateEnrollmentStatus",
"cost-optimization-hub:UpdatePreferences",
"cur:GetClassicReport",
"cur:GetClassicReportPreferences",
"cur:GetUsageReport",
"cur:DescribeReportDefinitions",
"cur:PutReportDefinition",
"dynamodb:ListTables",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeNatGateways",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeRegions",
"ec2:DescribeReservedInstances",
"ec2:DescribeVolumes",
"ec2:DescribeVpcs",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInstanceStatus",
"ec2:DescribeSnapshots",
"ec2:DescribeSecurityGroups",
"ecs:ListClusters",
"eks:ListTagsForResource",
"eks:ListClusters",
"eks:ListNodegroups",
"eks:DescribeCluster",
"eks:DescribeNodegroup",
"elasticache:DescribeCacheClusters",
"elasticache:DescribeCacheSubnetGroups",
"elasticfilesystem:DescribeFileSystems",
"elasticloadbalancing:DescribeLoadBalancers",
"es:DescribeElasticsearchDomains",
"es:ListDomainNames",
"events:ListRules",
"guardduty:ListDetectors",
"iam:GetRole",
"iam:GetAccountSummary",
"iam:ListAccountAliases",
"iam:ListAttachedUserPolicies",
"iam:ListRoles",
"iam:ListUsers",
"kms:Decrypt",
"lambda:GetFunction",
"lambda:GetPolicy",
"lambda:ListFunctions",
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"rds:DescribeDBSnapshots",
"rds:DescribeDBClusterSnapshotAttributes",
"rds:DescribeDBClusterSnapshots",
"rds:DescribeDBRecommendations",
"rds:DescribeDBSecurityGroups",
"rds:ListTagsForResource",
"redshift:DescribeClusters",
"s3:ListAllMyBuckets",
"s3:GetBucketVersioning",
"savingsplans:DescribeSavingsPlanRates",
"savingsplans:DescribeSavingsPlans",
"savingsplans:DescribeSavingsPlansOfferingRates",
"savingsplans:DescribeSavingsPlansOfferings",
"savingsplans:ListTagsForResource",
"support:CreateCase",
"support:DescribeCases",
"tag:GetResources",
"tag:GetTagValues",
"tag:DescribeReportCreation",
"tag:GetTagKeys",
"tag:GetComplianceSummary",
"organizations:ListAccounts",
"organizations:DescribeOrganization",
"organizations:ListRoots"
],
"Resource": "*"
}
]
}

Essentials Permissions

Use this policy if you plan to use the Essentials solution. You can add this policy at any time:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudwatch:ListMetrics",
"events:CreateEventBus",
"scheduler:GetSchedule",
"scheduler:GetScheduleGroup",
"scheduler:ListScheduleGroups",
"scheduler:ListSchedules",
"scheduler:ListTagsForResource"
],
"Resource": "*"
}
]
}

Compute Copilot Permissions (EKS/ECS/ASG/BATCH)

Use this policy if you plan to use Compute Copilot. You can add it whenever required:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeLaunchTemplateVersions",
"ec2:DescribeLaunchConfigurations",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypes",
"ec2:DescribeReservedInstances",
"lambda:InvokeFunction",
"cloudformation:ListStacks",
"cloudformation:DescribeStacks",
"savingsplans:DescribeSavingsPlans"
],
"Resource": "*"
}
]
}

IAM Role Setup

Now that the policies are created, you’re ready to create an IAM Role.

  1. Go to IAM → Roles and click on Create role.
  2. Choose Custom trust policy and paste the following JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::202279780353:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<generated>"
}
}
}
]
}

note

The ExternalId will be provided by nOps.

Minimum Permissions

Find and attach the following policies to the Role:

  • The Platform Permissions policy you created above for basic usage.
  • (Optional) The Essentials policy if you're using nOps Essentials.
  • (Optional) The Compute Copilot policy if you're using Compute Copilot features.

Once the policies are attached:

  1. Specify any meaningful Role name.
  2. Click on Create role.

After the role is created, share the following information via the nOps onboarding form:

  • The IAM Role name
  • Your S3 bucket name
  • Your CUR export name

This completes the minimum permissions onboarding setup for nOps.


Note: Please follow the same process for Child account onboarding as well — using either Full Permissions or Minimum Permissions, based on your organization's preference.