Limited IAM Permissions for AWS RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch Active Discount Management

To effectively monitor your usage of RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch and manage an optimal portfolio of Reserved Instances, we require the core IAM permissions for AWS Compute Real-time mode as well as additional service-specific permissions for these resources.

We're firm believers in the security principle of least privilege, so our permission sets include the minimum amount of access we need to run and nothing more.

At no point in time do we have access to:

  • Your data plane (e.g. instances, clusters, containers)
  • Manipulate the control plane (e.g. start or terminate an instance, cluster, or task)
  • Your data, whether local or in a managed storage/datastore service 

Read more: What level of access ProsperOps needs


We require one set of permissions on the AWS Management account and a separate, smaller permission set on all AWS Member accounts.

Management Account

These permissions allow us to:

  • Access Cost Explorer data
  • Setup and access a Cost and Usage Report (CUR)
  • Understand the EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch instances and images being used
  • Establish a real-time event feed of EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch instance state change notifications
  • Fully manage EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch Reserved Instances
  • Fully manage Savings Plans
  • Understand Capacity Reservations
  • Understand and increase the monthly EC2, RDS, ElastiCache, MemoryDB, and Redshift Reserved Instance purchase service quota limit
  • Understand Organizations metadata and AWS account structure
  • Verify our permissions are applied correctly

The Real-time mode Management account IAM policy with RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch support is:

{
    "Version" : "2012-10-17",
    "Statement" : [
        {
            "Effect" : "Allow",
            "Action" : [
                "ce:Get*",
                "ce:List*",
                "cur:DescribeReportDefinitions",
                "ec2:AcceptReservedInstancesExchangeQuote",
                "ec2:CancelReservedInstancesListing",
                "ec2:CreateReservedInstancesListing",
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeCapacityReservations",
                "ec2:DescribeImages",
                "ec2:DescribeInstances",
                "ec2:DescribeReservedInstances",
                "ec2:DescribeReservedInstancesListings",
                "ec2:DescribeReservedInstancesModifications",
                "ec2:DescribeReservedInstancesOfferings",
                "ec2:GetCapacityReservationUsage",
                "ec2:GetReservedInstancesExchangeQuote",
                "ec2:ModifyReservedInstances",
                "ec2:PurchaseReservedInstancesOffering",
                "elasticache:DescribeReservedCacheNodes",
                "elasticache:DescribeReservedCacheNodesOfferings",
                "elasticache:PurchaseReservedCacheNodesOffering",
                "es:DescribeReservedInstanceOfferings",
                "es:DescribeReservedInstances",
                "es:PurchaseReservedInstanceOffering",
                "memorydb:DescribeReservedNodes",
                "memorydb:DescribeReservedNodesOfferings",
                "memorydb:PurchaseReservedNodesOffering",
                "organizations:DescribeOrganization",
                "organizations:ListAccounts",
                "rds:DescribeAccountAttributes",
                "rds:DescribeReservedDBInstances",
                "rds:DescribeReservedDBInstancesOfferings",
                "rds:PurchaseReservedDBInstancesOffering",
                "redshift:AcceptReservedNodeExchange",
                "redshift:DescribeReservedNodeExchangeStatus",
                "redshift:DescribeReservedNodeOfferings",
                "redshift:DescribeReservedNodes",
                "redshift:GetReservedNodeExchangeConfigurationOptions",
                "redshift:GetReservedNodeExchangeOfferings",
                "redshift:PurchaseReservedNodeOffering",
                "savingsplans:CreateSavingsPlan",
                "savingsplans:Describe*",
                "savingsplans:ReturnSavingsPlan",
                "servicequotas:GetServiceQuota",
                "servicequotas:ListRequestedServiceQuotaChangeHistoryByQuota"
            ],
            "Resource" : "*"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "cur:DeleteReportDefinition",
                "cur:ModifyReportDefinition",
                "cur:PutReportDefinition"
            ],
            "Resource" : "arn:aws:cur:*:*:definition/prosperops-*"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "events:DescribeRule",
                "events:ListTargetsByRule",
                "events:PutRule",
                "events:PutTargets"
            ],
            "Resource" : "arn:aws:events:*:*:rule/ProsperOps-EC2-Instance-State-Changes"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "iam:GetRolePolicy",
                "iam:ListRolePolicies",
                "iam:SimulatePrincipalPolicy"
            ],
            "Resource" : "arn:aws:iam::*:role/ProsperOps"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "s3:CreateBucket",
                "s3:ListBucket",
                "s3:PutBucketPolicy"
            ],
            "Resource" : "arn:aws:s3:::prosperops-cur-*"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:GetObject"
            ],
            "Resource" : "arn:aws:s3:::prosperops-cur-*/*"
        },
        {
            "Effect" : "Allow",
            "Action" : "servicequotas:RequestServiceQuotaIncrease",
            "Resource" : [
                "arn:aws:servicequotas:*:*:ec2/L-D0B7243C",
                "arn:aws:servicequotas:*:*:elasticache/L-DFE45DF3",
                "arn:aws:servicequotas:*:*:rds/L-78E853F4",
                "arn:aws:servicequotas:*:*:redshift/L-58C8C0E8"
            ]
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "sns:CreateTopic",
                "sns:GetTopicAttributes",
                "sns:ListSubscriptionsByTopic",
                "sns:SetTopicAttributes",
                "sns:Subscribe"
            ],
            "Resource" : "arn:aws:sns:*:*:ProsperOps-EC2-Instance-State-Changes"
        },
        {
            "Effect" : "Allow",
            "Action" : "iam:CreateServiceLinkedRole",
            "Resource" : "*",
            "Condition" : {
                "StringLike" : {
                    "iam:AWSServiceName" : [
                        "servicequotas.amazonaws.com",
                        "elasticache.amazonaws.com",
                        "memorydb.amazonaws.com"
                    ]
                }
            }
        }
    ]
}

