-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Terraform module to setup OIDC for AWS and GitHub (#2)
* feat: Terraform module to setup OIDC for AWS and GitHub (initial version) * chore: update terraform validate workflow * chore: fix ci * chore: fix docs * chore: review comments * chore: review comments * chore: review comments * chore: editor config * chore: add vscode suggestions * refactor: removed managed variable * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md Co-authored-by: Scott Guymer <[email protected]>
- Loading branch information
1 parent
5f9713e
commit 6b44784
Showing
32 changed files
with
866 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[*] | ||
end_of_line = lf | ||
indent_style = space | ||
indent_size = 2 | ||
insert_final_newline = true | ||
|
||
[*.md] | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,59 @@ | ||
name: Terraform code check | ||
name: "Terraform checks" | ||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
paths-ignore: | ||
- "*.md" | ||
|
||
jobs: | ||
validate_module: | ||
name: Check module | ||
verify_module: | ||
name: Verify module | ||
strategy: | ||
matrix: | ||
terraform: [1.1.6] | ||
terraform: [1.1.6, "latest"] | ||
runs-on: ubuntu-latest | ||
container: | ||
image: hashicorp/terraform:${{ matrix.terraform }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- run: terraform init | ||
- run: terraform fmt --recursive -check=true | ||
- run: terraform validate | ||
- name: "Checkout" | ||
uses: actions/checkout@v2 | ||
- name: terraform init | ||
run: terraform init -get -backend=false -input=false | ||
- if: contains(matrix.terraform, '1.1.') | ||
name: check terraform formatting | ||
run: terraform fmt -recursive -check=true -write=false | ||
- if: contains(matrix.terraform, 'latest') # check formatting for the latest release but avoid failing the build | ||
name: check terraform formatting | ||
run: terraform fmt -recursive -check=true -write=false | ||
continue-on-error: true | ||
- name: validate terraform | ||
run: terraform validate | ||
|
||
validate_examples: | ||
name: Check examples | ||
verify_examples: | ||
name: Verify examples | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
terraform: [1.1.6] | ||
terraform: [1.1.6, "latest"] | ||
example: ["single-repo", "multi-repo"] | ||
defaults: | ||
run: | ||
working-directory: examples/${{ matrix.example }} | ||
runs-on: ubuntu-latest | ||
container: | ||
image: hashicorp/terraform:${{ matrix.terraform }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Validate Examples | ||
run: | | ||
for example in $(find examples -maxdepth 1 -mindepth 1 -type d); do | ||
cd $example | ||
terraform init | ||
terraform fmt --recursive -check=true | ||
terraform validate | ||
cd - | ||
done | ||
- name: terraform init | ||
run: terraform init -get -backend=false -input=false | ||
- if: contains(matrix.terraform, '1.1.') | ||
name: check terraform formatting | ||
run: terraform fmt -recursive -check=true -write=false | ||
- if: contains(matrix.terraform, 'latest') # check formatting for the latest release but avoid failing the build | ||
name: check terraform formatting | ||
run: terraform fmt -recursive -check=true -write=false | ||
continue-on-error: true | ||
- name: validate terraform | ||
run: terraform validate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
|
||
# Created by https://www.toptal.com/developers/gitignore/api/terraform | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=terraform | ||
|
||
### Terraform ### | ||
# Local .terraform directories | ||
**/.terraform/* | ||
|
||
# .tfstate files | ||
*.tfstate | ||
*.tfstate.* | ||
|
||
# Crash log files | ||
crash.log | ||
crash.*.log | ||
|
||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as | ||
# password, private keys, and other secrets. These should not be part of version | ||
# control as they are data points which are potentially sensitive and subject | ||
# to change depending on the environment. | ||
# | ||
*.tfvars | ||
|
||
# Ignore override files as they are usually used to override resources locally and so | ||
# are not checked in | ||
override.tf | ||
override.tf.json | ||
*_override.tf | ||
*_override.tf.json | ||
|
||
# Include override files you do wish to add to version control using negated pattern | ||
# !example_override.tf | ||
|
||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan | ||
# example: *tfplan* | ||
|
||
# Ignore CLI configuration files | ||
.terraformrc | ||
terraform.rc | ||
|
||
# End of https://www.toptal.com/developers/gitignore/api/terraform |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
repos: | ||
- repo: git://github.com/antonbabenko/pre-commit-terraform | ||
rev: v1.64.0 | ||
hooks: | ||
- id: terraform_fmt | ||
- id: terraform_docs | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.1.0 | ||
hooks: | ||
- id: check-merge-conflict | ||
- id: end-of-file-fixer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
// See http://go.microsoft.com/fwlink/?LinkId=827846 | ||
// for the documentation about the extensions.json format | ||
"recommendations": [ | ||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp | ||
"editorconfig.editorconfig", | ||
"yzhang.markdown-all-in-one", | ||
"hashicorp.terraform" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Contributing | ||
|
||
When contributing we follow semantic versioning and [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) in our Pull Requests and releases. You must prefix your PR and commit name with a type as below as well as a scope to identify what has changed, e.g. `type(scope): - Description`. Releases will be calculated based on PR labels that are automatically applied based on the PR title. Therefore the PR title needs also to follow the same rules as semantic commit. | ||
|
||
Available types to use in your PR: | ||
|
||
- feat: A new feature | ||
- fix: A bugfix | ||
- docs: Documentation only changes | ||
- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) | ||
- refactor: A code change that neither fixes a bug nor adds a feature | ||
- perf: A code change that improves performance | ||
- test: Adding missing tests or correcting existing tests | ||
- build: Changes that affect the build tool or external dependencies (example scopes: gulp, broccoli, npm) | ||
- ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) | ||
- chore: Other changes that don't modify src or test files | ||
- revert: Reverts a previous commit | ||
|
||
This is enforced by the workflow [`semantic_commit_check.yaml`](.github/workflows/pr-lint.yaml) which is run on every PR. | ||
|
||
## Releasing | ||
|
||
Releases are automatically generated based on the PR labels automatically added with [workflow](.github/workflows/release.yml) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
The MIT License (MIT) Copyright © 2022 Koninklijke Philips N.V, https://www.philips.com | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Scott Guymer <[email protected]> | ||
Niek Palm <[email protected]> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Terraform module AWS OICD integration GitHub Actions | ||
|
||
This [Terraform](https://www.terraform.io/) module manages OpenID Connect (OIDC) integration between [GitHub Actions and AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). | ||
|
||
## Description | ||
|
||
The module is strict on the claim checks to avoid that creating an OpenID connect integration opens your AWS account to any GitHub repo. However this strictness is not taking all the risk away. Ensure you familiarize yourself with OpenID Connect and the docs provided by GitHub and AWS. As always think about minimizing the privileges. | ||
|
||
The module can manage the following: | ||
|
||
- The OpenID Connect identity provider for GitHub in your AWS account. | ||
- A role and assume role policy to check to check OIDC claims. | ||
|
||
### Manage the OIDC identity provider | ||
|
||
The module provides two options for creating an OpenID connect provider. The first one is for the simple case you only need to create a single role, for one repo in one AWS account. In this case you should not set the `openid_connect_provider_arn` property. The second option is using the internal `provider` module to create the OpenID Connect provider. This configuration will create the provider and output the ARN. This output can be passed to other instances of the module to setup roles for multiple repositories on the same provider. | ||
|
||
### Manage roles for a repo | ||
|
||
The module creates a role with an assume role policy to check the OIDC claims for the given repo. Be default the policy is set to only allow actions running on the main branch and deny pull request actions. You can choose based on your need one (or more) of the default conditions to check. Additionally, a list of conditions can be provided. The role can only be assumed when all conditions evaluate to true. The following default conditions can be set. | ||
|
||
- `allow_main` : Allow GitHub Actions only running on the main branch. | ||
- `allow_environment`: Allow GitHub Actions only for environments, by setting `github_environments` you can limit to a dedicated environment. | ||
- `deny_pull_request`: Denies assuming the role for a pull request. | ||
- `allow_all` : Allow GitHub Actions for any claim for the repository. Be careful, this allows forks as well to assume the role! | ||
|
||
|
||
## Usages | ||
|
||
Setup for a single repository in a single AWS account, see also the examples. | ||
|
||
```hcl | ||
module "oidc" { | ||
source = "github.com/philips-labs/terraform-aws-github-oidc?ref=<version>" | ||
repo = var.repo | ||
role_name = "repo-s3" | ||
} | ||
``` | ||
|
||
Setup for multiple repositories connecting to a single AWS account, see also the examples. | ||
|
||
```hcl | ||
module "oidc_provider" { | ||
source = "github.com/philips-labs/terraform-aws-github-oidc/?ref=<version>//modules/provider" | ||
} | ||
module "oidc_repo_s3" { | ||
source = "github.com/philips-labs/terraform-aws-github-oidc?ref=<version>" | ||
openid_connect_provider_arn = module.oidc_provider.openid_connect_provider.arn | ||
repo = var.repo_s3 | ||
role_name = "repo-s3" | ||
} | ||
``` | ||
|
||
|
||
## Examples | ||
|
||
The following examples are provided: | ||
|
||
1. [Single repository](./examples/single-repo/README.md): using the module for a single repository and managing the identity provider by the same instance. | ||
2. [Multiple repositories](./examples/multi-repo/README.md): using the module for multiple repositories and managing the identity provider in separate module instances. | ||
|
||
|
||
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3 | | ||
| <a name="provider_random"></a> [random](#provider\_random) | n/a | | ||
|
||
## Modules | ||
|
||
| Name | Source | Version | | ||
|------|--------|---------| | ||
| <a name="module_oidc_provider"></a> [oidc\_provider](#module\_oidc\_provider) | ./modules/provider | n/a | | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_iam_role.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | ||
| [aws_iam_policy_document.github_actions_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_conditions"></a> [conditions](#input\_conditions) | (Optional) Additonal conditions for checking the OIDC claim. | <pre>list(object({<br> test = string<br> variable = string<br> values = list(string)<br> }))</pre> | `[]` | no | | ||
| <a name="input_default_conditions"></a> [default\_conditions](#input\_default\_conditions) | (Optional) Default condtions to apply, at least one of the following is madatory: 'allow\_main', 'allow\_environment', 'deny\_pull\_request' and 'allow\_all'. | `list(string)` | <pre>[<br> "allow_main",<br> "deny_pull_request"<br>]</pre> | no | | ||
| <a name="input_github_environments"></a> [github\_environments](#input\_github\_environments) | (Optional) Allow GitHub action to deploy to all (default) or to one of the environments in the list. | `list(string)` | <pre>[<br> "*"<br>]</pre> | no | | ||
| <a name="input_openid_connect_provider_arn"></a> [openid\_connect\_provider\_arn](#input\_openid\_connect\_provider\_arn) | Set the openid connect provider ARN when the provider is not managed by the module. | `string` | `null` | no | | ||
| <a name="input_repo"></a> [repo](#input\_repo) | (Optional) GitHub repository to grant access to assume a role via OIDC. When the repo is set, a role will be created. | `string` | `null` | no | | ||
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | (Optional) role name of the created role, if not provided the `namespace` will be used. | `string` | `null` | no | | ||
| <a name="input_role_path"></a> [role\_path](#input\_role\_path) | (Optional) Path for the created role, requires `repo` is set. | `string` | `"/github-actions/"` | no | | ||
| <a name="input_role_permissions_boundary"></a> [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | (Optional) Boundary for the created role, requires `repo` is set. | `string` | `null` | no | | ||
| <a name="input_thumbprint_list"></a> [thumbprint\_list](#input\_thumbprint\_list) | (Optional) A list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s). | `list(string)` | <pre>[<br> "6938fd4d98bab03faadb97b34396831e3780aea1"<br>]</pre> | no | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_role"></a> [role](#output\_role) | The crated role that can be assumed for the configured repository. | | ||
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
|
||
## Contribution | ||
|
||
We welcome contribution, please checkout the [contribution guide](CONTRIBUTING.md). Be-aware we use [pre commit hooks](https://pre-commit.com/) to update the docs. | ||
|
||
## Release | ||
|
||
Releases are create automated from the main branch using conventional commit messages. | ||
|
||
## Contact | ||
|
||
For question you can reach out to one of the [maintainers](./MAINTAINERS.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/bash | ||
## Script to generate the Thumbprint | ||
## | ||
## https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html | ||
## | ||
## | ||
HOST=$(curl https://vstoken.actions.githubusercontent.com/.well-known/openid-configuration | | ||
jq -r '.jwks_uri | split("/")[2]') | ||
% echo | openssl s_client -servername $HOST -showcerts -connect $HOST:443 2>/dev/null | | ||
sed -n -e '/BEGIN/h' -e '/BEGIN/,/END/H' -e '$x' -e '$p' | tail +2 | | ||
openssl x509 -fingerprint -noout | | ||
sed -e "s/.*=//" -e "s/://g" | | ||
tr "ABCDEF" "abcdef" |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Managing multiple repo's for a single AWS account | ||
|
||
The module provides an example how to setup roles to to use with OIDC for multiple repositories. | ||
|
||
- A repository with some access to S3 (same as in the [single example](../single-repo/README.md)) | ||
- A repository with access to ECR with the tag `allow-gh-action-access` | ||
- Environment for ECR repo (requires a paid GitHub subscription) | ||
|
||
## Usages | ||
|
||
Create a GitHub repositories (private) for S3 and ECR and set teh variable `repo` to the name of your created repo. Add as secret `AWS_ACCOUNT_ID` and set the value to your account. | ||
|
||
```bash | ||
terraform init | ||
terraform apply | ||
``` | ||
|
||
For the S3 repository follow the directions in the single example. On the console the name of the ECR repo and role are printed. Next update [workflow](../repositories/.github/workflows/../../repo-ecr/.github/workflows/ecr.yml) for the repo and role. Add, commit and push. The job should now push a busybox container to your ECR repo. | ||
|
||
Finally you can clean up with `terraform destroy` |
Oops, something went wrong.