├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── Feature_request.md │ └── Support_question.md ├── release-drafter.yml ├── settings.yml ├── stale.yml └── workflows │ ├── linter.yml │ ├── oidc.example.yml │ ├── pr-title.yml │ └── release.draft.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .tflint.hcl ├── LICENSE ├── Makefile ├── README.md ├── docs └── hot-to-eks.md ├── examples ├── README.md └── basic │ ├── README.md │ └── main.tf ├── main.tf ├── outputs.tf ├── renovate.json ├── variables.tf └── versions.tf /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | charset = utf-8 4 | indent_style = space 5 | indent_size = 2 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.py] 10 | indent_style = space 11 | indent_size = 4 12 | max_line_length = 140 13 | 14 | [*.sh] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [Makefile] 19 | indent_style = tab 20 | 21 | [*.{tf,tfvars}] 22 | indent_size = 2 23 | indent_style = space 24 | 25 | [*.{yml,yaml}] 26 | indent_style = space 27 | indent_size = 2 28 | 29 | [*.feature] 30 | indent_size = 2 31 | 32 | [*.{json,tpl}] 33 | indent_style = space 34 | indent_size = 2 35 | 36 | [Jenkinsfile] 37 | indent_size = 2 38 | indent_style = space 39 | 40 | [*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] 41 | indent_size = 2 42 | 43 | [{*.scala,*.sbt}] 44 | indent_size = 2 45 | max_line_length = 80 46 | 47 | [{*.hcl,*.conf}] 48 | indent_size = 2 49 | max_line_length = 100 50 | 51 | # JS 52 | [*.js, **/*.js] 53 | indent_size = 4 54 | indent_style = space 55 | 56 | [{package.json}] 57 | indent_size = 2 58 | indent_style = space 59 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: If something isn't working as expected 🤔. 4 | 5 | --- 6 | 7 | ## Bug Report 8 | 9 | ### Steps to Reproduce: 10 | 1. ...step 1 description... 11 | 2. ...step 2 description... 12 | 3. ...step 3 description... 13 | 14 | ### Expected Result: 15 | ...description of what you expected to see... 16 | 17 | ### Actual Result: 18 | ...what actually happened, including full exceptions (please include the entire stack trace, including "caused by" entries), log entries, screen shots etc. where appropriate... 19 | 20 | ### Environment: 21 | ...version and build of the project, OS and runtime versions, virtualised environment (if any), etc. ... 22 | 23 | ### Additional Context: 24 | ...add any other context about the problem here. If applicable, add screenshots to help explain... -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: I have a suggestion (and may want to implement it 🙂)! 4 | 5 | --- 6 | 7 | ## Feature Request 8 | 9 | ### Description of Problem: 10 | ...what *problem* are you trying to solve that the project doesn't currently solve? 11 | 12 | ...please resist the temptation to describe your request in terms of a solution. Job Story form ("When [triggering condition], I want to [motivation/goal], so I can [outcome].") can help ensure you're expressing a problem statement. 13 | 14 | ### Potential Solutions: 15 | ...clearly and concisely describe what you want to happen. Add any considered drawbacks. 16 | 17 | ... if you've considered alternatives, clearly and concisely describe those too. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Support_question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🤗 Support Question 3 | about: If you have a question about configuration, usage, etc. 💬 4 | 5 | --- 6 | 7 | ## Support Question 8 | 9 | ...ask your question here. 10 | 11 | ...be sure to search existing issues since someone might have already asked something similar. -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Configuration for Release Drafter: https://github.com/toolmantim/release-drafter 2 | _extends: .github 3 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # These settings are synced to GitHub by https://probot.github.io/apps/settings/ 2 | _extends: .github 3 | 4 | repository: 5 | # See https://developer.github.com/v3/repos/#edit for all available settings. 6 | name: terraform-aws-github-oidc-provider 7 | description: "ℹ️ Terraform GitHub OIDC module." 8 | homepage: https://ivankatliarchuk.github.io 9 | topics: ivank, terraform, terraform-module, github, oidc 10 | private: false 11 | has_issues: true 12 | has_projects: false 13 | has_wiki: false 14 | has_downloads: false 15 | has_pages: true 16 | is_template: true 17 | default_branch: master 18 | allow_squash_merge: true 19 | allow_merge_commit: true 20 | allow_rebase_merge: true 21 | delete_branch_on_merge: true 22 | enable_automated_security_fixes: true 23 | enable_vulnerability_alerts: false 24 | 25 | branches: 26 | - name: master 27 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for https://github.com/probot/stale 2 | _extends: .github 3 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: linter 3 | # This workflow is triggered on pushes to the repository. 4 | on: 5 | push: 6 | pull_request: 7 | branches: 8 | - main 9 | - master 10 | workflow_dispatch: 11 | 12 | jobs: 13 | terraform-validate: 14 | name: code format 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@master 18 | # https://github.com/hashicorp/setup-terraform 19 | - uses: hashicorp/setup-terraform@v2 20 | 21 | - name: Cache terraform folder 22 | uses: actions/cache@v3 23 | with: 24 | path: ./.terraform 25 | key: terraform 26 | 27 | - name: terraform fmt 28 | run: terraform fmt -check -recursive -diff 29 | continue-on-error: true 30 | 31 | - name: terraform init 32 | run: terraform init 33 | 34 | - name: terraform validate 35 | run: terraform validate 36 | 37 | tflint: 38 | name: "tflint" 39 | runs-on: ubuntu-latest 40 | steps: 41 | - uses: actions/checkout@v3 42 | - uses: actions/cache@v3 43 | name: Cache tflint plugin dir 44 | with: 45 | path: ~/.tflint.d/plugins 46 | key: ${{ matrix.os }}-tflint-${{ hashFiles('.tflint.hcl') }} 47 | - uses: terraform-linters/setup-tflint@v3 48 | name: setup tflint 49 | - name: init tflint 50 | run: tflint --init --config .tflint.hcl 51 | - name: run tflint 52 | run: tflint -f compact --config .tflint.hcl 53 | -------------------------------------------------------------------------------- /.github/workflows/oidc.example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: oidc.example 3 | 4 | on: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | caller-identity: 9 | name: check caller identity 10 | # These permissions are needed to interact with GitHub's OIDC Token endpoint. 11 | permissions: 12 | contents: read 13 | id-token: write 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | 18 | - name: Configure AWS credentials 19 | uses: aws-actions/configure-aws-credentials@v2.2.0 20 | with: 21 | aws-region: ${{ secrets.AWS_REGION }} 22 | role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} # github_oidc_role 23 | 24 | - run: aws sts get-caller-identity 25 | 26 | - run: aws s3 ls 27 | -------------------------------------------------------------------------------- /.github/workflows/pr-title.yml: -------------------------------------------------------------------------------- 1 | name: 'validate-pr-title' 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | name: validate pr title 13 | runs-on: ubuntu-latest 14 | steps: 15 | # Please look up the latest version from 16 | # https://github.com/amannn/action-semantic-pull-request/releases 17 | - uses: amannn/action-semantic-pull-request@v5.2.0 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | with: 21 | # Configure which types are allowed. 22 | # Default: https://github.com/commitizen/conventional-commit-types 23 | types: | 24 | fix 25 | feat 26 | docs 27 | ci 28 | chore 29 | # Configure that a scope must always be provided. 30 | requireScope: false 31 | # If `subjectPattern` is configured, you can use this property to override 32 | # the default error message that is shown when the pattern doesn't match. 33 | # The variables `subject` and `title` can be used within the message. 34 | subjectPatternError: | 35 | The subject "{subject}" found in the pull request title "{title}" 36 | didn't match the configured pattern. Please ensure that the subject 37 | starts with an uppercase character. 38 | # For work-in-progress PRs you can typically use draft pull requests 39 | # from Github. However, private repositories on the free plan don't have 40 | # this option and therefore this action allows you to opt-in to using the 41 | # special "[WIP]" prefix to indicate this state. This will avoid the 42 | # validation of the PR title and the pull request checks remain pending. 43 | # Note that a second check will be reported if this is enabled. 44 | wip: true 45 | # When using "Squash and merge" on a PR with only one commit, GitHub 46 | # will suggest using that commit message instead of the PR title for the 47 | # merge commit, and it's easy to commit this by mistake. Enable this option 48 | # to also validate the commit message for one commit PRs. 49 | validateSingleCommit: false 50 | -------------------------------------------------------------------------------- /.github/workflows/release.draft.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: release.draft 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | workflow_dispatch: 9 | inputs: 10 | prerelease: 11 | description: Is this a pre-release 12 | required: true 13 | default: true 14 | type: boolean 15 | publish: 16 | description: Publish release 17 | required: false 18 | default: false 19 | type: boolean 20 | bump: 21 | description: 'Bumping (#major, #minor or #patch)' 22 | required: false 23 | default: patch 24 | type: choice 25 | options: 26 | - 'patch' 27 | - 'minor' 28 | - 'major' 29 | 30 | jobs: 31 | draft-a-release: 32 | runs-on: ubuntu-latest 33 | steps: 34 | 35 | - uses: actions/checkout@v3 36 | 37 | - name: check next version 38 | uses: anothrNick/github-tag-action@1.62.0 39 | id: tag 40 | env: 41 | DRY_RUN: true 42 | WITH_V: true 43 | DEFAULT_BUMP: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.bump || 'patch' }} 44 | 45 | - name: release-draft 46 | uses: release-drafter/release-drafter@v5.23.0 47 | if: "!contains(github.event.head_commit.message, 'skip')" 48 | id: release 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | publish: ${{ github.event.inputs.publish }} 53 | prerelease: ${{ github.event.inputs.prerelease }} 54 | tag: ${{ steps.tag.outputs.new_tag }} 55 | 56 | - name: check-version 57 | run: | 58 | echo "release it: ${{ github.event.inputs.prerelease }}" 59 | echo "out: ${{ steps.release.name }}" 60 | echo "tag: ${{ steps.release.outputs.tag_name }}" 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # .tfvars files 9 | *.tfvars 10 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v5.0.0 4 | hooks: 5 | - id: check-added-large-files 6 | args: ['--maxkb=500'] 7 | - id: check-executables-have-shebangs 8 | - id: pretty-format-json 9 | args: ['--autofix', '--no-sort-keys', '--indent=2'] 10 | - id: check-byte-order-marker 11 | - id: check-case-conflict 12 | - id: check-executables-have-shebangs 13 | - id: check-merge-conflict 14 | - id: check-symlinks 15 | - id: detect-private-key 16 | - id: check-merge-conflict 17 | - id: detect-aws-credentials 18 | args: ['--allow-missing-credentials'] 19 | - repo: https://github.com/antonbabenko/pre-commit-terraform 20 | rev: v1.99.1 21 | hooks: 22 | - id: terraform_fmt 23 | - id: terraform_docs 24 | - id: terraform_tflint 25 | -------------------------------------------------------------------------------- /.tflint.hcl: -------------------------------------------------------------------------------- 1 | config { 2 | module = false 3 | } 4 | 5 | plugin "aws" { 6 | enabled = true 7 | version = "0.22.1" 8 | source = "github.com/terraform-linters/tflint-ruleset-aws" 9 | } 10 | 11 | rule "terraform_comment_syntax" { 12 | enabled = true 13 | } 14 | 15 | rule "terraform_deprecated_index" { 16 | enabled = true 17 | } 18 | 19 | rule "terraform_deprecated_interpolation" { 20 | enabled = true 21 | } 22 | 23 | rule "terraform_documented_outputs" { 24 | enabled = true 25 | } 26 | 27 | rule "terraform_documented_variables" { 28 | enabled = true 29 | } 30 | 31 | rule "terraform_module_pinned_source" { 32 | enabled = true 33 | style = "flexible" 34 | } 35 | 36 | rule "terraform_module_version" { 37 | enabled = true 38 | } 39 | 40 | rule "terraform_naming_convention" { 41 | enabled = true 42 | format = "snake_case" 43 | } 44 | 45 | rule "terraform_standard_module_structure" { 46 | enabled = true 47 | } 48 | 49 | rule "terraform_typed_variables" { 50 | enabled = true 51 | } 52 | 53 | rule "terraform_unused_declarations" { 54 | enabled = true 55 | } 56 | 57 | rule "terraform_unused_required_providers" { 58 | enabled = true 59 | } 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ivan Katliarchuk, https://github.com/ivankatliarchuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/bash 2 | .ONESHELL: 3 | .SHELLFLAGS := -eu -o pipefail -c 4 | MAKEFLAGS += --warn-undefined-variables 5 | MAKEFLAGS += --no-builtin-rules 6 | 7 | .PHONY: pre-commit changelog release 8 | 9 | # -include $(shell curl -sSL -o .build-harness "https://git.io/build-harness"; echo .build-harness) 10 | 11 | help/local: 12 | @cat Makefile* | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 13 | 14 | help: help/local 15 | 16 | hooks: ## Commit hooks setup 17 | @pre-commit install 18 | @pre-commit gc 19 | 20 | validate: ## Validate with pre-commit hooks 21 | @pre-commit run --all-files 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Github OIDC Provider Terraform Module 2 | 3 | This module allows you to create a GitHub OIDC provider and the associated IAM roles, that will help Github Actions to securely authenticate against the AWS API using an IAM role. 4 | 5 | We recommend using GitHub's OIDC provider to get short-lived credentials needed for your actions. Specifying role-to-assume without providing an aws-access-key-id or a web-identity-token-file will signal to the action that you wish to use the OIDC provider. The default session duration is 1 hour when using the OIDC provider to directly assume an IAM Role. The default session duration is 6 hours when using an IAM User to assume an IAM Role (by providing an aws-access-key-id, aws-secret-access-key, and a role-to-assume) . If you would like to adjust this you can pass a duration to role-duration-seconds, but the duration cannot exceed the maximum that was defined when the IAM Role was created. The default session name is GitHubActions, and you can modify it by specifying the desired name in role-session-name. 6 | 7 | - [How to Hook EKS](docs/hot-to-eks.md) 8 | 9 | ## Features 10 | 11 | 1. Create an AWS OIDC provider for GitHub Actions 12 | 1. Create one or more IAM role that can be assumed by GitHub Actions 13 | 1. IAM roles can be scoped to : 14 | * One or more GitHub organisations 15 | * One or more GitHub repository 16 | * One or more branches in a repository 17 | 18 | 19 | | Feature | Status | 20 | |--------------------------------------------------------------------------------------------------------|--------| 21 | | Create a role for all repositories in a specific Github organisation | ✅ | 22 | | Create a role specific to a repository for a specific organisation | ✅ | 23 | | Create a role specific to a branch in a repository | ✅ | 24 | | Create a role for multiple organisations/repositories/branches | ✅ | 25 | | Create a role for organisations/repositories/branches selected by wildcard (e.g. `feature/*` branches) | ✅ | 26 | 27 | --- 28 | 29 | [![linter](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/linter.yml/badge.svg)](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/linter.yml) 30 | [![release.draft](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/release.draft.yml/badge.svg)](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/release.draft.yml) 31 | 32 | [![](https://img.shields.io/github/license/terraform-module/terraform-aws-github-oidc-provider)](https://github.com/terraform-module/terraform-aws-github-oidc-provider) 33 | ![](https://img.shields.io/github/v/tag/terraform-module/terraform-aws-github-oidc-provider) 34 | ![](https://img.shields.io/issues/github/terraform-module/terraform-aws-github-oidc-provider) 35 | ![](https://img.shields.io/github/issues/terraform-module/terraform-aws-github-oidc-provider) 36 | ![](https://img.shields.io/github/issues-closed/terraform-module/terraform-aws-github-oidc-provider) 37 | [![](https://img.shields.io/github/languages/code-size/terraform-module/terraform-aws-github-oidc-provider)](https://github.com/terraform-module/terraform-aws-github-oidc-provider) 38 | [![](https://img.shields.io/github/repo-size/terraform-module/terraform-aws-github-oidc-provider)](https://github.com/terraform-module/terraform-aws-github-oidc-provider) 39 | ![](https://img.shields.io/github/languages/top/terraform-module/terraform-aws-github-oidc-provider?color=green&logo=terraform&logoColor=blue) 40 | ![](https://img.shields.io/github/commit-activity/m/terraform-module/terraform-aws-github-oidc-provider) 41 | ![](https://img.shields.io/github/contributors/terraform-module/terraform-aws-github-oidc-provider) 42 | ![](https://img.shields.io/github/last-commit/terraform-module/terraform-aws-github-oidc-provider) 43 | [![Maintenance](https://img.shields.io/badge/Maintenu%3F-oui-green.svg)](https://GitHub.com/terraform-module/terraform-aws-github-oidc-provider/graphs/commit-activity) 44 | [![GitHub forks](https://img.shields.io/github/forks/terraform-module/terraform-aws-github-oidc-provider.svg?style=social&label=Fork)](https://github.com/terraform-module/terraform-aws-github-oidc-provider) 45 | 46 | --- 47 | 48 | ## Documentation 49 | 50 | - [TFLint Rules](https://github.com/terraform-linters/tflint/tree/master/docs/rules) 51 | 52 | ## Usage example 53 | 54 | IMPORTANT: The master branch is used in source just as an example. In your code, do not pin to master because there may be breaking changes between releases. Instead pin to the release tag (e.g. ?ref=tags/x.y.z) of one of our [latest releases](https://github.com/terraform-module/terraform-aws-github-oidc-provider/releases). 55 | 56 | ```hcl 57 | module "github-oidc" { 58 | source = "terraform-module/github-oidc-provider/aws" 59 | version = "~> 1" 60 | 61 | create_oidc_provider = true 62 | create_oidc_role = true 63 | 64 | repositories = ["terraform-module/module-blueprint"] 65 | oidc_role_attach_policies = ["arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"] 66 | } 67 | ``` 68 | 69 | ## Examples 70 | 71 | See `examples` directory for working examples to reference 72 | 73 | - [Examples Dir](https://github.com/terraform-module/module-blueprint/tree/master/examples/) 74 | 75 | ## Assumptions 76 | 77 | ## Available features 78 | 79 | 80 | # AWS Github OIDC Provider Terraform Module 81 | 82 | ## Purpose 83 | This module allows you to create a Github OIDC provider for your AWS account, that will help Github Actions to securely authenticate against the AWS API using an IAM role 84 | 85 | ## Requirements 86 | 87 | | Name | Version | 88 | |------|---------| 89 | | [terraform](#requirement\_terraform) | >= 1 | 90 | 91 | ## Providers 92 | 93 | | Name | Version | 94 | |------|---------| 95 | | [aws](#provider\_aws) | n/a | 96 | 97 | ## Modules 98 | 99 | No modules. 100 | 101 | ## Resources 102 | 103 | | Name | Type | 104 | |------|------| 105 | | [aws_iam_openid_connect_provider.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource | 106 | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 107 | | [aws_iam_role_policy_attachment.attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | 108 | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 109 | 110 | ## Inputs 111 | 112 | | Name | Description | Type | Default | Required | 113 | |------|-------------|------|---------|:--------:| 114 | | [create\_oidc\_provider](#input\_create\_oidc\_provider) | Whether or not to create the associated oidc provider. If false, variable 'oidc\_provider\_arn' is required | `bool` | `true` | no | 115 | | [oidc\_provider\_arn](#input\_oidc\_provider\_arn) | ARN of the OIDC provider to use. Required if 'create_oidc_provider' is false | `string` | `null` | no | 116 | | [create\_oidc\_role](#input\_create\_oidc\_role) | Whether or not to create the OIDC attached role | `bool` | `true` | no | 117 | | [github\_thumbprint](#input\_github\_thumbprint) | GitHub OpenID TLS certificate thumbprint. | `string` | `"6938fd4d98bab03faadb97b34396831e3780aea1"` | no | 118 | | [max\_session\_duration](#input\_max\_session\_duration) | Maximum session duration in seconds. | `number` | `3600` | no | 119 | | [oidc\_role\_attach\_policies](#input\_oidc\_role\_attach\_policies) | Attach policies to OIDC role. | `list(string)` | `[]` | no | 120 | | [repositories](#input\_repositories) | List of GitHub organization/repository names authorized to assume the role. | `list(string)` | `[]` | no | 121 | | [role\_description](#input\_role\_description) | (Optional) Description of the role. | `string` | `"Role assumed by the GitHub OIDC provider."` | no | 122 | | [role\_name](#input\_role\_name) | (Optional, Forces new resource) Friendly name of the role. | `string` | `"github-oidc-provider-aws"` | no | 123 | | [tags](#input\_tags) | A mapping of tags to assign to all resources | `map(string)` | `{}` | no | 124 | 125 | ## Outputs 126 | 127 | | Name | Description | 128 | |------|-------------| 129 | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | OIDC provider ARN | 130 | | [oidc\_role](#output\_oidc\_role) | CICD GitHub role. | 131 | 132 | 133 | 134 | ### :memo: Guidelines 135 | 136 | - :memo: Use a succinct title and description. 137 | - :bug: Bugs & feature requests can be be opened 138 | - :signal_strength: Support questions are better asked on [Stack Overflow](https://stackoverflow.com/) 139 | - :blush: Be nice, civil and polite ([as always](http://contributor-covenant.org/version/1/4/)). 140 | 141 | ## License 142 | 143 | Copyright 2022 Ivan Katliarhcuk 144 | 145 | MIT Licensed. See [LICENSE](./LICENSE) for full details. 146 | 147 | ## How to Contribute 148 | 149 | Submit a pull request 150 | 151 | # Authors 152 | 153 | Currently maintained by [Ivan Katliarchuk](https://github.com/ivankatliarchuk) and these [awesome contributors](https://github.com/terraform-module/terraform-aws-github-oidc-provider/graphs/contributors). 154 | 155 | [![ForTheBadge uses-git](http://ForTheBadge.com/images/badges/uses-git.svg)](https://GitHub.com/) 156 | 157 | ## Terraform Registry 158 | 159 | - [Module](https://registry.terraform.io/modules/terraform-module/github-oidc-provider/aws/latest) 160 | 161 | ## Resources 162 | 163 | - [AWS: create oidc](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) 164 | - [Github: configure OIDC aws](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) 165 | - [Github: OIDC cloud](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-cloud-providers) 166 | - [AWS creds github action](https://github.com/aws-actions/configure-aws-credentials) 167 | - [AWS Docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) 168 | - [Github OIDC](https://www.cloudquery.io/blog/keyless-access-to-aws-in-github-actions-with-oidc) 169 | - [Terraform: oidc complex](https://github.com/SamuelBagattin/terraform-aws-github-oidc-provider) 170 | - [Terraform: oidc simple](https://github.com/unfunco/terraform-aws-oidc-github) 171 | - [Terraform: oidc](https://github.com/philips-labs/terraform-aws-github-oidc) 172 | 173 | ## Clone Me 174 | 175 | [**Create a repository using this template →**][template.generate] 176 | 177 | 178 | [template.generate]: https://github.com/terraform-module/terraform-aws-github-oidc-provider/generate 179 | -------------------------------------------------------------------------------- /docs/hot-to-eks.md: -------------------------------------------------------------------------------- 1 | # How to Connect to EKS 2 | 3 | - [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) 4 | 5 | Assumptions 6 | 7 | - The AWS IAM role is created `arn:aws:iam::XXXX:role/github-oidc-provider-aws` 8 | - With `Statement` to be set, as the action should be able to pull a kubeconfig 9 | 10 | ```json 11 | "Statement": [ 12 | { 13 | "Action": "eks:DescribeCluster", 14 | "Effect": "Allow", 15 | "Resource": [ 16 | "arn:aws:eks:REGION:XXXXX:cluster/" 17 | ], 18 | "Sid": "AwsEksGetDescribeToPullKubeConfig" 19 | }, 20 | ] 21 | ``` 22 | 23 | - As well as `Trust relationships` looks as belov 24 | 25 | ```json 26 | { 27 | "Version": "2012-10-17", 28 | "Statement": [ 29 | { 30 | "Sid": "", 31 | "Effect": "Allow", 32 | "Principal": { 33 | "Federated": "arn:aws:iam::XXX:oidc-provider/token.actions.githubusercontent.com" 34 | }, 35 | "Action": "sts:AssumeRoleWithWebIdentity", 36 | "Condition": { 37 | "StringLike": { 38 | "token.actions.githubusercontent.com:sub": "repo:/:ref:refs/heads/main" 39 | } 40 | } 41 | } 42 | ] 43 | } 44 | ``` 45 | 46 | - Next step is to update `kubectl edit configmap aws-auth -n kube-system`. Add following line 47 | 48 | ```yml 49 | apiVersion: v1 50 | data: 51 | mapRoles: | 52 | - rolearn: arn:aws:iam::XXXXX:role/github-oidc-provider-aws 53 | username: github-action 54 | groups: 55 | - support:github-action 56 | ``` 57 | 58 | Where `support:github-action` is a role with 59 | 60 | Example `app-access` role for namespace `app`. CMD `kubectl get role app-access -o yaml` 61 | 62 | ```yml 63 | apiVersion: rbac.authorization.k8s.io/v1 64 | kind: Role 65 | metadata: 66 | labels: 67 | description: namespace-access 68 | name: app-access 69 | namespace: app 70 | rules: 71 | - apiGroups: 72 | - "" 73 | resources: 74 | - '*' 75 | verbs: 76 | - '*' 77 | - apiGroups: 78 | - extensions 79 | resources: 80 | - '*' 81 | verbs: 82 | - '*' 83 | ``` 84 | 85 | And role binding is `managed:app-access` . Command `kubectl get rolebinding managed:app-access -o yaml` 86 | 87 | ```yml 88 | apiVersion: rbac.authorization.k8s.io/v1 89 | kind: RoleBinding 90 | metadata: 91 | creationTimestamp: "2022-04-28T08:42:40Z" 92 | name: managed:app-access 93 | namespace: app 94 | resourceVersion: "6634" 95 | uid: 4bc413a0-8984-49bf-9530-0b03bd2a6849 96 | roleRef: 97 | apiGroup: rbac.authorization.k8s.io 98 | kind: ClusterRole 99 | name: admin 100 | subjects: 101 | - apiGroup: rbac.authorization.k8s.io 102 | kind: Group 103 | name: support:operator 104 | namespace: default 105 | ``` 106 | 107 | **Notes** 108 | 109 | > It seems that you have no other ways in Kubernetes to do it. There is no object like Group that you can "get" inside the Kubernetes configuration. Group information in Kubernetes is currently provided by the Authenticator modules and usually it's just string in the user property. 110 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Please note - the examples provided serve two primary means: 4 | 5 | 1. Show users working examples of the various ways in which the module can be configured and features supported 6 | 1. A means of testing/validating module changes 7 | 8 | Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc. 9 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | Configuration in this directory creates a MySQL Aurora cluster. 4 | 5 | ## Usage 6 | 7 | To run this example you need to execute: 8 | 9 | ```bash 10 | $ terraform init 11 | $ terraform plan 12 | $ terraform apply 13 | ``` 14 | 15 | Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. 16 | 17 | 18 | ## Requirements 19 | 20 | No requirements. 21 | 22 | ## Providers 23 | 24 | No providers. 25 | 26 | ## Modules 27 | 28 | | Name | Source | Version | 29 | |------|--------|---------| 30 | | [github-oidc](#module\_github-oidc) | ../.. | n/a | 31 | 32 | ## Resources 33 | 34 | No resources. 35 | 36 | ## Inputs 37 | 38 | No inputs. 39 | 40 | ## Outputs 41 | 42 | | Name | Description | 43 | |------|-------------| 44 | | [github\_oidc\_role](#output\_github\_oidc\_role) | CICD GitHub role. | 45 | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | OIDC provider ARN | 46 | 47 | -------------------------------------------------------------------------------- /examples/basic/main.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Resources 3 | ################################################################################ 4 | module "github-oidc" { 5 | source = "../.." 6 | 7 | create_oidc_provider = true 8 | create_oidc_role = true 9 | 10 | repositories = ["terraform-module/terraform-aws-github-oidc-provider:ref:refs/heads/main"] 11 | oidc_role_attach_policies = ["arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"] 12 | } 13 | ################################################################################ 14 | # OUTPUTS 15 | ################################################################################ 16 | output "oidc_provider_arn" { 17 | description = "OIDC provider ARN" 18 | value = module.github-oidc.oidc_provider_arn 19 | } 20 | 21 | output "github_oidc_role" { 22 | description = "CICD GitHub role." 23 | value = module.github-oidc.oidc_role 24 | } 25 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * # AWS Github OIDC Provider Terraform Module 3 | * 4 | * ## Purpose 5 | * This module allows you to create a Github OIDC provider for your AWS account, that will help Github Actions to securely authenticate against the AWS API using an IAM role 6 | * 7 | */ 8 | resource "aws_iam_openid_connect_provider" "this" { 9 | count = var.create_oidc_provider ? 1 : 0 10 | client_id_list = [ 11 | "sts.amazonaws.com", 12 | ] 13 | thumbprint_list = [var.github_thumbprint] 14 | url = "https://token.actions.githubusercontent.com" 15 | } 16 | 17 | resource "aws_iam_role" "this" { 18 | count = var.create_oidc_role ? 1 : 0 19 | name = var.role_name 20 | description = var.role_description 21 | max_session_duration = var.max_session_duration 22 | assume_role_policy = join("", data.aws_iam_policy_document.this[0].*.json) 23 | tags = var.tags 24 | # path = var.iam_role_path 25 | # permissions_boundary = var.iam_role_permissions_boundary 26 | depends_on = [aws_iam_openid_connect_provider.this] 27 | } 28 | 29 | resource "aws_iam_role_policy_attachment" "attach" { 30 | count = var.create_oidc_role ? length(var.oidc_role_attach_policies) : 0 31 | 32 | policy_arn = var.oidc_role_attach_policies[count.index] 33 | role = join("", aws_iam_role.this.*.name) 34 | 35 | depends_on = [aws_iam_role.this] 36 | } 37 | 38 | data "aws_iam_policy_document" "this" { 39 | count = var.create_oidc_role ? 1 : 0 40 | 41 | statement { 42 | actions = ["sts:AssumeRoleWithWebIdentity"] 43 | effect = "Allow" 44 | 45 | condition { 46 | test = "StringLike" 47 | values = [ 48 | for repo in var.repositories : 49 | "repo:%{if length(regexall(":+", repo)) > 0}${repo}%{else}${repo}:*%{endif}" 50 | ] 51 | variable = "token.actions.githubusercontent.com:sub" 52 | } 53 | 54 | principals { 55 | identifiers = [try(aws_iam_openid_connect_provider.this[0].arn, var.oidc_provider_arn)] 56 | type = "Federated" 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "oidc_provider_arn" { 2 | description = "OIDC provider ARN" 3 | value = try(aws_iam_openid_connect_provider.this[0].arn, "") 4 | } 5 | 6 | output "oidc_role" { 7 | description = "CICD GitHub role." 8 | value = try(aws_iam_role.this[0].arn, "") 9 | } 10 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "create_oidc_provider" { 2 | description = "Whether or not to create the associated oidc provider. If false, variable 'oidc_provider_arn' is required" 3 | type = bool 4 | default = true 5 | } 6 | 7 | variable "oidc_provider_arn" { 8 | description = "ARN of the OIDC provider to use. Required if 'create_oidc_provider' is false" 9 | type = string 10 | default = null 11 | } 12 | 13 | variable "create_oidc_role" { 14 | description = "Whether or not to create the OIDC attached role" 15 | type = bool 16 | default = true 17 | } 18 | 19 | # Refer to the README for information on obtaining the thumbprint. 20 | # This is specified as a variable to allow it to be updated quickly if it is 21 | # unexpectedly changed by GitHub. 22 | # See: https://github.blog/changelog/2022-01-13-github-actions-update-on-oidc-based-deployments-to-aws/ 23 | variable "github_thumbprint" { 24 | description = "GitHub OpenID TLS certificate thumbprint." 25 | type = string 26 | default = "6938fd4d98bab03faadb97b34396831e3780aea1" 27 | } 28 | 29 | variable "repositories" { 30 | description = "List of GitHub organization/repository names authorized to assume the role." 31 | type = list(string) 32 | default = [] 33 | 34 | validation { 35 | # Ensures each element of github_repositories list matches the 36 | # organization/repository format used by GitHub. 37 | condition = length([ 38 | for repo in var.repositories : 1 39 | if length(regexall("^[A-Za-z0-9_.-]+?/([A-Za-z0-9_.:/-]+|\\*)$", repo)) > 0 40 | ]) == length(var.repositories) 41 | error_message = "Repositories must be specified in the organization/repository format." 42 | } 43 | } 44 | 45 | variable "max_session_duration" { 46 | description = "Maximum session duration in seconds." 47 | type = number 48 | default = 3600 49 | 50 | validation { 51 | condition = var.max_session_duration >= 3600 && var.max_session_duration <= 43200 52 | error_message = "Maximum session duration must be between 3600 and 43200 seconds." 53 | } 54 | } 55 | 56 | variable "oidc_role_attach_policies" { 57 | description = "Attach policies to OIDC role." 58 | type = list(string) 59 | default = [] 60 | } 61 | 62 | variable "tags" { 63 | description = "A mapping of tags to assign to all resources" 64 | type = map(string) 65 | default = {} 66 | } 67 | 68 | variable "role_name" { 69 | description = "(Optional, Forces new resource) Friendly name of the role." 70 | type = string 71 | default = "github-oidc-provider-aws" 72 | } 73 | 74 | variable "role_description" { 75 | description = "(Optional) Description of the role." 76 | type = string 77 | default = "Role assumed by the GitHub OIDC provider." 78 | } 79 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1" 3 | required_providers { 4 | aws = { 5 | source = "hashicorp/aws" 6 | } 7 | } 8 | } 9 | --------------------------------------------------------------------------------