diff --git a/docs/configuration.md b/docs/configuration.md index be0ea03975..eaa3da3c7d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -14,6 +14,7 @@ To be able to support a number of use-cases, the module has quite a lot of confi - Spot vs on-demand. The runners use either the EC2 spot or on-demand life cycle. Runners will be created via the AWS [CreateFleet API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html). The module (scale up lambda) will request via the CreateFleet API to create instances in one of the subnets and of the specified instance types. - ARM64 support via Graviton/Graviton2 instance-types. When using the default example or top-level module, specifying `instance_types` that match a Graviton/Graviton 2 (ARM64) architecture (e.g. a1, t4g or any 6th-gen `g` or `gd` type), you must also specify `runner_architecture = "arm64"` and the sub-modules will be automatically configured to provision with ARM64 AMIs and leverage GitHub's ARM64 action runner. See below for more details. - Disable default labels for the runners (os, architecture and `self-hosted`) can achieve by setting `runner_disable_default_labels` = true. If enabled, the runner will only have the extra labels provided in `runner_extra_labels`. In case you on own start script is used, this configuration parameter needs to be parsed via SSM. +- Managed vs self-managed webhook secret. The module can manage the webhook secret for you. In that case simply do not provide a value for `github_app.webhook_secret`. If you want to manage the secret yourself, provide a value for `github_app.webhook_secret`. The secret will be managed and a rotation is triggered once running terraform apply again after `github_app.webhook_secret_rotation_days` days. **Important note**: THe managed webhook secret depends on a local-exec (bash) to update the secret in GitNub. It will also update the webhook url. ## AWS SSM Parameters diff --git a/docs/getting-started.md b/docs/getting-started.md index cfd8f7b88b..37872d7eb7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -85,7 +85,7 @@ module "github-runner" { github_app = { key_base64 = "base64string" id = "1" - webhook_secret = "webhook_secret" + webhook_secret = "webhook_secret" # optional, if not set the module will manage the secret. } webhook_lambda_zip = "lambdas-download/webhook.zip" @@ -109,7 +109,7 @@ The lambda for syncing the GitHub distribution to S3 is triggered via CloudWatch ### Setup the webhook / GitHub App (part 2) At this point you have two options. Either create a separate webhook (enterprise, -org, or repo), or create a webhook in the App. +org, or repo), or create a webhook in the App. In case you have not provided a Webhook secret the module will create one and update the GitHub app with both the secret and the webhook url. #### Option 1: Webhook diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index 045fb7350a..c236658c15 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -83,3 +83,23 @@ provider "registry.terraform.io/hashicorp/random" { "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", ] } + +provider "registry.terraform.io/hashicorp/time" { + version = "0.12.1" + constraints = "~> 0.7" + hashes = [ + "h1:JzYsPugN8Fb7C4NlfLoFu7BBPuRVT2/fCOdCaxshveI=", + "zh:090023137df8effe8804e81c65f636dadf8f9d35b79c3afff282d39367ba44b2", + "zh:26f1e458358ba55f6558613f1427dcfa6ae2be5119b722d0b3adb27cd001efea", + "zh:272ccc73a03384b72b964918c7afeb22c2e6be22460d92b150aaf28f29a7d511", + "zh:438b8c74f5ed62fe921bd1078abe628a6675e44912933100ea4fa26863e340e9", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:85c8bd8eefc4afc33445de2ee7fbf33a7807bc34eb3734b8eefa4e98e4cddf38", + "zh:98bbe309c9ff5b2352de6a047e0ec6c7e3764b4ed3dfd370839c4be2fbfff869", + "zh:9c7bf8c56da1b124e0e2f3210a1915e778bab2be924481af684695b52672891e", + "zh:d2200f7f6ab8ecb8373cda796b864ad4867f5c255cff9d3b032f666e4c78f625", + "zh:d8c7926feaddfdc08d5ebb41b03445166df8c125417b28d64712dccd9feef136", + "zh:e2412a192fc340c61b373d6c20c9d805d7d3dee6c720c34db23c2a8ff0abd71b", + "zh:e6ac6bba391afe728a099df344dbd6481425b06d61697522017b8f7a59957d44", + ] +} diff --git a/examples/default/main.tf b/examples/default/main.tf index 42608fae40..7ff2a97ac9 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -3,10 +3,6 @@ locals { aws_region = var.aws_region } -resource "random_id" "random" { - byte_length = 20 -} - module "base" { source = "../base" @@ -27,9 +23,9 @@ module "runners" { } github_app = { - key_base64 = var.github_app.key_base64 - id = var.github_app.id - webhook_secret = random_id.random.hex + key_base64 = var.github_app.key_base64 + id = var.github_app.id + # webhook_secret = random_id.random.hex } # configure the block device mappings, default for Amazon Linux2 @@ -143,18 +139,6 @@ module "runners" { # kms_key_arn = aws_kms_key.github.arn } -module "webhook_github_app" { - source = "../../modules/webhook-github-app" - depends_on = [module.runners] - - github_app = { - key_base64 = var.github_app.key_base64 - id = var.github_app.id - webhook_secret = random_id.random.hex - } - webhook_endpoint = module.runners.webhook.endpoint -} - # enable CMK instead of aws managed key for encryptions # resource "aws_kms_key" "github" { # is_enabled = true diff --git a/examples/default/outputs.tf b/examples/default/outputs.tf index c50214f566..2709fc69b3 100644 --- a/examples/default/outputs.tf +++ b/examples/default/outputs.tf @@ -7,9 +7,3 @@ output "runners" { output "webhook_endpoint" { value = module.runners.webhook.endpoint } - -output "webhook_secret" { - sensitive = true - value = random_id.random.hex -} - diff --git a/main.tf b/main.tf index 3f3c9808b4..19e5c61036 100644 --- a/main.tf +++ b/main.tf @@ -12,6 +12,17 @@ locals { runner_labels = (var.runner_disable_default_labels == false) ? sort(concat(local.default_runner_labels, var.runner_extra_labels)) : var.runner_extra_labels ssm_root_path = var.ssm_paths.use_prefix ? "/${var.ssm_paths.root}/${var.prefix}" : "/${var.ssm_paths.root}" + + github_app = merge(var.github_app, { + webhook_secret = var.github_app.webhook_secret != null ? var.github_app.webhook_secret : module.rotating_random[0].random.hex + }) +} + +module "rotating_random" { + count = var.github_app.webhook_secret == null ? 1 : 0 + source = "./modules/rotating-random" + + rotation_days = var.github_app.webhook_secret_rotation_days } resource "random_string" "random" { @@ -91,10 +102,18 @@ module "ssm" { kms_key_arn = var.kms_key_arn path_prefix = "${local.ssm_root_path}/${var.ssm_paths.app}" - github_app = var.github_app + github_app = local.github_app tags = local.tags } +module "webhook_github_app" { + count = var.github_app.webhook_secret == null ? 1 : 0 + source = "./modules/webhook-github-app" + + github_app = local.github_app + webhook_endpoint = "${module.webhook.gateway.api_endpoint}/${module.webhook.endpoint_relative_path}" +} + module "webhook" { source = "./modules/webhook" diff --git a/modules/multi-runner/main.tf b/modules/multi-runner/main.tf index 22ec0df3ba..ecdf79eb9a 100644 --- a/modules/multi-runner/main.tf +++ b/modules/multi-runner/main.tf @@ -16,6 +16,17 @@ locals { unique_os_and_arch = { for i, v in local.tmp_distinct_list_unique_os_and_arch : "${v.os_type}_${v.architecture}" => v } ssm_root_path = "/${var.ssm_paths.root}/${var.prefix}" + + github_app = merge(var.github_app, { + webhook_secret = var.github_app.webhook_secret != null ? var.github_app.webhook_secret : module.rotating_random[0].random.hex + }) +} + +module "rotating_random" { + count = var.github_app.webhook_secret == null ? 1 : 0 + source = "./../rotating-random" + + rotation_days = var.github_app.webhook_secret_rotation_days } resource "random_string" "random" { diff --git a/modules/multi-runner/ssm.tf b/modules/multi-runner/ssm.tf index 6b2591f465..ae914e7471 100644 --- a/modules/multi-runner/ssm.tf +++ b/modules/multi-runner/ssm.tf @@ -3,6 +3,6 @@ module "ssm" { kms_key_arn = var.kms_key_arn path_prefix = "${local.ssm_root_path}/${var.ssm_paths.app}" - github_app = var.github_app + github_app = local.github_app tags = local.tags } diff --git a/modules/multi-runner/variables.tf b/modules/multi-runner/variables.tf index f962d1ea8c..07359e6624 100644 --- a/modules/multi-runner/variables.tf +++ b/modules/multi-runner/variables.tf @@ -1,9 +1,15 @@ variable "github_app" { - description = "GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`)." + description = < This module is treated as internal module, breaking changes will not trigger a major release bump. + + + diff --git a/modules/rotating-random/main.tf b/modules/rotating-random/main.tf new file mode 100644 index 0000000000..c6235ac79a --- /dev/null +++ b/modules/rotating-random/main.tf @@ -0,0 +1,10 @@ +resource "time_rotating" "rotation_days" { + rotation_days = var.rotation_days +} + +resource "random_id" "random" { + byte_length = 20 + keepers = { + rotation = time_rotating.rotation_days.id + } +} diff --git a/modules/rotating-random/outputs.tf b/modules/rotating-random/outputs.tf new file mode 100644 index 0000000000..5d4e64e6d9 --- /dev/null +++ b/modules/rotating-random/outputs.tf @@ -0,0 +1,3 @@ +output "random" { + value = random_id.random +} diff --git a/modules/rotating-random/variables.tf b/modules/rotating-random/variables.tf new file mode 100644 index 0000000000..f68bab0c04 --- /dev/null +++ b/modules/rotating-random/variables.tf @@ -0,0 +1,5 @@ +variable "rotation_days" { + description = "Number of days before rotating the random." + type = number + default = 30 +} diff --git a/modules/rotating-random/versions.tf b/modules/rotating-random/versions.tf new file mode 100644 index 0000000000..db2e796d6f --- /dev/null +++ b/modules/rotating-random/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.3.0" + + required_providers { + random = { + source = "hashicorp/random" + version = "~> 3" + } + time = { + source = "hashicorp/time" + version = "~> 0.12" + } + } +} diff --git a/outputs.tf b/outputs.tf index 699867ec2e..403402e495 100644 --- a/outputs.tf +++ b/outputs.tf @@ -47,7 +47,6 @@ output "ssm_parameters" { value = module.ssm.parameters } - output "queues" { description = "SQS queues." value = { diff --git a/variables.tf b/variables.tf index 5c57606edf..543b532ad4 100644 --- a/variables.tf +++ b/variables.tf @@ -32,11 +32,17 @@ variable "enable_organization_runners" { } variable "github_app" { - description = "GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`)." + description = <