AWS permissions

Exactly what access KloudLytics asks for

You create one IAM role in your account. This page lists every permission on it, why each is there, every AWS API a scan calls, and what is never read. It is generated from the same template the onboarding wizard gives you, so you can review it before you sign up and compare it afterwards.

AWS-managed read policies
2
additional actions, each explained below
54
write actions in any policy we author
0
longest a session can last
60 min

Role template v4 · role name kloudlyticsReadOnlyRole

The role and who can use it

The role lives in your account and you can delete it at any time, which ends our access immediately. Its trust policy decides who may assume it. Two conditions must both hold:

  • An external ID unique to you. Without it, someone who learned your role’s ARN could ask KloudLytics to assume it on their behalf. AWS calls this the confused deputy problem.
  • One named role in our account. Only the scanner’s own role may assume yours, not any identity in the KloudLytics AWS account.

KloudLytics holds no AWS access keys for your account. Each scan asks AWS for temporary credentials, and the role caps a session at 60 minutes.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<KLOUDLYTICS_ACCOUNT_ID>:role/<KLOUDLYTICS_SCANNER_ROLE>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<YOUR_EXTERNAL_ID>"
        },
        "ArnEquals": {
          "aws:PrincipalArn": "arn:aws:iam::<KLOUDLYTICS_ACCOUNT_ID>:role/<KLOUDLYTICS_SCANNER_ROLE>"
        }
      }
    }
  ]
}

<YOUR_EXTERNAL_ID> and the account and role in arn:aws:iam::<KLOUDLYTICS_ACCOUNT_ID>:role/<KLOUDLYTICS_SCANNER_ROLE> are filled in by the onboarding wizard. They are the only differences between this page and your template.

AWS-managed policies

Two policies written and maintained by AWS provide the baseline. They are broad, and AWS can add services to them. We link to AWS’s own reference for each rather than restating their contents here.

SecurityAudit

arn:aws:iam::aws:policy/SecurityAudit

AWS-managed. Read access to security configuration across services: IAM, encryption settings, logging, network rules, resource policies.

SecurityAudit in the AWS policy reference

ViewOnlyAccess

arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

AWS-managed. Lets the role list and describe resources so there is an inventory to check. AWS maintains it and adds services over time.

ViewOnlyAccess in the AWS policy reference

KloudLytics does not use AWS’s ReadOnlyAccess policy, which also allows reading the contents of S3 objects and other stored data.

Additional permissions, one by one

Where the AWS-managed policies do not reach, the role adds 54 specific actions in 6 small policies. Every one is a Get, List, Describe or equivalent read. None creates, changes or deletes anything.

KloudLyticsThreatDetectionReadOnly

Reads whether GuardDuty is on and the findings it has already raised.

Actions granted by KloudLyticsThreatDetectionReadOnly and why
ActionWhy it is needed
guardduty:ListDetectorsChecks whether GuardDuty is enabled in each region.
guardduty:GetDetectorReads the detector's settings and which protections are on.
guardduty:ListFindingsLists GuardDuty's findings so they appear beside configuration risks.
guardduty:GetFindingsReads the detail of those findings: severity, type, affected resource.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsThreatDetectionReadOnly",
      "Effect": "Allow",
      "Action": [
        "guardduty:ListDetectors",
        "guardduty:GetDetector",
        "guardduty:ListFindings",
        "guardduty:GetFindings"
      ],
      "Resource": "*"
    }
  ]
}

KloudLyticsAISecurityReadOnly

Reads Amazon Bedrock configuration: guardrails, logging, agents, knowledge bases and how models are served. No model is invoked.

