feat(azure/cloud): support passing authentication credentials as variables#381
Merged
Conversation
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>
sebastiancorrea81
approved these changes
Jun 5, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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:
And without a parent at org level with `authentication = {}`: `authentication` is absent from the response entirely.