Summary
The federation IaC handler has a fail-loud guard for empty AWS source account IDs but not for empty Azure/GCP source identities. When AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, or GCP_PROJECT_ID are unset on the Lambda, the rendered IaC bundle ships with empty identity fields and customers hit a cryptic terraform apply error.
Captured in: known_issues/25_federation_azure_gcp_source_identity_failloud.md
Current behaviour
internal/api/handler.go::resolveSourceIdentity (≈line 446) reads Azure/GCP identity from environment variables. If any are unset, empty strings flow into the generated tfvars/scripts and the federation bundle downloads successfully. The apply-time failure is a blank client_id / missing project — the operator has no clear signal that CUDly's own env is misconfigured.
The AWS source path in internal/api/handler_federation.go::populateSourceAccountID (≈line 171) already fails loud:
func (h *Handler) populateSourceAccountID(ctx context.Context, source string, data *federationIaCData) error {
if sourceCloud() != "aws" {
return nil
}
data.SourceAccountID = h.resolveSourceAccountID(ctx)
if source == "aws" && data.SourceAccountID == "" {
return fmt.Errorf("federation iac: CUDly failed to resolve its own AWS account ID; ...")
}
return nil
}
The Azure/GCP equivalent is missing — populateSourceAccountID returns nil immediately for non-AWS source clouds, and nothing else validates the source identity before rendering the bundle.
Expected behaviour
The same fail-loud treatment for Azure and GCP deployments, naming the missing env var so the operator knows exactly what to fix.
Steps to reproduce
- Deploy CUDly on Azure (or GCP).
- Unset
AZURE_SUBSCRIPTION_ID on the Lambda/Function App (or GCP_PROJECT_ID on Cloud Run).
- From the UI, download a federation bundle.
- Observe: bundle downloads 200 OK,
terraform apply later fails with blank client_id / missing project — no actionable error at download time.
Proposed fix
Extend populateSourceAccountID (or add a sibling populateSourceIdentity) to cover Azure and GCP. Sketch:
if sourceCloud() == "azure" {
id := h.resolveSourceIdentity(ctx)
if id.SubscriptionID == "" || id.TenantID == "" {
return fmt.Errorf("federation iac: AZURE_SUBSCRIPTION_ID or AZURE_TENANT_ID is not set; check the Lambda environment variables")
}
}
if sourceCloud() == "gcp" {
id := h.resolveSourceIdentity(ctx)
if id.ProjectID == "" {
return fmt.Errorf("federation iac: GCP_PROJECT_ID is not set; check the Lambda environment variables")
}
}
Test plan
Four tests in internal/api/handler_federation_test.go that mock resolveSourceIdentity to return empty fields and assert a non-client-error 500 response is surfaced:
- Azure:
SubscriptionID="" → 500
- Azure:
TenantID="" → 500
- GCP:
ProjectID="" → 500
- Positive control: all fields populated → 200
References
- Companion commit:
fix(api): pre-fill ContactEmail from Session.Email and fail loud on empty SourceAccountID (the AWS-only fix this extends).
- Files:
internal/api/handler_federation.go::populateSourceAccountID, internal/api/handler.go::resolveSourceIdentity.
- Known-issue doc:
known_issues/25_federation_azure_gcp_source_identity_failloud.md.
Severity
Medium — no customer data loss, but an operator misconfiguration leaks through to apply-time errors that look like a CUDly bundle bug.
Effort
Small — ~5 LOC + 4 tests.
Summary
The federation IaC handler has a fail-loud guard for empty AWS source account IDs but not for empty Azure/GCP source identities. When
AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID, orGCP_PROJECT_IDare unset on the Lambda, the rendered IaC bundle ships with empty identity fields and customers hit a crypticterraform applyerror.Captured in:
known_issues/25_federation_azure_gcp_source_identity_failloud.mdCurrent behaviour
internal/api/handler.go::resolveSourceIdentity(≈line 446) reads Azure/GCP identity from environment variables. If any are unset, empty strings flow into the generated tfvars/scripts and the federation bundle downloads successfully. The apply-time failure is a blankclient_id/ missing project — the operator has no clear signal that CUDly's own env is misconfigured.The AWS source path in
internal/api/handler_federation.go::populateSourceAccountID(≈line 171) already fails loud:The Azure/GCP equivalent is missing —
populateSourceAccountIDreturns nil immediately for non-AWS source clouds, and nothing else validates the source identity before rendering the bundle.Expected behaviour
The same fail-loud treatment for Azure and GCP deployments, naming the missing env var so the operator knows exactly what to fix.
Steps to reproduce
AZURE_SUBSCRIPTION_IDon the Lambda/Function App (orGCP_PROJECT_IDon Cloud Run).terraform applylater fails with blankclient_id/ missing project — no actionable error at download time.Proposed fix
Extend
populateSourceAccountID(or add a siblingpopulateSourceIdentity) to cover Azure and GCP. Sketch:Test plan
Four tests in
internal/api/handler_federation_test.gothat mockresolveSourceIdentityto return empty fields and assert a non-client-error 500 response is surfaced:SubscriptionID=""→ 500TenantID=""→ 500ProjectID=""→ 500References
fix(api): pre-fill ContactEmail from Session.Email and fail loud on empty SourceAccountID(the AWS-only fix this extends).internal/api/handler_federation.go::populateSourceAccountID,internal/api/handler.go::resolveSourceIdentity.known_issues/25_federation_azure_gcp_source_identity_failloud.md.Severity
Medium — no customer data loss, but an operator misconfiguration leaks through to apply-time errors that look like a CUDly bundle bug.
Effort
Small — ~5 LOC + 4 tests.