Actions granted by KloudLyticsAISecurityReadOnly and why
ActionWhy it is needed
bedrock:GetModelInvocationLoggingConfigurationChecks whether model invocation logging is enabled.
bedrock:ListFoundationModelsLists the foundation models available, to tell an unused account from one using Bedrock.
bedrock:ListGuardrailsLists guardrails, to flag workloads running without one.
bedrock:GetGuardrailReads a guardrail's configuration to check what it filters.
bedrock:ListCustomModelsLists custom models for the AI inventory.
bedrock:GetCustomModelReads a custom model's encryption and training-data settings.
bedrock:ListAgentsLists Bedrock agents.
bedrock:GetAgentReads an agent's role and guardrail, to flag over-permissioned agents.
bedrock:ListKnowledgeBasesLists knowledge bases.
bedrock:GetKnowledgeBaseReads a knowledge base's storage and encryption settings.
bedrock:ListTagsForResourceReads tags on Bedrock resources.
bedrock:ListImportedModelsLists imported models for the AI inventory.
bedrock:ListModelInvocationJobsLists batch inference jobs, to detect Bedrock usage.
bedrock:ListPromptRoutersLists prompt routers, to detect Bedrock usage.
bedrock:ListInferenceProfilesLists inference profiles, to detect cross-region inference.
bedrock:ListCustomModelDeploymentsDetects models served on demand. Without it an account using Bedrock looks unused and AI checks pass on nothing.
bedrock:ListMarketplaceModelEndpointsDetects models served through Marketplace endpoints.
bedrock:ListProvisionedModelThroughputsDetects models served through provisioned throughput.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsAISecurityReadOnly",
      "Effect": "Allow",
      "Action": [
        "bedrock:GetModelInvocationLoggingConfiguration",
        "bedrock:ListFoundationModels",
        "bedrock:ListGuardrails",
        "bedrock:GetGuardrail",
        "bedrock:ListCustomModels",
        "bedrock:GetCustomModel",
        "bedrock:ListAgents",
        "bedrock:GetAgent",
        "bedrock:ListKnowledgeBases",
        "bedrock:GetKnowledgeBase",
        "bedrock:ListTagsForResource",
        "bedrock:ListImportedModels",
        "bedrock:ListModelInvocationJobs",
        "bedrock:ListPromptRouters",
        "bedrock:ListInferenceProfiles",
        "bedrock:ListCustomModelDeployments",
        "bedrock:ListMarketplaceModelEndpoints",
        "bedrock:ListProvisionedModelThroughputs"
      ],
      "Resource": "*"
    }
  ]
}

KloudLyticsCostGovernanceReadOnly

Reads whether AWS Budgets are configured.

Actions granted by KloudLyticsCostGovernanceReadOnly and why
ActionWhy it is needed
budgets:ViewBudgetChecks whether any budget exists for the account.
budgets:DescribeBudgetActionReads whether a budget has an action attached.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsCostGovernanceReadOnly",
      "Effect": "Allow",
      "Action": [
        "budgets:ViewBudget",
        "budgets:DescribeBudgetAction"
      ],
      "Resource": "*"
    }
  ]
}

KloudLyticsSecurityReadOnly

Security settings the AWS-managed policies do not cover.

Actions granted by KloudLyticsSecurityReadOnly and why
ActionWhy it is needed
kms:GetKeyRotationStatusChecks whether automatic rotation is on for each key.
kms:GetKeyPolicyReads key policies to find keys usable from outside the account.
kms:ListKeyPoliciesLists the policies attached to each key.
glue:GetTriggersReads Glue triggers for the data-pipeline inventory.
ssm:GetDocumentReads the Session Manager preferences document, to check whether sessions are logged.
ssm:DescribeParametersLists Parameter Store names and types to flag secrets not stored as SecureString. Values are not read.
macie2:GetMacieSessionChecks whether Macie is enabled.
lambda:ListFunctionUrlConfigsLists Lambda function URLs.
lambda:GetFunctionUrlConfigReads a function URL's auth type, to flag ones open to the internet.
cognito-idp:ListUserPoolsLists Cognito user pools. Users are not listed.
cognito-idp:DescribeUserPoolReads a pool's password policy, MFA and advanced-security settings.
ecr:GetRegistryScanningConfigurationChecks whether image scanning is configured for the registry.
dms:DescribeReplicationInstancesFlags publicly accessible DMS replication instances.
redshift:DescribeLoggingStatusChecks whether audit logging is on for each Redshift cluster.
account:GetAlternateContactChecks that a security contact is set. The name, e-mail and phone are removed before the response is stored.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsSecurityReadOnly",
      "Effect": "Allow",
      "Action": [
        "kms:GetKeyRotationStatus",
        "kms:GetKeyPolicy",
        "kms:ListKeyPolicies",
        "glue:GetTriggers",
        "ssm:GetDocument",
        "ssm:DescribeParameters",
        "macie2:GetMacieSession",
        "lambda:ListFunctionUrlConfigs",
        "lambda:GetFunctionUrlConfig",
        "cognito-idp:ListUserPools",
        "cognito-idp:DescribeUserPool",
        "ecr:GetRegistryScanningConfiguration",
        "dms:DescribeReplicationInstances",
        "redshift:DescribeLoggingStatus",
        "account:GetAlternateContact"
      ],
      "Resource": "*"
    }
  ]
}