Member Accounts

These permissions allow us to:

  • Understand the EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch instances and images being used
  • Establish a real-time event feed of EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch instance state change notifications
  • Fully manage EC2, RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch Reserved Instances
  • Fully manage Savings Plans
  • Understand Capacity Reservations
  • Understand and increase the monthly EC2, RDS, ElastiCache, MemoryDB, and Redshift Reserved Instance purchase service quota limit
  • Understand Organizations metadata
  • Verify our permissions are applied correctly

The Real-time mode Member account IAM policy with RDS, ElastiCache, MemoryDB, Redshift, and OpenSearch support is:

{
    "Version" : "2012-10-17",
    "Statement" : [
        {
            "Effect" : "Allow",
            "Action" : [
                "ec2:AcceptReservedInstancesExchangeQuote",
                "ec2:CancelReservedInstancesListing",
                "ec2:CreateReservedInstancesListing",
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeCapacityReservations",
                "ec2:DescribeImages",
                "ec2:DescribeInstances",
                "ec2:DescribeReservedInstances",
                "ec2:DescribeReservedInstancesListings",
                "ec2:DescribeReservedInstancesModifications",
                "ec2:DescribeReservedInstancesOfferings",
                "ec2:GetCapacityReservationUsage",
                "ec2:GetReservedInstancesExchangeQuote",
                "ec2:ModifyReservedInstances",
                "ec2:PurchaseReservedInstancesOffering",
                "elasticache:DescribeReservedCacheNodes",
                "elasticache:DescribeReservedCacheNodesOfferings",
                "elasticache:PurchaseReservedCacheNodesOffering",
                "es:DescribeReservedInstanceOfferings",
                "es:DescribeReservedInstances",
                "es:PurchaseReservedInstanceOffering",
                "memorydb:DescribeReservedNodes",
                "memorydb:DescribeReservedNodesOfferings",
                "memorydb:PurchaseReservedNodesOffering",
                "organizations:DescribeOrganization",
                "rds:DescribeAccountAttributes",
                "rds:DescribeReservedDBInstances",
                "rds:DescribeReservedDBInstancesOfferings",
                "rds:PurchaseReservedDBInstancesOffering",
                "redshift:AcceptReservedNodeExchange",
                "redshift:DescribeReservedNodeExchangeStatus",
                "redshift:DescribeReservedNodeOfferings",
                "redshift:DescribeReservedNodes",
                "redshift:GetReservedNodeExchangeConfigurationOptions",
                "redshift:GetReservedNodeExchangeOfferings",
                "redshift:PurchaseReservedNodeOffering",
                "savingsplans:CreateSavingsPlan",
                "savingsplans:Describe*",
                "savingsplans:ReturnSavingsPlan",
                "servicequotas:GetServiceQuota",
                "servicequotas:ListRequestedServiceQuotaChangeHistoryByQuota"
            ],
            "Resource" : "*"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "events:DescribeRule",
                "events:ListTargetsByRule",
                "events:PutRule",
                "events:PutTargets"
            ],
            "Resource" : "arn:aws:events:*:*:rule/ProsperOps-EC2-Instance-State-Changes"
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "iam:GetRolePolicy",
                "iam:ListRolePolicies",
                "iam:SimulatePrincipalPolicy"
            ],
            "Resource" : "arn:aws:iam::*:role/ProsperOps"
        },
        {
            "Effect" : "Allow",
            "Action" : "servicequotas:RequestServiceQuotaIncrease",
            "Resource" : [
                "arn:aws:servicequotas:*:*:ec2/L-D0B7243C",
                "arn:aws:servicequotas:*:*:elasticache/L-DFE45DF3",
                "arn:aws:servicequotas:*:*:rds/L-78E853F4",
                "arn:aws:servicequotas:*:*:redshift/L-58C8C0E8"
            ]
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "sns:CreateTopic",
                "sns:GetTopicAttributes",
                "sns:ListSubscriptionsByTopic",
                "sns:SetTopicAttributes",
                "sns:Subscribe"
            ],
            "Resource" : "arn:aws:sns:*:*:ProsperOps-EC2-Instance-State-Changes"
        },
        {
            "Effect" : "Allow",
            "Action" : "iam:CreateServiceLinkedRole",
            "Resource" : "*",
            "Condition" : {
                "StringLike" : {
                    "iam:AWSServiceName" : [
                        "servicequotas.amazonaws.com",
                        "elasticache.amazonaws.com",
                        "memorydb.amazonaws.com"
                    ]
                }
            }
        }
    ]
}