From 188fb4aacf631a0ea64bfad08669fb9d16cc3e36 Mon Sep 17 00:00:00 2001 From: Brian Ojeda <9335829+sgtoj@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:53:05 -0500 Subject: [PATCH] feat: add support for admin token --- README.md | 23 ++++++++++++++++++----- main.tf | 12 ++++++++++++ outputs.tf | 6 ++++++ variables.tf | 12 ++++++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 937a2b2..29c1aa4 100644 --- a/README.md +++ b/README.md @@ -91,18 +91,19 @@ module "github_ops_app" { | Name | Description | Type | Default | Required | |-------------------------------|------------------------------------------------------------------------------|----------------|------------------------------------------------------|:--------:| -| `github_app_config` | GitHub App configuration for authentication and webhook handling | `object` | n/a | yes | -| `bot_version` | Version of the GitHub Ops App to use (`latest` or specific tag like `v0.1.0`)| `string` | `"latest"` | no | -| `bot_repo` | GitHub repository URL for the GitHub Ops App source code | `string` | `"https://github.com/cruxstack/github-ops-app.git"` | no | +| `admin_token_config` | Configuration for admin token protecting some endpoints | `object` | `{ enabled = true }` | no | +| `api_gateway_config` | Configuration for the API Gateway | `object` | `{}` | no | | `bot_force_rebuild_id` | ID to force rebuilding the Lambda function source code | `string` | `""` | no | +| `bot_repo` | GitHub repository URL for the GitHub Ops App source code | `string` | `"https://github.com/cruxstack/github-ops-app.git"` | no | +| `bot_version` | Version of the GitHub Ops App to use (`latest` or specific tag like `v0.1.0`)| `string` | `"latest"` | no | +| `github_app_config` | GitHub App configuration for authentication and webhook handling | `object` | n/a | yes | | `lambda_config` | Configuration for the Lambda function | `object` | `{}` | no | -| `lambda_log_retention_days` | Number of days to retain Lambda function logs | `number` | `30` | no | | `lambda_environment_variables`| Additional environment variables for the Lambda function | `map(string)` | `{}` | no | +| `lambda_log_retention_days` | Number of days to retain Lambda function logs | `number` | `30` | no | | `okta_config` | Okta configuration for user and group synchronization | `object` | `{}` | no | | `okta_sync_schedule` | EventBridge schedule configuration for automatic Okta sync | `object` | `{}` | no | | `pr_compliance_config` | Configuration for PR compliance monitoring | `object` | `{}` | no | | `slack_config` | Slack integration configuration for notifications | `object` | `{}` | no | -| `api_gateway_config` | Configuration for the API Gateway | `object` | `{}` | no | | `ssm_parameter_arns` | List of SSM Parameter Store ARNs for secrets retrieval | `list(string)` | `[]` | no | ### GitHub App Config @@ -189,6 +190,17 @@ slack_config = { Per-notification channels are optional and fall back to the default `channel` if not specified. +### Admin Token Config + +```hcl +admin_token_config = { + enabled = bool # Enable admin token protection (default: true) + token = string # (optional) Admin token - auto-generated if not provided +} +``` + +When enabled, requests to `/server/*` and `/scheduled/*` endpoints require an `Authorization: Bearer ` header. If no token is provided, a secure 32-character token is automatically generated and available via the `admin_token` output. + ## Outputs | Name | Description | @@ -207,6 +219,7 @@ Per-notification channels are optional and fall back to the default `channel` if | `api_gateway_execution_arn` | Execution ARN of the API Gateway | | `webhook_url` | Full webhook URL to configure in GitHub App settings | | `webhook_secret` | Webhook secret to configure in GitHub App | +| `admin_token` | Admin token for `/server/*` and `/scheduled/*` endpoints | | `eventbridge_rule_arn` | ARN of the EventBridge rule for scheduled Okta sync | | `eventbridge_rule_name` | Name of the EventBridge rule | diff --git a/main.tf b/main.tf index 5328d09..5c18f92 100644 --- a/main.tf +++ b/main.tf @@ -10,6 +10,9 @@ locals { # use provided webhook secret or generate one github_webhook_secret = var.github_app_config.webhook_secret != "" ? var.github_app_config.webhook_secret : random_password.webhook_secret[0].result + # use provided admin token or generate one (only if enabled) + admin_token = var.admin_token_config.enabled ? (var.admin_token_config.token != "" ? var.admin_token_config.token : random_password.admin_token[0].result) : "" + lambda_environment = merge( { # github app config @@ -26,6 +29,8 @@ locals { APP_PR_COMPLIANCE_ENABLED = tostring(var.pr_compliance_config.enabled) APP_PR_MONITORED_BRANCHES = var.pr_compliance_config.enabled ? join(",", var.pr_compliance_config.monitored_branches) : "" }, + # admin token config (conditional) + local.admin_token != "" ? { APP_ADMIN_TOKEN = local.admin_token } : {}, # okta config (conditional) var.okta_config.enabled ? merge({ APP_OKTA_DOMAIN = var.okta_config.domain @@ -66,6 +71,13 @@ resource "random_password" "webhook_secret" { special = false } +resource "random_password" "admin_token" { + count = local.enabled && var.admin_token_config.enabled && var.admin_token_config.token == "" ? 1 : 0 + + length = 32 + special = false +} + # ================================================================== lambda === module "bot_artifact" { diff --git a/outputs.tf b/outputs.tf index 2c23b0a..ff7f856 100644 --- a/outputs.tf +++ b/outputs.tf @@ -77,6 +77,12 @@ output "webhook_secret" { sensitive = true } +output "admin_token" { + description = "Admin token for accessing /server/* and /scheduled/* endpoints (generated if not provided)" + value = try(local.admin_token, null) + sensitive = true +} + # ============================================================== eventbridge === output "eventbridge_rule_arn" { diff --git a/variables.tf b/variables.tf index 9083b29..66b36a6 100644 --- a/variables.tf +++ b/variables.tf @@ -181,6 +181,18 @@ variable "api_gateway_config" { default = {} } +# ------------------------------------------------------------------- admin --- + +variable "admin_token_config" { + description = "Configuration for the admin token that protects /server/* and /scheduled/* endpoints. When enabled and token is not provided, one will be automatically generated." + sensitive = true + type = object({ + enabled = optional(bool, true) + token = optional(string, "") + }) + default = {} +} + # --------------------------------------------------------------------- ssm --- variable "ssm_parameter_arns" {