-
Notifications
You must be signed in to change notification settings - Fork 56
[ChangeSafety] Phase 1: AcquirePolicyToken Support #449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Related to this change: Azure/azure-powershell#28711 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request implements Phase 1 of the ChangeSafety feature, adding support for acquiring Azure Policy tokens to validate resource operations. The implementation introduces a new -AcquirePolicyToken dynamic parameter and handler that intercepts write operations to automatically obtain policy tokens from the Azure Authorization API.
Key changes:
- Introduces
AcquirePolicyTokenHandlerto intercept HTTP requests and acquire policy tokens for write operations - Adds
-AcquirePolicyTokendynamic parameter to Azure cmdlets (excludes read-only operations like Get-/List-/Show-*) - Implements feature flag support via environment variable
AZ_ENABLE_POLICY_TOKENand config keyEnablePolicyToken
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Common/AcquirePolicyTokenHandler.cs | New handler that acquires policy tokens from Azure Authorization API and attaches them to outgoing requests |
| src/Common/AzurePSCmdlet.cs | Adds dynamic parameter support, feature flag logic, and handler registration for policy token acquisition |
| src/ResourceManager/Version2016_09_01/AzureRMCmdlet.cs | Updates GetDynamicParameters to call base implementation to support inherited dynamic parameters |
| src/Common/Utilities/GeneralUtilities.cs | Adds policy token header to authorization header sanitization list |
| src/Authentication.Abstractions/Models/ConfigKeysForCommon.cs | Defines new config key for EnablePolicyToken feature flag |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| || commandName.EndsWith("List", StringComparison.OrdinalIgnoreCase) | ||
| || commandName.EndsWith("Show", StringComparison.OrdinalIgnoreCase)) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for excluding read-only cmdlets checks if the command name ends with 'List' or 'Show', but cmdlets typically follow the pattern 'Get-', 'Remove-', 'Set-*' where the verb comes first. The check should use StartsWith for 'List' and 'Show' as well, not EndsWith. For example, 'List-AzResource' would be caught correctly, but a cmdlet named 'Get-ResourceList' would incorrectly be excluded.
| || commandName.EndsWith("List", StringComparison.OrdinalIgnoreCase) | |
| || commandName.EndsWith("Show", StringComparison.OrdinalIgnoreCase)) | |
| || commandName.StartsWith("List", StringComparison.OrdinalIgnoreCase) | |
| || commandName.StartsWith("Show", StringComparison.OrdinalIgnoreCase)) |
|
|
||
| if (!(_cmdlet?.IsPolicyTokenFeatureEnabled() ?? false)) | ||
| { | ||
| EnqueueDebug("Skip: feature disabled (EnableAcquirePolicyToken config set to false)."); |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The debug message incorrectly references 'EnableAcquirePolicyToken' config, but the actual config key is 'EnablePolicyToken' as defined in ConfigKeysForCommon.cs. This could confuse users troubleshooting feature flag issues.
| EnqueueDebug("Skip: feature disabled (EnableAcquirePolicyToken config set to false)."); | |
| EnqueueDebug("Skip: feature disabled (EnablePolicyToken config set to false)."); |
| using (var http = new HttpClient()) | ||
| { | ||
| EnqueueDebug($"POST acquirePolicyToken {tokenUri}"); | ||
| var response = await http.SendAsync(tokenRequest, cancellationToken).ConfigureAwait(false); |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a new HttpClient instance for each token request is inefficient and can lead to socket exhaustion under load. HttpClient should be reused or managed via a static instance or IHttpClientFactory. Consider using a shared static HttpClient instance for this handler.
| if (string.IsNullOrEmpty(token)) | ||
| { | ||
| EnqueueDebug("Response OK but token missing."); | ||
| throw new InvalidOperationException($"No token returned. Response:{responseContent}"); |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space after colon in error message. Should be 'Response: {responseContent}' for consistency with other error messages in the file.
| throw new InvalidOperationException($"No token returned. Response:{responseContent}"); | |
| throw new InvalidOperationException($"No token returned. Response: {responseContent}"); |
| catch { } | ||
| } | ||
| } | ||
| catch { } | ||
|
|
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty catch blocks silently swallow exceptions without logging, making debugging configuration issues difficult. Consider logging the exception or at minimum adding a comment explaining why the exception is intentionally ignored.
| catch { } | |
| } | |
| } | |
| catch { } | |
| catch (Exception ex) | |
| { | |
| Debug.WriteLine($"Exception in configManager.GetConfigValue: {ex}"); | |
| } | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| Debug.WriteLine($"Exception in IsPolicyTokenFeatureEnabled: {ex}"); | |
| } |
No description provided.