KloudLyticsApiGatewayReadOnly

Reads API Gateway configuration. Neither AWS-managed policy grants it.

Actions granted by KloudLyticsApiGatewayReadOnly and why
ActionWhy it is needed
apigateway:GETReads REST and HTTP API configuration: stages, authorisers, validators, domains. Limited to those resources; request and response bodies are not read.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsApiGatewayReadOnly",
      "Effect": "Allow",
      "Action": [
        "apigateway:GET"
      ],
      "Resource": [
        "arn:aws:apigateway:*::/restapis",
        "arn:aws:apigateway:*::/restapis/*",
        "arn:aws:apigateway:*::/apis",
        "arn:aws:apigateway:*::/apis/*",
        "arn:aws:apigateway:*::/domainnames",
        "arn:aws:apigateway:*::/domainnames/*"
      ]
    }
  ]
}

KloudLyticsExtendedReadOnly

Account-level defaults and service enablement the AWS-managed policies do not grant.

Actions granted by KloudLyticsExtendedReadOnly and why
ActionWhy it is needed
ec2:GetEbsEncryptionByDefaultChecks whether new EBS volumes are encrypted by default.
s3:ListBucketMultipartUploadsFinds incomplete multipart uploads that are silently billed. Lists the keys and ids of unfinished uploads, never object contents.
ec2:GetSnapshotBlockPublicAccessStateChecks the account-level block on public EBS snapshots.
ec2:GetInstanceMetadataDefaultsChecks whether IMDSv2 is the account default.
cloudtrail:GetInsightSelectorsChecks whether CloudTrail Insights is enabled.
iam:SimulatePrincipalPolicyAsks IAM whether this role holds a permission, so a missing grant is never reported as a finding. Evaluates policies; returns no account data.
backup:ListBackupVaultsChecks whether a backup vault exists.
inspector2:BatchGetAccountStatusChecks whether Inspector is enabled.
detective:ListGraphsChecks whether Detective is enabled.
glue:GetJobsReads Glue job definitions for the inventory.
codebuild:ListProjectsLists CodeBuild projects.
codebuild:BatchGetProjectsReads project configuration, including environment variables, to flag credentials stored in plain text.
lightsail:GetInstancesDetects Lightsail instances, which sit outside the usual EC2 controls.
lightsail:GetLoadBalancersDetects Lightsail load balancers.
Policy document
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "KloudLyticsExtendedReadOnly",
      "Effect": "Allow",
      "Action": [
        "ec2:GetEbsEncryptionByDefault",
        "s3:ListBucketMultipartUploads",
        "ec2:GetSnapshotBlockPublicAccessState",
        "ec2:GetInstanceMetadataDefaults",
        "cloudtrail:GetInsightSelectors",
        "iam:SimulatePrincipalPolicy",
        "backup:ListBackupVaults",
        "inspector2:BatchGetAccountStatus",
        "detective:ListGraphs",
        "glue:GetJobs",
        "codebuild:ListProjects",
        "codebuild:BatchGetProjects",
        "lightsail:GetInstances",
        "lightsail:GetLoadBalancers"
      ],
      "Resource": "*"
    }
  ]
}

