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:
- The AWS ReadOnlyAccess Managed Policy
- The AWS ViewOnlyAccess Managed Policy
- The Vantage.sh recommended policy for integration
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" } }
}
}
}