{"id":13541731,"url":"https://github.com/awslabs/aws-iam-generator","last_synced_at":"2025-04-02T09:32:18.082Z","repository":{"id":44368210,"uuid":"97280556","full_name":"awslabs/aws-iam-generator","owner":"awslabs","description":"Generate Multi-Account IAM users/groups/roles/policies from a simple YAML configuration file and Jinja2 templates. ","archived":false,"fork":false,"pushed_at":"2021-04-27T14:41:33.000Z","size":3889,"stargazers_count":244,"open_issues_count":11,"forks_count":57,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-13T02:37:46.198Z","etag":null,"topics":["aws","aws-cloudformation","aws-iam","aws-manage","aws-multiaccount"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/awslabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-14T23:51:29.000Z","updated_at":"2025-02-10T15:29:37.000Z","dependencies_parsed_at":"2022-07-15T08:51:29.873Z","dependency_job_id":null,"html_url":"https://github.com/awslabs/aws-iam-generator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awslabs%2Faws-iam-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awslabs%2Faws-iam-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awslabs%2Faws-iam-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awslabs%2Faws-iam-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/awslabs","download_url":"https://codeload.github.com/awslabs/aws-iam-generator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246788685,"owners_count":20834143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["aws","aws-cloudformation","aws-iam","aws-manage","aws-multiaccount"],"created_at":"2024-08-01T10:00:55.482Z","updated_at":"2025-04-02T09:32:17.551Z","avatar_url":"https://github.com/awslabs.png","language":"Python","funding_links":[],"categories":["Projects","Python"],"sub_categories":["Identity and Access Management"],"readme":"# iam_generator\n\nGenerates AWS IAM Users, Groups, Roles, and Managed Policies from a YAML configuration and Jinja2 Templates\n\n## Build Environment\n\nA Python interpreter with required libraries installed. Use `pip` to install the requirements:\n\n```bash\nsudo pip install -r requirements.txt\n```\n\n**NOTE:** At present, build is tested on OSX and Linux.  Pull requests welcome for Windows build support!\n\n## Usage\n\n```bash\n$ ./build.py --help\nusage: build.py [-h] [-c CONFIG] [-f {json,yaml}] [-o OUTPUT_PATH]\n                [-p POLICY_PATH]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -c CONFIG, --config CONFIG\n                        Path to config.yaml (default: ./config.yaml)\n  -f {json,yaml}, --format {json,yaml}\n                        The CloudFormation format to use (default: json)\n  -o OUTPUT_PATH, --output-path OUTPUT_PATH\n                        Path into which the CloudFormation templates will be\n                        written (default: ./output_templates)\n  -p POLICY_PATH, --policy-path POLICY_PATH\n                        Path to jinja2 policy templates (default: ./policy)\n```\n\n## Docker Image\n\nA `Dockerfile` is provided to make this project portable.\n\n### Building the Image\n\n```shell\ndocker build . -t iam_generator\n```\n\n### Running as a docker container\n\nLet's say you have a local config in `./config/iam.yml`, some policy templates in `./policy_documents`, and you want the generated CloudFormation templates to be created locally in `./cloudformation`.\n\nHere's how to run the code from the container:\n\n```shell\ndocker run -ti --rm -v ${PWD}/cloudformation:/iam_generator/cloudformation \\\n                    -v ${PWD}/config:/iam_generator/config \\\n                    -v ${PWD}/policy_documents:/iam_generator/policy_documents \\\n                    iam_generator -c config/iam.yml \\\n                                  -f yaml \\\n                                  -o cloudformation/ \\\n                                  -p policy_documents/\n```\n\n## General Function\n\nEverything is driven by the config.yaml file.  In this file you describe your account structure, and desired managed policies, roles, users and groups.\n\nManaged policy structure (in JSON or YAML) is kept in [jinja2 templates](http://jinja.pocoo.org/docs/2.9/) files to allow for variable substitution for specific customization of ARNs and trusts etc.\n\nWhen build.py is executed a CloudFormation template is built per account.  They are availble in the configured `OUTPUT_PATH` directory to be uploaded to [CloudFormation](https://aws.amazon.com/cloudformation/) for deployment in each account.\n\nThis project wouldn't be possible without the hard work done by the [Troposphere](https://github.com/cloudtools/troposphere) and [Jinja](https://github.com/pallets/jinja) project teams.  Thanks!\n\n## config.yaml key sections\n\nThere are five main sections of the config.yaml:\n\n```yaml\nglobal:\n  ...\naccounts:\n  ...\npolicies:\n  ...\nroles:\n  ...\nusers:\n  ...\ngroups:\n  ...\n```\n\n### `global:` section\n\nControls our our genereated templates behaviour.  There are two key sections.  `names:` and `template_outputs`.\n\nThe `names:` section looks like this:\n\n```yaml\nglobal:\n  names:\n    policies: False\n    roles: True\n    users: True\n    groups: True\n```\n\nThis section allows control over the IAM Naming of the resources.  When values are set to `True` they will be explicitly named based on the config.yaml entry.  When set to `False` CloudFormation will generate a name for you.\n\nFor example:\n\n```yaml\npolicies:\n  cloudFormationAdmin:\n    description: CloudFormation Administrator\n    policy_file: cloudFormationAdmin.j2\n```\n\nif `polices: True` is set, the name of the managed policy that CloudFormation creates will be `cloudFormationAdmin`.  If `polices: False` then CloudFormation will generate a unique value using the stack prefix and a suffix eg: `PolicyStack-cloudFormationAdmin-ACH753NADF`.\n\nIf the `global:` section is omitted, it will function with the following default values:\n\n```yaml\nglobal:\n  names:\n    policies: False\n    roles: True\n    users: True\n    groups: True\n  template_outputs: enabled\n```\n\nThe `template_outputs:` value allows control over whether the CloudFormation templates will include Output values for the elements they create.  There is a limit in CloudFormation templates of 60 output values.  You will hit this much sooner than the 200 Resource limit.  The main reason to include an output is so it can be imported in a stack layered above.  If you don't intend on layering any stacks above this one then disabling outputs is absolutely fine.\n\nSet `template_outputs: enabled` to include template outputs.  Set `template_outputs: disabled` to disable output values for templates.\n\n### `accounts:` section\n\nHere's an example of the accounts section:\n\n```yaml\naccounts:\n  central:\n    id: 123456678910\n    parent: true\n    saml_provider: ProdADFS\n  dev1:\n    id: 109876543210\n  dev2:\n    id: 309876543210\n  prod:\n    id: 209876543210\n```\n\n`accounts:` is a dictionary of friendly account names.  These friendly names can be used throughout the rest of the YAML file and are available to the jinja2 templates.\n\nNote that `saml_provider` is optional.  If it is used in a Role's `trust:` list it will generate the appropriate trust policy for console federation.\n\nAccount resolution in the yaml:\n\n* Use the keyword `all` to refer to all of the accounts in the `accounts:` section.\n* Use the keyword `parent` to refer to the account you've marked as `parent: true`.\n* Use the keyword `children` to refer to all accounts except the parent.\n* You can also refer to a specific account by friendly name or it's ID.  eg: `dev1`\n* You can also use python regular expressions.  eg: `dev.*` to target both developement accounts.\n\nUsing these mechanisms it should be easy to specifically manage what account each element lands in.\n\n### `policies:` section\n\n#### Managed Policies derived from a jinja2 template\n\nHere's an example of a managed policy based on a jinja2 policy template:\n\n```yaml\npolicies:\n  cloudFormationAdmin:\n    description: CloudFormation Administrator\n    policy_file: cloudFormationAdmin.j2\n    template_vars:\n      cloudformation_bucket: bucket-cloudformation\n    in_accounts:\n      - parent\n      - dev.*\n```\n\nThis will create a managed policy with the name cloudFormationAdmin (along with the prefix and suffix that CloudFormation Adds automatically).  It will base the policy document on the contents of of the cloudFormationAdmin.j2 jinja2 template.  It will be placed into the accounts 123456678910 (which is our `parent`) as well as accounts 109876543210 and 309876543210 because their friendly names (`dev1` and `dev2`) match our regular expression `dev.*`.\n\nLets disect this a bit.\n\n`policies:` is a dictionary of policy names.  This assures they are kept unique within the account and generated CloudFormation template.\n\n`policy_file:` needs to be located in the configurable `POLICY_PATH` directory, and would look something like this:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"cloudformation:*\"\n      ],\n      \"Resource\": [\n        \"*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"s3:ListBucket\"\n      ],\n      \"Resource\": [\n        \"arn:aws:s3:::{{ template_vars.cloudformation_bucket }}\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"s3:PutObject\",\n        \"s3:GetObject\",\n        \"s3:DeleteObject\"\n      ],\n      \"Resource\": [\"arn:aws:s3:::{{ template_vars.cloudformation_bucket }}/*\"]\n    }\n  ]\n}\n```\n\nNotice the variable substitution in the template ``{{ template_vars.cloudformation_bucket }}``.\n\nNotice the value for this is derived from this section of the config.yaml:\n\n```yaml\n...\n    template_vars:\n      cloudformation_bucket: bucket-cloudformation\n...\n```\n\nJinja2 templates will get the following variable namespaces passed to them:\n\n* `template_vars` as described above.\n* `account` which is the account ID of the account that is being worked on.\n* `parent_account` which is the account ID of the account marked as `parent: true`.\n* `config` which is the entire config.yaml file!\n\n#### Managed Policies for sts:AssumeRole (auto generated!)\n\nHere's an example of the yaml to create a managed policy for sts:AssumeRole with the specified roles into the specified accounts.\n\n```yaml\npolicies:\n  assumeAdmin:\n    description: Allow assumption of the Admin role in all children accounts from the parent\n    assume:\n      roles:\n        - Admin\n      accounts:\n        - children\n    in_accounts:\n      - parent\n```\n\nThis will create this policy document . . .\n\n```json\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n  {\n    \"Action\": \"sts:AssumeRole\",\n    \"Effect\": \"Allow\",\n    \"Resource\": \"arn:aws:iam::109876543210:role/Admin\"\n  },\n  {\n    \"Action\": \"sts:AssumeRole\",\n    \"Effect\": \"Allow\",\n    \"Resource\": \"arn:aws:iam::309876543210:role/Admin\"\n  },\n  {\n    \"Action\": \"sts:AssumeRole\",\n    \"Effect\": \"Allow\",\n    \"Resource\": \"arn:aws:iam::209876543210:role/Admin\"\n  },\n]\n```\n\n. . . and insert it into the CloudFormation template for account 123456678910 (which was marked parent).\n\n### `roles:` section\n\n#### Example of a role that can be assumed from another account\n\n```yaml\nroles:\n  NetworkAdmin:\n    trusts:\n      - parent\n    managed_policies:\n      - arn:aws:iam::aws:policy/job-function/NetworkAdministrator\n      - arn:aws:iam::aws:policy/ReadOnlyAccess\n      - cloudFormationAdmin\n    in_accounts:\n      - all\n    max_role_duration: 3600\n```\n\nThis will create a role called NetworkAdmin.  It will have two AWS managed policies, and one policy referenced from the `policies:` section of the config.yaml.  It allows for a list of `managed_policies:` to attach to the role. It has a MaxSessionDuration of 1 hour.\n\nThe assume role policy document will be automatically generated to trust the parent:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Action\": \"sts:AssumeRole\",\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"AWS\": \"arn:aws:iam::123456678910:root\"\n      }\n    }\n  ]\n}\n```\n\n#### Example of an ec2 role\n\n```yaml\nroles:\n  s3andDynamoWrite:\n    trusts:\n      - ec2.amazonaws.com\n    inline_policies: []\n    managed_policies:\n      - arn:aws:iam::aws:policy/AmazonS3FullAccess\n      - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess\n      - arn:aws:iam::aws:policy/AmazonElasticMapReduceFullAccess\n    in_accounts:\n      - all\n```\n\nIn this case our `trusts:` is ec2.amazonaws.com.  This can be any service like config.amazonaws.com, lambda.amazonaws.com, etc.\n\nSince we're trusting ec2.amazonaws.com we will automatically create an instance profile for this role so it can be used from ec2.  No additional configuration required.\n\n#### Example of a federated role\n\nIn cases that we have a `saml_provider:` in our parent account we can reference it in our trust.\n\n```yaml\nroles:\n  AWS_Admins:\n    trusts:\n      - ProdADFS\n    managed_policies:\n      - assumeAdmin\n    in_accounts:\n      - parent\n```\n\nThis will generate the following assume role policy document automatically . . .\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Action\": \"sts:AssumeRoleWithSAML\",\n      \"Condition\": {\n        \"StringEquals\": {\n          \"SAML:aud\": \"https://signin.aws.amazon.com/saml\"\n        }\n      },\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Federated\": \"arn:aws:iam::123456678910:saml-provider/ProdADFS\"\n      }\n    }\n  ]\n}\n```\n\n. . . and place it (along with the role definition) in the parent CloudFormation template.\n\n### `users:` section\n\n#### An example of a user that is not a member of a group, and has a managed_policy directly attached\n\n```yaml\nusers:\n  adam:\n    managed_policies:\n      - assumeAdmin\n    password: CHANGEME\n    in_accounts:\n      - parent\n```\n\nOptionally specify a `password:` for the user.  The flag is set to force a password change at first login.  The password is clear text, so be careful!\n\n#### An example of a user as a member of groups\n\n```yaml\nusers:\n  adam:\n    groups:\n      - Admins\n    in_accounts:\n      - parent\n```\n\nOur `groups:` field is the name of a group.  This can be a name that already exists, or is in the config.yaml file.  Existing groups just need to be the name of the group, not an ARN.\n\n### `groups:` section\n\n```yaml\ngroups:\n  Admins:\n    managed_policies:\n      - assumeAdmin\n      - arn:aws:iam::aws:policy/ReadOnlyAccess\n    in_accounts:\n      - parent\n```\n\n`groups:` is once again a dictionary of group names that you'd like created.  Each allows for a list of `managed_policies:` to attach.\n\n### `retain_on_delete` variable\n\nCloudFormation permits retention on deletion of a resource.  This is described [here](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html).\n\nFor any resource in the `policies:` `roles:` `groups:` or `users:` section include `retain_on_delete: true` to configure the CloudFormation template to retain that resource on deletion.  This let's you keep a resource that may not necessarily remain under management of this CloudFormation template any longer.\n\neg:\n\n```yaml\nroles:\n  NetworkAdmin:\n    retain_on_delete: true\n    trusts:\n      - parent\n    managed_policies:\n      - arn:aws:iam::aws:policy/job-function/NetworkAdministrator\n      - arn:aws:iam::aws:policy/ReadOnlyAccess\n      - cloudFormationAdmin\n    in_accounts:\n      - all\n```\n\nIf this section is removed from the config.yaml, and a stack-update executed, the 'NetworkAdmin' Role will persist in the account and no longer be managed by CloudFormation.\n\nDefault value is `retain_on_delete: false` which does not need to be explicitly declared anywhere.  This matches the default behaviour of CloudFormation.\n\n### A note about `managed_policies`\n\nFor those config sections that support `managed_policies`, each entry can be an existing managed policy ARN or the name of a policy created in the `policies:` section of the YAML.  Existing ARN strings can optionally contain [AWS Pseudo Parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html).  These are especially useful for account-specific customer managed policies that were created out-of-band, e.g.:\n\n```yaml\nroles:\n  NetworkAdmin:\n    trusts:\n      - parent\n    managed_policies:\n      - arn:aws:iam::aws:policy/job-function/NetworkAdministrator\n      - arn:aws:iam::aws:policy/ReadOnlyAccess\n      - arn:aws:iam::${AWS::AccountId}:policy/CustomerManagedPolicy\n    in_accounts:\n      - children\n```\n\n### Importing resources from other templates\n\nYou are able to specify the keyword of `import:` within the config.yaml file.  Use this for `managed_policies`, `users`, `groups`, or `roles`. This will substiute the appropraite [Fn:ImportValue](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html) within the template to import from an existing CloudFormation templates Exports.\n\nExample of an import for a role:\n\n```yaml\nroles:\n  NetworkAdmin:\n    trusts:\n      - parent\n    managed_policies:\n      - import:name_of_cfn_export\n    in_accounts:\n      - all\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawslabs%2Faws-iam-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fawslabs%2Faws-iam-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawslabs%2Faws-iam-generator/lists"}