Optional cost policy

Not part of the role. Offered separately because it is the one grant that reads billing data; the product works without it.

Actions in the optional cost policy and why
ActionWhy it is needed
ce:GetCostAndUsageReads spend by service for the cost view.
ce:GetCostForecastReads AWS's own forecast for the month.
ce:GetDimensionValuesLists the services and regions spend can be grouped by.
cloudwatch:GetMetricDataReads utilisation metrics to find idle resources.

AWS APIs a scan calls

A scan makes 209 distinct calls across 59 AWS services. CloudTrail records them under the role’s name, so you can check this list against what actually happened.

accessanalyzer2 calls
  • list-analyzers
  • list-findings
account1 call
  • get-alternate-contact
acm2 calls
  • describe-certificate
  • list-certificates
apigateway5 calls
  • get-domain-names
  • get-request-validators
  • get-resources
  • get-rest-apis
  • get-stages
apigatewayv23 calls
  • get-apis
  • get-authorizers
  • get-domain-names
autoscaling2 calls
  • describe-auto-scaling-groups
  • describe-policies
backup1 call
  • list-backup-vaults
bedrock12 calls
  • get-guardrail
  • get-model-invocation-logging-configuration
  • list-custom-model-deployments
  • list-custom-models
  • list-foundation-models
  • list-guardrails
  • list-imported-models
  • list-inference-profiles
  • list-marketplace-model-endpoints
  • list-model-invocation-jobs
  • list-prompt-routers
  • list-provisioned-model-throughputs
bedrock-agent3 calls
  • get-agent
  • list-agents
  • list-knowledge-bases
budgets1 call
  • describe-budgets
cloudformation3 calls
  • describe-stack-resources
  • describe-stacks
  • get-template
cloudfront1 call
  • list-distributions
cloudsearch2 calls
  • describe-domains
  • describe-service-access-policies
cloudtrail3 calls
  • describe-trails
  • get-event-selectors
  • get-insight-selectors
cloudwatch2 calls
  • describe-alarms
  • list-metrics
codebuild2 calls
  • batch-get-projects
  • list-projects
cognito-idp2 calls
  • describe-user-pool
  • list-user-pools
config3 calls
  • describe-config-rules
  • describe-configuration-recorders
  • describe-delivery-channels
detective1 call
  • list-graphs
directconnect1 call
  • describe-connections
dms1 call
  • describe-replication-instances
dynamodb3 calls
  • describe-continuous-backups
  • describe-table
  • list-tables
ec225 calls
  • describe-addresses
  • describe-availability-zones
  • describe-flow-logs
  • describe-images
  • describe-instance-attribute
  • describe-instances
  • describe-internet-gateways
  • describe-nat-gateways
  • describe-network-acls
  • describe-network-interfaces
  • describe-route-tables
  • describe-security-groups
  • describe-snapshot-attribute
  • describe-snapshots
  • describe-subnets
  • describe-volumes
  • describe-vpc-endpoint-connections
  • describe-vpc-endpoints
  • describe-vpc-peering-connections
  • describe-vpcs
  • describe-vpn-connections
  • describe-vpn-gateways
  • get-ebs-encryption-by-default
  • get-instance-metadata-defaults
  • get-snapshot-block-public-access-state
ecr3 calls
  • describe-repositories
  • get-registry-scanning-configuration
  • get-repository-policy
ecs7 calls
  • describe-container-instances
  • describe-task-definition
  • describe-tasks
  • list-clusters
  • list-container-instances
  • list-task-definitions
  • list-tasks
efs1 call
  • describe-file-systems
eks2 calls
  • describe-cluster
  • list-clusters
elasticache2 calls
  • describe-cache-clusters
  • describe-replication-groups
elasticbeanstalk2 calls
  • describe-applications
  • describe-configuration-settings
