Deploy the Spotto AWS IAM Role with Bash
Overview
The Spotto AWS Bash wizard creates or updates SpottoReadOnlyRole in the accounts listed in your company's setup package. It applies the exact trust and permission policies generated by Spotto, checks every AWS session's account identity before making changes, and writes results for the Portal or your Spotto contact.
Use it on Linux, macOS or in AWS CloudShell's default Bash session. It supports up to 100 enabled accounts and a setup package up to 1 MiB. The PowerShell wizard and Terraform module use the same package and results format. None of these methods creates AWS accounts, billing exports, S3 buckets or security services.
Prerequisites
- Bash 3.2 or later. Run the script with
bash, notsh. - AWS CLI v2, jq 1.6 or later, and GNU
timeout(orgtimeouton macOS). On macOS,brew install jq coreutilssupplies jq andgtimeout; install AWS CLI v2 separately. CloudShell includes jq, but check the required capabilities there too; the script checks them before processing the package. - Your company's
spotto-aws-setup.json. On Deploy Access, choose Bash, PowerShell or Terraform, then Download Setup Package. Preview customers without Portal access receive the package from Spotto. - An authorized administrator session or AWS CLI profile for each account. Management account access does not grant IAM administration in member accounts. Never send administrator credentials to Spotto.
- For a narrower operator role:
sts:GetCallerIdentity;iam:GetRole,iam:ListAttachedRolePolicies,iam:ListRolePolicies,iam:GetRolePolicy; and, as needed for approved changes,iam:CreateRole,iam:TagRole,iam:UpdateAssumeRolePolicy,iam:PutRolePolicy,iam:DeleteRolePolicy,iam:AttachRolePolicy.
Authenticate before starting the wizard. Its supervised AWS CLI jobs cannot accept MFA or credential-helper prompts. For an MFA assume-role profile, run aws sts get-caller-identity --profile PROFILE once in your terminal to authenticate and cache the role session. For IAM Identity Center (SSO), run aws sso login --profile PROFILE. Credential helpers such as aws-vault, granted or saml2aws must supply a preauthenticated, cached session without prompting. Repeat for each profile in a profile map, and rerun authentication if the session expires.
Review the setup package before approving changes. Keep its server-issued company External ID unchanged. The script supports only the standard SpottoReadOnlyRole; use manual IAM setup for custom role names or paths.
Enter billing details before downloading the package for a single setup pass. If you need role-based export discovery first, follow discover a Data Export instead: configure a discovery-only package, apply the generated bootstrap billing policy, then download and configure a fresh package after completing the export destination.
Step 1: Download And Review The Script
Review setup-spotto-aws.sh on GitHub and the AWS onboarding README. It is a standalone file; no Terraform installation or companion module is needed.
-
Download the raw Bash script:
curl --fail --show-error --location \https://raw.githubusercontent.com/spottoai/spotto-tools/main/onboarding/aws/setup-spotto-aws.sh \--output ./setup-spotto-aws.sh -
Save your setup package alongside it, or use its full path in the commands below.
-
Sign in with your normal authorized AWS CLI profile. In CloudShell, upload the package with Actions > Upload file and use the current AWS session by omitting
--profile.
Step 2: Check Or Preview The Configuration
Start with a read-only comparison:
bash ./setup-spotto-aws.sh \
--setup-package ./spotto-aws-setup.json \
--profile customer-admin --check-only
In CloudShell's current Bash session:
bash ./setup-spotto-aws.sh \
--setup-package ./spotto-aws-setup.json --check-only
Without a mode flag, the interactive prompt defaults to checking; press Enter for a read-only run. --non-interactive also defaults to check-only. --dry-run previews changes without applying them. These checks inspect IAM configuration; they do not prove operator write permissions or Spotto's effective access.
For several accounts, create profiles.json with account IDs as strings and authorized profile names only:
{
"111122223333": "management-admin",
"000011112222": "billing-storage-admin"
}
bash ./setup-spotto-aws.sh \
--setup-package ./spotto-aws-setup.json \
--profile-map ./profiles.json --dry-run
The wizard checks all resolved sessions before changing any account. --profile provides a fallback for accounts absent from the map; an explicitly mapped empty string uses the current AWS session. In unattended multi-account runs without a fallback profile, map every account. A profile that resolves to the wrong account stops the run before changes and writes no results file.
Step 3: Approve And Configure IAM Access
-
Select configure mode explicitly, or choose 2 at the interactive mode prompt:
bash ./setup-spotto-aws.sh \--setup-package ./spotto-aws-setup.json \--profile customer-admin --configure -
Review each account's listed IAM changes and approve them. Immediately before applying, the script rechecks the AWS account, immutable role ID, ownership, trust and approved plan. A changed role requires a fresh review.
-
For reviewed unattended configuration, use all three flags:
bash ./setup-spotto-aws.sh \--setup-package ./spotto-aws-setup.json \--profile-map ./profiles.json \--configure --non-interactive --yes
--yes requires --configure. End of input never implies approval. Run one writer at a time for each role: IAM changes cannot be made atomic against another administrator's concurrent changes.
Options
| Option | Behavior |
|---|---|
--setup-package FILE | Company setup package; required without prompts. |
--profile NAME | Authorized AWS CLI profile; otherwise uses the current session. |
--profile-map FILE | JSON mapping account IDs to profile names. |
--check-only | Read-only comparison; the default mode. |
--dry-run | Preview without IAM writes. |
--configure | Review and approve changes before applying. |
--non-interactive | Disable prompts; unattended configuration also needs --yes. |
--yes | Approve explicit configure mode without prompting. |
--repair-existing-role | Explicitly adopt an unmanaged existing role after review. |
--output FILE | Write results to a new path in an existing directory; existing paths are never overwritten. |
--region REGION | Commercial AWS Region for CLI calls; defaults to us-east-1. China and GovCloud Regions are refused. |
--help | Show command help. |
Choose only one of --check-only, --configure and --dry-run.
Existing Roles And Ownership
New roles are tagged SpottoCompanyId and SpottoManagedBy=Setup-SpottoAws. Bash and PowerShell share these tags, so either script can maintain a role created by the other. Ownership tag keys are checked case-insensitively; values must match exactly.
An existing role that already matches the package needs no IAM writes. To change an unmanaged role, review it and rerun with --repair-existing-role. The script refuses another company's ownership or a trust policy bound to another or ambiguous External ID.
A SpottoManagedBy tag with any value other than the exact Setup-SpottoAws, including an empty value, makes the role verify-only. CloudFormation's own aws:cloudformation:* tags also make it verify-only. Matching roles report success without writes; configuration drift is listed and refused in configure mode, even with --repair-existing-role. Apply changes through the owning Terraform configuration, CloudFormation stack or other tool.
The script manages only the generated Spotto policies. It can replace trust (removing other trust statements) and remove the named optional billing or commitments policies when deselected. Other customer policies and permissions boundaries remain. Both scripts report a non-blocking warning if legacy ReadOnlyAccess or SecurityAudit attachments are present but not requested by the package. They do not detach them, and the warning does not prevent a configuration-matches result. Apply the generated replacement, verify effective access and collection in Spotto, then remove those attachments through the tool that owns the role. Review AWS permissions for policy details and migration of older managed-policy attachments.
An unchanged rerun performs no IAM writes. After a partial failure, rerun to inspect and finish missing changes. Cancelling with Ctrl+C or TERM stops further IAM writes; a write already in flight may have completed. Inspect the role with a fresh check before configuring again. Cancellation may stop before a results file is written.
Step 4: Return Results And Validate In Spotto
The script writes a new SpottoAwsOnboarding-<timestamp>-<suffix>.json, with owner-only file permissions on Linux/macOS. Use --output for another new path. The results contain your company ID, the unchanged account and billing configuration, account role ARNs and outcomes, with no credentials or External ID.
- For Portal users, paste the complete file into Setup Results JSON, then select Read Setup Results. Preview customers without Portal access send the file to their Spotto contact.
- Select Create or Update to save and let Spotto validate role assumption, resource reads, billing definitions and S3/KMS access. Reading results alone does not save or validate the connection.
- Review AWS Setup Status and follow any account or billing notices.
| Result | Meaning |
|---|---|
configured | IAM configuration completed or already matched. Effective access still needs Spotto validation. |
configuration-matches | A read-only comparison matched the package. |
changes-required | A check found differences; review and configure them through the owning tool. |
planned | Changes were previewed or not approved. |
failed | Account setup failed; review the console output before rerunning. |
Account failures return exit code 1 and still write results for attempted accounts. SCPs, permissions boundaries, S3 bucket policies and KMS key policies may still deny access; the script does not change those governance controls. Billing exports without delivered files remain pending.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Install GNU timeout (on macOS: brew install coreutils). | GNU timeout is missing. | Install coreutils; on macOS run brew install jq coreutils, then check gtimeout is on your path. |
sts get-caller-identity failed (Timeout) | The CLI exceeded its deadline; an MFA or credential-helper prompt may need an interactive terminal. | Authenticate first with aws sts get-caller-identity --profile PROFILE for MFA assume-role profiles or aws sso login --profile PROFILE for SSO. Ensure credential helpers provide a cached session without prompts, then rerun. |
AWS profile resolves to another account | A profile targets a different account from the package. | Correct the profile or map, sign in again and rerun. No changes were made. |
Existing role is not script-owned | An unmanaged existing role needs explicit adoption. | Review ownership and the plan, then use --repair-existing-role only for an unmanaged role. |
| A role is verify-only and changes are refused | Another tool owns it, including roles with CloudFormation stack tags or an empty manager value. | Apply the package through that tool or update the stack. The repair option cannot override ownership. |
Output path already exists. Choose a new file. | The selected results path exists. | Choose a new --output path; files are never overwritten. |
| Results cannot be read in Spotto | The company or configuration changed, the file was edited, or it exceeds 1 MiB. | Download a fresh package for the current company, rerun and paste the complete unchanged results file. |
AWS calls have a 45-second deadline, with two more seconds before forced termination. AWS CLI standard retries allow up to three attempts within that deadline. The script also retries selected IAM propagation errors with bounded backoff. For access-denied errors or missing billing data, see AWS setup troubleshooting.
Get Help
Contact Spotto with your company name, the account IDs and the reported error. Never send AWS access keys, session tokens or KMS key material.