Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,34 @@ gcloud compute url-maps invalidate-cdn-cache cudly-url-map --path "/*"

---

## Archera insured-commitment comparison (optional)

The explicit "Compare with Archera" feature is off by default. It is enabled only when all three settings are set; with none set, the platform makes no Archera request.

| Terraform variable (environment) | Runtime setting | Meaning |
|---|---|---|
| `archera_org_id` | `ARCHERA_ORG_ID` | Archera organization UUID |
| `archera_plan_id` | `ARCHERA_PLAN_ID` | Archera commitment plan UUID (an Archera ID, not a CUDly plan ID) |
| `archera_api_key_secret_arn` (AWS), `archera_api_key_secret_id` (GCP), `archera_api_key_secret_name` (Azure) | `ARCHERA_API_KEY_SECRET` | Reference to the secret holding the Archera API key |

Create the secret yourself, outside Terraform, so the key never enters Terraform state; Terraform only passes the reference. The platform resolves the key lazily on the first comparison request through the configured secret provider.

Runtime access is scoped to that one secret:

- AWS (Lambda and Fargate): `secretsmanager:GetSecretValue` on the secret ARN only.
- GCP (Cloud Run and GKE): a per-secret `roles/secretmanager.secretAccessor` binding on that secret only.
- Azure (Container Apps and AKS): no new role assignment. The secret lives in the platform Key Vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role. For a secret in a different vault, add a secret-scoped role assignment for the runtime identity on that secret; narrowing the vault-wide grant is a separate owner decision.

Required disclosures, shown verbatim wherever Archera is offered (pkg/common `ArcheraNonGatingDisclosure` and `ArcheraSponsorshipDisclosure`):

> This is entirely optional. CUDly's purchase and management features work fully without Archera.
>
> For full disclosure, Archera sponsors CUDly's Open Source development from a fraction of their insurance premiums.

The GCP secret variable takes the short secret ID, not the `projects/<number>/secrets/<id>` resource name: the per-secret binding sets the project, and the full name makes the binding be replaced on every apply.

The comparison shows Archera's own figures as returned by its API. Amounts carry no currency (Archera provides none), premiums are already included in totals, and an unknown value is shown as unknown, never as zero. Products Archera does not document as supported are shown as "not known to be supported by Archera". Nothing in this view is a guarantee or a purchase; the existing Archera disclosures stay in place.

## Deploying Code Updates

When infrastructure already exists and you only need to update application code:
Expand Down
8 changes: 8 additions & 0 deletions terraform/environments/aws/compute.tf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ module "compute_lambda" {
fire_scheduled_purchases_schedule = var.fire_scheduled_purchases_schedule

# Additional environment variables
archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_arn = var.archera_api_key_secret_arn

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down Expand Up @@ -208,6 +212,10 @@ module "compute_fargate" {
enable_execute_command = var.fargate_enable_execute_command

# Additional environment variables
archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_arn = var.archera_api_key_secret_arn

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down
18 changes: 18 additions & 0 deletions terraform/environments/aws/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -532,3 +532,21 @@ variable "enable_docker_build" {
type = bool
default = true
}

variable "archera_org_id" {
description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID for the comparison. Empty disables it."
type = string
default = ""
}

variable "archera_api_key_secret_arn" {
description = "ARN of the Secrets Manager secret holding the Archera API key (created out-of-band). Empty disables the Archera comparison."
type = string
default = ""
}
14 changes: 11 additions & 3 deletions terraform/environments/azure/compute.tf
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ module "compute_container_apps" {
auto_migrate = var.auto_migrate
admin_email = var.admin_email
admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "")
archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_name = var.archera_api_key_secret_name

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down Expand Up @@ -160,9 +164,13 @@ module "compute_aks" {
key_vault_uri = module.secrets.key_vault_uri

# Application configuration
admin_email = var.admin_email
admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "")
auto_migrate = var.auto_migrate
admin_email = var.admin_email
admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "")
auto_migrate = var.auto_migrate
archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_name = var.archera_api_key_secret_name

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down
18 changes: 18 additions & 0 deletions terraform/environments/azure/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,21 @@ variable "max_account_parallelism" {
type = number
default = 10
}

variable "archera_org_id" {
description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID for the comparison. Empty disables it."
type = string
default = ""
}

variable "archera_api_key_secret_name" {
description = "Name of the platform Key Vault secret holding the Archera API key (created out-of-band). Empty disables the Archera comparison."
type = string
default = ""
}
8 changes: 8 additions & 0 deletions terraform/environments/gcp/compute.tf
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ module "compute_cloud_run" {
billing_account_id = var.billing_account_id

# Additional environment variables
archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_id = var.archera_api_key_secret_id

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down Expand Up @@ -183,6 +187,10 @@ module "compute_gke" {
credential_encryption_key = module.secrets.credential_encryption_key_secret_id
}

archera_org_id = var.archera_org_id
archera_plan_id = var.archera_plan_id
archera_api_key_secret_id = var.archera_api_key_secret_id

additional_env_vars = merge(
{
STATIC_DIR = "/app/static"
Expand Down
18 changes: 18 additions & 0 deletions terraform/environments/gcp/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,21 @@ variable "max_account_parallelism" {
type = number
default = 10
}

variable "archera_org_id" {
description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID for the comparison. Empty disables it."
type = string
default = ""
}

variable "archera_api_key_secret_id" {
description = "Short Secret Manager secret ID (not the full resource name) holding the Archera API key (created out-of-band). Empty disables the Archera comparison."
type = string
default = ""
}
18 changes: 18 additions & 0 deletions terraform/modules/compute/aws/fargate/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ resource "aws_iam_role_policy" "task_secrets" {
var.credential_encryption_key_secret_arn != "" ? "${var.credential_encryption_key_secret_arn}*" : "",
var.scheduled_task_secret_arn,
var.scheduled_task_secret_arn != "" ? "${var.scheduled_task_secret_arn}*" : "",
var.archera_api_key_secret_arn,
var.archera_api_key_secret_arn != "" ? "${var.archera_api_key_secret_arn}*" : "",
])
},
{
Expand Down Expand Up @@ -645,6 +647,12 @@ resource "aws_ecs_task_definition" "main" {
value = var.scheduled_task_secret_name
}
],
[
for k, v in local.archera_env : {
name = k
value = v
}
],
[
for k, v in var.additional_env_vars : {
name = k
Expand Down Expand Up @@ -1263,3 +1271,13 @@ resource "aws_iam_role_policy" "eventbridge_fire_scheduled_purchases" {
]
})
}

locals {
# Archera settings, set only when non-empty so an unconfigured deployment
# carries no ARCHERA_* variable at all (feature off).
archera_env = merge(
var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {},
var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {},
var.archera_api_key_secret_arn != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_arn } : {},
)
}
21 changes: 21 additions & 0 deletions terraform/modules/compute/aws/fargate/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,24 @@ variable "email_from_domain" {
type = string
default = ""
}

# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md).
# All three must be set for the feature to be configured; the key itself is never
# managed here, the operator creates the secret out-of-band.
variable "archera_org_id" {
description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_api_key_secret_arn" {
description = "ARN of the Secrets Manager secret holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and granted GetSecretValue on this one secret only. Empty disables the comparison."
type = string
default = ""
}
13 changes: 13 additions & 0 deletions terraform/modules/compute/aws/lambda/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ resource "aws_lambda_function" "main" {
var.purchase_approved_reap_after != "" ? {
PURCHASE_APPROVED_REAP_AFTER = var.purchase_approved_reap_after
} : {},
local.archera_env,
var.additional_env_vars
)
}
Expand Down Expand Up @@ -260,6 +261,8 @@ resource "aws_iam_role_policy" "secrets_access" {
var.credential_encryption_key_secret_arn != "" ? "${var.credential_encryption_key_secret_arn}*" : "",
var.scheduled_task_secret_arn,
var.scheduled_task_secret_arn != "" ? "${var.scheduled_task_secret_arn}*" : "",
var.archera_api_key_secret_arn,
var.archera_api_key_secret_arn != "" ? "${var.archera_api_key_secret_arn}*" : "",
])
},
{
Expand Down Expand Up @@ -801,3 +804,13 @@ resource "aws_lambda_permission" "eventbridge_fire_scheduled_purchases" {
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.fire_scheduled_purchases[0].arn
}

locals {
# Archera settings, set only when non-empty so an unconfigured deployment
# carries no ARCHERA_* variable at all (feature off).
archera_env = merge(
var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {},
var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {},
var.archera_api_key_secret_arn != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_arn } : {},
)
}
21 changes: 21 additions & 0 deletions terraform/modules/compute/aws/lambda/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,24 @@ variable "tags" {
type = map(string)
default = {}
}

# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md).
# All three must be set for the feature to be configured; the key itself is never
# managed here, the operator creates the secret out-of-band.
variable "archera_org_id" {
description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_api_key_secret_arn" {
description = "ARN of the Secrets Manager secret holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and granted GetSecretValue on this one secret only. Empty disables the comparison."
type = string
default = ""
}
18 changes: 18 additions & 0 deletions terraform/modules/compute/azure/aks/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,14 @@ resource "kubernetes_deployment" "app" {
value = "bearer"
}

dynamic "env" {
for_each = local.archera_env
content {
name = env.key
value = env.value
}
}

dynamic "env" {
for_each = var.additional_env_vars
content {
Expand Down Expand Up @@ -780,3 +788,13 @@ data "kubernetes_service" "nginx_ingress" {
time_sleep.wait_for_lb_ip,
]
}

locals {
# Archera settings, set only when non-empty so an unconfigured deployment
# carries no ARCHERA_* variable at all (feature off).
archera_env = merge(
var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {},
var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {},
var.archera_api_key_secret_name != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_name } : {},
)
}
21 changes: 21 additions & 0 deletions terraform/modules/compute/azure/aks/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,24 @@ variable "admin_group_object_ids" {
type = list(string)
default = []
}

# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md).
# All three must be set for the feature to be configured; the key itself is never
# managed here, the operator creates the secret out-of-band.
variable "archera_org_id" {
description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_api_key_secret_name" {
description = "Name of the Key Vault secret holding the Archera API key, passed as ARCHERA_API_KEY_SECRET. The secret lives in the platform vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role, so no role assignment is added here. Empty disables the comparison."
type = string
default = ""
}
11 changes: 11 additions & 0 deletions terraform/modules/compute/azure/container-apps/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ resource "azurerm_container_app" "main" {
# not emit on the HTTP Connector trigger we use.
SCHEDULED_TASK_AUTH_MODE = "bearer"
},
local.archera_env,
var.additional_env_vars
)
content {
Expand Down Expand Up @@ -343,3 +344,13 @@ resource "azurerm_monitor_diagnostic_setting" "container_app" {
enabled = true
}
}

locals {
# Archera settings, set only when non-empty so an unconfigured deployment
# carries no ARCHERA_* variable at all (feature off).
archera_env = merge(
var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {},
var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {},
var.archera_api_key_secret_name != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_name } : {},
)
}
21 changes: 21 additions & 0 deletions terraform/modules/compute/azure/container-apps/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,24 @@ variable "ri_exchange_schedule" {
type = string
default = "0 */6 * * *"
}

# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md).
# All three must be set for the feature to be configured; the key itself is never
# managed here, the operator creates the secret out-of-band.
variable "archera_org_id" {
description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_plan_id" {
description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison."
type = string
default = ""
}

variable "archera_api_key_secret_name" {
description = "Name of the Key Vault secret holding the Archera API key, passed as ARCHERA_API_KEY_SECRET. The secret lives in the platform vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role, so no role assignment is added here. Empty disables the comparison."
type = string
default = ""
}
Loading
Loading