---
title: "Read-Only Role Template | Vishcore Inc."
description: "The CloudFormation template for the read-only role you create for a Vishcore scan, explained part by part, with AWS CLI commands to verify its denies yourself."
canonical: https://vishcore.com/resources/read-only-role
---

1. [Resources](https://vishcore.com/resources)
2. Read-Only Role Template

role template

# The read-only role, explained line by line.

You create this role in your own AWS account from our CloudFormation template. Here is every part of it: who it trusts, what it allows, what it explicitly denies, and how to check each part yourself.

[Start discovery](https://vishcore.com/start-discovery) Verify it yourself

The template at a glance

**Creates**

One IAM role and one managed policy, owned by you

**Trusts**

One Vishcore scanner role, and only with your External ID

**Explicitly denies**

32 write patterns, 11 secret-value and environment reads, and API key reads

**Allows**

132 named read-only actions

**Teardown**

Delete the stack

the template

## Nine parts, in plain English.

Each excerpt is copied line for line from the template. Its allow statements name exactly the actions in our scanner allowlist's default set, and a test in the scanner's codebase fails if the two ever differ. IAM refuses any call they do not name.

[Download the template (YAML)](https://vishcore.com/resources/vishcore-read-only-discovery-role.cloudformation.yaml)

1. Parameters lines 4–25 · shown in full

   ```
   Parameters:
     RoleName:
       Type: String
       Default: VishcoreReadOnlyDiscovery
       Description: Name for the client-owned read-only discovery role.
     PolicyName:
       Type: String
       Default: VishcoreReadOnlyDiscoveryPolicy
       Description: Name for the client-owned read-only scanner policy.
     VishcorePrincipalArn:
       Type: String
       Description: AWS principal ARN approved to assume this role.
       AllowedPattern: "^arn:aws:iam::[0-9]{12}:(role|user)/[A-Za-z0-9+=,.@_/-]+$"
     ExternalId:
       Type: String
       NoEcho: true
       MinLength: 16
       Description: External ID generated for this engagement and shared through the approved secure channel.
     ApprovedRegions:
       Type: CommaDelimitedList
       Default: ca-central-1
       Description: Comma-separated AWS Regions approved for regional scanner metadata reads; include the enabled-Region discovery scope if used.
   ```

   Part 1

   ### You fill in five values.

   `RoleName` and `PolicyName` default to `VishcoreReadOnlyDiscovery` and `VishcoreReadOnlyDiscoveryPolicy`; you can rename them. `VishcorePrincipalArn` is the one Vishcore scanner role allowed in. We send you its value, shaped like `arn:aws:iam::<VISHCORE_ACCOUNT_ID>:role/<VISHCORE_SCANNER_ROLE_NAME>`, and its pattern accepts only a role or user ARN, never a whole account or a wildcard.

   `ExternalId` must be at least 16 characters, and `NoEcho` masks it wherever CloudFormation shows the stack's parameters. `ApprovedRegions` (default `ca-central-1`) limits the regional reads to the Regions you list.
2. Resources: the role and its trust policy lines 28–44 · shown in full

   ```
   VishcoreReadOnlyDiscoveryRole:
     Type: AWS::IAM::Role
     Properties:
       RoleName: !Ref RoleName
       Description: Read-only Vishcore Cloud Control Scan discovery role. No remediation/write permissions.
       AssumeRolePolicyDocument:
         Version: "2012-10-17"
         Statement:
           - Effect: Allow
             Principal:
               AWS: !Ref VishcorePrincipalArn
             Action: sts:AssumeRole
             Condition:
               StringEquals:
                 sts:ExternalId: !Ref ExternalId
       ManagedPolicyArns:
         - !Ref VishcoreReadOnlyDiscoveryPolicy
   ```

   Part 2

   ### It trusts one role, and only with your External ID.

   The trust policy has one statement and one principal: the ARN you entered for `VishcorePrincipalArn`. No other identity, inside Vishcore or outside it, can assume the role.

   The `sts:ExternalId` condition refuses even that role unless it also presents the External ID for your engagement. Knowing your role ARN is not enough to reach your account through Vishcore.

   The role carries one policy, the managed policy below, and nothing else.
3. The policy's own comment lines 53–60 · shown in full

   ```
   # Residual read exposure the denies do not remove, disclosed on purpose:
   # - cloudfront:GetDistributionConfig and cloudfront:ListDistributions both return
   #   origin custom header values; the scanner keeps aliases and booleans only.
   # - apigateway:GET on stage collections returns stage variables; the scanner keeps
   #   logging and tracing booleans only. API key values are denied below.
   # - inspector2:ListFindings returns finding metadata (resource identifiers, package
   #   and CVE names) with no environment or secret fields; the scanner keeps
   #   severity counts and age buckets only.
   ```

   Part 3

   ### The template names what its denies leave readable.

   Before its first statement, the policy says in a comment that four allowed reads return more than the scanner keeps: `cloudfront:GetDistributionConfig`, `cloudfront:ListDistributions`, `apigateway:GET`, and `inspector2:ListFindings`. We put it in the template so the disclosure travels with the role.

   Both CloudFront reads return origin custom header values, which are often shared secrets between CloudFront and your origin, and AWS has no CloudFront read that leaves them out. API Gateway stage lists return stage variables. Inspector findings carry finding metadata such as resource identifiers and package and CVE names, with no environment or secret fields.

   The scanner keeps aliases and booleans from CloudFront, logging and tracing booleans from API Gateway stages, and severity counts and age buckets from Inspector. It drops the rest before anything is stored.
4. Policy statement 1 of 6 lines 62–97 · shown in full

   ```
   - Sid: DenyMutatingOperations
     Effect: Deny
     Action:
       - "*:Create*"
       - "*:Put*"
       - "*:Delete*"
       - "*:Modify*"
       - "*:Update*"
       - "*:Start*"
       - "*:Stop*"
       - "*:Terminate*"
       - "*:Run*"
       - "*:Register*"
       - "*:Deregister*"
       - "*:Associate*"
       - "*:Disassociate*"
       - "*:Attach*"
       - "*:Detach*"
       - "*:Authorize*"
       - "*:Revoke*"
       - "*:Tag*"
       - "*:Untag*"
       - "*:Enable*"
       - "*:Disable*"
       - "*:Schedule*"
       - "*:Cancel*"
       - "*:Reboot*"
       - "*:Restore*"
       - "*:BatchWrite*"
       - "*:Invoke*"
       - "*:Publish*"
       - "*:Send*"
       - "*:AddTags*"
       - "*:RemoveTags*"
       - "*:Set*"
     Resource: "*"
   ```

   Part 4

   ### Write patterns, denied on every service.

   This statement denies 32 write patterns on every AWS service, such as `*:Create*`, `*:Put*`, and `*:Delete*`: each one matches every call whose name starts with that verb.

   In IAM an explicit deny always wins over an allow, so an allow added later by mistake could not reopen a call these patterns match. Writes whose names start with other verbs, such as `apigateway:POST` and `iam:PassRole`, are refused because no allow names them. The allow lists name only reads, so discovery cannot change production.
5. Policy statement 2 of 6 lines 98–112 · shown in full

   ```
   - Sid: DenySecretValueAndDeepEnvironmentReads
     Effect: Deny
     Action:
       - secretsmanager:GetSecretValue
       - ssm:GetParameter
       - ssm:GetParameters
       - ssm:GetParametersByPath
       - ssm:GetParameterHistory
       - lambda:ListFunctions
       - lambda:GetFunctionConfiguration
       - ecs:ListTaskDefinitions
       - ecs:DescribeTaskDefinition
       - config:SelectResourceConfig
       - securityhub:GetFindings
     Resource: "*"
   ```

   Part 5

   ### Secret-value calls, and reads that can return environment values, are explicitly denied.

   The first five actions are the main calls that return secret values from Secrets Manager and SSM Parameter Store, parameter history included. Other reads that can return those values, such as `secretsmanager:BatchGetSecretValue`, are refused because no allow names them; that one also needs `secretsmanager:GetSecretValue` on each secret, which this statement denies.

   The next four cover Lambda and ECS configuration: `lambda:ListFunctions`, `lambda:GetFunctionConfiguration`, and `ecs:DescribeTaskDefinition` can return environment values, and `ecs:ListTaskDefinitions`, which returns only task-definition ARNs, is denied with them as the first step of that path. The last two, `config:SelectResourceConfig` and `securityhub:GetFindings`, run AWS Config advanced queries and read Security Hub findings, which can return that same recorded configuration. IAM cannot narrow these reads to leave that content out, so the template denies them all.

   Scanner tests that need these reads, such as the Lambda environment KMS key test and the Security Hub failed-finding test, report “Not tested: read-only boundary” under this role.

   The role also grants no KMS decrypt or key-material access: no secret values read from Secrets Manager, SSM, or KMS.
6. Policy statement 3 of 6 lines 113–121 · shown in full

   ```
   - Sid: DenyApiGatewayKeyValueReads
     Effect: Deny
     Action:
       - apigateway:GET
     Resource:
       - arn:aws:apigateway:*::/apikeys
       - arn:aws:apigateway:*::/apikeys/*
       - arn:aws:apigateway:*::/usageplans/*/keys
       - arn:aws:apigateway:*::/usageplans/*/keys/*
   ```

   Part 6

   ### The API key paths are explicitly denied.

   API Gateway has one IAM action for every management read, `apigateway:GET`, so IAM cannot grant its reads one call at a time. The template scopes it by `Resource` path instead.

   This statement denies `apigateway:GET` on `/apikeys`, `/apikeys/*`, `/usageplans/*/keys`, and `/usageplans/*/keys/*`, the API key and usage-plan key paths. As an explicit deny, it holds on those paths even if an allow is widened later. No allow grants them today either: the allow statement below names six other paths.
7. Policy statements 4 and 5 of 6 lines 122–263 · shortened

   ```
   - Sid: AllowGlobalDiscoveryMetadata
     Effect: Allow
     Action:
       - sts:GetCallerIdentity
       - iam:GetAccountPasswordPolicy
       - iam:GetAccountSummary
       - iam:GetGroupPolicy
       - iam:GetLoginProfile
       # … 31 more of 36 actions in this statement
     Resource: "*"
   - Sid: AllowRegionalDiscoveryMetadata
     Effect: Allow
     Action:
       - acm:DescribeCertificate
       - acm:ListCertificates
       - cloudtrail:DescribeTrails
       - access-analyzer:ListAnalyzers
       - access-analyzer:ListFindings
       # … 90 more of 95 actions in this statement
     Resource: "*"
     Condition:
       StringEquals:
         aws:RequestedRegion: !Ref ApprovedRegions
   ```

   See all 131 actions in these two statements

   AllowGlobalDiscoveryMetadata (36)

   ```
   sts:GetCallerIdentity
   iam:GetAccountPasswordPolicy
   iam:GetAccountSummary
   iam:GetGroupPolicy
   iam:GetLoginProfile
   iam:GetPolicy
   iam:GetPolicyVersion
   iam:GetUserPolicy
   iam:ListAccessKeys
   iam:ListAttachedGroupPolicies
   iam:ListAttachedUserPolicies
   iam:ListGroupPolicies
   iam:ListGroupsForUser
   iam:ListMFADevices
   iam:ListUserPolicies
   iam:ListUsers
   iam:GetAccessKeyLastUsed
   iam:ListServerCertificates
   cloudfront:GetDistributionConfig
   cloudfront:ListDistributions
   route53:GetDNSSEC
   route53:ListHostedZones
   s3:ListAllMyBuckets
   s3:GetBucketAcl
   s3:GetBucketLogging
   s3:GetBucketPolicy
   s3:GetBucketPolicyStatus
   s3:GetBucketTagging
   s3:GetBucketVersioning
   s3:GetEncryptionConfiguration
   s3:GetLifecycleConfiguration
   s3:GetBucketPublicAccessBlock
   s3control:GetPublicAccessBlock
   organizations:DescribeOrganization
   organizations:ListPolicies
   s3:GetReplicationConfiguration
   ```

   AllowRegionalDiscoveryMetadata (95)

   ```
   acm:DescribeCertificate
   acm:ListCertificates
   cloudtrail:DescribeTrails
   access-analyzer:ListAnalyzers
   access-analyzer:ListFindings
   backup:ListBackupPlans
   backup:ListBackupVaults
   backup:ListProtectedResources
   backup:ListRecoveryPointsByBackupVault
   cloudwatch:DescribeAlarms
   cloudwatch:DescribeAlarmsForMetric
   config:DescribeConfigurationRecorders
   config:DescribeConfigurationRecorderStatus
   config:DescribeDeliveryChannels
   config:ListDiscoveredResources
   cognito-idp:DescribeUserPool
   cognito-idp:ListUserPools
   dynamodb:DescribeContinuousBackups
   dynamodb:DescribeTable
   dynamodb:ListTagsOfResource
   dynamodb:ListTables
   ec2:DescribeFlowLogs
   ec2:DescribeImageAttribute
   ec2:DescribeImages
   ec2:DescribeInstances
   ec2:DescribeNetworkAcls
   ec2:DescribeRegions
   ec2:DescribeRouteTables
   ec2:DescribeSecurityGroups
   ec2:DescribeSnapshotAttribute
   ec2:DescribeSnapshots
   ec2:DescribeSubnets
   ec2:DescribeVolumes
   ec2:DescribeVpcs
   ec2:GetEbsEncryptionByDefault
   ecr:DescribeRepositories
   ecr:DescribeImages
   ecr:GetRegistryScanningConfiguration
   ecr:GetLifecyclePolicy
   ecr:GetRepositoryPolicy
   ecr:ListTagsForResource
   ecs:DescribeClusters
   ecs:DescribeServices
   ecs:ListClusters
   ecs:ListServices
   ecs:ListTagsForResource
   elasticache:DescribeCacheClusters
   elasticache:DescribeReplicationGroups
   elasticache:DescribeSnapshots
   elasticache:ListTagsForResource
   eks:DescribeCluster
   eks:ListClusters
   elasticfilesystem:DescribeBackupPolicy
   elasticfilesystem:DescribeFileSystems
   elasticfilesystem:ListTagsForResource
   elasticloadbalancing:DescribeListeners
   elasticloadbalancing:DescribeLoadBalancerAttributes
   elasticloadbalancing:DescribeLoadBalancers
   elasticloadbalancing:DescribeRules
   elasticloadbalancing:DescribeTags
   events:ListRules
   events:ListTagsForResource
   events:ListTargetsByRule
   guardduty:ListDetectors
   inspector2:BatchGetAccountStatus
   inspector2:ListFindings
   kms:DescribeKey
   kms:GetKeyRotationStatus
   kms:ListKeys
   logs:DescribeLogGroups
   lambda:GetPolicy
   lambda:ListFunctionUrlConfigs
   rds:DescribeDBClusterParameters
   rds:DescribeDBClusterSnapshotAttributes
   rds:DescribeDBClusterSnapshots
   rds:DescribeDBClusters
   rds:DescribeDBInstances
   rds:DescribeDBParameters
   rds:DescribeDBSnapshotAttributes
   rds:DescribeDBSnapshots
   rds:ListTagsForResource
   secretsmanager:ListSecrets
   securityhub:DescribeHub
   securityhub:GetEnabledStandards
   sns:GetTopicAttributes
   sns:ListTagsForResource
   sns:ListTopics
   sqs:GetQueueAttributes
   sqs:ListQueueTags
   sqs:ListQueues
   ssm:DescribeInstanceInformation
   wafv2:GetWebACLForResource
   elasticloadbalancing:DescribeSSLPolicies
   cloudtrail:GetTrailStatus
   cloudtrail:GetEventSelectors
   ```

   Part 7

   ### Only configuration metadata, and only where you said.

   These two statements name 131 read calls one by one, with no wildcards: 36 account-wide and 95 regional. All but one are Describe, Get, or List calls; that one is the read-only `inspector2:BatchGetAccountStatus`.

   The regional reads work only in the Regions you put in `ApprovedRegions`, through the `aws:RequestedRegion` condition. Nothing allows data-plane reads, so S3 objects, table items, and log events fall to an implicit deny.

   Some allowed configuration reads, such as CloudFront distribution settings, can include sensitive fields; the scanner reduces those responses to aliases and booleans before anything is stored.
8. Policy statement 6 of 6 lines 264–277 · shown in full

   ```
   - Sid: AllowApiGatewayReadPaths
     Effect: Allow
     Action:
       - apigateway:GET
     Resource:
       - arn:aws:apigateway:*::/restapis
       - arn:aws:apigateway:*::/restapis/*/stages
       - arn:aws:apigateway:*::/restapis/*/authorizers
       - arn:aws:apigateway:*::/apis
       - arn:aws:apigateway:*::/apis/*/stages
       - arn:aws:apigateway:*::/apis/*/authorizers
     Condition:
       StringEquals:
         aws:RequestedRegion: !Ref ApprovedRegions
   ```

   Part 8

   ### API Gateway reads, only on the scanner's paths.

   This statement allows `apigateway:GET` on six paths only: `/restapis`, `/restapis/*/stages`, `/restapis/*/authorizers`, `/apis`, `/apis/*/stages`, and `/apis/*/authorizers`. Those are the two API lists and each API's stages and authorizers, the calls the scanner makes.

   The same `aws:RequestedRegion` condition keeps it to the Regions in `ApprovedRegions`. Any other API Gateway path, such as an API's integrations or deployments, falls to an implicit deny.

   Stage lists include stage variables; the scanner keeps only logging and tracing booleans from them.
9. Outputs lines 279–288 · shown in full

   ```
   Outputs:
     RoleArn:
       Description: Share this role ARN with Vishcore through the approved secure channel.
       Value: !GetAtt VishcoreReadOnlyDiscoveryRole.Arn
     PolicyArn:
       Description: Client-owned read-only discovery policy ARN.
       Value: !Ref VishcoreReadOnlyDiscoveryPolicy
     Teardown:
       Description: Delete this CloudFormation stack to remove the role and policy after the engagement.
       Value: Delete the stack after the scan engagement closes or when access is no longer approved.
   ```

   Part 9

   ### What you send us, and how you end it.

   Send the `RoleArn` output to Vishcore through the approved secure channel, as its description says. `PolicyArn` names the policy.

   The `Teardown` output is the exit plan: delete the stack, and the role and policy are gone, and with them our access.

Copied from client-read-only-discovery-role.cloudformation.yaml, with each excerpt shifted left; a shortened excerpt marks its cut with a # … comment. The template takes account IDs and principals as parameters and contains none.

verify it yourself

## Check the role from your own account.

Plain AWS CLI commands you run after you deploy the stack. Steps 1 to 6 only read your configuration; step 7 removes the role. You need IAM permission to call them, including iam:GetRole and iam:SimulatePrincipalPolicy.

1. Step 1

   ### Confirm the stack and its outputs

   The stack should be complete (UPDATE_COMPLETE after an update) and list its three outputs, in any order. The second command prints the role ARN that the next steps call <role-arn>.

   Run

   ```
   aws cloudformation describe-stacks \
     --stack-name <stack-name> \
     --query "Stacks[0].[StackStatus, Outputs[].OutputKey]"
   ```

   Expect

   ```
   [
       "CREATE_COMPLETE",
       [
           "RoleArn",
           "PolicyArn",
           "Teardown"
       ]
   ]
   ```

   Run

   ```
   aws cloudformation describe-stacks \
     --stack-name <stack-name> \
     --query "Stacks[0].Outputs[?OutputKey=='RoleArn'].OutputValue" \
     --output text
   ```

   Expect

   ```
   arn:aws:iam::<CLIENT_ACCOUNT_ID>:role/VishcoreReadOnlyDiscovery
   ```
2. Step 2

   ### Check who the role trusts

   One statement with one principal, the Vishcore scanner role, and the External ID condition.

   Run

   ```
   aws iam get-role \
     --role-name VishcoreReadOnlyDiscovery \
     --query "Role.AssumeRolePolicyDocument.Statement[].[Principal.AWS, Action, Condition.StringEquals]"
   ```

   Expect

   ```
   [
       [
           "arn:aws:iam::<VISHCORE_ACCOUNT_ID>:role/<VISHCORE_SCANNER_ROLE_NAME>",
           "sts:AssumeRole",
           {
               "sts:ExternalId": "<EXTERNAL_ID>"
           }
       ]
   ]
   ```
3. Step 3

   ### Prove writes, secret values, and environment reads are denied

   IAM's policy simulator evaluates the role's own policy without calling any service. Every action here should come back as an explicit deny: writes, Secrets Manager and SSM values, and the Lambda, AWS Config query, and Security Hub reads that can return environment values.

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names s3:PutObject \
       ec2:TerminateInstances \
       secretsmanager:GetSecretValue \
       ssm:GetParameter \
       lambda:GetFunctionConfiguration \
       config:SelectResourceConfig \
       securityhub:GetFindings \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   s3:PutObject                     explicitDeny
   ec2:TerminateInstances           explicitDeny
   secretsmanager:GetSecretValue    explicitDeny
   ssm:GetParameter                 explicitDeny
   lambda:GetFunctionConfiguration  explicitDeny
   config:SelectResourceConfig      explicitDeny
   securityhub:GetFindings          explicitDeny
   ```
4. Step 4

   ### Prove data and keys were never granted

   Object reads and KMS decrypt are not allowed anywhere, so they fall to an implicit deny. A metadata read comes back allowed, which shows the simulation works; a service control policy in your organization can still deny it.

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names s3:GetObject \
       kms:Decrypt \
       iam:ListUsers \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   s3:GetObject   implicitDeny
   kms:Decrypt    implicitDeny
   iam:ListUsers  allowed
   ```
5. Step 5

   ### Prove the regional reads stay in your Regions

   Simulate a regional read in a Region you approved, then in one you did not. The template's default approved Region is ca-central-1.

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names ec2:DescribeInstances \
     --context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyValues=ca-central-1,ContextKeyType=string" \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   ec2:DescribeInstances  allowed
   ```

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names ec2:DescribeInstances \
     --context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyValues=us-east-1,ContextKeyType=string" \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   ec2:DescribeInstances  implicitDeny
   ```
6. Step 6

   ### Prove API Gateway reads stop at the scanner's paths

   API Gateway reads share one action, so each run names a path with --resource-arns. The API key path comes back as an explicit deny, even in your approved Region; the API list at /restapis, one of the scanner's paths, comes back allowed.

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names apigateway:GET \
     --resource-arns arn:aws:apigateway:ca-central-1::/apikeys \
     --context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyValues=ca-central-1,ContextKeyType=string" \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   apigateway:GET  explicitDeny
   ```

   Run

   ```
   aws iam simulate-principal-policy \
     --policy-source-arn <role-arn> \
     --action-names apigateway:GET \
     --resource-arns arn:aws:apigateway:ca-central-1::/restapis \
     --context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyValues=ca-central-1,ContextKeyType=string" \
     --query "EvaluationResults[].[EvalActionName,EvalDecision]" \
     --output text
   ```

   Expect

   ```
   apigateway:GET  allowed
   ```
7. Step 7 · changes your account

   ### Delete the stack when we finish

   This removes the role and the policy, which ends our access. The last command then fails, because the role no longer exists.

   Run

   ```
   aws cloudformation delete-stack \
     --stack-name <stack-name>
   ```

   Expect

   ```
   (no output)
   ```

   Run

   ```
   aws cloudformation wait stack-delete-complete \
     --stack-name <stack-name>
   ```

   Expect

   ```
   (no output once the stack is gone)
   ```

   Run

   ```
   aws iam get-role \
     --role-name VishcoreReadOnlyDiscovery
   ```

   Expect

   ```
   An error occurred (NoSuchEntity) when calling the GetRole operation: The role with name VishcoreReadOnlyDiscovery cannot be found.
   ```

Placeholders in angle brackets are yours to fill in. The CLI separates text output with tabs; this page aligns it for reading. The expected decisions are computed from the published template's policy alone, so a service control policy or permissions boundary in your account can only make them stricter.

## Happy with the role? Start with a short note.

We confirm fit before any access. No secrets, account IDs, or access in the first message.

[How the scan works](https://vishcore.com/scan)

[Start discovery](https://vishcore.com/start-discovery)
