{"id":45388130,"url":"https://github.com/cloud-copilot/iam-policy","last_synced_at":"2026-05-10T21:25:08.114Z","repository":{"id":257804094,"uuid":"864679152","full_name":"cloud-copilot/iam-policy","owner":"cloud-copilot","description":"A validator and ORM for IAM Policies","archived":false,"fork":false,"pushed_at":"2026-02-21T16:26:44.000Z","size":691,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-21T23:13:50.288Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloud-copilot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-09-28T21:36:32.000Z","updated_at":"2026-02-21T16:26:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"3e88db51-fb1b-467f-809e-f52f615f8e69","html_url":"https://github.com/cloud-copilot/iam-policy","commit_stats":null,"previous_names":["cloud-copilot/iam-policy"],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/cloud-copilot/iam-policy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-policy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-policy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-policy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-policy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloud-copilot","download_url":"https://codeload.github.com/cloud-copilot/iam-policy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-policy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29765745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T21:02:23.375Z","status":"ssl_error","status_checked_at":"2026-02-23T20:58:31.539Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-21T18:09:37.933Z","updated_at":"2026-02-24T01:14:01.988Z","avatar_url":"https://github.com/cloud-copilot.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IAM Policy Syntax Validator and Parser\n\n[![NPM Version](https://img.shields.io/npm/v/@cloud-copilot/iam-policy.svg?logo=nodedotjs)](https://www.npmjs.com/package/@cloud-copilot/iam-policy) [![License: AGPL v3](https://img.shields.io/github/license/cloud-copilot/iam-policy)](LICENSE.txt) [![GuardDog](https://github.com/cloud-copilot/iam-policy/actions/workflows/guarddog.yml/badge.svg)](https://github.com/cloud-copilot/iam-policy/actions/workflows/guarddog.yml) [![Known Vulnerabilities](https://snyk.io/test/github/cloud-copilot/iam-policy/badge.svg?targetFile=package.json\u0026style=flat-square)](https://snyk.io/test/github/cloud-copilot/iam-policy?targetFile=package.json)\n\nThis is a simple IAM policy library that allows you to safely parse and navigate IAM policies without worrying about the more difficult details of parsing policies or validating syntax.\n\nThis may be updated in the future to allow modifying policies, right now it's read-only.\n\n## Validate Policy Syntax with `validatePolicySyntax`\n\n`validatePolicySyntax` is a syntax linter and will not validate the the policy is logical, secure, or correct.\n\nThis will take any object and return back an array of findings. If the array is empty then the policy is valid.\n\n```typescript\nimport { validatePolicySyntax } from '@cloud-copilot/iam-policy'\n\nvalidatePolicySyntax({\n  Version: '2012-10-17',\n  Statement: [\n    {\n      Sid: 'VisualEditor0',\n      Effect: 'Allow',\n      Action: 's3:GetObject',\n      Resource: 'arn:aws:s3:::mybucket/*'\n    }\n  ]\n}) // []\n\nvalidatePolicySyntax({\n  Version: '2012-10-17',\n  Statement: [\n    {\n      Sid: 7,\n      Effect: 'Allow',\n      Action: 's3:GetObject',\n      Resource: 'arn:aws:s3:::mybucket/*'\n    }\n  ]\n}) // [{ message: 'Found data type number allowed type(s) are string', path: 'Statement[0].Sid'}]\n\n/* It will attempt to find as many issues as possible in one pass */\nvalidatePolicySyntax({\n  Version: '2012-10-17',\n  Comment: 'Jacob is kewl',\n  Statement: [\n    {\n      Sid: 'SomeStatement',\n      Effect: 7,\n      Action: 's3:GetObject',\n      Resource: 'arn:aws:s3:::mybucket/*'\n    },\n    {\n      Sid: 'SomeStatement',\n      Effect: ['Allow'],\n      Action: 's3:GetObject',\n      Resource: 'arn:aws:s3:::mybucket/*',\n      Condition: {\n        NumericLessThan: {\n          's3:max-keys': 7\n        },\n        StringLike: {\n          's3:authType': new RegExp(/REST.*/),\n          'aws:TagKeys/Foo': ['Bar*', 'Baz*']\n        }\n      }\n    }\n  ]\n}) /*\n[\n  { message: 'Invalid key Comment', path: 'Comment' },\n  { message: 'Effect must be present and exactly \"Allow\" or \"Deny\"', path: 'Statement[0].Effect' },\n  { message: 'Effect must be present and exactly \"Allow\" or \"Deny\"', path: 'Statement[1].Effect' },\n  { message: 'Found data type number allowed type(s) are string', path: 'Statement[1].Condition.NumericLessThan s3:max-keys' },\n  { message: 'Found data type object allowed type(s) are string', path: 'Statement[1].Condition.StringLike.s3:authType' }\n]\n*/\n```\n\n### Validate Specific Policy Types\n\nThere are functions to validate specific policy types, these do all of the general policy validation and additional checks for the specific policy type. For instance Service Control Policies only allow the Condition element when the Effect is Deny.\n\n- `validateIdentityPolicy(policy: any): ValidationError[]`\n- `validateServiceControlPolicy(policy: any): ValidationError[]`\n- `validateResourcePolicy(policy: any): ValidationError[]`\n- `validateTrustPolicy(policy: any): ValidationError[]`\n- `validateResourceControlPolicy(policy: any): ValidationError[]`\n- `validateEndpointPolicy(policy: any): ValidationError[]`\n- `validateSessionPolicy(policy: any): ValidationError[]`\n\n## IAM Policy Parsing and Processing with `loadPolicy`\n\n`loadPolicy` _**does not validate policies**_, if you want validation ahead of time use `validatePolicySyntax`.\n\n### Normalizes Policy Elements that are Objects/Array of Objects or String/Array of Strings\n\n```typescript\nimport { loadPolicy } from '@cloud-copilot/iam-policy'\n\n//Statement can be an array of objects\nconst policyOne = {\n  Version: '2012-10-17',\n  Statement: [\n    {\n      Sid: 'ArrayStatement',\n      Effect: 'Allow',\n      Action: ['s3:GetObject'],\n      Resource: 'arn:aws:s3:::government-secrets/*'\n    }\n  ]\n}\n\n//Statement can also be a single object\nconst policyTwo = {\n  Version: '2012-10-17',\n  Statement: {\n    Sid: 'ObjectStatement',\n    Effect: 'Allow',\n    Action: ['s3:GetObject'],\n    Resource: 'arn:aws:s3:::government-secrets/*'\n  }\n}\n\n//In both cases you can use the `statements` function to get an array of statements\nconst p1 = loadPolicy(policyOne)\nconst p2 = loadPolicy(policyTwo)\nconsole.log(p1.statements()[0].sid()) //ArrayStatement\nconsole.log(p2.statements()[0].sid()) //ObjectStatement\n```\n\nThere is similar support for condition values, principals, and resources.\n\n### Mutually Exclusive or Optional Policy Elements\n\nIn IAM policies there are some elements that are mutually exclusive. For example, you can't have a `Principal` and a `NotPrincipal` in the same statement. Some elements are completely optional. We leverage the Typescript type system to make sure you only access data that is confirmed to exist in the policy.\n\n```typescript\nimport{ loadPolicy } from '@cloud-copilot/iam-policy'\n\nconst actionPolicy = {\n  \"Version\": \"2012-10-17\",\n  \"Statement\": {\n    \"Effect\": \"Allow\",\n    \"Action\": [\n      \"s3:GetObject\",\n    ],\n    \"Resource\": \"arn:aws:s3:::government-secrets/*\"\n  }\n};\n\nconst p = loadPolicy(actionPolicy);\nconst statement = p.statements()[0]; // Get the first statement out\n\nstatement.actions() // Compile time error because Statement does not the `actions` function\n\nif(statement.isActionStatement()) {\n  // Type is narrowed to ActionStatement so `actions` is now available\n  statement.actions() /\n}\n\nif(statement.isNotActionStatement()) {\n  // Will not exectue because the statement does not have a NotAction element\n}\n```\n\n`isNotActionStatement` checks for the presence of the NotAction element and is not the inverse of `isActionStatement`. It's possible for a statement to return false for both `isActionStatement` and `isNotActionStatement` if both elements are absent in the statement.\n\nThere is similar support for `Action`, `NotAction`, `Principal`, `NotPrincipal`, `Resource`, and `NotResource` elements.\n\n### Flatten Complex Structures\n\nSimplifies complex elements by flattening them into an array of homogenous objects. For example the Principal value can be a string or an object; the object values can be strings or arrays of strings. We flatten those into an array of objects similar to what you would define in a terraform policy.\n\n```typescript\nimport { loadPolicy } from '@cloud-copilot/iam-policy'\n\nconst principalPolicy = {\n  Version: '2012-10-17',\n  Statement: {\n    Effect: 'Allow',\n    Principal: {\n      AWS: ['arn:aws:iam::123456789012:root', 'arn:aws:iam::123456789013:user/FoxMulder'],\n      CanonicalUser: '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be',\n      Federated: 'cognito-identity.amazonaws.com'\n    },\n    Action: ['s3:GetObject'],\n    Resource: 'arn:aws:s3:::government-secrets/*'\n  }\n}\n\nconst p = loadPolicy(principalPolicy)\n\nconst statement = p.statements()[0] // Get the first statement out\nif (statement.isPrincipalStatement()) {\n  //Get an array of 4 Principal objects with a type and value\n  const principals = statement.principals()\n  principals[0].type() //AWS\n  principals[0].value() //arn:aws:iam::123456789012:root\n  //and so on\n  principals[3].type() //Federated\n  principals[3].value() //cognito-identity.amazonaws.com\n}\n```\n\nThere is similar flattening for the `Condition` element.\n\n```typescript\nimport { loadPolicy } from '@cloud-copilot/iam-policy'\n\nconst principalPolicy = {\n  Version: '2012-10-17',\n  Statement: {\n    Effect: 'Allow',\n    Principal: {\n      AWS: 'arn:aws:iam::123456789012:root'\n    },\n    Action: ['s3:GetObject'],\n    Resource: 'arn:aws:s3:::government-secrets/*',\n    Condition: {\n      StringEquals: {\n        's3:prefix': 'home/${aws:username}',\n        'aws:PrincipalOrgID': 'o-1234567890'\n      },\n      StringLike: {\n        's3:authType': 'REST*',\n        'aws:TagKeys/Foo': ['Bar*', 'Baz*']\n      }\n    }\n  }\n}\n\nconst p = loadPolicy(principalPolicy)\n\nconst statement = p.statements()[0] // Get the first statement out\n\nconst conditions = statement.conditions()\nconditions[0].operation().value() //StringEquals\nconditions[0].conditionKey() //s3:prefix\nconditions[0].conditionValues() //[ home/${aws:username} ]\n//and so on\nconditions[3].operation().value() //StringLike\nconditions[3].conditionKey() //aws:TagKeys/Foo\nconditions[3].conditionValues() // [Bar*, Baz*]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-copilot%2Fiam-policy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloud-copilot%2Fiam-policy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-copilot%2Fiam-policy/lists"}