Create Least Privilege Policies

As part of your account preparation, you will create least privilege policies—individual policies you will attach to your cross-account role that allow CloudCheckr to access the AWS data it needs to create its reports.

Each least privilege policy provides permissions to a core function in our application:

  • Cost
  • Billing
  • Security/Compliance
  • Inventory
  • CloudTrail
  • CloudWatch Flow Logs

Although it may seem like one big policy would be easier to manage, applying these policies separately ensures that whoever uses the cross-account role only has access to the permissions they need to do their job—and nothing more.

This procedure will show you how to create the least privileged policies in the AWS Management Console.


Procedure

  1. Log in to the AWS Management Console.

    The AWS services page opens.

  2. Scroll down to the Security, Identity & Compliance section and select IAM.

    The Welcome to Identity and Access Management screen displays.

  3. From the dashboard, click Policies.

    A list of policies displays.

  4. Click Create policy.

    The Create Policy page opens.

  5. For each core function of CloudCheckr that you want a cross-account role to have access to, follow these steps:
    1. Click a button to display the selected policy document.

      {  
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"CloudCheckrCostPermissions",
      "Effect":"Allow",
      "Action":[
      "ce:GetReservationUtilization",
      "ec2:DescribeAccountAttributes",
      "ec2:DescribeAvailabilityZones",
      "ec2:DescribeReservedInstancesOfferings",
      "ec2:DescribeReservedInstances",
      "ec2:DescribeReservedInstancesListings",
      "ec2:DescribeHostReservationOfferings",
      "ec2:DescribeReservedInstancesModifications",
      "ec2:DescribeHostReservations",
      "ec2:DescribeInstances",
      "ec2:DescribeInstanceStatus",
      "ec2:DescribeRegions",
      "ec2:DescribeKeyPairs",
      "ec2:DescribePlacementGroups",
      "ec2:DescribeAddresses",
      "ec2:DescribeSpotInstanceRequests",
      "ec2:DescribeImages",
      "ec2:DescribeImageAttribute",
      "ec2:DescribeSnapshots",
      "ec2:DescribeVolumes",
      "ec2:DescribeTags",
      "ec2:DescribeNetworkInterfaces",
      "ec2:DescribeSecurityGroups",
      "ec2:DescribeInstanceAttribute",
      "ec2:DescribeVolumeStatus",
      "elasticache:DescribeReservedCacheNodes",
      "elasticache:DescribeReservedCacheNodesOfferings",
      "rds:DescribeReservedDBInstances",
      "rds:DescribeReservedDBInstancesOfferings",
      "rds:DescribeDBInstances",
      "redshift:DescribeReservedNodes",
      "redshift:DescribeReservedNodeOfferings",
      "s3:GetBucketACL",
      "s3:GetBucketLocation",
      "s3:GetBucketLogging",
      "s3:GetBucketPolicy",
      "s3:GetBucketTagging",
      "s3:GetBucketWebsite",
      "s3:GetBucketNotification",
      "s3:GetLifecycleConfiguration",
      "s3:GetNotificationConfiguration",
      "s3:List*",
      "dynamodb:DescribeReservedCapacity",
      "dynamodb:DescribeReservedCapacityOfferings",
      "iam:GetAccountAuthorizationDetails",
      "iam:ListRolePolicies",
      "iam:ListAttachedRolePolicies"
      ],
      "Resource":"*"
      }
      ]
      }

      {
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"CostReadDBR",
      "Effect":"Allow",
      "Action":[
      "s3:GetBucketACL",
      "s3:GetBucketLocation",
      "s3:GetBucketLogging",
      "s3:GetBucketPolicy",
      "s3:GetBucketTagging",
      "s3:GetBucketWebsite",
      "s3:GetBucketNotification",
      "s3:GetLifecycleConfiguration",
      "s3:GetNotificationConfiguration",
      "s3:GetObject"
      ],
      "Resource":[
      "arn:aws:s3:::[YOUR DETAILED BILLING REPORT BUCKET]",
      "arn:aws:s3:::[YOUR DETAILED BILLING REPORT BUCKET]/*",
      ]
      }
      ]
      }

      {
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"CostReadCUR",
      "Effect":"Allow",
      "Action":[
      "s3:GetObject"
      ],
      "Resource":[
      "arn:aws:s3::[YOUR COST AND USAGE REPORT BUCKET]",
      "arn:aws:s3::[YOUR COST AND USAGE REPORT BUCKET]/*"
      ]
      }
      ]
      }

      { 
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"SecurityPermissons",
      "Effect":"Allow",
      "Action":[
      "acm:DescribeCertificate",
      "acm:ListCertificates",
      "acm:GetCertificate",
      "cloudtrail:DescribeTrails",
      "cloudtrail:GetTrailStatus",
      "logs:GetLogEvents",
      "logs:DescribeLogGroups",
      "logs:DescribeLogStreams",
      "config:DescribeConfigRules",
      "config:GetComplianceDetailsByConfigRule",
      "config:DescribeDeliveryChannels",
      "config:DescribeDeliveryChannelStatus",
      "config:DescribeConfigurationRecorders",
      "config:DescribeConfigurationRecorderStatus",
      "ec2:Describe*",
      "iam:Get*",
      "iam:List*",
      "iam:GenerateCredentialReport",
      "kms:DescribeKey",
      "kms:GetKeyPolicy",
      "kms:GetKeyRotationStatus",
      "kms:ListAliases",
      "kms:ListGrants",
      "kms:ListKeys",
      "kms:ListKeyPolicies",
      "kms:ListResourceTags",
      "rds:Describe*",
      "ses:ListIdentities",
      "ses:GetSendStatistics",
      "ses:GetIdentityDkimAttributes",
      "ses:GetIdentityVerificationAttributes",
      "ses:GetSendQuota",
      "sns:GetSnsTopic",
      "sns:GetTopicAttributes",
      "sns:GetSubscriptionAttributes",
      "sns:ListTopics",
      "sns:ListSubscriptionsByTopic",
      "sqs:ListQueues",
      "sqs:GetQueueAttributes"
      ],
      "Resource":"*"
      }
      ]
      }

      {
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"InventoryAndUtilization",
      "Effect":"Allow",
      "Action":[
      "acm:DescribeCertificate",
      "acm:ListCertificates",
      "acm:GetCertificate",
      "ec2:Describe*",
      "ec2:GetConsoleOutput",
      "autoscaling:Describe*",
      "cloudformation:DescribeStacks",
      "cloudformation:GetStackPolicy",
      "cloudformation:GetTemplate",
      "cloudformation:ListStackResources",
      "cloudfront:List*",
      "cloudfront:GetDistributionConfig",
      "cloudfront:GetStreamingDistributionConfig",
      "cloudhsm:Describe*",
      "cloudhsm:List*",
      "cloudsearch:Describe*",
      "cloudtrail:DescribeTrails",
      "cloudtrail:GetTrailStatus",
      "cloudwatch:DescribeAlarms",
      "cloudwatch:GetMetricStatistics",
      "cloudwatch:ListMetrics",
      "cognito-identity:ListIdentities",
      "cognito-identity:ListIdentityPools",
      "cognito-idp:ListGroups",
      "cognito-idp:ListIdentityProviders",
      "cognito-idp:ListUserPools",
      "cognito-idp:ListUsers",
      "cognito-idp:ListUsersInGroup",
      "config:DescribeConfigRules",
      "config:GetComplianceDetailsByConfigRule",
      "config:Describe*",
      "datapipeline:ListPipelines",
      "datapipeline:GetPipelineDefinition",
      "datapipeline:DescribePipelines",
      "directconnect:DescribeLocations",
      "directconnect:DescribeConnections",
      "directconnect:DescribeVirtualInterfaces",
      "dynamodb:ListTables",
      "dynamodb:DescribeTable",
      "dynamodb:ListTagsOfResource",
      "ecs:ListClusters",
      "ecs:DescribeClusters",
      "ecs:ListContainerInstances",
      "ecs:DescribeContainerInstances",
      "ecs:ListServices",
      "ecs:DescribeServices",
      "ecs:ListTaskDefinitions",
      "ecs:DescribeTaskDefinition",
      "ecs:ListTasks",
      "ecs:DescribeTasks",
      "ssm:ListResourceDataSync",
      "ssm:ListAssociations",
      "ssm:ListDocumentVersions",
      "ssm:ListDocuments",
      "ssm:ListInstanceAssociations",
      "ssm:ListInventoryEntries",
      "elasticache:Describe*",
      "elasticache:List*",
      "elasticbeanstalk:Describe*",
      "elasticfilesystem:DescribeFileSystem",
      "elasticfilesystem:DescribeTags",
      "elasticloadbalancing:Describe*",
      "elasticmapreduce:Describe*",
      "elasticmapreduce:List*",
      "es:ListDomainNames",
      "es:DescribeElasticsearchDomains",
      "glacier:ListTagsForVault",
      "glacier:DescribeVault",
      "glacier:GetVaultNotifications",
      "glacier:DescribeJob",
      "glacier:GetJobOutput",
      "glacier:ListJobs",
      "glacier:ListVaults",
      "iam:Get*",
      "iam:List*",
      "iam:GenerateCredentialReport",
      "iot:DescribeThing",
      "iot:ListThings",
      "kms:DescribeKey",
      "kms:GetKeyPolicy",
      "kms:GetKeyRotationStatus",
      "kms:ListAliases",
      "kms:ListGrants",
      "kms:ListKeys",
      "kms:ListKeyPolicies",
      "kms:ListResourceTags",
      "kinesis:ListStreams",
      "kinesis:DescribeStream",
      "kinesis:GetShardIterator",
      "kinesis:GetRecords",
      "lambda:ListFunctions",
      "lambda:ListTags",
      "Organizations:List*",
      "Organizations:Describe*",
      "rds:Describe*",
      "rds:List*",
      "redshift:Describe*",
      "route53:ListHealthChecks",
      "route53:ListHostedZones",
      "route53:ListResourceRecordSets",
      "s3:GetBucketACL",
      "s3:GetBucketLocation",
      "s3:GetBucketLogging",
      "s3:GetBucketPolicy",
      "s3:GetBucketTagging",
      "s3:GetBucketWebsite",
      "s3:GetBucketNotification",
      "s3:GetLifecycleConfiguration",
      "s3:GetNotificationConfiguration",
      "s3:List*",
      "sdb:ListDomains",
      "sdb:DomainMetadata",
      "ses:ListIdentities",
      "ses:GetSendStatistics",
      "ses:GetIdentityDkimAttributes",
      "ses:GetIdentityVerificationAttributes",
      "ses:GetSendQuota",
      "sns:GetSnsTopic",
      "sns:GetTopicAttributes",
      "sns:GetSubscriptionAttributes",
      "sns:ListTopics",
      "sns:ListSubscriptionsByTopic",
      "sqs:ListQueues",
      "sqs:GetQueueAttributes",
      "storagegateway:Describe*",
      "storagegateway:List*",
      "support:*",
      "swf:ListClosedWorkflowExecutions",
      "swf:ListDomains",
      "swf:ListActivityTypes",
      "swf:ListWorkflowTypes",
      "workspaces:DescribeWorkspaceDirectories",
      "workspaces:DescribeWorkspaceBundles",
      "workspaces:DescribeWorkspaces"
      ],
      "Resource":"*"
      }
      ]
      }

      {
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"CloudTrailPermissions",
      "Effect":"Allow",
      "Action":[
      "s3:GetBucketACL",
      "s3:GetBucketLocation",
      "s3:GetBucketLogging",
      "s3:GetBucketPolicy",
      "s3:GetBucketTagging",
      "s3:GetBucketWebsite",
      "s3:GetBucketNotification",
      "s3:GetLifecycleConfiguration",
      "s3:GetNotificationConfiguration",
      "s3:GetObject",
      "s3:List*"
      ],
      "Resource":[
      "arn:aws:s3:::[YOUR CLOUDTRAIL BUCKET]",
      "arn:aws:s3:::[YOUR CLOUDTRAIL BUCKET]/*"
      ]
      }
      ]
      }

      {
      "Version":"2012-10-17",
      "Statement":[
      {
      "Sid":"CloudWatchLogsSpecific",
      "Effect":"Allow",
      "Action":[
      "logs:GetLogEvents",
      "logs:DescribeLogGroups",
      "logs:DescribeLogStreams"
      ],
      "Resource":[
      "arn:aws:logs:*:*:*"
      ]
      }
      ]
      }
    2. Copy the entire contents of the policy document to your clipboard.
    3. Return to the Create Policy page in the AWS Management Console.
    4. Click the JSON tab.

    5. Replace the text in the JSON tab with the policy you just copied.

      For any Billing and CloudTrail policies, replace the dummy S3 bucket name with the name of the S3 bucket where AWS stores your Detailed Billing Report (DBR) or Cost Usage Report (CUR). Here is an example from the Billing JSON file:

    6. Click Review policy.

      The Review policy page opens.

    7. Type a name for the policy and click Create policy.

      A message at the top of the policy page indicates that your policy has been created.

  6. Repeat step 5 for each least privilege policy you want to attach to your cross-account role.
  7. Continue to the next step in your account preparation: Create a Cross-Account Role Manually.

