-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from fluxcd/aws-github-actions
Add aws-github-actions terraform module
- Loading branch information
Showing
4 changed files
with
329 additions
and
0 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,118 @@ | ||
# AWS GitHub Actions Secrets and Variables | ||
|
||
This terraform module creates AWS policy and role to be used in GitHub actions | ||
by assuming the created role with OIDC federation. The GitHub action assumes the | ||
AWS role by authenticating via GitHub OpenID Connect (OIDC) identity provider, | ||
refer [Use IAM roles to connect GitHub Actions to actions in | ||
AWS](https://aws.amazon.com/blogs/security/use-iam-roles-to-connect-github-actions-to-actions-in-aws/). | ||
This can be made easy by using [Configure AWS | ||
Credentials](https://github.com/marketplace/actions/configure-aws-credentials-action-for-github-actions) | ||
GitHub action. | ||
|
||
By default, the following GitHub actions secrets are created: | ||
- `AWS_ACCOUNT_ID` | ||
- `AWS_ASSUME_ROLE_NAME` | ||
|
||
and `AWS_REGION` actions variable is created. All these names are | ||
overridable, see `variables.tf`. | ||
|
||
It also supports adding custom secrets and variables in addition to the above. | ||
|
||
**NOTE:** Overwriting existing GitHub secrets and variables is not supported. | ||
|
||
## Usage | ||
|
||
```hcl | ||
module "aws_gh_actions" { | ||
source = "git::https://github.com/fluxcd/test-infra.git//tf-modules/aws/github-actions" | ||
aws_policy_name = "test-policy-1" | ||
aws_policy_description = "For running e2e tests" | ||
aws_provision_perms = [ | ||
"ec2:CreateInternetGateway", | ||
"ec2:CreateLaunchTemplate", | ||
"ec2:CreateLaunchTemplateVersion", | ||
] | ||
aws_cluster_role_prefix = [ | ||
"flux-test-", | ||
"blue-eks-node-group-", | ||
"green-eks-node-group-" | ||
] | ||
aws_role_name = "test-role-1" | ||
aws_role_description = "Role to be assumed by github actions" | ||
github_repo_owner = "fluxcd" | ||
github_project = "repo-name" | ||
github_repo_branch_ref = "ref:refs/heads/main" | ||
github_variable_custom = { | ||
"SOME_VAR1" = "some-val1", | ||
"SOME_var2" = "some-val2" | ||
} | ||
github_secret_custom = { | ||
"SECRET1" = "some-secret1", | ||
"SECRET2" = "some-secret2" | ||
} | ||
} | ||
``` | ||
|
||
## AWS Requirements | ||
|
||
Use the following IAM policy document to grant the needed permissions. | ||
|
||
```json | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Sid": "VisualEditor0", | ||
"Effect": "Allow", | ||
"Action": [ | ||
"iam:AttachRolePolicy", | ||
"iam:CreatePolicy", | ||
"iam:CreatePolicyVersion", | ||
"iam:CreateRole", | ||
"iam:DeletePolicy", | ||
"iam:DeletePolicyVersion", | ||
"iam:DeleteRole", | ||
"iam:DetachRolePolicy", | ||
"iam:GetPolicy", | ||
"iam:GetPolicyVersion", | ||
"iam:GetRole", | ||
"iam:ListAttachedRolePolicies", | ||
"iam:ListInstanceProfilesForRole", | ||
"iam:ListPolicyVersions", | ||
"iam:ListRolePolicies" | ||
], | ||
"Resource": "*" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
Since the GitHub actions use GitHub OIDC identity provider, the AWS account must | ||
have GitHub as an existing identity provider, see [Configuring OpenID Connect in | ||
Amazon Web | ||
Services](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). | ||
The provider URL is expected to be `https://token.actions.githubusercontent.com` | ||
and the audience `sts.amazonaws.com`, as an account can only have a single | ||
instance of this identity provider. These are hard-coded in the configurations | ||
and should be updated in the source, if needed. | ||
|
||
## GitHub Requirements | ||
|
||
Create a GitHub fine-grained token for the target repository with the following | ||
repository permissions: | ||
- `Read access to metadata` | ||
- `Read and Write access to actions variables and secrets` | ||
|
||
## Provider Configuration | ||
|
||
Configure the AWS and GitHub provider with the following environment variables: | ||
```sh | ||
export AWS_ACCESS_KEY_ID="" | ||
export AWS_SECRET_ACCESS_KEY="" | ||
|
||
export GITHUB_TOKEN="" | ||
``` | ||
|
||
Check the respective provider docs for more details. |
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,108 @@ | ||
data "aws_caller_identity" "current" {} | ||
|
||
locals { | ||
# Set the provider values from input variables and provider configuration. | ||
account_id = var.aws_account_id == "" ? data.aws_caller_identity.current.account_id : var.aws_account_id | ||
|
||
# Construct a list of role ARN from the given role prefixes to use in cluster | ||
# permissions below. | ||
clusterperms_resources = [for prefix in var.aws_cluster_role_prefix : "arn:aws:iam::${local.account_id}:role/${prefix}*"] | ||
} | ||
|
||
data "aws_iam_policy_document" "policy_doc" { | ||
# Permissions for provisioning the infrastructure. | ||
statement { | ||
sid = "testinfra" | ||
actions = var.aws_provision_perms | ||
resources = ["*"] | ||
} | ||
|
||
# Pass cluster permissions to the following roles: cluster, node-groups, etc. | ||
statement { | ||
sid = "clusterperms" | ||
actions = ["iam:PassRole"] | ||
resources = local.clusterperms_resources | ||
} | ||
} | ||
|
||
resource "aws_iam_policy" "policy" { | ||
name = var.aws_policy_name | ||
policy = data.aws_iam_policy_document.policy_doc.json | ||
description = var.aws_policy_description | ||
} | ||
|
||
# Create assume role policy document for defining the trust relationship with | ||
# GitHub OIDC and the target repository. | ||
data "aws_iam_policy_document" "assume_role_doc" { | ||
statement { | ||
# Create trusted identity of type Web identity with github as the provider. | ||
actions = ["sts:AssumeRoleWithWebIdentity"] | ||
principals { | ||
type = "Federated" | ||
identifiers = ["arn:aws:iam::${local.account_id}:oidc-provider/token.actions.githubusercontent.com"] | ||
} | ||
# Set the audience to STS. | ||
condition { | ||
test = "StringEquals" | ||
variable = "token.actions.githubusercontent.com:aud" | ||
values = ["sts.amazonaws.com"] | ||
} | ||
# Set the GitHub repository. | ||
condition { | ||
test = "StringLike" | ||
variable = "token.actions.githubusercontent.com:sub" | ||
values = ["repo:${var.github_repo_owner}/${var.github_project}:${var.github_repo_branch_ref}"] | ||
} | ||
} | ||
} | ||
|
||
# Create a role to assume by github actions. | ||
resource "aws_iam_role" "github_actions_role" { | ||
name = var.aws_role_name | ||
assume_role_policy = data.aws_iam_policy_document.assume_role_doc.json | ||
description = var.aws_role_description | ||
} | ||
|
||
# Attach the policy to the role. | ||
resource "aws_iam_role_policy_attachment" "github_actions_role_attachment" { | ||
role = aws_iam_role.github_actions_role.name | ||
policy_arn = aws_iam_policy.policy.arn | ||
} | ||
|
||
# Add a GitHub secret variable for the AWS account ID. | ||
resource "github_actions_secret" "account_id" { | ||
repository = var.github_project | ||
secret_name = var.github_secret_accound_id_name | ||
plaintext_value = local.account_id | ||
} | ||
|
||
# Add a GitHub secret for the AWS role name to assume. | ||
resource "github_actions_secret" "role_name" { | ||
repository = var.github_project | ||
secret_name = var.github_secret_assume_role_name | ||
plaintext_value = var.aws_role_name | ||
} | ||
|
||
# Add a GitHub variable for the AWS region. | ||
resource "github_actions_variable" "region" { | ||
repository = var.github_project | ||
variable_name = var.github_variable_region_name | ||
value = var.aws_region | ||
} | ||
|
||
resource "github_actions_variable" "custom" { | ||
for_each = var.github_variable_custom | ||
|
||
repository = var.github_project | ||
variable_name = each.key | ||
value = each.value | ||
} | ||
|
||
resource "github_actions_secret" "custom" { | ||
# Mark only the key as nonsensitive. | ||
for_each = nonsensitive(toset(keys(var.github_secret_custom))) | ||
|
||
repository = var.github_project | ||
secret_name = each.key | ||
plaintext_value = var.github_secret_custom[each.key] | ||
} |
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,90 @@ | ||
variable "aws_account_id" { | ||
description = "AWS account ID" | ||
type = string | ||
default = "" | ||
} | ||
|
||
variable "aws_region" { | ||
description = "AWS region used by the tests" | ||
type = string | ||
default = "us-east-1" | ||
} | ||
|
||
variable "aws_policy_name" { | ||
description = "Name of the policy with all the required permissions" | ||
type = string | ||
} | ||
|
||
variable "aws_policy_description" { | ||
description = "IAM policy description" | ||
type = string | ||
} | ||
|
||
variable "aws_provision_perms" { | ||
description = "List of permissions for provisioning the infrastructure" | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "aws_cluster_role_prefix" { | ||
description = "List of name prefixes of the resources that get cluster permission through IAM pass role" | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "aws_role_name" { | ||
description = "Name of the role that will be assumed by the GitHub actions" | ||
type = string | ||
} | ||
|
||
variable "aws_role_description" { | ||
description = "IAM role description" | ||
type = string | ||
} | ||
|
||
variable "github_repo_owner" { | ||
description = "Name of the GitHub owner (org or user) of the target repository" | ||
type = string | ||
} | ||
|
||
variable "github_project" { | ||
description = "Name of the GitHub project where the actions run, and secrets/variables are added" | ||
type = string | ||
} | ||
|
||
variable "github_repo_branch_ref" { | ||
description = "Reference to the target branch in the GitHub repository. Use * for any branch" | ||
type = string | ||
default = "ref:refs/heads/main" | ||
} | ||
|
||
variable "github_secret_accound_id_name" { | ||
description = "GitHub secret name for AWS accound ID" | ||
type = string | ||
default = "AWS_ACCOUNT_ID" | ||
} | ||
|
||
variable "github_secret_assume_role_name" { | ||
description = "GitHub secret name for AWS role name to assume" | ||
type = string | ||
default = "AWS_ASSUME_ROLE_NAME" | ||
} | ||
|
||
variable "github_variable_region_name" { | ||
description = "GitHub variable name for AWS region" | ||
type = string | ||
default = "AWS_REGION" | ||
} | ||
|
||
variable "github_variable_custom" { | ||
description = "A map of custom GitHub variables to be created" | ||
type = map(string) | ||
default = {} | ||
} | ||
|
||
variable "github_secret_custom" { | ||
description = "A map of custom GitHub secrets to be created" | ||
type = map(string) | ||
default = {} | ||
sensitive = 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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
terraform { | ||
required_providers { | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = ">= 5.40" | ||
} | ||
|
||
github = { | ||
source = "integrations/github" | ||
version = ">= 6.2" | ||
} | ||
} | ||
} |