Skip to content

feat(azure/cloud): support passing authentication credentials as variables#381

Merged
gdrojas merged 6 commits into
mainfrom
fix/azure-cloud-require-authentication
Jun 10, 2026
Merged

feat(azure/cloud): support passing authentication credentials as variables#381
gdrojas merged 6 commits into
mainfrom
fix/azure-cloud-require-authentication

Conversation

@gdrojas

@gdrojas gdrojas commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Problem

The `azure/cloud` module hardcoded `authentication = {}` with no way to pass Azure credentials via Terraform. The intended workflow was to fill them via the UI after `tofu apply`, but the UI does not display Cloud Providers with an empty `authentication` block and no parent to inherit from — creating a chicken-and-egg: the provider exists in the API but is invisible in the UI.

Confirmed by comparing `data_source.stored_keys` between a working provider (credentials filled post-creation) and a new one created with the current module:

Field Working provider New provider
`authentication.client_id`
`authentication.client_secret`
`authentication.subscription_id`
`authentication.tenant_id`

Fix

Add optional variables `client_id`, `client_secret` (sensitive), `subscription_id`, and `tenant_id` (all `default = null`).

The `authentication` block is built dynamically — only keys with non-null values are included:

```hcl
authentication = {
for k, v in {
client_id = var.client_id
client_secret = var.client_secret
subscription_id = var.subscription_id
tenant_id = var.tenant_id
} : k => v if v != null
}
```

A `precondition` enforces all-or-none: passing a partial set (e.g. only `client_id`) produces an inconsistent authentication block and is rejected at plan time.

This is non-breaking: when all variables are omitted, the expression produces `authentication = {}` — identical to the previous hardcoded behavior.

Inheritance — empirically verified

NullPlatform merges provider attributes across the NRN scope hierarchy (org → account → namespace). A provider created with `authentication = {}` inherits credentials from the nearest ancestor that has them set.

Verified by creating a provider at account level with `authentication = {}` where a base provider with real credentials existed:

Endpoint Result
`GET /provider/{id}` (merged) Returns parent's `authentication` block
`GET /provider/{id}?no_merge=true` `authentication` absent — not stored locally
Same parent `tag.id` in both Confirms the values come from the parent, not a copy

And without a parent at org level with `authentication = {}`: `authentication` is absent from the response entirely.

Previously the module hardcoded `authentication = {}` and relied on
users to fill credentials via the UI after apply. This caused a
chicken-and-egg: the UI does not display providers with an empty
authentication block, so users had no way to complete the setup.

Add required variables for client_id, client_secret, subscription_id,
and tenant_id. Remove the `lifecycle { ignore_changes = [attributes] }`
block since Terraform now owns the full attribute set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gdrojas and others added 4 commits June 5, 2026 14:39
The new client_id, client_secret, subscription_id and tenant_id variables
are required — add dummy values to the test fixtures so the plan succeeds.
Also add assertions to verify authentication fields are present in attributes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…inheritance

When authentication variables are omitted (default = null), the attributes
block sends authentication = {} which triggers inheritance from a parent
cloud provider at org or account scope. When provided, Terraform manages
the credentials explicitly.

This replaces the previous lifecycle { ignore_changes = [attributes] }
workaround: Terraform now correctly owns what it sets and inherits the
rest from the NullPlatform provider hierarchy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents Terraform from overwriting authentication credentials set via
UI or API after initial apply.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ables

- Remove sensitive = true from client_id (not a secret — appears in
  Azure logs and OAuth URLs; keeping it sensitive hides networking
  changes in plan output)
- Add precondition enforcing all-or-none: caller must provide all four
  credentials (client_id, client_secret, subscription_id, tenant_id)
  or none — partial sets produce an inconsistent authentication block
- Add test case verifying that partial credentials trigger the precondition

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gdrojas gdrojas changed the title fix(azure/cloud): require authentication credentials as variables feat(azure/cloud): support passing authentication credentials as variables Jun 5, 2026
@gdrojas gdrojas merged commit 2313640 into main Jun 10, 2026
44 checks passed
@gdrojas gdrojas deleted the fix/azure-cloud-require-authentication branch June 10, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants