├── .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 | [](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/linter.yml)
30 | [](https://github.com/terraform-module/terraform-aws-github-oidc-provider/actions/workflows/release.draft.yml)
31 |
32 | [](https://github.com/terraform-module/terraform-aws-github-oidc-provider)
33 | 
34 | 
35 | 
36 | 
37 | [](https://github.com/terraform-module/terraform-aws-github-oidc-provider)
38 | [](https://github.com/terraform-module/terraform-aws-github-oidc-provider)
39 | 
40 | 
41 | 
42 | 
43 | [](https://GitHub.com/terraform-module/terraform-aws-github-oidc-provider/graphs/commit-activity)
44 | [](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 | [](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 |
--------------------------------------------------------------------------------