aegis-devops 0.3.2__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aegis_devops-0.3.2/src/aegis_devops.egg-info → aegis_devops-1.1.0}/PKG-INFO +84 -19
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/README.md +82 -17
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/pyproject.toml +2 -2
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/__init__.py +1 -1
- aegis_devops-1.1.0/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/agents.example.yaml +3 -0
- aegis_devops-1.1.0/src/aegis_core/_examples/agents.example.yaml.sig +2 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/authority.example.yaml +1 -0
- aegis_devops-1.1.0/src/aegis_core/_examples/authority.example.yaml.sig +2 -0
- aegis_devops-1.1.0/src/aegis_core/_examples/budget.example.yaml +21 -0
- aegis_devops-1.1.0/src/aegis_core/_examples/budget.example.yaml.sig +2 -0
- aegis_devops-1.1.0/src/aegis_core/budget/__init__.py +27 -0
- aegis_devops-1.1.0/src/aegis_core/budget/accounting.py +693 -0
- aegis_devops-1.1.0/src/aegis_core/budget/evaluate.py +259 -0
- aegis_devops-1.1.0/src/aegis_core/budget/gate.py +124 -0
- aegis_devops-1.1.0/src/aegis_core/budget/logs.py +678 -0
- aegis_devops-1.1.0/src/aegis_core/budget/policy.py +235 -0
- aegis_devops-1.1.0/src/aegis_core/budget/prices.json +282 -0
- aegis_devops-1.1.0/src/aegis_core/budget/prices.yaml +77 -0
- aegis_devops-1.1.0/src/aegis_core/budget/pricing.py +186 -0
- aegis_devops-1.1.0/src/aegis_core/budget/report.py +205 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/cli.py +307 -2
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/environments.py +98 -28
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/hook.py +248 -44
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/identity.py +17 -3
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/integrations/opencode-plugin.js +51 -12
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/interceptor.py +53 -6
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/parser.py +11 -3
- aegis_devops-1.1.0/src/aegis_core/report_aws.py +481 -0
- aegis_devops-1.1.0/src/aegis_core/report_kubernetes.py +354 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/shell.py +179 -3
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/store.py +99 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0/src/aegis_devops.egg-info}/PKG-INFO +84 -19
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_devops.egg-info/SOURCES.txt +23 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_adversarial.py +14 -12
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_authority.py +2 -2
- aegis_devops-1.1.0/tests/test_budget_accounting.py +492 -0
- aegis_devops-1.1.0/tests/test_budget_cli.py +247 -0
- aegis_devops-1.1.0/tests/test_budget_evaluate.py +130 -0
- aegis_devops-1.1.0/tests/test_budget_hook.py +274 -0
- aegis_devops-1.1.0/tests/test_budget_logs.py +365 -0
- aegis_devops-1.1.0/tests/test_budget_policy.py +304 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_docs_consistency.py +31 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_environments.py +47 -1
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_hook.py +74 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_identity.py +36 -0
- aegis_devops-1.1.0/tests/test_kubectl_namespace_and_manifests.py +222 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_opencode_plugin.py +37 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_parser.py +7 -5
- aegis_devops-1.1.0/tests/test_plugins.py +253 -0
- aegis_devops-1.1.0/tests/test_report_aws.py +349 -0
- aegis_devops-1.1.0/tests/test_report_kubernetes.py +247 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_shell.py +64 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_signing.py +2 -1
- aegis_devops-0.3.2/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- aegis_devops-0.3.2/src/aegis_core/_examples/agents.example.yaml.sig +0 -2
- aegis_devops-0.3.2/src/aegis_core/_examples/authority.example.yaml.sig +0 -2
- aegis_devops-0.3.2/tests/test_plugins.py +0 -112
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/LICENSE +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/MANIFEST.in +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/setup.cfg +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/__init__.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/constraints.example.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/constraints.example.yaml.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/environments.example.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/environments.example.yaml.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/example-signing.key +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/plan_constraints.example.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/plan_constraints.example.yaml.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/repos.example.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/repos.example.yaml.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/signers.example.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/signers.example.yaml.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/PRINCIPALS.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-4001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6003.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6004.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6005.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6006.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6007.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6008.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-6009.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-789abc.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-abc123.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-bcd234.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/git-def456.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-1001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-1002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-2001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-2002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-3001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-3002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-3003.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-3004.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-3005.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-5001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-5002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-5003.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-5004.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/jira-5006.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/plan-1001.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/plan-1002.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/plan-1003.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/plan-1004.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/plan-5005.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/_examples/sources/slack-perma-1.json +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/adversarial.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/audit_aws.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/audit_kubernetes.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/authority.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/__init__.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/base.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/external.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/llm.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/metrics.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/baselines/opa.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/compile/__init__.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/compile/actions/aws.yaml +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/compile/aws.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/compile/kubernetes.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/config.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/gitsource.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/intent.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/ledger.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/parsers/__init__.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/parsers/pulumi.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/parsers/sql.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/plan.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/provenance.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_core/signing.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_devops.egg-info/dependency_links.txt +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_devops.egg-info/entry_points.txt +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_devops.egg-info/requires.txt +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/src/aegis_devops.egg-info/top_level.txt +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_audit_aws.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_audit_kubernetes.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_baselines.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_benchmark.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_cli.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_compile_aws.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_compile_kubernetes.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_config.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_corpus.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_default_rules.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_gitsource.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_intent.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_interceptor.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_ledger.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_parsers_pulumi.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_parsers_sql.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_plan.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_provenance.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_snapshot.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_store.py +0 -0
- {aegis_devops-0.3.2 → aegis_devops-1.1.0}/tests/test_store_match.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aegis-devops
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Provenance-backed, authority-aware policy verifier for agentic DevOps actions.
|
|
5
5
|
Author: Vamshidher Reddy Jannapu Reddy
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/moneytool/aegis-devops
|
|
8
8
|
Project-URL: Repository, https://github.com/moneytool/aegis-devops
|
|
9
9
|
Keywords: agentops,agent-security,policy-as-code,provenance,kubernetes,terraform,guardrails,prompt-injection,context-poisoning
|
|
10
|
-
Classifier: Development Status ::
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Environment :: Console
|
|
12
12
|
Classifier: Intended Audience :: System Administrators
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
@@ -46,30 +46,43 @@ become policy.
|
|
|
46
46
|
|
|
47
47
|

|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
## Try it in 60 seconds
|
|
50
|
+
|
|
51
|
+
**1. Watch it block a pull request (nothing to install).** Open the demo's
|
|
52
|
+
[example PR](https://github.com/moneytool/aegis-devops-demo/pull/1): it deletes a production
|
|
53
|
+
database, and the failing check is Aegis blocking it, with the verdict posted as a comment. Fork
|
|
54
|
+
the [demo repository](https://github.com/moneytool/aegis-devops-demo) to try your own change; no
|
|
55
|
+
cloud account needed.
|
|
56
|
+
|
|
57
|
+
**2. Check a command yourself:**
|
|
50
58
|
|
|
51
59
|
```bash
|
|
52
60
|
pip install aegis-devops && aegis init .aegis
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
aegis check command --pretty -- "kubectl delete namespace prod" # BLOCK (exit 3)
|
|
62
|
+
aegis check command --pretty -- "kubectl get pods -n prod" # ALLOW (exit 0)
|
|
55
63
|
```
|
|
56
64
|
|
|
57
|
-
|
|
65
|
+
**3. Put it in front of your coding agent.** In the same project:
|
|
58
66
|
|
|
59
67
|
```bash
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
claude plugin marketplace add moneytool/aegis-devops
|
|
69
|
+
claude plugin install aegis-devops@aegis-devops
|
|
62
70
|
```
|
|
63
71
|
|
|
64
|
-
|
|
65
|
-
`
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
[
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
Then ask Claude Code to delete the `prod` namespace: the hook blocks the command before it runs.
|
|
73
|
+
Gemini CLI: `gemini extensions install https://github.com/moneytool/aegis-devops`. Codex, GitHub
|
|
74
|
+
Copilot (CLI and VS Code), Cursor and OpenCode: `aegis install codex|copilot|vscode|cursor|opencode`
|
|
75
|
+
(see [Coding agents](docs/agents.md)). Aegis only acts in projects with a `.aegis/` policy, and
|
|
76
|
+
only blocks what that policy blocks. `aegis init` writes example rules signed with a public
|
|
77
|
+
example key; replace both before relying on it ([Configuration](docs/configuration.md)). It
|
|
78
|
+
works alongside RBAC and your agent's own permission settings; see
|
|
79
|
+
[Why not RBAC](#why-not-rbac-or-the-agents-own-permission-settings).
|
|
80
|
+
|
|
81
|
+
In CI, the [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check)
|
|
82
|
+
Action checks a Terraform or OpenTofu plan on every pull request
|
|
83
|
+
(`uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`); `aegis check terraform
|
|
84
|
+
plan.json --exit-style ci` does the same in any pipeline, and Aegis also works as a Python
|
|
85
|
+
library ([Quick start](#quick-start)).
|
|
73
86
|
|
|
74
87
|
## What it does
|
|
75
88
|
|
|
@@ -226,6 +239,45 @@ about who wrote a rule, but it cannot recompute a hash or fetch a source. Up to
|
|
|
226
239
|
rows were scored against all 500 rules, which counted rules the models never saw as resisted
|
|
227
240
|
poison and understated their susceptibility (0.23–0.33); see [`CHANGELOG.md`](CHANGELOG.md).
|
|
228
241
|
|
|
242
|
+
## Why not RBAC, or the agent's own permission settings?
|
|
243
|
+
|
|
244
|
+
Keep both. Aegis sits alongside them; it doesn't replace either.
|
|
245
|
+
|
|
246
|
+
**Agent permission settings** (Claude Code's allow/deny rules, Copilot's tool approvals and
|
|
247
|
+
similar) decide which commands an agent may run without asking you. They match the command
|
|
248
|
+
text. Claude Code's documentation says a Bash deny rule ["isn't a security boundary around the
|
|
249
|
+
program"](https://code.claude.com/docs/en/permissions#bash-rule-limits), and recommends a
|
|
250
|
+
PreToolUse hook when you need to inspect the full command before it runs. Aegis is that hook. It
|
|
251
|
+
works out what the command will do, so every spelling of the same action reaches the same rule:
|
|
252
|
+
|
|
253
|
+
| Command the agent writes | Aegis with the example policy |
|
|
254
|
+
|---|---|
|
|
255
|
+
| `kubectl delete deploy web -n prod` | BLOCK (`no-delete-in-prod-namespace`) |
|
|
256
|
+
| `kubectl -n prod delete deploy web` | BLOCK, same rule |
|
|
257
|
+
| `/usr/bin/kubectl …`, `sudo kubectl …`, `env kubectl …` | BLOCK, same rule |
|
|
258
|
+
| `bash -c 'kubectl delete deploy web -n prod'` | BLOCK, same rule |
|
|
259
|
+
| `cd /tmp && kubectl delete deploy web -n prod` | BLOCK, same rule |
|
|
260
|
+
| `git -C . push --force origin main` | BLOCK (`git-block-force-push-main`) |
|
|
261
|
+
| `K=kubectl; $K delete deploy web -n prod` | Refused: it can't be checked statically, so the hook denies it and asks for the command on its own |
|
|
262
|
+
|
|
263
|
+
Permission settings also record *what* is allowed, not who decided it. An Aegis rule only gets a
|
|
264
|
+
vote if nobody has changed it since it was signed and its author was allowed to write that kind
|
|
265
|
+
of rule.
|
|
266
|
+
|
|
267
|
+
**RBAC and IAM** decide what an identity may do. A coding agent usually runs with the
|
|
268
|
+
developer's own kubeconfig and cloud credentials, so RBAC sees the developer and grants the
|
|
269
|
+
agent the same rights. Aegis decides each action against the policy: no deletes in the `prod`
|
|
270
|
+
namespace, no `kubectl --as` impersonation, no plan that deletes a database. Once agents do have
|
|
271
|
+
their own identities, the same policy compiles into the platform layer, so it holds even for
|
|
272
|
+
calls that never pass through the hook (an SDK script, a leaked key):
|
|
273
|
+
|
|
274
|
+
- `aegis compile aws`: Service Control Policies scoped to agent identities.
|
|
275
|
+
- `aegis compile kubernetes`: ValidatingAdmissionPolicies scoped to agent identities, plus
|
|
276
|
+
`aegis audit-identity kubernetes` to report the RBAC permissions that would let an agent get
|
|
277
|
+
around them (impersonation, editing admission policies, RBAC escalation).
|
|
278
|
+
|
|
279
|
+
Both are previews; see [server-side enforcement](docs/server-side.md).
|
|
280
|
+
|
|
229
281
|
## Why not OPA/Gatekeeper?
|
|
230
282
|
|
|
231
283
|
OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rules**. Aegis
|
|
@@ -256,7 +308,12 @@ context a rule can arrive from a ticket or a chat message as easily as from you.
|
|
|
256
308
|
|
|
257
309
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
258
310
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
259
|
-
|
|
311
|
+
v1.1.0 is on PyPI, with the [session budget cap](docs/budget.md) and denial reports for the
|
|
312
|
+
server-side layer (`aegis report aws`, `aegis report kubernetes`). **1.0 is a promise about the
|
|
313
|
+
interface:** the policy file formats, the CLI commands and exit codes, the hook protocol and the
|
|
314
|
+
Action's inputs and outputs stay compatible until 2.0; the server-side compilers and the
|
|
315
|
+
identity audit remain previews ([CHANGELOG](CHANGELOG.md)). It is not a claim that the open gaps
|
|
316
|
+
below are closed. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
260
317
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
261
318
|
through the Codex CLI, and a local `mistral:latest`.
|
|
262
319
|
|
|
@@ -274,11 +331,13 @@ of anything you care about.
|
|
|
274
331
|
|
|
275
332
|
| Page | Covers |
|
|
276
333
|
| :--- | :--- |
|
|
334
|
+
| [`docs/guides/`](docs/guides/README.md) | Task-first guides: stop Claude Code, Cursor, Codex, Copilot or Gemini CLI from running destructive commands; block risky Terraform plans in CI |
|
|
277
335
|
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
278
336
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
279
337
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
280
338
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, the identity model (`agents.yaml`), rate limits & ledger |
|
|
281
339
|
| [`docs/server-side.md`](docs/server-side.md) | Preview: compiling the policy to AWS Service Control Policies scoped to agent identities |
|
|
340
|
+
| [`docs/budget.md`](docs/budget.md) | The session budget cap: per-session and per-project-per-day limits in estimated USD or tokens, across Claude Code, Codex, Gemini CLI, OpenCode and Copilot CLI |
|
|
282
341
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
283
342
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
284
343
|
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
@@ -289,7 +348,7 @@ of anything you care about.
|
|
|
289
348
|
## Development
|
|
290
349
|
|
|
291
350
|
```bash
|
|
292
|
-
venv/bin/python -m pytest -q #
|
|
351
|
+
venv/bin/python -m pytest -q # 1,791 passed (CI runs this on 3.11/3.13/3.14, Linux and macOS)
|
|
293
352
|
venv/bin/python -m ruff check src tests scripts examples
|
|
294
353
|
vhs docs/demo.tape # regenerate docs/demo.gif
|
|
295
354
|
```
|
|
@@ -299,6 +358,12 @@ Reporting a bypass: see [`SECURITY.md`](SECURITY.md) — parser evasion is the l
|
|
|
299
358
|
attack surface and the most useful thing to report. Release history is in
|
|
300
359
|
[`CHANGELOG.md`](CHANGELOG.md).
|
|
301
360
|
|
|
361
|
+
## Support
|
|
362
|
+
|
|
363
|
+
If Aegis-DevOps is useful to you, a ⭐ on [GitHub](https://github.com/moneytool/aegis-devops)
|
|
364
|
+
helps other people find it. Bug reports, ideas and bypasses are welcome too: open an issue, or
|
|
365
|
+
see [`SECURITY.md`](SECURITY.md) for anything that gets a blocked command through.
|
|
366
|
+
|
|
302
367
|
## License
|
|
303
368
|
|
|
304
369
|
Apache-2.0 — see [LICENSE](LICENSE).
|
|
@@ -13,30 +13,43 @@ become policy.
|
|
|
13
13
|
|
|
14
14
|

|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
## Try it in 60 seconds
|
|
17
|
+
|
|
18
|
+
**1. Watch it block a pull request (nothing to install).** Open the demo's
|
|
19
|
+
[example PR](https://github.com/moneytool/aegis-devops-demo/pull/1): it deletes a production
|
|
20
|
+
database, and the failing check is Aegis blocking it, with the verdict posted as a comment. Fork
|
|
21
|
+
the [demo repository](https://github.com/moneytool/aegis-devops-demo) to try your own change; no
|
|
22
|
+
cloud account needed.
|
|
23
|
+
|
|
24
|
+
**2. Check a command yourself:**
|
|
17
25
|
|
|
18
26
|
```bash
|
|
19
27
|
pip install aegis-devops && aegis init .aegis
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
aegis check command --pretty -- "kubectl delete namespace prod" # BLOCK (exit 3)
|
|
29
|
+
aegis check command --pretty -- "kubectl get pods -n prod" # ALLOW (exit 0)
|
|
22
30
|
```
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
**3. Put it in front of your coding agent.** In the same project:
|
|
25
33
|
|
|
26
34
|
```bash
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
claude plugin marketplace add moneytool/aegis-devops
|
|
36
|
+
claude plugin install aegis-devops@aegis-devops
|
|
29
37
|
```
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
`
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
[
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
Then ask Claude Code to delete the `prod` namespace: the hook blocks the command before it runs.
|
|
40
|
+
Gemini CLI: `gemini extensions install https://github.com/moneytool/aegis-devops`. Codex, GitHub
|
|
41
|
+
Copilot (CLI and VS Code), Cursor and OpenCode: `aegis install codex|copilot|vscode|cursor|opencode`
|
|
42
|
+
(see [Coding agents](docs/agents.md)). Aegis only acts in projects with a `.aegis/` policy, and
|
|
43
|
+
only blocks what that policy blocks. `aegis init` writes example rules signed with a public
|
|
44
|
+
example key; replace both before relying on it ([Configuration](docs/configuration.md)). It
|
|
45
|
+
works alongside RBAC and your agent's own permission settings; see
|
|
46
|
+
[Why not RBAC](#why-not-rbac-or-the-agents-own-permission-settings).
|
|
47
|
+
|
|
48
|
+
In CI, the [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check)
|
|
49
|
+
Action checks a Terraform or OpenTofu plan on every pull request
|
|
50
|
+
(`uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`); `aegis check terraform
|
|
51
|
+
plan.json --exit-style ci` does the same in any pipeline, and Aegis also works as a Python
|
|
52
|
+
library ([Quick start](#quick-start)).
|
|
40
53
|
|
|
41
54
|
## What it does
|
|
42
55
|
|
|
@@ -193,6 +206,45 @@ about who wrote a rule, but it cannot recompute a hash or fetch a source. Up to
|
|
|
193
206
|
rows were scored against all 500 rules, which counted rules the models never saw as resisted
|
|
194
207
|
poison and understated their susceptibility (0.23–0.33); see [`CHANGELOG.md`](CHANGELOG.md).
|
|
195
208
|
|
|
209
|
+
## Why not RBAC, or the agent's own permission settings?
|
|
210
|
+
|
|
211
|
+
Keep both. Aegis sits alongside them; it doesn't replace either.
|
|
212
|
+
|
|
213
|
+
**Agent permission settings** (Claude Code's allow/deny rules, Copilot's tool approvals and
|
|
214
|
+
similar) decide which commands an agent may run without asking you. They match the command
|
|
215
|
+
text. Claude Code's documentation says a Bash deny rule ["isn't a security boundary around the
|
|
216
|
+
program"](https://code.claude.com/docs/en/permissions#bash-rule-limits), and recommends a
|
|
217
|
+
PreToolUse hook when you need to inspect the full command before it runs. Aegis is that hook. It
|
|
218
|
+
works out what the command will do, so every spelling of the same action reaches the same rule:
|
|
219
|
+
|
|
220
|
+
| Command the agent writes | Aegis with the example policy |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `kubectl delete deploy web -n prod` | BLOCK (`no-delete-in-prod-namespace`) |
|
|
223
|
+
| `kubectl -n prod delete deploy web` | BLOCK, same rule |
|
|
224
|
+
| `/usr/bin/kubectl …`, `sudo kubectl …`, `env kubectl …` | BLOCK, same rule |
|
|
225
|
+
| `bash -c 'kubectl delete deploy web -n prod'` | BLOCK, same rule |
|
|
226
|
+
| `cd /tmp && kubectl delete deploy web -n prod` | BLOCK, same rule |
|
|
227
|
+
| `git -C . push --force origin main` | BLOCK (`git-block-force-push-main`) |
|
|
228
|
+
| `K=kubectl; $K delete deploy web -n prod` | Refused: it can't be checked statically, so the hook denies it and asks for the command on its own |
|
|
229
|
+
|
|
230
|
+
Permission settings also record *what* is allowed, not who decided it. An Aegis rule only gets a
|
|
231
|
+
vote if nobody has changed it since it was signed and its author was allowed to write that kind
|
|
232
|
+
of rule.
|
|
233
|
+
|
|
234
|
+
**RBAC and IAM** decide what an identity may do. A coding agent usually runs with the
|
|
235
|
+
developer's own kubeconfig and cloud credentials, so RBAC sees the developer and grants the
|
|
236
|
+
agent the same rights. Aegis decides each action against the policy: no deletes in the `prod`
|
|
237
|
+
namespace, no `kubectl --as` impersonation, no plan that deletes a database. Once agents do have
|
|
238
|
+
their own identities, the same policy compiles into the platform layer, so it holds even for
|
|
239
|
+
calls that never pass through the hook (an SDK script, a leaked key):
|
|
240
|
+
|
|
241
|
+
- `aegis compile aws`: Service Control Policies scoped to agent identities.
|
|
242
|
+
- `aegis compile kubernetes`: ValidatingAdmissionPolicies scoped to agent identities, plus
|
|
243
|
+
`aegis audit-identity kubernetes` to report the RBAC permissions that would let an agent get
|
|
244
|
+
around them (impersonation, editing admission policies, RBAC escalation).
|
|
245
|
+
|
|
246
|
+
Both are previews; see [server-side enforcement](docs/server-side.md).
|
|
247
|
+
|
|
196
248
|
## Why not OPA/Gatekeeper?
|
|
197
249
|
|
|
198
250
|
OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rules**. Aegis
|
|
@@ -223,7 +275,12 @@ context a rule can arrive from a ticket or a chat message as easily as from you.
|
|
|
223
275
|
|
|
224
276
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
225
277
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
226
|
-
|
|
278
|
+
v1.1.0 is on PyPI, with the [session budget cap](docs/budget.md) and denial reports for the
|
|
279
|
+
server-side layer (`aegis report aws`, `aegis report kubernetes`). **1.0 is a promise about the
|
|
280
|
+
interface:** the policy file formats, the CLI commands and exit codes, the hook protocol and the
|
|
281
|
+
Action's inputs and outputs stay compatible until 2.0; the server-side compilers and the
|
|
282
|
+
identity audit remain previews ([CHANGELOG](CHANGELOG.md)). It is not a claim that the open gaps
|
|
283
|
+
below are closed. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
227
284
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
228
285
|
through the Codex CLI, and a local `mistral:latest`.
|
|
229
286
|
|
|
@@ -241,11 +298,13 @@ of anything you care about.
|
|
|
241
298
|
|
|
242
299
|
| Page | Covers |
|
|
243
300
|
| :--- | :--- |
|
|
301
|
+
| [`docs/guides/`](docs/guides/README.md) | Task-first guides: stop Claude Code, Cursor, Codex, Copilot or Gemini CLI from running destructive commands; block risky Terraform plans in CI |
|
|
244
302
|
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
245
303
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
246
304
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
247
305
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, the identity model (`agents.yaml`), rate limits & ledger |
|
|
248
306
|
| [`docs/server-side.md`](docs/server-side.md) | Preview: compiling the policy to AWS Service Control Policies scoped to agent identities |
|
|
307
|
+
| [`docs/budget.md`](docs/budget.md) | The session budget cap: per-session and per-project-per-day limits in estimated USD or tokens, across Claude Code, Codex, Gemini CLI, OpenCode and Copilot CLI |
|
|
249
308
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
250
309
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
251
310
|
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
@@ -256,7 +315,7 @@ of anything you care about.
|
|
|
256
315
|
## Development
|
|
257
316
|
|
|
258
317
|
```bash
|
|
259
|
-
venv/bin/python -m pytest -q #
|
|
318
|
+
venv/bin/python -m pytest -q # 1,791 passed (CI runs this on 3.11/3.13/3.14, Linux and macOS)
|
|
260
319
|
venv/bin/python -m ruff check src tests scripts examples
|
|
261
320
|
vhs docs/demo.tape # regenerate docs/demo.gif
|
|
262
321
|
```
|
|
@@ -266,6 +325,12 @@ Reporting a bypass: see [`SECURITY.md`](SECURITY.md) — parser evasion is the l
|
|
|
266
325
|
attack surface and the most useful thing to report. Release history is in
|
|
267
326
|
[`CHANGELOG.md`](CHANGELOG.md).
|
|
268
327
|
|
|
328
|
+
## Support
|
|
329
|
+
|
|
330
|
+
If Aegis-DevOps is useful to you, a ⭐ on [GitHub](https://github.com/moneytool/aegis-devops)
|
|
331
|
+
helps other people find it. Bug reports, ideas and bypasses are welcome too: open an issue, or
|
|
332
|
+
see [`SECURITY.md`](SECURITY.md) for anything that gets a blocked command through.
|
|
333
|
+
|
|
269
334
|
## License
|
|
270
335
|
|
|
271
336
|
Apache-2.0 — see [LICENSE](LICENSE).
|
|
@@ -25,7 +25,7 @@ keywords = [
|
|
|
25
25
|
"context-poisoning",
|
|
26
26
|
]
|
|
27
27
|
classifiers = [
|
|
28
|
-
"Development Status ::
|
|
28
|
+
"Development Status :: 4 - Beta",
|
|
29
29
|
"Environment :: Console",
|
|
30
30
|
"Intended Audience :: System Administrators",
|
|
31
31
|
"Intended Audience :: Developers",
|
|
@@ -63,7 +63,7 @@ version = {attr = "aegis_core.__version__"}
|
|
|
63
63
|
where = ["src"]
|
|
64
64
|
|
|
65
65
|
[tool.setuptools.package-data]
|
|
66
|
-
aegis_core = ["_examples/**/*", "integrations/*", "compile/actions/*"]
|
|
66
|
+
aegis_core = ["_examples/**/*", "integrations/*", "compile/actions/*", "budget/*.yaml", "budget/*.json"]
|
|
67
67
|
|
|
68
68
|
[tool.ruff]
|
|
69
69
|
line-length = 100
|
|
@@ -34,6 +34,9 @@ trusted:
|
|
|
34
34
|
- platform: aws
|
|
35
35
|
kind: source-identity
|
|
36
36
|
id: alice@example.com
|
|
37
|
+
# A source identity survives role chaining, so an agent started in alice's session would
|
|
38
|
+
# carry it and be exempt. Trust one only if no agent ever runs under it, and say so:
|
|
39
|
+
no_agents: true
|
|
37
40
|
- platform: github
|
|
38
41
|
kind: oidc-subject
|
|
39
42
|
# bound to one reusable workflow at a protected ref, so an agent job in the same
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# The session budget cap (docs/budget.md). Copy to budget.yaml, set your own limits, and sign
|
|
2
|
+
# it with `aegis sign`; its principal must hold the 'budget' class in authority.yaml. Until
|
|
3
|
+
# it is named budget.yaml it does nothing. Then reinstall your agents' hooks (`aegis install
|
|
4
|
+
# <agent>`) so they see every tool call, and check with: aegis budget status
|
|
5
|
+
version: 1
|
|
6
|
+
principal: admin # must hold the 'budget' class in authority.yaml
|
|
7
|
+
unit: usd # usd (estimated from list prices) | tokens; required
|
|
8
|
+
session:
|
|
9
|
+
limit: 20 # per agent session
|
|
10
|
+
warn_at: 0.8 # warn once at 80%
|
|
11
|
+
project_day:
|
|
12
|
+
limit: 100 # every measured session in this project, per day
|
|
13
|
+
warn_at: 0.8
|
|
14
|
+
tz: UTC # the day boundary
|
|
15
|
+
agents: [claude, codex, gemini, opencode, copilot] # only listed agents are measured
|
|
16
|
+
on_unknown_log: allow # allow (warn) | deny: usage Aegis cannot verify
|
|
17
|
+
on_unknown_price: estimate # estimate (warn) | deny: models with no price
|
|
18
|
+
pricing: {} # signed overrides, USD per million tokens:
|
|
19
|
+
# claude-opus-5-5: {input: 4, output: 20, cache_read: 0.2, cache_write: 8}
|
|
20
|
+
copilot:
|
|
21
|
+
premium_requests: 50 # Copilot CLI reports premium requests, not tokens
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Cross-agent session budget cap (design: docs/dev/DESIGN-v1.0-budget-cap.md).
|
|
2
|
+
|
|
3
|
+
* :mod:`~aegis_core.budget.policy` -- the signed ``budget.yaml``;
|
|
4
|
+
* :mod:`~aegis_core.budget.pricing` -- tokens to estimated dollars;
|
|
5
|
+
* :mod:`~aegis_core.budget.logs` -- reading usage from each agent's logs;
|
|
6
|
+
* :mod:`~aegis_core.budget.accounting` -- session records, project/day
|
|
7
|
+
totals, revisions, locks, the inventory and rebuilds;
|
|
8
|
+
* :mod:`~aegis_core.budget.evaluate` -- allow / warn / deny.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from aegis_core.budget.accounting import BudgetStore, Snapshot, rebuild, refresh
|
|
12
|
+
from aegis_core.budget.evaluate import ALLOW, DENY, WARN, Verdict, evaluate
|
|
13
|
+
from aegis_core.budget.logs import Locator, default_logs
|
|
14
|
+
from aegis_core.budget.policy import BUDGET_CLASS, BUDGET_FILE, BudgetPolicy, load_budget_policy
|
|
15
|
+
from aegis_core.budget.pricing import PriceTable, load_builtin_table
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def price_table(policy: BudgetPolicy) -> PriceTable:
|
|
19
|
+
"""The built-in prices with the policy's signed overrides."""
|
|
20
|
+
return PriceTable(load_builtin_table(), policy.pricing)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"ALLOW", "BUDGET_CLASS", "BUDGET_FILE", "DENY", "WARN", "BudgetPolicy", "BudgetStore",
|
|
25
|
+
"Locator", "PriceTable", "Snapshot", "Verdict", "default_logs", "evaluate",
|
|
26
|
+
"load_budget_policy", "load_builtin_table", "price_table", "rebuild", "refresh",
|
|
27
|
+
]
|