https://github.com/cloud-copilot/iam-simulate
An IAM Simulator that outputs detailed explains of how a request was evaluated.
https://github.com/cloud-copilot/iam-simulate
aws iam
Last synced: about 1 month ago
JSON representation
An IAM Simulator that outputs detailed explains of how a request was evaluated.
- Host: GitHub
- URL: https://github.com/cloud-copilot/iam-simulate
- Owner: cloud-copilot
- License: agpl-3.0
- Created: 2024-10-08T01:41:12.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-12-22T00:52:15.000Z (6 months ago)
- Last Synced: 2025-12-23T00:48:32.620Z (6 months ago)
- Topics: aws, iam
- Language: TypeScript
- Homepage: https://iam.cloudcopilot.io/tools/policy-tester
- Size: 851 KB
- Stars: 95
- Watchers: 2
- Forks: 8
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# IAM Simulate
[](https://www.npmjs.com/package/@cloud-copilot/iam-simulate) [](LICENSE.txt) [](https://github.com/cloud-copilot/iam-simulate/actions/workflows/guarddog.yml) [](https://snyk.io/test/github/cloud-copilot/iam-simulate?targetFile=package.json)
An AWS IAM Simulator and Policy Tester built as a Node/Typescript library.
The simulator currently supports these features of AWS IAM
### IAM Feature Support
- Identity Policies
- Resource Policies
- Service Control Policies
- Resource Control Policies
- Permission Boundaries
- All [AWS Condition Operators](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html)
- Same Account and Cross Account Requests
- Custom trust behavior for IAM Trust Policies and KMS Key Policies
### Request Validation
iam-simulate will automatically validate inputs including
- IAM policies using [iam-policy](https://github.com/cloud-copilot/iam-policy)
- IAM Actions using [iam-data](https://github.com/cloud-copilot/iam-data)
- The resource ARN against allowed resource types for the action
- The context keys allowed for the action/resource and their types.
Currently all [global condition keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html) are allowed for all requests which is not strictly true. More validation will be added in the future.
### Explanation
iam-simulate will detail which statements were decisive in the final decision to allow or deny a request.
It will also return "explains" for each statement that was evaluated, detailing why that statement applied to the request or not.
### Features Coming Soon
- Session Policies
- Validation of Global Condition Keys for each action
- Automatically populating context keys from the request such as `aws:PrincipalServiceName`
- Support for anonymous requests
## Installation
```bash
npm install @cloud-copilot/iam-simulate
```
## Usage
```typescript
import { runSimulation, type Simulation } from '@cloud-copilot/iam-simulate'
const simulation: Simulation = {
identityPolicies: [
{
name: 'userpolicy',
policy: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['s3:GetObject'],
Resource: ['arn:aws:s3:::mybucket/*']
}
]
}
}
],
serviceControlPolicies: [
{
orgIdentifier: 'ou-12345',
policies: [
{
name: 'AllowAll',
policy: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: '*',
Resource: '*'
}
]
}
}
]
}
],
/*
The default RCP `RCPFullAWSAccess` is always applied implicitly and you do not need to include it here. https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps_examples.html#example-rcp-full-aws-access
*/
resourceControlPolicies: [
{
orgIdentifier: 'o-123456789012',
policies: [
{
name: 'EnforceSecureTransport',
policy: {
Version: '2012-10-17',
Statement: [
{
Sid: 'EnforceSecureTransport',
Effect: 'Deny',
Principal: '*',
Action: ['sts:*', 's3:*', 'sqs:*', 'secretsmanager:*', 'kms:*'],
Resource: '*',
Condition: {
BoolIfExists: {
'aws:SecureTransport': 'false'
}
}
}
]
}
}
]
}
],
resourcePolicy: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['s3:GetObject'],
Resource: ['arn:aws:s3:::mybucket/*'],
Principal: 'aws:arn:iam::123456789012:root',
Condition: {
StringEquals: {
'aws:PrincipalOrgID': 'o-123456789012'
}
}
}
]
},
request: {
action: 's3:GetObject',
principal: 'arn:aws:iam::123456789012:user/username',
resource: {
accountId: '123456789012',
resource: 'arn:aws:s3:::mybucket/file.txt'
},
contextVariables: {
'aws:PrincipalOrgID': 'o-123456789012'
}
}
}
`runSimulation` returns a discriminated union with `resultType`:
- `resultType: 'error'` includes `errors` and no simulation results.
- `resultType: 'single'` includes `overallResult` and a single `result`.
- `resultType: 'wildcard'` includes `overallResult` and `results` for each matching pattern.
const response = await runSimulation(simulation, {})
//Check for validation errors (errors are returned at the response level):
if (response.resultType === 'error') {
console.log(response.errors.message)
console.log(JSON.stringify(response.errors, null, 2))
}
//The simulation ran successfully
if (response.resultType === 'single') {
const result = response.result
console.log(response.overallResult) // 'Allowed', 'ExplicitlyDenied', or 'ImplicitlyDenied'
console.log(result.analysis?.result)
//Output the identity statements that allowed the request
const identityAllowExplains =
result?.analysis?.identityAnalysis?.allowStatements.map((s) => s.explain) || []
//Show which statements applied and exactly how.
for (const explain of identityAllowExplains) {
console.log(explain)
}
}
if (response.resultType === 'wildcard') {
console.log(response.overallResult)
for (const result of response.results) {
console.log(result.resourcePattern, result.analysis?.result)
}
}
```
This would output an explain that shows how the identity statement was evaluated:
```javascript
{
effect: 'Allow',
identifier: '1',
matches: true,
actionMatch: true,
principalMatch: 'Match',
resourceMatch: true,
conditionMatch: true,
resources: [
{
resource: 'arn:aws:s3:::mybucket/*',
matches: true,
}
],
actions: [ { action: 's3:GetObject', matches: true } ],
}
```