elb4 calls
  • describe-load-balancer-attributes
  • describe-load-balancer-policies
  • describe-load-balancers
  • describe-tags
elbv27 calls
  • describe-listeners
  • describe-load-balancer-attributes
  • describe-load-balancers
  • describe-rules
  • describe-tags
  • describe-target-groups
  • describe-target-health
es2 calls
  • describe-elasticsearch-domain
  • list-domain-names
events2 calls
  • describe-event-bus
  • list-rules
firehose2 calls
  • describe-delivery-stream
  • list-delivery-streams
glacier2 calls
  • get-vault-access-policy
  • list-vaults
glue2 calls
  • get-jobs
  • get-triggers
guardduty2 calls
  • get-detector
  • list-detectors
iam17 calls
  • generate-credential-report
  • generate-service-last-accessed-details
  • get-account-authorization-details
  • get-account-password-policy
  • get-account-summary
  • get-credential-report
  • get-open-id-connect-provider
  • get-role
  • get-saml-provider
  • get-service-last-accessed-details
  • get-user
  • list-account-aliases
  • list-open-id-connect-providers
  • list-saml-providers
  • list-server-certificates
  • list-service-specific-credentials
  • list-virtual-mfa-devices
inspector21 call
  • batch-get-account-status
kms6 calls
  • describe-key
  • get-key-policy
  • get-key-rotation-status
  • list-grants
  • list-key-policies
  • list-keys
lambda6 calls
  • get-policy
  • list-function-url-configs
  • list-functions
  • list-layer-versions
  • list-layers
  • list-tags
lightsail2 calls
  • get-instances
  • get-load-balancers
logs4 calls
  • describe-destinations
  • describe-log-groups
  • describe-metric-filters
  • describe-resource-policies
macie21 call
  • get-macie-session
organizations2 calls
  • describe-organization
  • list-accounts
rds8 calls
  • describe-db-clusters
  • describe-db-engine-versions
  • describe-db-instances
  • describe-db-parameters
  • describe-db-snapshot-attributes
  • describe-db-snapshots
  • describe-event-subscriptions
  • list-tags-for-resource
redshift3 calls
  • describe-cluster-subnet-groups
  • describe-clusters
  • describe-logging-status
route533 calls
  • list-hosted-zones
  • list-hosted-zones-by-vpc
  • list-resource-record-sets
route53domains1 call
  • list-domains
s310 calls
  • get-bucket-acl
  • get-bucket-encryption
  • get-bucket-lifecycle-configuration
  • get-bucket-location
  • get-bucket-logging
  • get-bucket-policy
  • get-bucket-tagging
  • get-bucket-versioning
  • list-buckets
  • list-multipart-uploads
s3control1 call
  • get-public-access-block
sagemaker6 calls
  • describe-endpoint
  • describe-notebook-instance
  • describe-training-job
  • list-endpoints
  • list-notebook-instances
  • list-training-jobs
secretsmanager2 calls
  • get-resource-policy
  • list-secrets
securityhub2 calls
  • describe-hub
  • get-enabled-standards
sns2 calls
  • get-topic-attributes
  • list-topics
sqs2 calls
  • get-queue-attributes
  • list-queues
ssm3 calls
  • describe-instance-patch-states
  • describe-parameters
  • get-document
sts1 call
  • get-caller-identity
wafv25 calls
  • get-logging-configuration
  • get-web-acl
  • list-resources-for-web-acl
  • list-web-acls
  • list-web-acls-cloudfront

Two calls are not plain reads. iam generate-credential-report and iam generate-service-last-accessed-details ask IAM to prepare a report about your account, which the scan then reads. They change no resource and no permission.

Outside the scan itself:

  • guardduty list-findings, every scan, where GuardDuty is enabled.
  • guardduty get-findings, every scan, where GuardDuty is enabled.
  • iam simulate-principal-policy, when you verify the role's permissions.
  • ce get-cost-and-usage, only with the optional cost policy.
  • ce get-cost-forecast, only with the optional cost policy.
  • cloudwatch get-metric-data, only with the optional cost policy.

