Skip to content

Instantly share code, notes, and snippets.

@khalidx
Last active May 12, 2025 17:13
Show Gist options
  • Save khalidx/78c7f9d95f25a7f6df5d2ab8806a089f to your computer and use it in GitHub Desktop.
Save khalidx/78c7f9d95f25a7f6df5d2ab8806a089f to your computer and use it in GitHub Desktop.
An AWS CloudFormation Template for creating a read/view-only IAM user with programmatic (CLI) access.

Read/View-Only User for AWS Account Analysis

An AWS CloudFormation Template for creating a read/view-only IAM user with programmatic (CLI) access.

Tip

This is useful for conducting a more complete analysis and inventorying of an AWS account.

The AWS IAM Role created in this CloudFormation Stack is similar to the following:

Usage

Deploy the following CloudFormation Stack and note the ReadOnlyIamUserAccessKeyId and ReadOnlyIamUserSecretAccessKey outputs, which you will need to be able to log in as the newly created read-only user.

Warning

Make sure to note the outputted credentials as they are only displayed once, on stack creation.

{
  "Resources": {
    "ReadOnlyIamUser": {
      "Type": "AWS::IAM::User"
    },
    "ReadOnlyIamUserAccessKey": {
      "Type": "AWS::IAM::AccessKey",
      "Properties": {
        "UserName": { "Ref": "ReadOnlyIamUser" }
      }
    },
    "ReadOnlyRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": { "Fn::GetAtt" : [ "ReadOnlyIamUser", "Arn" ] }
              },
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "ManagedPolicyArns": ["arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"],
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "AdditionalResourcesReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Resource": "*",
                  "Action": [
                    "a4b:List*",
                    "a4b:Search*",
                    "acm:Describe*",
                    "acm:List*",
                    "acm-pca:Describe*",
                    "acm-pca:List*",
                    "amplify:ListApps",
                    "amplify:ListBranches",
                    "amplify:ListDomainAssociations",
                    "amplify:ListJobs",
                    "application-autoscaling:Describe*",
                    "applicationinsights:Describe*",
                    "applicationinsights:List*",
                    "appmesh:Describe*",
                    "appmesh:List*",
                    "appstream:Describe*",
                    "appstream:List*",
                    "appsync:List*",
                    "autoscaling:Describe*",
                    "autoscaling-plans:Describe*",
                    "athena:Batch*",
                    "aws-portal:ViewBilling",
                    "aws-portal:ViewUsage",
                    "backup:Describe*",
                    "backup:List*",
                    "batch:List*",
                    "batch:Describe*",
                    "budgets:Describe*",
                    "budgets:View*",
                    "ce:Get*",
                    "ce:Describe*",
                    "ce:List*",
                    "chatbot:Describe*",
                    "chime:List*",
                    "chime:Retrieve*",
                    "chime:Search*",
                    "chime:Validate*",
                    "cloud9:Describe*",
                    "cloud9:List*",
                    "clouddirectory:List*",
                    "cloudformation:Describe*",
                    "cloudhsm:List*",
                    "cloudhsm:Describe*",
                    "cloudsearch:Describe*",
                    "cloudtrail:Describe*",
                    "cloudtrail:Get*",
                    "cloudtrail:List*",
                    "cloudwatch:Describe*",
                    "cloudwatch:Get*",
                    "cloudwatch:List*",
                    "codeartifact:DescribeDomain",
                    "codeartifact:DescribePackageVersion",
                    "codeartifact:DescribeRepository",
                    "codeartifact:ListDomains",
                    "codeartifact:ListPackages",
                    "codeartifact:ListPackageVersionAssets",
                    "codeartifact:ListPackageVersionDependencies",
                    "codeartifact:ListPackageVersions",
                    "codeartifact:ListRepositories",
                    "codeartifact:ListRepositoriesInDomain",
                    "codebuild:DescribeCodeCoverages",
                    "codebuild:DescribeTestCases",
                    "codebuild:Get*",
                    "codebuild:List*",
                    "codebuild:BatchGetBuilds",
                    "codebuild:BatchGetProjects",
                    "codecommit:Describe*",
                    "codeguru-profiler:Describe*",
                    "codeguru-profiler:List*",
                    "codeguru-reviewer:Describe*",
                    "codeguru-reviewer:List*",
                    "codepipeline:List*",
                    "codepipeline:Get*",
                    "codestar:Describe*",
                    "compute-optimizer:Get*",
                    "connect:Describe*",
                    "cur:Describe*",
                    "dataexchange:List*",
                    "datasync:Describe*",
                    "datasync:List*",
                    "datapipeline:Describe*",
                    "datapipeline:List*",
                    "detective:List*",
                    "discovery:Describe*",
                    "dms:Describe*",
                    "ds:Check*",
                    "ds:Describe*",
                    "ds:List*",
                    "dynamodb:Describe*",
                    "dynamodb:List*",
                    "ec2:Describe*",
                    "ec2:GetCapacityReservationUsage",
                    "ec2:GetEbsEncryptionByDefault",
                    "ec2:SearchTransitGatewayRoutes",
                    "ecr:BatchCheck*",
                    "ecr:BatchGet*",
                    "ecr:Describe*",
                    "ecr:List*",
                    "eks:DescribeCluster",
                    "eks:DescribeUpdate",
                    "eks:Describe*",
                    "eks:ListClusters",
                    "eks:ListUpdates",
                    "eks:List*",
                    "elasticache:List*",
                    "elasticbeanstalk:Check*",
                    "elasticbeanstalk:Describe*",
                    "elasticbeanstalk:List*",
                    "elasticbeanstalk:Request*",
                    "elasticbeanstalk:Retrieve*",
                    "elasticbeanstalk:Validate*",
                    "elasticfilesystem:Describe*",
                    "elasticloadbalancing:Describe*",
                    "elasticmapreduce:Describe*",
                    "elasticmapreduce:View*",
                    "elemental-appliances-software:List*",
                    "es:Describe*",
                    "es:List*",
                    "events:Describe*",
                    "events:List*",
                    "events:Test*",
                    "firehose:Describe*",
                    "fsx:Describe*",
                    "fsx:List*",
                    "freertos:Describe*",
                    "freertos:List*",
                    "glacier:Describe*",
                    "globalaccelerator:Describe*",
                    "globalaccelerator:List*",
                    "glue:ListCrawlers",
                    "glue:ListDevEndpoints",
                    "glue:ListJobs",
                    "glue:ListMLTransforms",
                    "glue:ListTriggers",
                    "glue:ListWorkflows",
                    "guardduty:List*",
                    "health:Describe*",
                    "iam:Get*",
                    "imagebuilder:List*",
                    "importexport:List*",
                    "inspector:Describe*",
                    "inspector:Preview*",
                    "iot:Describe*",
                    "iotanalytics:Describe*",
                    "iotanalytics:List*",
                    "iotsitewise:Describe*",
                    "iotsitewise:List*",
                    "kafka:Describe*",
                    "kafka:List*",
                    "kinesisanalytics:Describe*",
                    "kinesisanalytics:Discover*",
                    "kinesisanalytics:List*",
                    "kinesisvideo:Describe*",
                    "kinesisvideo:List*",
                    "kinesis:Describe*",
                    "kinesis:List*",
                    "kms:Describe*",
                    "kms:List*",
                    "license-manager:List*",
                    "logs:ListTagsLogGroup",
                    "logs:TestMetricFilter",
                    "mediaconvert:DescribeEndpoints",
                    "mediaconvert:List*",
                    "mediapackage:List*",
                    "mediapackage:Describe*",
                    "medialive:List*",
                    "medialive:Describe*",
                    "mediaconnect:List*",
                    "mediaconnect:Describe*",
                    "mediapackage-vod:List*",
                    "mediapackage-vod:Describe*",
                    "mediastore:List*",
                    "mediastore:Describe*",
                    "mediatailor:List*",
                    "mediatailor:Describe*",
                    "mgh:Describe*",
                    "mgh:List*",
                    "mobilehub:Describe*",
                    "mobilehub:List*",
                    "mobiletargeting:List*",
                    "mq:Describe*",
                    "mq:List*",
                    "opsworks-cm:List*",
                    "organizations:Describe*",
                    "organizations:List*",
                    "outposts:List*",
                    "outposts:Get*",
                    "personalize:Describe*",
                    "personalize:List*",
                    "pi:DescribeDimensionKeys",
                    "pricing:*",
                    "qldb:ListLedgers",
                    "qldb:ListTagsForResource",
                    "ram:List*",
                    "rekognition:List*",
                    "rds:List*",
                    "redshift:Describe*",
                    "redshift:GetReservedNodeExchangeConfigurationOptions",
                    "redshift:GetReservedNodeExchangeOfferings",
                    "redshift:View*",
                    "resource-groups:Get*",
                    "resource-groups:List*",
                    "resource-groups:Search*",
                    "robomaker:BatchDescribe*",
                    "robomaker:Describe*",
                    "robomaker:List*",
                    "route53domains:Check*",
                    "route53domains:Get*",
                    "route53domains:View*",
                    "s3:List*",
                    "s3:GetBucketLocation",
                    "s3:GetBucketTagging",
                    "savingsplans:Describe*",
                    "schemas:Describe*",
                    "schemas:List*",
                    "secretsmanager:List*",
                    "secretsmanager:Describe*",
                    "securityhub:Describe*",
                    "securityhub:List*",
                    "serverlessrepo:List*",
                    "servicecatalog:Describe*",
                    "servicediscovery:Get*",
                    "servicediscovery:List*",
                    "servicequotas:Get*",
                    "servicequotas:List*",
                    "ses:Describe*",
                    "shield:Describe*",
                    "snowball:Describe*",
                    "snowball:List*",
                    "sqs:List*",
                    "ssm:Describe*",
                    "ssm:List*",
                    "sso:Describe*",
                    "sso:List*",
                    "sso:Search*",
                    "sso-directory:Describe*",
                    "sso-directory:List*",
                    "sso-directory:Search*",
                    "states:List*",
                    "states:Describe*",
                    "storagegateway:Describe*",
                    "storagegateway:List*",
                    "sts:GetCallerIdentity",
                    "sts:GetSessionToken",
                    "swf:Describe*",
                    "synthetics:Describe*",
                    "synthetics:List*",
                    "tag:Get*",
                    "transfer:Describe*",
                    "transfer:List*",
                    "transcribe:List*",
                    "wafv2:Describe*",
                    "worklink:Describe*",
                    "worklink:List*"
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  },
  "Outputs": {
    "ReadOnlyRoleArn": {
      "Description": "The ARN of the IAM Role with read-only permissions",
      "Value": { "Fn::GetAtt": ["ReadOnlyRole", "Arn"] },
      "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-RoleArn" } }
    },
    "ReadOnlyIamUserAccessKeyId": {
      "Description": "The accessKeyId for the IAM user",
      "Value": { "Ref": "ReadOnlyIamUserAccessKey" },
      "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-AccessKeyId" } }
    },
    "ReadOnlyIamUserSecretAccessKey": {
      "Description": "The secretAccessKey for the IAM user (only visible at stack creation)",
      "Value": { "Fn::GetAtt": [ "ReadOnlyIamUserAccessKey", "SecretAccessKey" ] },
      "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-SecretAccessKey" } }
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment