Hacksaws
Hacksaws is an AWS login and IAM lifecycle CLI built for humans working beside agents. It can authenticate with MFA or AWS browser login, then optionally assume a role with a session policy so the credentials left on disk have a smaller blast radius than the credentials used to obtain them.
It also manages the accounts, targets, boundaries, reusable policies, IAM roles, and customer-managed policies used by that workflow. Every remote mutation is account-scoped, previewed, and recoverable where AWS permits it.
Install and run
Python 3.13 or newer is required. Run the published CLI without installing it:
uvx hacksaws --help
For development:
git clone https://github.com/rocketboosters/hacksaws.git
cd hacksaws
uv sync
uv run hacksaws --help
uv run test
uv run test is the repository quality gate. It runs formatting, linting, type
checking, the warning-free test suite, and enforces at least 95% coverage.
Quick start
Browser login needs no pre-existing profile. Hacksaws creates the destination profile when needed:
hacksaws web in debug
aws sts get-caller-identity --profile debug
Regions accept canonical names and friendly aliases. Hacksaws explains the resolution and always persists the canonical AWS name:
hacksaws region explain oregon
# Canonical region: us-west-2
pk is an exact alias for web:
hacksaws pk in admin --name horizon
MFA login starts from persistent source credentials:
hacksaws mfa in admin --name horizon 123456
Omit the code in an interactive terminal for a hidden prompt, or use
--mfa-code-stdin to read one line from standard input. JSON and other
non-interactive use never prompts.
The source above is profile admin in ~/.aws-horizon. To write temporary
credentials somewhere else, use --to LOCATION:PROFILE:
hacksaws mfa in admin --name horizon --to default:debug 123456
. and default both mean the default AWS directory or profile in their
respective position.
Boundary sessions
A boundary assumes a role after authentication. With no --policy, the role's
full permissions are used. Supplying a policy creates an intersected session:
AWS allows only actions permitted by both the role and the session policy.
hacksaws web in debug \
--role AgentSession \
--policy CloudWatchReadOnlyAccess
Policies may be AWS/customer-managed policy names, ARNs, stored-policy names, or
local JSON/YAML/TOML files. Hacksaws resolves and minifies the document before
calling AssumeRole. AWS also applies a separate packed-policy limit; Hacksaws
reports that limit explicitly but does not rewrite policy semantics.
Save role/policy/duration combinations as boundaries and full login presets as targets:
hacksaws boundary add cloudwatch AgentSession \
--account prod --policy CloudWatchReadOnlyAccess --duration 1h
hacksaws target add hacw \
--source-account prod --source-profile admin \
--source-location horizon --boundary cloudwatch
hacksaws web in +hacw
# Equivalent explicit spelling:
hacksaws web in --target hacw
A successful login can also teach Hacksaws the complete reusable target:
hacksaws web in debug --role AgentSession \
--policy CloudWatchReadOnlyAccess --save=debug-agent
hacksaws web in +debug-agent
Use bare --save in an interactive terminal to choose the name after the
credentials are committed. Automation must use --save=NAME or
--save-name NAME. See Saving login workflows for
account discovery, advanced naming, local-policy storage, and recovery from a
successful session whose configuration save did not complete.
Durations accept forms such as 15m, 15minutes, 1h, hour, 600s, and
600seconds. Rigid aliases --htl, --mtl, and --stl accept floating-point
hours, minutes, and seconds; sub-second results round to whole seconds.
If credentials are already logged in, constrain them without repeating the authentication step:
hacksaws assume admin --name horizon \
--role AgentSession --policy CloudWatchReadOnlyAccess \
--to default:agent
For a destination profile in the same AWS location,
hacksaws assume SOURCE DEST --role ... is the short form of
--to-profile DEST.
The destination is always explicit. The source is removed after a successful
handoff unless --keep-source is deliberate; use --self for an intentional
in-place replacement. See Assume a role for destination,
confirmation, ECR, and automation safeguards.
Inspect before acting
The human views are compact tables. Add global --json for automation and
--no-color when ANSI styling is undesirable:
hacksaws status
hacksaws profile list
hacksaws profile list --verify
hacksaws iam list --profile admin --wide
hacksaws cache status
hacksaws config show
hacksaws history list --since 24h
iam list verifies live ownership tags within the canonical /hacksaws/ paths
by default. That fast scope can miss adopted resources elsewhere, custom or
changed paths, and untagged legacy resources; add --all-account for the
comprehensive supported-resource scan. Add --details when dependency
information is worth the additional AWS calls. Human terminals receive delayed
progress on stderr while stdout remains safe to pipe; use --progress to force
plain milestones or --no-progress to suppress them. JSON mode is always quiet
until its single result envelope.
Local history records redacted command families, outcomes, timings, and
validated identifiers—not raw arguments, output, prompts, paths, policy
documents, or credentials. Use hacksaws history status to inspect retention
and health. See Local command history for the full security
contract, filters, exports, and clearing behavior.
Global output flags may appear anywhere before --:
hacksaws --json iam policy list
hacksaws iam policy list --color never
Remote IAM lifecycle
iam and remote are exact aliases. Credential selectors belong on terminal
commands, so the following is intentionally supported:
hacksaws iam policy create agent.yaml --profile admin --dry-run
hacksaws iam policy create agent.yaml --profile admin --yes
hacksaws iam role create AgentSession --profile admin --trust-caller --dry-run
Create commands never silently overwrite a differing resource. An identical
resource reports NO CHANGE; a difference reports CONFLICT. Use the normal
update command, or deliberate create --replace plus confirmation.
Normal remote IAM mutations accept --dry-run. A dry run performs discovery,
validation, collision checks, and planning, but creates no recovery journal and
changes neither AWS nor local state. Recovery continue and rollback commands
resume an already-journaled operation and therefore do not accept --dry-run.
Mutation previews and results use one credential-free contract: exact resource identity and ownership, scalar before/after changes, ordered AWS actions, dependencies, warnings, confirmation, applied actions, resource IDs/ARNs, console links, and recovery journal IDs. Policy documents and tag values are represented only by non-reversible summaries.
Leave No Trace cleanup
Cleanup deletes only resources whose Hacksaws ownership can be established in
the selected account. A pattern, --all, --smoke, or --smoke-run is
mandatory. With no type flags, all supported types are considered.
hacksaws cleanup "*ServiceBuzz*" --policies --profile admin --dry-run
hacksaws cleanup --all --profile admin --dry-run
hacksaws cleanup --smoke --profile admin --yes
--roles, --policies, and --group-grants narrow resource types. --created
and --adopted narrow ownership origin. Cross-retained dependencies require
explicit --cascade, --remove-boundaries, or
--remove-from-instance-profiles consent. hacksaws iam cleanup and
hacksaws remote cleanup use the same planner and executor.
Log out safely
Logout removes Hacksaws-managed live credentials without contacting an AWS logout endpoint. It never stores the intermediate MFA-authenticated credentials used to assume a boundary role.
hacksaws logout debug
hacksaws logout --all
hacksaws logout --all --except "default:prod*" --except "+hacw"
Tracked ECR logins are removed by default; use --keep-ecr deliberately.
Unknown external profiles are never altered.
Credential threat model
The MFA workflow involves three distinct credentials:
- Persistent unauthenticated source credentials remain on the device. Give them only the permissions needed to perform MFA/session bootstrap, because a local agent may be able to read them.
- MFA-authenticated intermediate credentials exist only while login and any ECR login are being completed. They are not backed up when a boundary is used.
- Boundary credentials are the role/session-policy credentials written to the destination for the user or agent.
Browser login similarly uses its authenticated credentials only to complete the requested workflow, then leaves the final requested credentials at the target.
Configure an assumable role
The role trust policy must allow the login identity to call sts:AssumeRole.
Hacksaws can generate the common caller-specific policy:
hacksaws iam role create AgentSession --trust-caller --profile admin
The equivalent trust statement is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:user/alice" },
"Action": "sts:AssumeRole"
}
]
}
The caller also needs an identity policy permitting sts:AssumeRole on the
role. A group cannot be an IAM trust principal. Hacksaws can instead grant a
group through a managed group policy, or expand the group's current users into
individual trust principals. See the trust guide before choosing between those
models.
Learn more
- Command cheat sheet
- Login pathways
- Saving login workflows
- Assume a role from an existing session
- Profiles, status, and logout
- IAM policies
- IAM roles and trust
- Cleanup and Leave No Trace
- Configuration
- Regions and aliases
- Policy cache
- Local command history
- Security model
- Automation and JSON
- Troubleshooting
- Development and smoke tests
Run hacksaws COMMAND --help at any level. The CLI is the canonical command
reference and includes selector, safety, confirmation, and repair guidance.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hacksaws-0.4.2.tar.gz.
File metadata
- Download URL: hacksaws-0.4.2.tar.gz
- Upload date:
- Size: 314.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15d7df47bacd0ef58a25f269825eb627358a8b9b7d8c91c2ebb37d75c265036e
|
|
| MD5 |
7886437144d015ef7b365338f22beba1
|
|
| BLAKE2b-256 |
65f4364aa51221da829bc9ca4d2a735b399e4ea8ab300e447b9a8effaea8e610
|
Provenance
The following attestation bundles were made for hacksaws-0.4.2.tar.gz:
Publisher:
publish.yaml on rocketboosters/hacksaws
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hacksaws-0.4.2.tar.gz -
Subject digest:
15d7df47bacd0ef58a25f269825eb627358a8b9b7d8c91c2ebb37d75c265036e - Sigstore transparency entry: 2360487797
- Sigstore integration time:
-
Permalink:
rocketboosters/hacksaws@8224a88f6ccebe32775520ceb1813313a47712d3 -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/rocketboosters
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@8224a88f6ccebe32775520ceb1813313a47712d3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hacksaws-0.4.2-py3-none-any.whl.
File metadata
- Download URL: hacksaws-0.4.2-py3-none-any.whl
- Upload date:
- Size: 262.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7efe5c0c0806a81b7aca560c680870a462e535fb47f48b82ec97842020675fd8
|
|
| MD5 |
37b15e400985099e0f02624bc7ccf950
|
|
| BLAKE2b-256 |
1e38b311fe346690ab1a5e57fd80837959f30bb820140a06546ee1f2c4012064
|
Provenance
The following attestation bundles were made for hacksaws-0.4.2-py3-none-any.whl:
Publisher:
publish.yaml on rocketboosters/hacksaws
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hacksaws-0.4.2-py3-none-any.whl -
Subject digest:
7efe5c0c0806a81b7aca560c680870a462e535fb47f48b82ec97842020675fd8 - Sigstore transparency entry: 2360487837
- Sigstore integration time:
-
Permalink:
rocketboosters/hacksaws@8224a88f6ccebe32775520ceb1813313a47712d3 -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/rocketboosters
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@8224a88f6ccebe32775520ceb1813313a47712d3 -
Trigger Event:
push
-
Statement type: