Metadata-Version: 2.5
Name: asp-iam
Version: 0.1.0
Summary: Agent Scoped Permissions: record the AWS calls your code (or AI agent) makes and get the least-privilege IAM policy
Project-URL: Homepage, https://github.com/Kxvya18/asp
Project-URL: Issues, https://github.com/Kxvya18/asp/issues
Project-URL: Changelog, https://github.com/Kxvya18/asp/blob/main/CHANGELOG.md
Author: Kxvya18
License-Expression: MIT
License-File: LICENSE
Keywords: ai-agents,aws,boto3,devsecops,iam,least-privilege,security
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.10
Requires-Dist: boto3>=1.26
Description-Content-Type: text/markdown

# asp: Agent Scoped Permissions

[![ci](https://github.com/Kxvya18/asp/actions/workflows/ci.yml/badge.svg)](https://github.com/Kxvya18/asp/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/asp-iam)](https://pypi.org/project/asp-iam/)
[![Python](https://img.shields.io/pypi/pyversions/asp-iam)](https://pypi.org/project/asp-iam/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

Record the AWS calls your Python code, or your **AI agent**, actually makes, and get the
**least-privilege IAM policy** for it.

```python
from asp import record

with record() as rec:
    run_my_script()            # or: agent.run("archive last month's reports")

print(rec.policy_json())
```

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {"Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::reports/*"},
    {"Effect": "Allow", "Action": ["s3:PutObject"], "Resource": "arn:aws:s3:::archive/*"}
  ]
}
```
It only reads from `reports` and only writes to `archive`, because that's all the code did.

## Why
AI agents and scripts are often given broad AWS permissions because nobody knows what they
really need. `asp` watches what they actually do and writes the smallest policy that allows it.
It works offline with [moto](https://github.com/getmoto/moto), so it fits in your tests.

## Install
```bash
pip install asp-iam
```

## Use
```python
from asp import record

# as a block
with record() as rec:
    ...
rec.actions()       # ['dynamodb:PutItem', 's3:GetObject']
rec.policy()        # dict
rec.save("policy.json")
rec.terraform()     # the same policy as a Terraform resource

# as a decorator
@record(save_to="policy.json")
def nightly_job():
    ...
```

## Correct permission names
Python call names aren't always permission names: `list_objects_v2` needs `s3:ListBucket`,
`copy_object` needs `s3:GetObject` + `s3:PutObject`, CloudWatch calls need `cloudwatch:*`,
Bedrock's `Converse` needs `bedrock:InvokeModel`. These exceptions live in one readable table,
[`mappings.py`](src/asp/mappings.py). Found a missing one? Add a row and a test.

## AI agents: give them only what they use
[`examples/ai_agent.py`](examples/ai_agent.py) gives an agent three AWS tools (list, read, write
files) and the task *"summarise the October report and save it to the archive"*. Recorded with asp:

```
The agent needed only this:
- read files in bucket 'reports'
- list files in bucket 'reports'
- write files in bucket 'archive'
```
Instead of broad S3 access "to be safe", the agent gets exactly this. If it is ever misled (for
example by instructions hidden in a file it reads), it cannot delete data or touch other buckets.

```bash
python examples/ai_agent.py            # scripted stand-in, no API key, fake AWS
python examples/ai_agent.py --claude   # real Claude drives the agent (pip install anthropic)
```
`rec.explain()` produces the plain-English summary with ordinary code, not an LLM, so it is
always exactly what the policy says.

## From your test suite (pytest plugin)
```bash
pytest --asp                    # writes asp-policy.json: the permissions your tests needed
pytest --asp-check role.json    # fails the run if the code needs actions role.json doesn't allow
```
Put `--asp-check` in CI and a change that suddenly needs a new AWS permission is caught before
it fails in production. Only calls made inside test bodies are recorded: put setup (like creating
fake buckets with moto) in fixtures so it stays out of the policy.

## Check an existing policy
```python
result = rec.check("role_policy.json")   # dict, JSON text or a file path
print(result.summary())
```
```
missing (code would fail): 0
unused (can be removed): 2
  - dynamodb:Scan
  - iam:CreateUser
too broad (wildcards): 1
  - s3:*
```
`result.ok` is False when the code needs something the policy doesn't allow, which is handy in CI.
This first version compares actions, not resources.

## Status
Early (v0.x). Policies name the exact actions and, for the services above, the exact resources.
Other services keep `"Resource": "*"`. `rec.policy(scope_resources=False)` gives the old all-`*` form.

Roadmap:
- [x] Terraform output (`rec.terraform()`)
- [x] exact IAM names where API and IAM names differ (`src/asp/mappings.py`, contributions welcome)
- [x] restrict `Resource` to the exact S3 buckets, DynamoDB tables (and indexes), SQS queues, SNS topics, Lambda functions used
- [x] `check` mode: compare an existing policy with what the code really needs (actions)
- [x] AI-agent example and plain-English `explain()`
- [x] pytest plugin: `pytest --asp` / `pytest --asp-check role.json`

## Contributing
Found an AWS call that gets the wrong permission name? Add one row to
[`mappings.py`](src/asp/mappings.py) plus a test, and open a PR. Issues labelled
**good first issue** are a good place to start.

## License
MIT