Configuration that can hold secrets

Read-only does not mean nothing sensitive is seen. Some configuration can contain a credential if someone put one there, and finding those is one of the things a scan is for. These are the places KloudLytics reads and checks:

Configuration read during a scan that may contain secrets
What is readThrough
Lambda environment variableslambda list-functions
EC2 instance user dataec2 describe-instance-attribute
ECS task definition environment variablesecs describe-task-definition
CodeBuild project environment variablescodebuild batch-get-projects
CloudFormation templates and stack parameterscloudformation get-template
API Gateway stage variablesapigateway get-stages
Elastic Beanstalk environment settingselasticbeanstalk describe-configuration-settings

A finding records where a secret is and what kind it looks like, for example an AWS access key in a named environment variable. It never records the secret itself.

The configuration a scan collects is stored encrypted in our AWS account. If one of the fields above holds a secret, that secret is part of what is stored. Moving it into Secrets Manager or a SecureString parameter, which the finding recommends, takes it out of reach of this role.

What is never read

KloudLytics assesses how your resources are configured. It does not read what they hold. None of the following is called by a scan, and none is granted by a policy we author.

  • S3 object contents

    s3: get-object, select-object-content, list-objects, list-objects-v2, list-object-versions

  • Secrets Manager secret values

    secretsmanager: get-secret-value, batch-get-secret-value

  • Parameter Store values

    ssm: get-parameter, get-parameters, get-parameters-by-path, get-parameter-history

  • Anything encrypted with your KMS keys

    kms: decrypt, generate-data-key, re-encrypt

  • DynamoDB items

    dynamodb: get-item, batch-get-item, query, scan

  • CloudWatch log events

    logs: get-log-events, filter-log-events, start-query, get-query-results

  • SQS messages

    sqs: receive-message

  • Lambda function code

    lambda: get-function, invoke

  • Database contents

    rds-data: execute-statement, batch-execute-statement

  • Bedrock model output

    bedrock-runtime: invoke-model, converse

  • Cognito users

    cognito-idp: list-users, admin-get-user

  • Nothing is created, changed or deleted in your account.
  • No agent, Lambda function or other software is deployed.
  • No remediation is applied for you. Fixes are shown for you to review and run.

The full template