Policy Structure Notes

Click each button to review the exceptions to our default policy structure.

CloudCheckr will attempt to ingest data from all of the AWS core features to populate the Cost, Billing, Security, Inventory, and CloudWatch Flow Log reports. Since CloudCheckr must make calls even to those categories where you have not enabled permissions, you will see Unauthorized Access attempts in your CloudTrail logs. These logs are only an indication of the CloudCheckr workflow and in no way reflect an attempt on the part of CloudCheckr to collect unauthorized information from customers.

To help you maintain a secure, least privilege configuration, CloudCheckr's Security/Compliance policy does not include any s3:GetObject permissions. However, you can add the s3:GetObject permission to the following reports:

  • S3 Encryption Details report: enables CloudCheckr scan your encrypted S3 buckets.

    We recommend restricting this permission to only selected S3 bucket(s).

  • List of VPCs report: enables CloudCheckr to ingest data from the Elastic Beanstalk applications for this report.

    The default Security/Compliance policy will only display 0 as the number of Elastic Beanstalk applications within a VPC.

To help maintain a secure, least privilege configuration, CloudCheckr's CloudFormation template and the Inventory policy does not include the s3:GetEncryptionConfiguration by default. Consult with your administrator to determine if the addition of this permission is necessary and valid for your deployment.

How did we do?