diff --git a/documentation/change-safety.md b/documentation/change-safety.md new file mode 100644 index 000000000000..6ef232a4f99b --- /dev/null +++ b/documentation/change-safety.md @@ -0,0 +1,74 @@ +# Azure Policy Change Safety (Preview) + +Azure Policy Change Safety introduces *policy evaluation tokens* that must accompany certain state-changing (write) operations to Azure Resource Manager (ARM). These short‑lived, signed tokens prove that any required external validators (approvals, safety checks, etc.) have run before the change is submitted. + +## Status +This feature is behind a configuration flag and requires a corresponding update to the shared `azure-powershell-common` library. Until that dependency is updated, enabling the flag has no effect. + +## Phased Rollout +| Phase | Scope | Visible Parameter(s) | Notes | +|-------|-------|----------------------|-------| +| Phase 1 (current) | Token acquisition only | `-AcquirePolicyToken` | `-ChangeReference` is suppressed/hidden. | +| Phase 2 (planned) | Adds change reference association | `-AcquirePolicyToken`, `-ChangeReference` | `-ChangeReference` implies token acquisition. | + +If you see references to `-ChangeReference` below, they describe future behavior (Phase 2) and are not yet active. + +## Enabling the Feature +```powershell +Update-AzConfig -EnablePolicyToken $true +``` + +You can also disable it later: +```powershell +Update-AzConfig -EnablePolicyToken $false +``` + +Environment variable override (session only): +```powershell +$env:AZ_ENABLE_POLICY_TOKEN = "true" +``` + +## Parameters (write cmdlets; conditional & phased) +| Parameter | Type | Phase | Purpose | +|----------|------|-------|---------| +| `-AcquirePolicyToken` | Switch | 1+ | Force acquisition of a change-safety policy token for the operation. | +| `-ChangeReference ` | String | 2 | (Planned) Associates the operation with an external change record (e.g., a ChangeState resource ID); implies token acquisition. Not yet surfaced. | + +Read-only (GET/list/show) cmdlets will not expose these parameters. + +## Example Usage (Phase 1) +```powershell +# Acquire a token automatically for a write operation +New-AzResourceGroup -Name rg-change -Location eastus -AcquirePolicyToken +``` + +### Phase 2 (Planned) Example (Not Yet Active) +```powershell +# This will only work once Phase 2 ships +New-AzVm -Name web01 -ResourceGroupName rg-change -ChangeReference \ + "/providers/Microsoft.Change/changes/abc123/changeStates/state456" -Image UbuntuLTS -Location eastus +``` + +## How It Works (Conceptual) +1. You provide `-AcquirePolicyToken` (Phase 1) or later `-ChangeReference` (Phase 2) on a write cmdlet. +2. The client calls `Microsoft.Authorization/acquirePolicyToken` (synchronously) with method, URI and body of the impending request plus optional change reference (Phase 2). +3. Service returns a signed token; it is attached as `x-ms-policy-external-evaluations` header on the actual ARM call. +4. ARM validates token; if missing or invalid and required policies exist, the request is rejected. + +## Troubleshooting +| Symptom | Possible Cause | Mitigation | +|--------|----------------|-----------| +| Parameters not visible | Feature flag not enabled or common library not updated | Run `Update-AzConfig -EnablePolicyToken $true` and ensure you have a version that includes the handler. | +| Error: failed to acquire policy token | Network / permission / unsupported scope | Re-run with `-Debug`; confirm subscription context and that the operation is write. | +| ARM denies request citing policy token | Missing `-AcquirePolicyToken` / `-ChangeReference` where a policy now requires it | Re-run with one of the parameters enabled. | + +## Logging & Privacy +The token is sensitive and should not appear in logs. The implementation sanitizes the header value in debug traces. + +## Roadmap (Subject to Change) +* Support asynchronous (202 Accepted) acquisition mode +* Retry and token reuse for identical retried writes +* Warning decoration for policy-denied responses when the feature is disabled + +--- +Feedback welcome—file an issue with `[ChangeSafety]` in the title. Please specify "Phase 1" in the issue if `-ChangeReference` is not yet available in your build. diff --git a/src/Accounts/Accounts.Test/UnitTest/EnablePolicyTokenConfigTest.cs b/src/Accounts/Accounts.Test/UnitTest/EnablePolicyTokenConfigTest.cs new file mode 100644 index 000000000000..14884a887857 --- /dev/null +++ b/src/Accounts/Accounts.Test/UnitTest/EnablePolicyTokenConfigTest.cs @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------------- +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// ---------------------------------------------------------------------------------- +using Microsoft.Azure.Commands.Common.Authentication.Config.Definitions; +using NUnit.Framework; + +namespace Microsoft.Azure.Commands.Profile.Test.UnitTest +{ + [TestFixture] + public class EnablePolicyTokenConfigTest + { + [Test] + public void Default_IsFalse_And_KeyMatches() + { + var cfg = new EnablePolicyTokenConfig(); + Assert.AreEqual(false, cfg.DefaultValue, "Default should be false for safety opt-in."); + Assert.AreEqual("EnablePolicyToken", cfg.Key, "Config key mismatch."); + } + } +} diff --git a/src/Accounts/Accounts.sln b/src/Accounts/Accounts.sln index 0354bb56e5e8..97dff36e5200 100644 --- a/src/Accounts/Accounts.sln +++ b/src/Accounts/Accounts.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 @@ -24,6 +24,38 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssemblyLoading", "Assembly EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyLoading.Test", "AssemblyLoading.Test\AssemblyLoading.Test.csproj", "{D4540550-9808-4DEB-9D5E-F88E38D58A85}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aks", "..\..\..\azure-powershell-common\src\Aks\Aks.csproj", "{4BD463A6-3D39-4D37-85ED-B6794563B229}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Authentication.Abstractions", "..\..\..\azure-powershell-common\src\Authentication.Abstractions\Authentication.Abstractions.csproj", "{CD310380-C39F-40FD-8EF8-6195377AE33E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Authorization", "..\..\..\azure-powershell-common\src\Authorization\Authorization.csproj", "{B65C0C51-0865-471E-9E0D-D80FCB5139BE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "..\..\..\azure-powershell-common\src\Common\Common.csproj", "{0E13990D-8388-40F2-A1A5-EF021904B639}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compute", "..\..\..\azure-powershell-common\src\Compute\Compute.csproj", "{20385AB9-6173-40AF-9682-3719EDCBB701}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph.Rbac", "..\..\..\azure-powershell-common\src\Graph.Rbac\Graph.Rbac.csproj", "{074F219F-3809-4E8C-851F-F9E500B4C613}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyVault", "..\..\..\azure-powershell-common\src\KeyVault\KeyVault.csproj", "{A12E0186-357D-40BB-9C57-54CB434124FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Monitor", "..\..\..\azure-powershell-common\src\Monitor\Monitor.csproj", "{CCD12822-329F-407F-8D13-B3A07380E4ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network", "..\..\..\azure-powershell-common\src\Network\Network.csproj", "{BE9F9291-5AA7-4F41-A15A-D40A0643D14D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyInsights", "..\..\..\azure-powershell-common\src\PolicyInsights\PolicyInsights.csproj", "{ED22DABE-350A-4583-8F1D-D339C4A7889F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceManager", "..\..\..\azure-powershell-common\src\ResourceManager\ResourceManager.csproj", "{2A573D7F-EEBA-4D79-A389-92CEA274D6A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Share", "..\..\..\azure-powershell-common\src\Share\Share.csproj", "{CBCB3967-93B0-405D-B9CC-535636019E59}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storage", "..\..\..\azure-powershell-common\src\Storage\Storage.csproj", "{63E504E1-F492-4029-B3EC-C6BEF7673B6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storage.Management", "..\..\..\azure-powershell-common\src\Storage.Management\Storage.Management.csproj", "{98E7A744-F071-4869-87C1-27F89B398FC0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Strategies", "..\..\..\azure-powershell-common\src\Strategies\Strategies.csproj", "{872F59A5-2444-48EA-808B-F7EB15784AC5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Websites", "..\..\..\azure-powershell-common\src\Websites\Websites.csproj", "{B721A545-D346-437A-9020-7179EEFCDB9E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +102,70 @@ Global {D4540550-9808-4DEB-9D5E-F88E38D58A85}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4540550-9808-4DEB-9D5E-F88E38D58A85}.Release|Any CPU.ActiveCfg = Release|Any CPU {D4540550-9808-4DEB-9D5E-F88E38D58A85}.Release|Any CPU.Build.0 = Release|Any CPU + {4BD463A6-3D39-4D37-85ED-B6794563B229}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BD463A6-3D39-4D37-85ED-B6794563B229}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BD463A6-3D39-4D37-85ED-B6794563B229}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BD463A6-3D39-4D37-85ED-B6794563B229}.Release|Any CPU.Build.0 = Release|Any CPU + {CD310380-C39F-40FD-8EF8-6195377AE33E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD310380-C39F-40FD-8EF8-6195377AE33E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD310380-C39F-40FD-8EF8-6195377AE33E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD310380-C39F-40FD-8EF8-6195377AE33E}.Release|Any CPU.Build.0 = Release|Any CPU + {B65C0C51-0865-471E-9E0D-D80FCB5139BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B65C0C51-0865-471E-9E0D-D80FCB5139BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B65C0C51-0865-471E-9E0D-D80FCB5139BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B65C0C51-0865-471E-9E0D-D80FCB5139BE}.Release|Any CPU.Build.0 = Release|Any CPU + {0E13990D-8388-40F2-A1A5-EF021904B639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E13990D-8388-40F2-A1A5-EF021904B639}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E13990D-8388-40F2-A1A5-EF021904B639}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E13990D-8388-40F2-A1A5-EF021904B639}.Release|Any CPU.Build.0 = Release|Any CPU + {20385AB9-6173-40AF-9682-3719EDCBB701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20385AB9-6173-40AF-9682-3719EDCBB701}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20385AB9-6173-40AF-9682-3719EDCBB701}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20385AB9-6173-40AF-9682-3719EDCBB701}.Release|Any CPU.Build.0 = Release|Any CPU + {074F219F-3809-4E8C-851F-F9E500B4C613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {074F219F-3809-4E8C-851F-F9E500B4C613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {074F219F-3809-4E8C-851F-F9E500B4C613}.Release|Any CPU.ActiveCfg = Release|Any CPU + {074F219F-3809-4E8C-851F-F9E500B4C613}.Release|Any CPU.Build.0 = Release|Any CPU + {A12E0186-357D-40BB-9C57-54CB434124FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A12E0186-357D-40BB-9C57-54CB434124FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A12E0186-357D-40BB-9C57-54CB434124FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A12E0186-357D-40BB-9C57-54CB434124FB}.Release|Any CPU.Build.0 = Release|Any CPU + {CCD12822-329F-407F-8D13-B3A07380E4ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCD12822-329F-407F-8D13-B3A07380E4ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCD12822-329F-407F-8D13-B3A07380E4ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCD12822-329F-407F-8D13-B3A07380E4ED}.Release|Any CPU.Build.0 = Release|Any CPU + {BE9F9291-5AA7-4F41-A15A-D40A0643D14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE9F9291-5AA7-4F41-A15A-D40A0643D14D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE9F9291-5AA7-4F41-A15A-D40A0643D14D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE9F9291-5AA7-4F41-A15A-D40A0643D14D}.Release|Any CPU.Build.0 = Release|Any CPU + {ED22DABE-350A-4583-8F1D-D339C4A7889F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED22DABE-350A-4583-8F1D-D339C4A7889F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED22DABE-350A-4583-8F1D-D339C4A7889F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED22DABE-350A-4583-8F1D-D339C4A7889F}.Release|Any CPU.Build.0 = Release|Any CPU + {2A573D7F-EEBA-4D79-A389-92CEA274D6A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A573D7F-EEBA-4D79-A389-92CEA274D6A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A573D7F-EEBA-4D79-A389-92CEA274D6A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A573D7F-EEBA-4D79-A389-92CEA274D6A8}.Release|Any CPU.Build.0 = Release|Any CPU + {CBCB3967-93B0-405D-B9CC-535636019E59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBCB3967-93B0-405D-B9CC-535636019E59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBCB3967-93B0-405D-B9CC-535636019E59}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBCB3967-93B0-405D-B9CC-535636019E59}.Release|Any CPU.Build.0 = Release|Any CPU + {63E504E1-F492-4029-B3EC-C6BEF7673B6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63E504E1-F492-4029-B3EC-C6BEF7673B6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63E504E1-F492-4029-B3EC-C6BEF7673B6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63E504E1-F492-4029-B3EC-C6BEF7673B6D}.Release|Any CPU.Build.0 = Release|Any CPU + {98E7A744-F071-4869-87C1-27F89B398FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98E7A744-F071-4869-87C1-27F89B398FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98E7A744-F071-4869-87C1-27F89B398FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98E7A744-F071-4869-87C1-27F89B398FC0}.Release|Any CPU.Build.0 = Release|Any CPU + {872F59A5-2444-48EA-808B-F7EB15784AC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {872F59A5-2444-48EA-808B-F7EB15784AC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {872F59A5-2444-48EA-808B-F7EB15784AC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {872F59A5-2444-48EA-808B-F7EB15784AC5}.Release|Any CPU.Build.0 = Release|Any CPU + {B721A545-D346-437A-9020-7179EEFCDB9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B721A545-D346-437A-9020-7179EEFCDB9E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B721A545-D346-437A-9020-7179EEFCDB9E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B721A545-D346-437A-9020-7179EEFCDB9E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Accounts/AssemblyLoading/AssemblyLoading.csproj b/src/Accounts/AssemblyLoading/AssemblyLoading.csproj index b9c2e2d65331..7abe794d81eb 100644 --- a/src/Accounts/AssemblyLoading/AssemblyLoading.csproj +++ b/src/Accounts/AssemblyLoading/AssemblyLoading.csproj @@ -1,4 +1,7 @@ + + + Accounts diff --git a/src/Accounts/Authentication/Authentication.csproj b/src/Accounts/Authentication/Authentication.csproj index db62a8659e78..2c36b85ac0d8 100644 --- a/src/Accounts/Authentication/Authentication.csproj +++ b/src/Accounts/Authentication/Authentication.csproj @@ -22,6 +22,23 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Accounts/Authentication/Config/ConfigInitializer.cs b/src/Accounts/Authentication/Config/ConfigInitializer.cs index 9ed0494523c7..94a4685bdf64 100644 --- a/src/Accounts/Authentication/Config/ConfigInitializer.cs +++ b/src/Accounts/Authentication/Config/ConfigInitializer.cs @@ -239,6 +239,7 @@ private void RegisterConfigs(IConfigManager configManager) "AZURE_CLIENTS_SHOW_SECRETS_WARNING", new[] { AppliesTo.Az })); configManager.RegisterConfig(new DisableInstanceDiscoveryConfig()); + configManager.RegisterConfig(new EnablePolicyTokenConfig()); } } } diff --git a/src/Accounts/Authentication/Config/Definitions/EnablePolicyTokenConfig.cs b/src/Accounts/Authentication/Config/Definitions/EnablePolicyTokenConfig.cs new file mode 100644 index 000000000000..f1a500b7d7a8 --- /dev/null +++ b/src/Accounts/Authentication/Config/Definitions/EnablePolicyTokenConfig.cs @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Microsoft.Azure.Commands.Common.Authentication.Config; +using Microsoft.Azure.PowerShell.Common.Config; +using Microsoft.Azure.Commands.Shared.Config; +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Common.Authentication.Config.Definitions +{ + /// + /// Enables acquisition and attachment of Azure Policy Change Safety tokens for write operations + /// when the user opts in and supplies -AcquirePolicyToken or -ChangeReference parameters (implemented + /// in the shared base cmdlet in azure-powershell-common). This repository only contributes the + /// configuration surface; functionality becomes active when the updated common library is present. + /// + internal class EnablePolicyTokenConfig : TypedConfig + { + public override object DefaultValue => false; + + public override string Key => ConfigKeys.EnablePolicyToken; + + public override string HelpMessage => "Enables acquisition and attachment of Azure Policy change-safety tokens on write operations when -AcquirePolicyToken or -ChangeReference are specified."; + + public override IReadOnlyCollection CanApplyTo => new[] { AppliesTo.Az }; + } +} diff --git a/src/Resources/Authorization.Management.Sdk/Authorization.Management.Sdk.csproj b/src/Resources/Authorization.Management.Sdk/Authorization.Management.Sdk.csproj index 600ac4477157..ae91d6f77a12 100644 --- a/src/Resources/Authorization.Management.Sdk/Authorization.Management.Sdk.csproj +++ b/src/Resources/Authorization.Management.Sdk/Authorization.Management.Sdk.csproj @@ -1,4 +1,23 @@ + + + + + + + + + + + + + + + + + + + Resources diff --git a/src/Resources/ResourceManager/ResourceManager.csproj b/src/Resources/ResourceManager/ResourceManager.csproj index a6ccd8aeed9b..0a2f21e41e51 100644 --- a/src/Resources/ResourceManager/ResourceManager.csproj +++ b/src/Resources/ResourceManager/ResourceManager.csproj @@ -20,6 +20,26 @@ + + + + + + + + + + + + + + + + + + + + True diff --git a/src/Resources/Tags/Tags.csproj b/src/Resources/Tags/Tags.csproj index e3dd8d64850b..89890cf90335 100644 --- a/src/Resources/Tags/Tags.csproj +++ b/src/Resources/Tags/Tags.csproj @@ -1,5 +1,25 @@ + + + + + + + + + + + + + + + + + + + + Resources diff --git a/src/Storage/Storage.Management.Sdk/Storage.Management.Sdk.csproj b/src/Storage/Storage.Management.Sdk/Storage.Management.Sdk.csproj index fdceffd821e1..21f91cbaa6e5 100644 --- a/src/Storage/Storage.Management.Sdk/Storage.Management.Sdk.csproj +++ b/src/Storage/Storage.Management.Sdk/Storage.Management.Sdk.csproj @@ -6,6 +6,26 @@ + + + + + + + + + + + + + + + + + + + + netstandard2.0 Microsoft.Azure.PowerShell.Storage.Management.Sdk diff --git a/src/Storage/Storage.Management/Storage.Management.csproj b/src/Storage/Storage.Management/Storage.Management.csproj index 6b3c2db719d5..926aaf11da90 100644 --- a/src/Storage/Storage.Management/Storage.Management.csproj +++ b/src/Storage/Storage.Management/Storage.Management.csproj @@ -24,6 +24,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Storage/Storage.common/Storage.common.csproj b/src/Storage/Storage.common/Storage.common.csproj index 4add4bf55085..5786e37f35b4 100644 --- a/src/Storage/Storage.common/Storage.common.csproj +++ b/src/Storage/Storage.common/Storage.common.csproj @@ -16,6 +16,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs index fc099dc02340..23dcdd148e11 100644 --- a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs @@ -29,6 +29,8 @@ namespace Microsoft.WindowsAzure.Commands.Storage.File.Cmdlet using Microsoft.WindowsAzure.Commands.Utilities.Common; using System; using System.Runtime.InteropServices; + using System.Linq; // For merging dynamic parameters + using System.Collections.ObjectModel; // For RuntimeDefinedParameter attribute collection using LocalConstants = Microsoft.WindowsAzure.Commands.Storage.File.Constants; using LocalDirectory = System.IO.Directory; using LocalPath = System.IO.Path; @@ -295,14 +297,34 @@ await DataMovementTransferHelper.DoTransfer(() => DoEndProcessing(); } } - public object GetDynamicParameters() + // Override to merge base dynamic parameters (e.g. AcquirePolicyToken) with existing Windows-only parameter. + public override object GetDynamicParameters() { + var baseResult = base.GetDynamicParameters(); + var dict = baseResult as RuntimeDefinedParameterDictionary; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { context = new WindowsOnlyParameters(); - return context; + + if (dict == null) + { + dict = new RuntimeDefinedParameterDictionary(); + } + + var winParamProp = typeof(WindowsOnlyParameters).GetProperty("PreserveSMBAttribute"); + if (winParamProp != null && !dict.ContainsKey(winParamProp.Name)) + { + var attrs = winParamProp.GetCustomAttributes(true).OfType().ToArray(); + var attrCollection = new Collection(attrs.ToList()); + var rd = new RuntimeDefinedParameter(winParamProp.Name, winParamProp.PropertyType, attrCollection); + dict.Add(winParamProp.Name, rd); + } + + return dict; } - else return null; + + return baseResult; } private WindowsOnlyParameters context; } diff --git a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs index 32143e94996a..605f4478648e 100644 --- a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs @@ -34,6 +34,8 @@ namespace Microsoft.WindowsAzure.Commands.Storage.File.Cmdlet using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Threading.Tasks; + using System.Linq; // For merging dynamic parameters (minimal addition) + using System.Collections.ObjectModel; // For RuntimeDefinedParameter attribute collection using LocalConstants = Microsoft.WindowsAzure.Commands.Storage.File.Constants; [Cmdlet("Set", Azure.Commands.ResourceManager.Common.AzureRMConstants.AzurePrefix + "StorageFileContent", SupportsShouldProcess = true, DefaultParameterSetName = LocalConstants.ShareNameParameterSetName), OutputType(typeof(AzureStorageFile))] @@ -469,14 +471,40 @@ private async Task BuildShareFileClientInstanceFromPathAsync(st } } - public object GetDynamicParameters() + // Override to cooperatively merge base dynamic parameters (e.g. AcquirePolicyToken) with existing Windows-only ones. + public override object GetDynamicParameters() { + // Get base dynamic parameters (may be null or a RuntimeDefinedParameterDictionary) + var baseResult = base.GetDynamicParameters(); + var dict = baseResult as RuntimeDefinedParameterDictionary; + + // If on Windows, we still need the previous dynamic parameter object (context) for PreserveSMBAttribute usage later. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { context = new WindowsOnlyParameters(); - return context; + + // If base didn't return a dictionary, create one so we can add our parameter while still preserving base param(s). + if (dict == null) + { + dict = new RuntimeDefinedParameterDictionary(); + } + + // Reflect the dynamic parameter properties from WindowsOnlyParameters (currently minimal: PreserveSMBAttribute). + // We only add if not already present to avoid collisions. + var winParamProp = typeof(WindowsOnlyParameters).GetProperty("PreserveSMBAttribute"); + if (winParamProp != null && !dict.ContainsKey(winParamProp.Name)) + { + var attrs = winParamProp.GetCustomAttributes(true).OfType().ToArray(); + var attrCollection = new Collection(attrs.ToList()); + var rd = new RuntimeDefinedParameter(winParamProp.Name, winParamProp.PropertyType, attrCollection); + dict.Add(winParamProp.Name, rd); + } + + return dict; // Return combined dictionary (base params + Windows-only param) } - else return null; + + // Non-Windows: just pass through whatever base produced (could be null or already a dictionary including AcquirePolicyToken) + return baseResult; } private WindowsOnlyParameters context; } diff --git a/src/Storage/Storage/Storage.csproj b/src/Storage/Storage/Storage.csproj index 25433d9563af..4a1eb3c2bce6 100644 --- a/src/Storage/Storage/Storage.csproj +++ b/src/Storage/Storage/Storage.csproj @@ -24,6 +24,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/shared/ConfigKeys.cs b/src/shared/ConfigKeys.cs index 91f6d7edae81..cd7868a38e64 100644 --- a/src/shared/ConfigKeys.cs +++ b/src/shared/ConfigKeys.cs @@ -38,5 +38,6 @@ internal static class ConfigKeys public const string EnvCheckForUpgrade = "AZUREPS_CHECK_FOR_UPGRADE"; public const string DisplaySecretsWarning = "DisplaySecretsWarning"; public const string LoginExperienceV2 = "LoginExperienceV2"; + public const string EnablePolicyToken = "EnablePolicyToken"; } } diff --git a/tools/AzDev/src/AzDev.csproj b/tools/AzDev/src/AzDev.csproj index b278d1fff81a..d5ec36d636d7 100644 --- a/tools/AzDev/src/AzDev.csproj +++ b/tools/AzDev/src/AzDev.csproj @@ -9,12 +9,14 @@ - + + - - + + + diff --git a/tools/Common.Netcore.Dependencies.targets b/tools/Common.Netcore.Dependencies.targets index d54042dd601a..1f318794108b 100644 --- a/tools/Common.Netcore.Dependencies.targets +++ b/tools/Common.Netcore.Dependencies.targets @@ -3,22 +3,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +