├── .github ├── CODEOWNERS └── workflows │ └── main.yml ├── go.mod ├── versions.tf ├── .pre-commit-config.yaml ├── test ├── iam_instance_profile_test.go ├── iam-instance-profile │ └── main.tf └── README.md ├── .gitignore ├── examples ├── iam-instance-profile │ ├── main.tf │ └── README.md └── README.md ├── outputs.tf ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Makefile ├── main.tf ├── variables.tf ├── LICENSE ├── README.md ├── README.tfdoc.hcl └── go.sum /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mariux @mineiros-io/terraform-service-catalog 2 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mineiros-io/terraform-aws-iam-role 2 | 3 | go 1.14 4 | 5 | require github.com/gruntwork-io/terratest v0.34.0 6 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20, < 2.0" 3 | 4 | required_providers { 5 | aws = ">= 2.0, < 4.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/mineiros-io/pre-commit-hooks 3 | rev: v0.2.3 4 | hooks: 5 | - id: terraform-fmt 6 | - id: terraform-validate 7 | exclude: ^examples|.terraform/ 8 | - id: tflint 9 | - id: gofmt 10 | - id: goimports 11 | - id: golangci-lint 12 | - id: phony-targets 13 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI/CD Pipeline 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | env: 12 | AWS_SECRET_ACCESS_KEY: ${{ secrets.MINEIROS_TESTING_AWS_SECRET_ACCESS_KEY }} 13 | AWS_ACCESS_KEY_ID: ${{ secrets.MINEIROS_TESTING_AWS_ACCESS_KEY_ID }} 14 | 15 | jobs: 16 | pre-commit: 17 | runs-on: ubuntu-latest 18 | name: Static Analysis 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | - name: Run pre-commit 23 | run: make test/pre-commit 24 | 25 | unit-tests: 26 | runs-on: ubuntu-latest 27 | name: Unit Tests 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v2 31 | - name: Run Unit Tests 32 | run: make test/unit-tests 33 | -------------------------------------------------------------------------------- /test/iam_instance_profile_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/aws" 7 | "github.com/gruntwork-io/terratest/modules/terraform" 8 | ) 9 | 10 | // TestIAMInstanceProfile tests the creation of the IAM Instance Profile 11 | func TestIAMInstanceProfile(t *testing.T) { 12 | t.Parallel() 13 | 14 | randomAwsRegion := aws.GetRandomRegion(t, nil, nil) 15 | 16 | terraformOptions := &terraform.Options{ 17 | // The path to where your Terraform code is located 18 | TerraformDir: "./iam-instance-profile", 19 | Vars: map[string]interface{}{ 20 | "aws_region": randomAwsRegion, 21 | }, 22 | Upgrade: true, 23 | } 24 | 25 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 26 | defer terraform.Destroy(t, terraformOptions) 27 | 28 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 29 | terraform.InitAndApply(t, terraformOptions) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /test/iam-instance-profile/main.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Provider Setup 3 | # ------------------------------------------------------------------------------ 4 | 5 | provider "aws" { 6 | region = var.aws_region 7 | } 8 | 9 | variable "aws_region" { 10 | type = string 11 | description = "The AWS region to run in. Default is 'us-east-1'" 12 | default = "us-east-1" 13 | } 14 | 15 | # ------------------------------------------------------------------------------ 16 | # Example Usage: Create a Full S3 Access Instance Profile 17 | # ------------------------------------------------------------------------------ 18 | 19 | module "instance-profile-s3-full-access" { 20 | source = "../.." 21 | 22 | name = "S3 Full Access" 23 | 24 | create_instance_profile = true 25 | 26 | policy_statements = [ 27 | { 28 | sid = "S3FullAccess" 29 | 30 | actions = ["s3:*"] 31 | resources = ["*"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ files 2 | .idea_modules 3 | *.iml 4 | *.iws 5 | *.ipr 6 | .idea/ 7 | build/ 8 | */build/ 9 | out/ 10 | 11 | # macOS files 12 | .history 13 | .DS_Store 14 | 15 | # Local .terraform directories 16 | **/.terraform/* 17 | 18 | # .tfstate files 19 | *.tfstate 20 | *.tfstate.* 21 | 22 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 23 | # .tfvars files are managed as part of configuration and so should be included in 24 | # version control. 25 | # 26 | # example.tfvars 27 | 28 | # Ignore override files as they are usually used to override resources locally and so 29 | # are not checked in 30 | override.tf 31 | override.tf.json 32 | *_override.tf 33 | *_override.tf.json 34 | 35 | # Include override files you do wish to add to version control using negated pattern 36 | # 37 | # !example_override.tf 38 | 39 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 40 | # example: *tfplan* 41 | 42 | # Go best practices dictate that libraries should not include the vendor directory 43 | vendor 44 | 45 | # Terratest directory used to store temporary data 46 | .test-data 47 | 48 | # Terraform crash log files 49 | crash.log 50 | -------------------------------------------------------------------------------- /examples/iam-instance-profile/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # CREATE AN IAM INSTANCE PROFILE 3 | # This example shows how to create an IAM Instance Profile that grants full 4 | # access to S3. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | # ------------------------------------------------------------------------------ 8 | # Provider Setup 9 | # ------------------------------------------------------------------------------ 10 | 11 | provider "aws" { 12 | region = var.region 13 | } 14 | 15 | variable "region" { 16 | type = string 17 | description = "The AWS region to run in. Default is 'eu-west-1'" 18 | default = "eu-west-1" 19 | } 20 | 21 | # ------------------------------------------------------------------------------ 22 | # Example Usage: Create a Full S3 Access Instance Profile 23 | # ------------------------------------------------------------------------------ 24 | 25 | module "instance-profile-s3-full-access" { 26 | source = "mineiros-io/iam-role/aws" 27 | version = "~> 0.6.0" 28 | 29 | # name of the role, policy and instance_profile 30 | name = "S3FullAccess" 31 | 32 | create_instance_profile = true 33 | 34 | # the policy granting access 35 | policy_statements = [ 36 | { 37 | sid = "S3FullAccess" 38 | 39 | actions = ["s3:*"] 40 | resources = ["*"] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![GitHub tag (latest SemVer)][badge-semver]][releases-github] 4 | [![license][badge-license]][apache20] 5 | [![Terraform Version][badge-terraform]][releases-terraform] 6 | [![Join Slack][badge-slack]][slack] 7 | 8 | # Examples for using the Mineiros IAM Role Module 9 | 10 | - [iam-instance-profile] 11 | Create an IAM Instance Profile that grants full access to S3. 12 | 13 | 14 | [example/]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples/example 15 | 16 | [homepage]: https://mineiros.io/?ref=terraform-aws-iam-role 17 | 18 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 19 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 20 | 21 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 22 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-iam-role.svg?label=latest&sort=semver 23 | 24 | [releases-github]: https://github.com/mineiros-io/terraform-aws-iam-role/releases 25 | [iam-instance-profile]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples/iam-instance-profile 26 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 27 | [apache20]: https://opensource.org/licenses/Apache-2.0 28 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 29 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # OUTPUT CALCULATED VARIABLES (prefer full objects) 3 | # ------------------------------------------------------------------------------ 4 | 5 | # ------------------------------------------------------------------------------ 6 | # OUTPUT ALL RESOURCES AS FULL OBJECTS 7 | # ------------------------------------------------------------------------------ 8 | 9 | output "role" { 10 | description = "The aws_iam_role object." 11 | value = try(aws_iam_role.role[0], null) 12 | } 13 | 14 | output "policy" { 15 | description = "The aws_iam_role_policy object." 16 | value = try(aws_iam_role_policy.policy[0], null) 17 | } 18 | 19 | output "policy_attachments" { 20 | description = "The aws_iam_role_policy_attachment objects." 21 | value = try(aws_iam_role_policy_attachment.policy_attachment, null) 22 | } 23 | 24 | output "instance_profile" { 25 | description = "The aws_iam_instance_profile object." 26 | value = try(aws_iam_instance_profile.instance_profile[0], null) 27 | } 28 | 29 | # ------------------------------------------------------------------------------ 30 | # OUTPUT ALL INPUT VARIABLES 31 | # ------------------------------------------------------------------------------ 32 | 33 | # ------------------------------------------------------------------------------ 34 | # OUTPUT MODULE CONFIGURATION 35 | # ------------------------------------------------------------------------------ 36 | 37 | output "module_enabled" { 38 | description = "Whether the module is enabled" 39 | value = var.module_enabled 40 | } 41 | 42 | output "module_tags" { 43 | description = "A map of tags that will be applied to all created resources that accept tags." 44 | value = var.module_tags 45 | } 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.6.1] 11 | 12 | ### Added 13 | 14 | - Add `module_tags` from template 15 | - Add `instance_profile_tags` for setting specific tags for the IAM instance profile 16 | 17 | ## [0.6.0] 18 | 19 | ### Added 20 | 21 | - Add support for Terraform `v1.x` 22 | 23 | ## [0.5.0] 24 | 25 | ### Added 26 | 27 | - Add support for Terraform `v0.15` 28 | 29 | ## [0.4.2] 30 | 31 | ### Added 32 | 33 | - Add support for Terraform `v0.14` 34 | 35 | ## [0.4.1] 36 | 37 | ### Added 38 | 39 | - Add `create_policy` argument to force creating inline policy 40 | 41 | ## [0.4.0] 42 | 43 | ### Changes 44 | 45 | - BREAKING CHANGE: Rename output `policy_attachment` to `policy_attachments` and export all policy attachments. 46 | 47 | ## [0.3.1] 48 | 49 | ### Added 50 | 51 | - Prepare support for Terraform `v0.14` (needs terraform `v0.12.20` or above) 52 | 53 | ## [0.3.0] 54 | 55 | ### Added 56 | 57 | - Add support for Terraform `v0.13` 58 | 59 | ### Changed 60 | 61 | - Fix invalid characters for names on the fly by replacing them with a single dash. 62 | - Rename name to `role_name` and `name_prefix` to role_prefix. 63 | - BREAKING CHANGE: Use `name` and `name_prefix` as defaults for `role_name*`, `policy_name*` and `instance_profile_name*` 64 | - to upgrade rename `name` to `role_name` and `name_prefix` to `role_name_prefix`. 65 | 66 | ## [0.2.0] 67 | 68 | ### Changed 69 | 70 | - Add support for Terraform AWS Provider `v3.x` 71 | 72 | ## [0.1.0] 73 | 74 | ### Added 75 | 76 | - Add CHANGELOG.md 77 | 78 | ### Changed 79 | 80 | - Align repository structure and style 81 | 82 | ## [0.0.2] 83 | 84 | ### Fixed 85 | 86 | - Fix an issue in `module_depends_on` argument 87 | 88 | ## [0.0.1] 89 | 90 | ### Added 91 | 92 | - Add support to create an IAM role 93 | - Add support to create an IAM role inline policy 94 | - Add support to create an IAM role policy attachments for custom and/or managed IAM policies 95 | - Add support to create an instance profile with attached IAM role 96 | 97 | 98 | 99 | [unreleased]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.6.1...HEAD 100 | [0.6.1]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.6.0...v0.6.1 101 | 102 | 103 | 104 | [0.6.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.5.0...v0.6.0 105 | [0.5.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.4.2...v0.5.0 106 | [0.4.2]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.4.1...v0.4.2 107 | [0.4.1]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.4.0...v0.4.1 108 | [0.4.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.3.1...v0.4.0 109 | [0.3.1]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.3.0...v0.3.1 110 | [0.3.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.2.0...v0.3.0 111 | [0.2.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.1.0...v0.2.0 112 | [0.1.0]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.0.2...v0.1.0 113 | [0.0.2]: https://github.com/mineiros-io/terraform-aws-iam-role/compare/v0.0.1...v0.0.2 114 | [0.0.1]: https://github.com/mineiros-io/terraform-aws-iam-role/releases/tag/v0.0.1 115 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![license][badge-license]][apache20] 4 | [![Terraform Version][badge-terraform]][releases-terraform] 5 | [![Join Slack][badge-slack]][slack] 6 | 7 | # Tests 8 | 9 | This directory contains a number of automated tests that cover the functionality of the modules that ship with this 10 | repository. 11 | 12 | ## Introduction 13 | 14 | We are using [Terratest] for automated tests of the examples. 15 | Terratest deploys _real_ infrastructure (e.g., servers) in a _real_ environment (e.g., AWS). 16 | 17 | The basic usage pattern for writing automated tests with Terratest is to: 18 | 19 | 1. Write tests using Go's built-in [package testing]: you create a file ending in 20 | `_test.go` and run tests with the `go test` command. 21 | 2. Use Terratest to execute your _real_ IaC tools (e.g., Terraform, Packer, etc.) to deploy _real_ infrastructure 22 | (e.g., servers) in a _real_ environment (e.g., AWS). 23 | 3. Validate that the infrastructure works correctly in that environment by making HTTP requests, API calls, SSH 24 | connections, etc. 25 | 4. Undeploy everything at the end of the test. 26 | 27 | **Note #1**: Many of these tests create real resources in an AWS account. That means they cost money to run, especially 28 | if you don't clean up after yourself. Please be considerate of the resources you create and take extra care to clean 29 | everything up when you're done! 30 | 31 | **Note #2**: Never hit `CTRL + C` or cancel a build once tests are running or the cleanup tasks won't run! 32 | 33 | **Note #3**: We set `-timeout 45m` on all tests not because they necessarily take 45 minutes, but because Go has a 34 | default test timeout of 10 minutes, after which it does a `SIGQUIT`, preventing the tests from properly cleaning up 35 | after themselves. Therefore, we set a timeout of 45 minutes to make sure all tests have enough time to finish and 36 | cleanup. 37 | 38 | ## How to run the tests 39 | 40 | This repository comes with a Dockerfile and a Makefile, that help you to run the tests in a convenient way. 41 | Alternatively, you can also run the tests without Docker. 42 | 43 | ### Run the tests with Docker 44 | 45 | 1. Install [Docker] 46 | 2. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` 47 | 3. Run `make docker-run-tests` 48 | 49 | ### Run the tests without Docker 50 | 51 | 1. Install the latest version of [Go]. 52 | 2. Install [Terraform]. 53 | 3. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` 54 | 4. Install go dependencies: `go mod download` 55 | 5. Run all tests: `go test -v -timeout 45m -parallel 128 test/` 56 | 6. Run a specific test: `go test -v -timeout 45m -parallel 128 test/example_test.go` 57 | 58 | 59 | 60 | [homepage]: https://mineiros.io/?ref=terraform-aws-iam-role 61 | [Terratest]: https://github.com/gruntwork-io/terratest 62 | [package testing]: https://golang.org/pkg/testing/ 63 | [Docker]: https://docs.docker.com/get-started/ 64 | [Go]: https://golang.org/ 65 | [Terraform]: https://www.terraform.io/downloads.html 66 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 67 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 68 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 69 | 70 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 71 | [apache20]: https://opensource.org/licenses/Apache-2.0 72 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 73 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | First and foremost, we’d like to express our gratitude to you for taking the time to contribute. 4 | We welcome and appreciate any and all contributions via 5 | [Pull Requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) 6 | along the [GitHub Flow](https://guides.github.com/introduction/flow/). 7 | 8 | 1. [Open a GitHub issue](#open-a-github-issue) 9 | 1. [Fork the repository on GitHub](#fork-the-repository-on-github) 10 | 1. [Install the pre-commit hooks](#install-the-pre-commit-hooks) 11 | 1. [Update the documentation](#update-the-documentation) 12 | 1. [Update the tests](#update-the-tests) 13 | 1. [Update the code](#update-the-code) 14 | 1. [Create a pull request](#create-a-pull-request) 15 | 1. [Merge and release](#merge-and-release) 16 | 17 | ## Open a GitHub issue 18 | 19 | For bug reports or requests, please submit your issue in the appropriate repository. 20 | 21 | We advise that you open an issue and ask the 22 | [CODEOWNERS](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) and 23 | community prior to starting a contribution. This is your chance to ask questions and receive feedback before you start 24 | writing ( potentially wrong ) code. We value the direct contact to our community a lot, so don't hesitate to ask any 25 | questions. 26 | 27 | ## Fork the repository on GitHub 28 | 29 | [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the repository into your own GitHub 30 | account and [create a new branch](https://guides.github.com/introduction/flow/) as described in the 31 | [GitHub Flow](https://guides.github.com/introduction/flow/). 32 | 33 | ## Install the pre-commit hooks 34 | 35 | If the repository you're working on ships with a `.pre-commit-config.yaml,` make sure the necessary hooks have been 36 | installed before you begin working (e.g. a `pre-commit install`). 37 | 38 | ## Update the documentation 39 | 40 | We encourage you to update the documentation before writing any code (please see 41 | [Readme Driven Development](https://tom.preston-werner.com/2010/08/23/readme-driven-development.html). This ensures the 42 | documentation stays up to date and allows you to think through the problem fully before you begin implementing any 43 | changes. 44 | 45 | ## Update the tests 46 | 47 | We also recommend updating the automated tests before updating any code 48 | (see [Test Driven Development](https://en.wikipedia.org/wiki/Test-driven_development)). 49 | 50 | That means that you should add or update a test case, run all tests and verify that the new test fails with a clear 51 | error message and then start implementing the code changes to get that test to pass. 52 | 53 | The test folder in every repository will have documentation on how to run the tests locally. 54 | 55 | ## Update the code 56 | 57 | At this point, make your code changes and constantly test again your new test case to make sure that everything working 58 | properly. Do [commit](https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project) 59 | early and often and make useful commit messages. 60 | 61 | If a backwards incompatible change cannot be avoided, please make sure to call that out when you submit a pull request, 62 | explaining why the change is absolutely necessary. 63 | 64 | ## Create a pull request 65 | 66 | [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) with your changes. 67 | Please make sure to include the following: 68 | 69 | 1. A description of the change, including a link to your GitHub issue. 70 | 1. Any notes on backwards incompatibility or downtime. 71 | 72 | ## Merge and release 73 | 74 | The [CODEOWNERS](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) 75 | of the repository will review your code and provide feedback. If everything looks good, they will merge the code and 76 | release a new version while following the principles of [Semantic Versioning (SemVer)](https://semver.org/). 77 | -------------------------------------------------------------------------------- /examples/iam-instance-profile/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![GitHub tag (latest SemVer)][badge-semver]][releases-github] 4 | [![license][badge-license]][apache20] 5 | [![Terraform Version][badge-terraform]][releases-terraform] 6 | [![Join Slack][badge-slack]][slack] 7 | 8 | # Create a Full Access S3 IAM Instance Profile 9 | 10 | The code in [main.tf] 11 | creates an IAM Role and an IAM Instance Profile both named 'S3FullAccess' granting 12 | full access to AWS Simple Storage Service (S3). 13 | Because an `instance_profile_name` is set, this role can be assumed 14 | by a `Service = "ec2.amazonaws.com"` principal by default. 15 | 16 | ## Basic Usage 17 | 18 | This is an extract from the code in 19 | [main.tf]: 20 | 21 | ```hcl 22 | module "instance-profile-s3-full-access" { 23 | source = "mineiros-io/iam-role/aws" 24 | version = "~> 0.6.0" 25 | 26 | # name of the role, policy and instance_profile 27 | name = "S3FullAccess" 28 | 29 | create_instance_profile = true 30 | 31 | # the policy granting access 32 | policy_statements = [ 33 | { 34 | sid = "S3FullAccess" 35 | 36 | actions = ["s3:*"] 37 | resources = ["*"] 38 | } 39 | ] 40 | } 41 | ``` 42 | 43 | ## Running the example 44 | 45 | ### Cloning the repository 46 | 47 | ```bash 48 | git clone https://github.com/mineiros-io/terraform-aws-iam-role.git 49 | cd terraform-aws-iam-role/terraform/examples/require-mfa-credentials 50 | ``` 51 | 52 | ### Initializing Terraform 53 | 54 | Run `terraform init` to initialize the example. The output should look like: 55 | 56 | ### Planning the example 57 | 58 | Run `terraform plan` to preview the creation of the resources. Attention: We are not creating a plan output file in this case. In a production environment, it would be recommended to create a plan file first that can be applied in an isolated apply run. 59 | 60 | ### Applying the example 61 | 62 | Run `terraform apply -auto-approve` to create the resources. Attention: this will not ask for confirmation and also not use the previously run plan as no plan output file was used. 63 | 64 | ### Destroying the example 65 | 66 | Run `terraform destroy -refresh=false -auto-approve` to destroy all previously created resources again. 67 | 68 | ## External documentation for the resources created in this example 69 | 70 | - Terraform AWS Provider Documentation: 71 | - https://www.terraform.io/docs/providers/aws/r/iam_role.html 72 | - https://www.terraform.io/docs/providers/aws/r/iam_role_policy.html 73 | - https://www.terraform.io/docs/providers/aws/r/iam_instance_profile.html 74 | 75 | - AWS Documentation IAM: 76 | - Roles: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html 77 | - Policies: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html 78 | - Instance Profile: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html 79 | 80 | 81 | [homepage]: https://mineiros.io/?ref=terraform-aws-iam-role 82 | 83 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 84 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 85 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 86 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-iam-role.svg?label=latest&sort=semver 87 | 88 | [releases-github]: https://github.com/mineiros-io/terraform-aws-iam-role/releases 89 | [main.tf]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples/iam-instance-profile/main.tf 90 | [example/]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples/example 91 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 92 | [apache20]: https://opensource.org/licenses/Apache-2.0 93 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 94 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Set default shell to bash 2 | SHELL := /bin/bash -o pipefail 3 | 4 | BUILD_TOOLS_VERSION ?= v0.12.0 5 | BUILD_TOOLS_DOCKER_REPO ?= mineiros/build-tools 6 | BUILD_TOOLS_DOCKER_IMAGE ?= ${BUILD_TOOLS_DOCKER_REPO}:${BUILD_TOOLS_VERSION} 7 | 8 | # Some CI providers such as GitHub Actions, CircleCI, and TravisCI are setting 9 | # the CI environment variable to a non-empty value by default to indicate that 10 | # the current workflow is running in a Continuous Integration environment. 11 | # 12 | # If TF_IN_AUTOMATION is set to any non-empty value, Terraform adjusts its 13 | # output to avoid suggesting specific commands to run next. 14 | # https://www.terraform.io/docs/commands/environment-variables.html#tf_in_automation 15 | # 16 | # We are using GNU style quiet commands to disable set V to non-empty e.g. V=1 17 | # https://www.gnu.org/software/automake/manual/html_node/Debugging-Make-Rules.html 18 | # 19 | ifdef CI 20 | TF_IN_AUTOMATION ?= yes 21 | export TF_IN_AUTOMATION 22 | 23 | V ?= 1 24 | endif 25 | 26 | ifndef NOCOLOR 27 | GREEN := $(shell tput -Txterm setaf 2) 28 | YELLOW := $(shell tput -Txterm setaf 3) 29 | WHITE := $(shell tput -Txterm setaf 7) 30 | RESET := $(shell tput -Txterm sgr0) 31 | endif 32 | 33 | GIT_TOPLEVEl = $(shell git rev-parse --show-toplevel) 34 | 35 | # Generic docker run flags 36 | DOCKER_RUN_FLAGS += -v ${GIT_TOPLEVEl}:/build 37 | DOCKER_RUN_FLAGS += --rm 38 | DOCKER_RUN_FLAGS += -e TF_IN_AUTOMATION 39 | 40 | # If SSH_AUTH_SOCK is set, we forward the SSH agent of the host system into 41 | # the docker container. This is useful when working with private repositories 42 | # and dependencies that might need to be cloned inside the container (e.g. 43 | # private Terraform modules). 44 | ifdef SSH_AUTH_SOCK 45 | DOCKER_SSH_FLAGS += -e SSH_AUTH_SOCK=/ssh-agent 46 | DOCKER_SSH_FLAGS += -v ${SSH_AUTH_SOCK}:/ssh-agent 47 | endif 48 | 49 | # If AWS_ACCESS_KEY_ID is defined, we are likely running inside an AWS provider 50 | # module. To enable AWS authentication inside the docker container, we inject 51 | # the relevant environment variables. 52 | ifdef AWS_ACCESS_KEY_ID 53 | DOCKER_AWS_FLAGS += -e AWS_ACCESS_KEY_ID 54 | DOCKER_AWS_FLAGS += -e AWS_SECRET_ACCESS_KEY 55 | DOCKER_AWS_FLAGS += -e AWS_SESSION_TOKEN 56 | endif 57 | 58 | # If GITHUB_OWNER is defined, we are likely running inside a GitHub provider 59 | # module. To enable GitHub authentication inside the docker container, 60 | # we inject the relevant environment variables. 61 | ifdef GITHUB_OWNER 62 | DOCKER_GITHUB_FLAGS += -e GITHUB_TOKEN 63 | DOCKER_GITHUB_FLAGS += -e GITHUB_OWNER 64 | endif 65 | 66 | .PHONY: default 67 | default: help 68 | 69 | # Not exposed as a callable target by `make help`, since this is a one-time shot to simplify the development of this module. 70 | .PHONY: template/adjust 71 | template/adjust: FILTER = -path ./.git -prune -a -type f -o -type f -not -name Makefile 72 | template/adjust: 73 | @find . $(FILTER) -exec sed -i -e "s,terraform-module-template,$${PWD##*/},g" {} \; 74 | 75 | ## Run pre-commit hooks inside a build-tools docker container. 76 | .PHONY: test/pre-commit 77 | test/pre-commit: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 78 | test/pre-commit: 79 | $(call docker-run,pre-commit run -a) 80 | 81 | ## Run all Go tests inside a build-tools docker container. This is complementary to running 'go test ./test/...'. 82 | .PHONY: test/unit-tests 83 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 84 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_GITHUB_FLAGS} 85 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_AWS_FLAGS} 86 | test/unit-tests: DOCKER_FLAGS += -e TF_DATA_DIR=.terratest 87 | test/unit-tests: TEST ?= "TestUnit" 88 | test/unit-tests: 89 | @echo "${YELLOW}[TEST] ${GREEN}Start Running Go Tests in Docker Container.${RESET}" 90 | $(call go-test,./test -run $(TEST)) 91 | 92 | ## Clean up cache and temporary files 93 | .PHONY: clean 94 | clean: 95 | $(call rm-command,.terraform) 96 | $(call rm-command,.terraform.lock.hcl) 97 | $(call rm-command,*.tfplan) 98 | $(call rm-command,*/*/.terraform) 99 | $(call rm-command,*/*/*.tfplan) 100 | $(call rm-command,*/*/.terraform.lock.hcl) 101 | 102 | ## Generate README.md with Terradoc 103 | .PHONY: terradoc 104 | terradoc: 105 | $(call quiet-command,terradoc -o README.md README.tfdoc.hcl) 106 | 107 | ## Display help for all targets 108 | .PHONY: help 109 | help: 110 | @awk '/^.PHONY: / { \ 111 | msg = match(lastLine, /^## /); \ 112 | if (msg) { \ 113 | cmd = substr($$0, 9, 100); \ 114 | msg = substr(lastLine, 4, 1000); \ 115 | printf " ${GREEN}%-30s${RESET} %s\n", cmd, msg; \ 116 | } \ 117 | } \ 118 | { lastLine = $$0 }' $(MAKEFILE_LIST) 119 | 120 | # Define helper functions 121 | DOCKER_FLAGS += ${DOCKER_RUN_FLAGS} 122 | DOCKER_RUN_CMD = docker run ${DOCKER_FLAGS} ${BUILD_TOOLS_DOCKER_IMAGE} 123 | 124 | quiet-command = $(if ${V},${1},$(if ${2},@echo ${2} && ${1}, @${1})) 125 | docker-run = $(call quiet-command,${DOCKER_RUN_CMD} ${1} | cat,"${YELLOW}[DOCKER RUN] ${GREEN}${1}${RESET}") 126 | go-test = $(call quiet-command,${DOCKER_RUN_CMD} go test -v -count 1 -timeout 45m -parallel 128 ${1} | cat,"${YELLOW}[TEST] ${GREEN}${1}${RESET}") 127 | rm-command = $(call quiet-command,rm -rf ${1},"${YELLOW}[CLEAN] ${GREEN}${1}${RESET}") 128 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # AWS Identity and Access Management (IAM) 3 | # ------------------------------------------------------------------------------ 4 | # IAM ROLES 5 | # ------------------------------------------------------------------------------ 6 | # An IAM role is an IAM identity that you can create in your account that has 7 | # specific permissions. 8 | # 9 | # AWS Documentation IAM: 10 | # - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html 11 | # - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html 12 | # - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html 13 | # 14 | # Terraform AWS Provider Documentation: 15 | # - https://www.terraform.io/docs/providers/aws/r/iam_role.html 16 | # - https://www.terraform.io/docs/providers/aws/r/iam_role_policy.html 17 | # - https://www.terraform.io/docs/providers/aws/r/iam_role_policy_attachment.html 18 | # - https://www.terraform.io/docs/providers/aws/r/iam_instance_profile.html 19 | # ------------------------------------------------------------------------------ 20 | 21 | locals { 22 | _replace = ["/[^\\w+=,.@-]+/", "-"] 23 | 24 | r_name = try(compact([var.role_name, var.name])[0], null) 25 | r_name_prefix = try(compact([var.role_name_prefix, var.name_prefix])[0], null) 26 | 27 | p_name = try(compact([var.policy_name, var.name])[0], null) 28 | p_name_prefix = try(compact([var.policy_name_prefix, var.name_prefix])[0], null) 29 | 30 | ip_name = try(compact([var.instance_profile_name, var.name])[0], null) 31 | ip_name_prefix = try(compact([var.instance_profile_name_prefix, var.name_prefix])[0], null) 32 | 33 | role_name = try(replace(local.r_name, local._replace...), null) 34 | role_name_prefix = try(replace(local.r_name_prefix, local._replace...), null) 35 | 36 | policy_name = try(replace(local.p_name, local._replace...), null) 37 | policy_name_prefix = try(replace(local.p_name_prefix, local._replace...), null) 38 | 39 | instance_profile_name = try(replace(local.ip_name, local._replace...), null) 40 | instance_profile_name_prefix = try(replace(local.ip_name_prefix, local._replace...), null) 41 | } 42 | 43 | resource "aws_iam_role" "role" { 44 | count = var.module_enabled ? 1 : 0 45 | 46 | name = local.role_name 47 | name_prefix = local.role_name_prefix 48 | assume_role_policy = local.assume_role_policy 49 | force_detach_policies = var.force_detach_policies 50 | path = var.path 51 | description = var.description 52 | max_session_duration = var.max_session_duration 53 | permissions_boundary = var.permissions_boundary 54 | 55 | tags = merge(var.module_tags, var.tags) 56 | depends_on = [var.module_depends_on] 57 | } 58 | 59 | locals { 60 | # set defaults 61 | _ec2_principles = [ 62 | { type = "Service" 63 | identifiers = ["ec2.amazonaws.com"] 64 | } 65 | ] 66 | # compute defaults 67 | _create_assume_role_policy = var.module_enabled && var.assume_role_policy == null 68 | _assume_role_principals = local.create_instance_profile ? local._ec2_principles : [] 69 | _create_instance_profile = var.instance_profile_name != null || var.instance_profile_name_prefix != null 70 | 71 | # translate variables to variables with defaults 72 | 73 | create_instance_profile = var.create_instance_profile != null ? var.create_instance_profile : local._create_instance_profile 74 | assume_role_policy = local._create_assume_role_policy ? data.aws_iam_policy_document.assume_role_policy[0].json : var.assume_role_policy 75 | assume_role_principals = length(var.assume_role_principals) > 0 ? var.assume_role_principals : local._assume_role_principals 76 | } 77 | 78 | data "aws_iam_policy_document" "assume_role_policy" { 79 | count = local._create_assume_role_policy ? 1 : 0 80 | 81 | statement { 82 | effect = "Allow" 83 | 84 | actions = var.assume_role_actions 85 | 86 | dynamic "principals" { 87 | for_each = local.assume_role_principals 88 | 89 | content { 90 | type = principals.value.type 91 | identifiers = principals.value.identifiers 92 | } 93 | } 94 | 95 | dynamic "condition" { 96 | for_each = var.assume_role_conditions 97 | 98 | content { 99 | test = condition.value.test 100 | variable = condition.value.variable 101 | values = condition.value.values 102 | } 103 | } 104 | } 105 | } 106 | 107 | locals { 108 | policy_enabled = var.module_enabled && (var.create_policy != null ? var.create_policy : length(var.policy_statements) > 0) 109 | } 110 | 111 | data "aws_iam_policy_document" "policy" { 112 | count = local.policy_enabled ? 1 : 0 113 | 114 | dynamic "statement" { 115 | for_each = var.policy_statements 116 | 117 | content { 118 | sid = try(statement.value.sid, null) 119 | effect = try(statement.value.effect, null) 120 | actions = try(statement.value.actions, null) 121 | not_actions = try(statement.value.not_actions, null) 122 | resources = try(statement.value.resources, null) 123 | not_resources = try(statement.value.not_resources, null) 124 | 125 | dynamic "condition" { 126 | for_each = try(statement.value.conditions, []) 127 | 128 | content { 129 | test = condition.value.test 130 | variable = condition.value.variable 131 | values = condition.value.values 132 | } 133 | } 134 | } 135 | } 136 | } 137 | 138 | resource "aws_iam_role_policy" "policy" { 139 | count = local.policy_enabled ? 1 : 0 140 | 141 | name = local.policy_name 142 | name_prefix = local.policy_name_prefix 143 | 144 | policy = data.aws_iam_policy_document.policy[0].json 145 | role = aws_iam_role.role[0].name 146 | 147 | depends_on = [var.module_depends_on] 148 | } 149 | 150 | # Attach custom or managed policies 151 | resource "aws_iam_role_policy_attachment" "policy_attachment" { 152 | count = var.module_enabled ? length(var.policy_arns) : 0 153 | 154 | role = aws_iam_role.role[0].name 155 | policy_arn = var.policy_arns[count.index] 156 | 157 | depends_on = [var.module_depends_on] 158 | } 159 | 160 | resource "aws_iam_instance_profile" "instance_profile" { 161 | count = var.module_enabled && local.create_instance_profile ? 1 : 0 162 | 163 | name = local.instance_profile_name 164 | name_prefix = local.instance_profile_name_prefix 165 | path = var.instance_profile_path 166 | 167 | role = aws_iam_role.role[0].name 168 | 169 | tags = merge(var.module_tags, var.instance_profile_tags) 170 | depends_on = [var.module_depends_on] 171 | } 172 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # ENVIRONMENT VARIABLES 3 | # Define these secrets as environment variables. 4 | # ------------------------------------------------------------------------------ 5 | 6 | # AWS_ACCESS_KEY_ID 7 | # AWS_SECRET_ACCESS_KEY 8 | 9 | # ------------------------------------------------------------------------------ 10 | # REQUIRED PARAMETERS 11 | # These variables must be set when using this module. 12 | # ------------------------------------------------------------------------------ 13 | 14 | variable "assume_role_policy" { 15 | type = string 16 | description = "(Required if assume_role_principals is not set) The policy that grants an entity permission to assume the role." 17 | default = null 18 | } 19 | 20 | variable "assume_role_principals" { 21 | type = set(object({ 22 | type = string 23 | identifiers = list(string) 24 | })) 25 | description = "(Required if assume_role_policy is not set) Principals for the assume role policy." 26 | default = [] 27 | } 28 | 29 | variable "assume_role_conditions" { 30 | type = set(object({ 31 | test = string 32 | variable = string 33 | values = list(string) 34 | })) 35 | description = "(Optional) Conditions for the assume role policy." 36 | default = [] 37 | } 38 | 39 | variable "assume_role_actions" { 40 | type = set(string) 41 | description = "(Required if assume_role_policy is not set) Actions for the assume role policy." 42 | default = ["sts:AssumeRole"] 43 | } 44 | 45 | 46 | # ------------------------------------------------------------------------------ 47 | # OPTIONAL PARAMETERS 48 | # These variables have defaults, but may be overridden. 49 | # ------------------------------------------------------------------------------ 50 | 51 | variable "name" { 52 | type = string 53 | description = "(Optional, Forces new resources) Default name for the role_name, the policy_name and the instance_profile_name arguments. Invalid characters will be replaced with dashes. Default is a random, unique name." 54 | default = null 55 | } 56 | 57 | variable "name_prefix" { 58 | type = string 59 | description = "(Optional, Forces new resources) Default prefix for the role_name_prefix, the policy_name_prefix and the instance_profile_name_prefix arguments. Invalid characters will be replaced with dashes. Conflicts with name." 60 | default = null 61 | } 62 | 63 | variable "role_name" { 64 | type = string 65 | description = "(Optional, Forces new resource) The name of the role. Invalid characters will be replaced with dashes. Default is the value of the name argument." 66 | default = null 67 | } 68 | 69 | variable "role_name_prefix" { 70 | type = string 71 | description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Invalid characters will be replaced with dashes. Conflicts with name." 72 | default = null 73 | } 74 | 75 | variable "force_detach_policies" { 76 | type = bool 77 | description = "(Optional) Specifies to force detaching any policies the role has before destroying it. Defaults to false." 78 | default = false 79 | } 80 | 81 | variable "path" { 82 | type = string 83 | description = "(Optional) The path to the role. See IAM Identifiers for more information." 84 | default = "/" 85 | } 86 | 87 | variable "description" { 88 | type = string 89 | description = "(Optional) The description of the role." 90 | default = "" 91 | } 92 | 93 | variable "max_session_duration" { 94 | type = number 95 | description = "(Optional) The maximum session duration (in seconds) that you want to set for the specified role. If you do not specify a value for this setting, the default maximum of one hour is applied. This setting can have a value from 1 hour (3600) to 12 hours (43200)." 96 | default = 3600 97 | } 98 | 99 | variable "permissions_boundary" { 100 | type = string 101 | description = "(Optional) The ARN of the policy that is used to set the permissions boundary for the role." 102 | default = null 103 | } 104 | 105 | variable "tags" { 106 | type = map(string) 107 | description = "(Optional) Key-value map of tags for the IAM role" 108 | default = {} 109 | } 110 | 111 | # inline policy 112 | 113 | variable "policy_statements" { 114 | type = any 115 | description = "(Optional) List of IAM policy statements to attach to the User as an inline policy." 116 | default = [] 117 | } 118 | 119 | variable "create_policy" { 120 | type = bool 121 | description = "(Optional) Force creation of inline policy, when policy_statements can not be computed" 122 | default = null 123 | } 124 | 125 | variable "policy_name" { 126 | type = string 127 | description = "(Optional) The name of the role policy. Invalid characters will be replaced with dashes. Default is the value of the name argument." 128 | default = null 129 | } 130 | 131 | variable "policy_name_prefix" { 132 | type = string 133 | description = "(Optional) Creates a unique name beginning with the specified prefix. Invalid characters will be replaced with dashes. Conflicts with policy_name." 134 | default = null 135 | } 136 | 137 | # managed / custom policies 138 | 139 | variable "policy_arns" { 140 | type = list(string) 141 | description = "(Optional) List of IAM custom or managed policies ARNs to attach to the User." 142 | default = [] 143 | } 144 | 145 | # instance profile 146 | 147 | variable "create_instance_profile" { 148 | type = bool 149 | description = "(Optional) Whether to create an instance profile. Default is true if name or name_prefix are set else false." 150 | default = null 151 | } 152 | 153 | variable "instance_profile_name" { 154 | type = string 155 | description = "(Optional, Forces new resource) The profile's name. Invalid characters will be replaced with dashes. Default is the value of the name argument." 156 | default = null 157 | } 158 | 159 | variable "instance_profile_name_prefix" { 160 | type = string 161 | description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Invalid characters will be replaced with dashes. Conflicts with instance_profile_name." 162 | default = null 163 | } 164 | 165 | variable "instance_profile_path" { 166 | type = string 167 | description = "(Optional) Path in which to create the profile. Defaults to /" 168 | default = "/" 169 | } 170 | 171 | variable "instance_profile_tags" { 172 | type = map(string) 173 | description = "(Optional) Key-value map of tags for the IAM instance profile" 174 | default = {} 175 | } 176 | 177 | # ------------------------------------------------------------------------------ 178 | # MODULE CONFIGURATION PARAMETERS 179 | # These variables are used to configure the module. 180 | # See https://medium.com/mineiros/the-ultimate-guide-on-how-to-write-terraform-modules-part-1-81f86d31f024 181 | # ------------------------------------------------------------------------------ 182 | 183 | variable "module_enabled" { 184 | type = bool 185 | description = "(Optional) Whether to create resources within the module or not. Default is true." 186 | default = true 187 | } 188 | 189 | variable "module_tags" { 190 | type = map(string) 191 | description = "(Optional) A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be overwritten by resource-specific tags." 192 | default = {} 193 | } 194 | 195 | variable "module_depends_on" { 196 | type = any 197 | description = "(Optional) A list of external resources the module depends_on. Default is []." 198 | default = [] 199 | } 200 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2020] [Mineiros GmbH] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://mineiros.io/?ref=terraform-aws-iam-role) 2 | 3 | [![Build Status](https://github.com/mineiros-io/terraform-aws-iam-role/workflows/CI/CD%20Pipeline/badge.svg)](https://github.com/mineiros-io/terraform-aws-iam-role/actions) 4 | [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-iam-role.svg?label=latest&sort=semver)](https://github.com/mineiros-io/terraform-aws-iam-role/releases) 5 | [![Terraform Version](https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform)](https://github.com/hashicorp/terraform/releases) 6 | [![AWS Provider Version](https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform)](https://github.com/terraform-providers/terraform-provider-aws/releases) 7 | [![Join Slack](https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack)](https://mineiros.io/slack) 8 | 9 | # terraform-aws-iam-role 10 | 11 | A [Terraform](https://www.terraform.io) base module for creating and managing 12 | [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) 13 | on [Amazon Web Services (AWS)](https://aws.amazon.com/). 14 | 15 | ***This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above 16 | and is compatible with the terraform AWS provider v3 as well as v2.0 and above.*** 17 | 18 | 19 | - [Module Features](#module-features) 20 | - [Getting Started](#getting-started) 21 | - [Module Argument Reference](#module-argument-reference) 22 | - [Module Configuration](#module-configuration) 23 | - [Top-level Arguments](#top-level-arguments) 24 | - [Main Resource Configuration](#main-resource-configuration) 25 | - [Extended Resource configuration](#extended-resource-configuration) 26 | - [Custom & Managed Policies](#custom--managed-policies) 27 | - [Inline Policiy](#inline-policiy) 28 | - [Instance Profile](#instance-profile) 29 | - [Module Outputs](#module-outputs) 30 | - [External Documentation](#external-documentation) 31 | - [AWS Documentation IAM](#aws-documentation-iam) 32 | - [Terraform AWS Provider Documentation](#terraform-aws-provider-documentation) 33 | - [Module Versioning](#module-versioning) 34 | - [Backwards compatibility in `0.0.z` and `0.y.z` version](#backwards-compatibility-in-00z-and-0yz-version) 35 | - [About Mineiros](#about-mineiros) 36 | - [Reporting Issues](#reporting-issues) 37 | - [Contributing](#contributing) 38 | - [Makefile Targets](#makefile-targets) 39 | - [License](#license) 40 | 41 | ## Module Features 42 | 43 | In contrast to the plain `aws_iam_role` resource this module simplifies adding IAM Policies to the role. 44 | 45 | - **Standard Module Features**: 46 | Create an IAM role. 47 | 48 | - **Extended Module Features**: 49 | Create an inline IAM policy, Attach custom or AWS managed policies. Create an IAM instance profile. 50 | 51 | ## Getting Started 52 | 53 | Basic usage for granting an AWS Account with Account ID `123456789012` access to assume a role that grants 54 | full access to AWS Simple Storage Service (S3) 55 | 56 | ```hcl 57 | module "role-s3-full-access" { 58 | source = "mineiros-io/iam-role/aws" 59 | version = "~> 0.6.0" 60 | 61 | name = "S3FullAccess" 62 | 63 | assume_role_principals = [ 64 | { 65 | type = "AWS" 66 | identifiers = ["arn:aws:iam::123456789012:root"] 67 | } 68 | ] 69 | 70 | policy_statements = [ 71 | { 72 | sid = "FullS3Access" 73 | 74 | effect = "Allow" 75 | actions = ["s3:*"] 76 | resources = ["*"] 77 | } 78 | ] 79 | } 80 | ``` 81 | 82 | ## Module Argument Reference 83 | 84 | See [variables.tf] and [examples/] for details and use-cases. 85 | 86 | ### Module Configuration 87 | 88 | - [**`module_enabled`**](#var-module_enabled): *(Optional `bool`)* 89 | 90 | Specifies whether resources in the module will be created. 91 | 92 | Default is `true`. 93 | 94 | - [**`module_tags`**](#var-module_tags): *(Optional `map(string)`)* 95 | 96 | A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be overwritten by resource-specific tags. 97 | 98 | Default is `{}`. 99 | 100 | - [**`module_depends_on`**](#var-module_depends_on): *(Optional `list(any)`)* 101 | 102 | A list of dependencies. Any object can be assigned to this list to define a hidden external dependency. 103 | 104 | ### Top-level Arguments 105 | 106 | #### Main Resource Configuration 107 | 108 | - [**`name`**](#var-name): *(Optional `string`)* 109 | 110 | The name of the role. 111 | Invalid characters will be replaced with dashes. 112 | If omitted, Terraform will assign a random, unique name. 113 | Forces new resource. 114 | 115 | - [**`name_prefix`**](#var-name_prefix): *(Optional `string`)* 116 | 117 | If omitted, Terraform will assign a random, unique name. 118 | Invalid characters will be replaced with dashes. 119 | Creates a unique name beginning with the specified prefix. 120 | Conflicts with name. 121 | Forces new resource. 122 | 123 | - [**`assume_role_policy`**](#var-assume_role_policy): *(**Required** `string`)* 124 | 125 | A JSON String representing the policy that grants an entity permission to assume the role. 126 | *(only required if `assume_role_principals` is not set)* 127 | 128 | Example: 129 | 130 | ```hcl 131 | assume_role_policy = < 149 | 150 | A Set of objects representing Principals in an IAM policy document. 151 | *(only required if `assume_role_policy` is not set)* 152 | 153 | Example: 154 | 155 | ```hcl 156 | assume_role_principals = [ 157 | { 158 | type = "Service" 159 | identifiers = [ "ec2.amazonaws.com" ] 160 | } 161 | ] 162 | ``` 163 | 164 | - [**`assume_role_conditions`**](#var-assume_role_conditions): *(Optional `set(condition)`)* 165 | 166 | A Set of objects representing Conditions in an IAM policy document. 167 | *(only evaluated when `assume_role_principals` is used)* 168 | 169 | Example: 170 | 171 | ```hcl 172 | assume_role_conditions = [ 173 | { 174 | test = "Bool" 175 | variable = "aws:MultiFactorAuthPresent" 176 | values = [ "true" ] 177 | } 178 | ] 179 | ``` 180 | 181 | - [**`assume_role_actions`**](#var-assume_role_actions): *(Optional `list(string)`)* 182 | 183 | A list of strings representing Action in an IAM policy document. 184 | *(only evaluated when `assume_role_principals` is used)* 185 | 186 | Default is `["sts:AssumeRole"]`. 187 | 188 | Example: 189 | 190 | ```hcl 191 | assume_role_actions = [ 192 | "sts:TagSession", 193 | "sts:AssumeRoleWithSAML" 194 | ] 195 | ``` 196 | 197 | - [**`force_detach_policies`**](#var-force_detach_policies): *(Optional `bool`)* 198 | 199 | Specifies to force detaching any policies the role has before destroying it. Defaults to false. 200 | 201 | Default is `false`. 202 | 203 | - [**`path`**](#var-path): *(Optional `string`)* 204 | 205 | The path to the role. See IAM Identifiers for more information. 206 | 207 | Default is `"/"`. 208 | 209 | - [**`description`**](#var-description): *(Optional `string`)* 210 | 211 | The description of the role. 212 | 213 | - [**`max_session_duration`**](#var-max_session_duration): *(Optional `number`)* 214 | 215 | The maximum session duration (in seconds) that you want to set for the specified role. 216 | If you do not specify a value for this setting, the default maximum of one hour is applied. 217 | This setting can have a value from 1 hour to 12 - hours. 218 | 219 | Default is `3600`. 220 | 221 | - [**`permissions_boundary`**](#var-permissions_boundary): *(Optional `string`)* 222 | 223 | The ARN of the policy that is used to set the permissions boundary for the role. 224 | 225 | - [**`tags`**](#var-tags): *(Optional `map(string)`)* 226 | 227 | Key-value map of tags for the IAM role. 228 | 229 | Default is `{}`. 230 | 231 | #### Extended Resource configuration 232 | 233 | ##### Custom & Managed Policies 234 | 235 | - [**`policy_arns`**](#var-policy_arns): *(Optional `list(string)`)* 236 | 237 | List of IAM custom or managed policies ARNs to attach to the role. 238 | 239 | Default is `[]`. 240 | 241 | ##### Inline Policiy 242 | 243 | - [**`policy_name`**](#var-policy_name): *(Optional `string`)* 244 | 245 | The name of the role policy. 246 | Invalid characters will be replaced with dashes. 247 | If omitted, Terraform will assign a random, unique name. 248 | 249 | - [**`policy_name_prefix`**](#var-policy_name_prefix): *(Optional `string`)* 250 | 251 | Creates a unique name beginning with the specified prefix. 252 | Invalid characters will be replaced with dashes. 253 | Conflicts with name. 254 | 255 | - [**`create_policy`**](#var-create_policy): *(Optional `bool`)* 256 | 257 | Force creation of inline policy, when `policy_statements` can not be computed. Defaults to true if `policy_statements` is a non-empty list and terraform can compute it. 258 | 259 | - [**`policy_statements`**](#var-policy_statements): *(Optional `list(statement)`)* 260 | 261 | List of IAM policy statements to attach to the role as an inline policy. 262 | 263 | Example: 264 | 265 | ```hcl 266 | policy_statements = [ 267 | { 268 | sid = "FullS3Access" 269 | 270 | effect = "Allow" 271 | 272 | actions = [ "s3:*" ] 273 | not_actions = [] 274 | 275 | resources = [ "*" ] 276 | not_resources = [] 277 | 278 | conditions = [ 279 | { test = "Bool" 280 | variable = "aws:MultiFactorAuthPresent" 281 | values = [ "true" ] 282 | } 283 | ] 284 | } 285 | ] 286 | ``` 287 | 288 | ##### Instance Profile 289 | 290 | - [**`create_instance_profile`**](#var-create_instance_profile): *(Optional `bool`)* 291 | 292 | Whether to create an instance profile. 293 | 294 | - [**`instance_profile_name`**](#var-instance_profile_name): *(Optional `string`)* 295 | 296 | Name of the instance profile. If omitted, Terraform will assign a random, unique name. Conflicts with name_prefix. Can be a string of characters consisting of upper and lowercase alphanumeric characters and these special characters: `_`, `+`, `=`, `,`, `.`, `@`, `-`. Spaces are not allowed. 297 | 298 | - [**`instance_profile_name_prefix`**](#var-instance_profile_name_prefix): *(Optional `string`)* 299 | 300 | Creates a unique name beginning with the specified prefix. 301 | Invalid characters will be replaced with dashes. 302 | Conflicts with name. 303 | Forces new resource. 304 | 305 | - [**`instance_profile_path`**](#var-instance_profile_path): *(Optional `string`)* 306 | 307 | Path in which to create the profile. 308 | 309 | Default is `"/"`. 310 | 311 | - [**`instance_profile_tags`**](#var-instance_profile_tags): *(Optional `map(string)`)* 312 | 313 | Key-value map of tags for the IAM instance profile. 314 | 315 | Default is `{}`. 316 | 317 | ## Module Outputs 318 | 319 | The following attributes are exported by the module: 320 | 321 | - [**`role`**](#output-role): *(`object(role)`)* 322 | 323 | The `aws_iam_role` object. 324 | 325 | - [**`policy`**](#output-policy): *(`object(policy)`)* 326 | 327 | The `aws_iam_role_policy` object. 328 | 329 | - [**`policy_attachments`**](#output-policy_attachments): *(`list(policy_attachment)`)* 330 | 331 | An array of `aws_iam_role_policy_attachment` objects. 332 | 333 | - [**`instance_profile`**](#output-instance_profile): *(`object(instance_profile)`)* 334 | 335 | The `aws_iam_instance_profile` object. 336 | 337 | ## External Documentation 338 | 339 | ### AWS Documentation IAM 340 | 341 | - Roles: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html 342 | - Policies: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html 343 | - Instance Profile: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html 344 | 345 | ### Terraform AWS Provider Documentation 346 | 347 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role 348 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy 349 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment 350 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile 351 | 352 | ## Module Versioning 353 | 354 | This Module follows the principles of [Semantic Versioning (SemVer)]. 355 | 356 | Given a version number `MAJOR.MINOR.PATCH`, we increment the: 357 | 358 | 1. `MAJOR` version when we make incompatible changes, 359 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and 360 | 3. `PATCH` version when we make backwards compatible bug fixes. 361 | 362 | ### Backwards compatibility in `0.0.z` and `0.y.z` version 363 | 364 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) 365 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) 366 | 367 | ## About Mineiros 368 | 369 | Mineiros is a [DevOps as a Service][homepage] company based in Berlin, Germany. 370 | We offer commercial support for all of our projects and encourage you to reach out 371 | if you have any questions or need help. Feel free to send us an email at [hello@mineiros.io] or join our [Community Slack channel][slack]. 372 | 373 | We can also help you with: 374 | 375 | - Terraform modules for all types of infrastructure such as VPCs, Docker clusters, databases, logging and monitoring, CI, etc. 376 | - Consulting & training on AWS, Terraform and DevOps 377 | 378 | ## Reporting Issues 379 | 380 | We use GitHub [Issues] to track community reported issues and missing features. 381 | 382 | ## Contributing 383 | 384 | Contributions are always encouraged and welcome! For the process of accepting changes, we use 385 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines]. 386 | 387 | ## Makefile Targets 388 | 389 | This repository comes with a handy [Makefile]. 390 | Run `make help` to see details on each available target. 391 | 392 | ## License 393 | 394 | [![license][badge-license]][apache20] 395 | 396 | This module is licensed under the Apache License Version 2.0, January 2004. 397 | Please see [LICENSE] for full details. 398 | 399 | Copyright © 2020-2022 [Mineiros GmbH][homepage] 400 | 401 | 402 | 403 | 404 | [homepage]: https://mineiros.io/?ref=terraform-aws-iam-role 405 | [hello@mineiros.io]: mailto:hello@mineiros.io 406 | [badge-build]: https://github.com/mineiros-io/terraform-aws-iam-role/workflows/CI/CD%20Pipeline/badge.svg 407 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-iam-role.svg?label=latest&sort=semver 408 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 409 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 410 | [badge-tf-aws]: https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform 411 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 412 | [build-status]: https://github.com/mineiros-io/terraform-aws-iam-role/actions 413 | [releases-github]: https://github.com/mineiros-io/terraform-aws-iam-role/releases 414 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 415 | [releases-aws-provider]: https://github.com/terraform-providers/terraform-provider-aws/releases 416 | [apache20]: https://opensource.org/licenses/Apache-2.0 417 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 418 | [Terraform]: https://www.terraform.io 419 | [AWS]: https://aws.amazon.com/ 420 | [Semantic Versioning (SemVer)]: https://semver.org/ 421 | [examples/example/main.tf]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples/example/main.tf 422 | [variables.tf]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/variables.tf 423 | [examples/]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/examples 424 | [Issues]: https://github.com/mineiros-io/terraform-aws-iam-role/issues 425 | [LICENSE]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/LICENSE 426 | [Makefile]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/Makefile 427 | [Pull Requests]: https://github.com/mineiros-io/terraform-aws-iam-role/pulls 428 | [Contribution Guidelines]: https://github.com/mineiros-io/terraform-aws-iam-role/blob/master/CONTRIBUTING.md 429 | -------------------------------------------------------------------------------- /README.tfdoc.hcl: -------------------------------------------------------------------------------- 1 | header { 2 | image = "https://raw.githubusercontent.com/mineiros-io/brand/3bffd30e8bdbbde32c143e2650b2faa55f1df3ea/mineiros-primary-logo.svg" 3 | url = "https://mineiros.io/?ref=terraform-aws-iam-role" 4 | 5 | badge "build" { 6 | image = "https://github.com/mineiros-io/terraform-aws-iam-role/workflows/CI/CD%20Pipeline/badge.svg" 7 | url = "https://github.com/mineiros-io/terraform-aws-iam-role/actions" 8 | text = "Build Status" 9 | } 10 | 11 | badge "semver" { 12 | image = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-iam-role.svg?label=latest&sort=semver" 13 | url = "https://github.com/mineiros-io/terraform-aws-iam-role/releases" 14 | text = "GitHub tag (latest SemVer)" 15 | } 16 | 17 | badge "terraform" { 18 | image = "https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform" 19 | url = "https://github.com/hashicorp/terraform/releases" 20 | text = "Terraform Version" 21 | } 22 | 23 | badge "tf-aws-provider" { 24 | image = "https://img.shields.io/badge/AWS-3%20and%202.0+-F8991D.svg?logo=terraform" 25 | url = "https://github.com/terraform-providers/terraform-provider-aws/releases" 26 | text = "AWS Provider Version" 27 | } 28 | 29 | badge "slack" { 30 | image = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack" 31 | url = "https://mineiros.io/slack" 32 | text = "Join Slack" 33 | } 34 | } 35 | 36 | section { 37 | title = "terraform-aws-iam-role" 38 | toc = true 39 | content = <<-END 40 | A [Terraform](https://www.terraform.io) base module for creating and managing 41 | [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) 42 | on [Amazon Web Services (AWS)](https://aws.amazon.com/). 43 | 44 | ***This module supports Terraform v1.x, v0.15, v0.14, v0.13 as well as v0.12.20 and above 45 | and is compatible with the terraform AWS provider v3 as well as v2.0 and above.*** 46 | END 47 | 48 | section { 49 | title = "Module Features" 50 | content = <<-END 51 | In contrast to the plain `aws_iam_role` resource this module simplifies adding IAM Policies to the role. 52 | 53 | - **Standard Module Features**: 54 | Create an IAM role. 55 | 56 | - **Extended Module Features**: 57 | Create an inline IAM policy, Attach custom or AWS managed policies. Create an IAM instance profile. 58 | END 59 | } 60 | 61 | section { 62 | title = "Getting Started" 63 | content = <<-END 64 | Basic usage for granting an AWS Account with Account ID `123456789012` access to assume a role that grants 65 | full access to AWS Simple Storage Service (S3) 66 | 67 | ```hcl 68 | module "role-s3-full-access" { 69 | source = "mineiros-io/iam-role/aws" 70 | version = "~> 0.6.0" 71 | 72 | name = "S3FullAccess" 73 | 74 | assume_role_principals = [ 75 | { 76 | type = "AWS" 77 | identifiers = ["arn:aws:iam::123456789012:root"] 78 | } 79 | ] 80 | 81 | policy_statements = [ 82 | { 83 | sid = "FullS3Access" 84 | 85 | effect = "Allow" 86 | actions = ["s3:*"] 87 | resources = ["*"] 88 | } 89 | ] 90 | } 91 | ``` 92 | END 93 | } 94 | 95 | section { 96 | title = "Module Argument Reference" 97 | content = <<-END 98 | See [variables.tf] and [examples/] for details and use-cases. 99 | END 100 | 101 | section { 102 | title = "Module Configuration" 103 | 104 | variable "module_enabled" { 105 | type = bool 106 | default = true 107 | description = <<-END 108 | Specifies whether resources in the module will be created. 109 | END 110 | } 111 | 112 | variable "module_tags" { 113 | type = map(string) 114 | default = {} 115 | description = <<-END 116 | A map of tags that will be applied to all created resources that accept tags. Tags defined with 'module_tags' can be overwritten by resource-specific tags. 117 | END 118 | } 119 | 120 | variable "module_depends_on" { 121 | type = list(any) 122 | description = <<-END 123 | A list of dependencies. Any object can be assigned to this list to define a hidden external dependency. 124 | END 125 | } 126 | } 127 | 128 | section { 129 | title = "Top-level Arguments" 130 | 131 | section { 132 | title = "Main Resource Configuration" 133 | 134 | variable "name" { 135 | type = string 136 | description = <<-END 137 | The name of the role. 138 | Invalid characters will be replaced with dashes. 139 | If omitted, Terraform will assign a random, unique name. 140 | Forces new resource. 141 | END 142 | } 143 | 144 | variable "name_prefix" { 145 | type = string 146 | description = <<-END 147 | If omitted, Terraform will assign a random, unique name. 148 | Invalid characters will be replaced with dashes. 149 | Creates a unique name beginning with the specified prefix. 150 | Conflicts with name. 151 | Forces new resource. 152 | END 153 | } 154 | 155 | variable "assume_role_policy" { 156 | required = true 157 | type = string 158 | description = <<-END 159 | A JSON String representing the policy that grants an entity permission to assume the role. 160 | *(only required if `assume_role_principals` is not set)* 161 | END 162 | readme_example = <<-END 163 | assume_role_policy = <