This is the CloudFormation template the onboarding wizard produces, with placeholders where your external ID and our scanner’s identity go. Sign up, download yours, and diff the two.

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "KloudLytics read-only IAM role for cross-account access (v4)",
  "Resources": {
    "KloudLyticsRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": "kloudlyticsReadOnlyRole",
        "MaxSessionDuration": 3600,
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::<KLOUDLYTICS_ACCOUNT_ID>:role/<KLOUDLYTICS_SCANNER_ROLE>"
              },
              "Action": "sts:AssumeRole",
              "Condition": {
                "StringEquals": {
                  "sts:ExternalId": "<YOUR_EXTERNAL_ID>"
                },
                "ArnEquals": {
                  "aws:PrincipalArn": "arn:aws:iam::<KLOUDLYTICS_ACCOUNT_ID>:role/<KLOUDLYTICS_SCANNER_ROLE>"
                }
              }
            }
          ]
        },
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/SecurityAudit",
          "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
        ],
        "Policies": [
          {
            "PolicyName": "KloudLyticsThreatDetectionReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsThreatDetectionReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "guardduty:ListDetectors",
                    "guardduty:GetDetector",
                    "guardduty:ListFindings",
                    "guardduty:GetFindings"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "KloudLyticsAISecurityReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsAISecurityReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "bedrock:GetModelInvocationLoggingConfiguration",
                    "bedrock:ListFoundationModels",
                    "bedrock:ListGuardrails",
                    "bedrock:GetGuardrail",
                    "bedrock:ListCustomModels",
                    "bedrock:GetCustomModel",
                    "bedrock:ListAgents",
                    "bedrock:GetAgent",
                    "bedrock:ListKnowledgeBases",
                    "bedrock:GetKnowledgeBase",
                    "bedrock:ListTagsForResource",
                    "bedrock:ListImportedModels",
                    "bedrock:ListModelInvocationJobs",
                    "bedrock:ListPromptRouters",
                    "bedrock:ListInferenceProfiles",
                    "bedrock:ListCustomModelDeployments",
                    "bedrock:ListMarketplaceModelEndpoints",
                    "bedrock:ListProvisionedModelThroughputs"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "KloudLyticsCostGovernanceReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsCostGovernanceReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "budgets:ViewBudget",
                    "budgets:DescribeBudgetAction"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "KloudLyticsSecurityReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsSecurityReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "kms:GetKeyRotationStatus",
                    "kms:GetKeyPolicy",
                    "kms:ListKeyPolicies",
                    "glue:GetTriggers",
                    "ssm:GetDocument",
                    "ssm:DescribeParameters",
                    "macie2:GetMacieSession",
                    "lambda:ListFunctionUrlConfigs",
                    "lambda:GetFunctionUrlConfig",
                    "cognito-idp:ListUserPools",
                    "cognito-idp:DescribeUserPool",
                    "ecr:GetRegistryScanningConfiguration",
                    "dms:DescribeReplicationInstances",
                    "redshift:DescribeLoggingStatus",
                    "account:GetAlternateContact"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "KloudLyticsApiGatewayReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsApiGatewayReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "apigateway:GET"
                  ],
                  "Resource": [
                    "arn:aws:apigateway:*::/restapis",
                    "arn:aws:apigateway:*::/restapis/*",
                    "arn:aws:apigateway:*::/apis",
                    "arn:aws:apigateway:*::/apis/*",
                    "arn:aws:apigateway:*::/domainnames",
                    "arn:aws:apigateway:*::/domainnames/*"
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "KloudLyticsExtendedReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "KloudLyticsExtendedReadOnly",
                  "Effect": "Allow",
                  "Action": [
                    "ec2:GetEbsEncryptionByDefault",
                    "s3:ListBucketMultipartUploads",
                    "ec2:GetSnapshotBlockPublicAccessState",
                    "ec2:GetInstanceMetadataDefaults",
                    "cloudtrail:GetInsightSelectors",
                    "iam:SimulatePrincipalPolicy",
                    "backup:ListBackupVaults",
                    "inspector2:BatchGetAccountStatus",
                    "detective:ListGraphs",
                    "glue:GetJobs",
                    "codebuild:ListProjects",
                    "codebuild:BatchGetProjects",
                    "lightsail:GetInstances",
                    "lightsail:GetLoadBalancers"
                  ],
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      }
    }
  },
  "Outputs": {
    "RoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "KloudLyticsRole",
          "Arn"
        ]
      },
      "Description": "Copy this ARN and paste it into KloudLytics to complete setup"
    }
  }
}

How the role has changed

A new permission never reaches an existing role on its own. When the template changes, the app tells you what the update adds and you choose when to apply it.

v4
  • Detection of Bedrock usage served on demand, via Marketplace endpoints, or through provisioned throughput — without it, AI governance checks silently passed on accounts that do use Bedrock
  • Bedrock API key (IAM service-specific credential) detection
v3
  • Incomplete S3 multipart upload detection (storage waste)
  • Direct IAM permission verification, so a scan error is never reported as a missing permission
v2
  • Account-level EBS snapshot public-access block check
  • Account-level IMDSv2 default check
  • CloudTrail Insights (API anomaly detection) check
v1
  • SecurityAudit + ViewOnlyAccess baseline
  • KMS key rotation and policy checks
  • Bedrock imported models, prompt routers, and guardrail inspection
  • API Gateway configuration checks
  • EBS default encryption, Backup, Inspector, and Detective enablement checks

How we store and protect what a scan collects

Find out what is actually exposed in your AWS environment.

Connect one AWS account and run your first security assessment.

No credit card · Agentless · Read-only