Skip to content

Commit 4b17c27

Browse files
committed
Merge pull request Azure#1141 from surabhi-pandey/bugbashfixes
additional input validation for Get-AzurermProviderOperation cmdlet
2 parents 5c74dc5 + d44fd91 commit 4b17c27

File tree

5 files changed

+164
-112
lines changed

5 files changed

+164
-112
lines changed

src/ResourceManager/Resources/Commands.Resources.Test/ScenarioTests/ProviderTests.ps1

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,17 @@ function Test-AzureProvider
5353
#>
5454
function Test-AzureProviderOperation
5555
{
56-
# Get all actions by all providers
56+
# Get all operations by all providers
5757
$allActions = Get-AzureRmProviderOperation *
5858
Assert-True { $allActions.Length -gt 0 }
5959

60-
# Get all actions of microsoft.insights provider
60+
# Get all operations of microsoft.insights provider
6161
$insightsActions = Get-AzureRmProviderOperation Microsoft.Insights/*
6262
$insightsActions
6363
Assert-True { $insightsActions.Length -gt 0 }
6464
Assert-True { $allActions.Length -gt $insightsActions.Length }
6565

66-
# Filter non-Microsoft.Insights actions and match the lengths
66+
# Filter non-Microsoft.Insights operations and match the lengths
6767
$nonInsightsActions = $allActions | Where-Object { $_.Operation.ToLower().StartsWith("microsoft.insights/") -eq $false }
6868
$actualLength = $allActions.Length - $nonInsightsActions.Length;
6969
$expectedLength = $insightsActions.Length;
@@ -83,7 +83,7 @@ function Test-AzureProviderOperation
8383
Assert-True { $action.Operation.ToLower().Startswith("microsoft.insights/"); }
8484
}
8585

86-
# Get all Read actions of microsoft.insights provider
86+
# Get all Read operations of microsoft.insights provider
8787
$insightsReadActions = Get-AzureRmProviderOperation Microsoft.Insights/*/read
8888
Assert-True { $insightsReadActions.Length -gt 0 }
8989
Assert-True { $insightsActions.Length -gt $insightsReadActions.Length }
@@ -93,7 +93,7 @@ function Test-AzureProviderOperation
9393
Assert-True { $action.Operation.ToLower().StartsWith("microsoft.insights/");}
9494
}
9595

96-
# Get all Read actions of all providers
96+
# Get all Read operations of all providers
9797
$readActions = Get-AzureRmProviderOperation */read
9898
Assert-True { $readActions.Length -gt 0 }
9999
Assert-True { $readActions.Length -lt $allActions.Length }
@@ -104,18 +104,30 @@ function Test-AzureProviderOperation
104104
Assert-True { $action.Operation.ToLower().EndsWith("/read"); }
105105
}
106106

107-
# Get a particular action
107+
# Get a particular operation
108108
$action = Get-AzureRmProviderOperation Microsoft.OperationalInsights/workspaces/usages/read
109109
Assert-AreEqual $action.Operation.ToLower() "Microsoft.OperationalInsights/workspaces/usages/read".ToLower();
110110

111-
# Get an invalid action
111+
# Get an invalid operation
112112
$action = Get-AzureRmProviderOperation Microsoft.OperationalInsights/workspaces/usages/read/123
113113
Assert-True { $action.Length -eq 0 }
114114

115-
# Get actions for non-existing provider
115+
# Get operations for non-existing provider
116116
$exceptionMessage = "ProviderNotFound: Provider NonExistentProvider not found.";
117117
Assert-Throws { Get-AzureRmProviderOperation NonExistentProvider/* } $exceptionMessage
118118

119-
# Get action for non-existing provider
119+
# Get operations for non-existing provider
120120
Assert-Throws { Get-AzureRmProviderOperation NonExistentProvider/servers/read } $exceptionMessage
121+
122+
# Get operations with invalid search string parts
123+
$exceptionMessage = "Individual parts in the search string should either equal * or not contain *.";
124+
Assert-Throws {Get-AzureRmProviderOperation Microsoft.ClassicCompute/virtual*/read } $exceptionMessage
125+
126+
# Get operations with invalid provider name
127+
$exceptionMessage = "To get all operations under Microsoft.Sql, please specify the search string as Microsoft.Sql/*.";
128+
Assert-Throws {Get-AzureRmProviderOperation Microsoft.Sql } $exceptionMessage
129+
130+
# Get operations with ? in search string
131+
$exceptionMessage = "Wildcard character ? is not supported.";
132+
Assert-Throws {Get-AzureRmProviderOperation Microsoft.Sql/servers/*/rea? } $exceptionMessage
121133
}

src/ResourceManager/Resources/Commands.Resources.Test/SessionRecords/Microsoft.Azure.Commands.Resources.Test.ScenarioTests.ProviderTests/TestAzureProviderOperation.json

Lines changed: 64 additions & 64 deletions
Large diffs are not rendered by default.

src/ResourceManager/Resources/Commands.Resources/Properties/Resources.Designer.cs

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ResourceManager/Resources/Commands.Resources/Properties/Resources.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,13 @@
324324
<data name="RoleDefinitionIdShouldBeAGuid" xml:space="preserve">
325325
<value>Role definition id should be a valid guid.</value>
326326
</data>
327+
<data name="OperationSearchStringInvalidProviderName" xml:space="preserve">
328+
<value>To get all operations under {0}, please specify the search string as {0}/*.</value>
329+
</data>
330+
<data name="OperationSearchStringInvalidWildcard" xml:space="preserve">
331+
<value>Individual parts in the search string should either equal * or not contain *.</value>
332+
</data>
333+
<data name="ProviderOperationUnsupportedWildcard" xml:space="preserve">
334+
<value>Wildcard character ? is not supported.</value>
335+
</data>
327336
</root>

src/ResourceManager/Resources/Commands.Resources/Providers/GetAzureProviderOperationCmdlet.cs

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace Microsoft.Azure.Commands.Resources
2020
using System.Management.Automation;
2121
using Microsoft.Azure.Commands.Resources.Models;
2222
using Microsoft.Azure.Management.Resources.Models;
23+
using ProjectResources = Microsoft.Azure.Commands.Resources.Properties.Resources;
2324

2425
/// <summary>
2526
/// Get an existing resource.
@@ -28,90 +29,93 @@ namespace Microsoft.Azure.Commands.Resources
2829
public class GetAzureProviderOperationCommand : ResourcesBaseCmdlet
2930
{
3031
private const string WildCardCharacter = "*";
32+
private static readonly char Separator = '/';
3133

3234
/// <summary>
3335
/// Gets or sets the provider namespace
3436
/// </summary>
3537
[Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = false, ValueFromPipeline = true, HelpMessage = "The action string.")]
3638
[ValidateNotNullOrEmpty]
37-
public string ActionString { get; set; }
39+
public string OperationSearchString { get; set; }
3840

3941
/// <summary>
4042
/// Executes the cmdlet
4143
/// </summary>
4244
protected override void ProcessRecord()
4345
{
4446
// remove leading and trailing whitespaces
45-
this.ActionString = this.ActionString.Trim();
47+
this.OperationSearchString = this.OperationSearchString.Trim();
4648

47-
List<PSResourceProviderOperation> operationsToDisplay;
49+
ValidateActionSearchString(this.OperationSearchString);
50+
51+
List<PSResourceProviderOperation> operationsToDisplay;
4852

49-
if (this.ActionString.Contains(WildCardCharacter))
53+
if (this.OperationSearchString.Contains(WildCardCharacter))
5054
{
51-
operationsToDisplay = this.ProcessProviderOperationsWithWildCard(ActionString);
55+
operationsToDisplay = this.ProcessProviderOperationsWithWildCard(OperationSearchString);
5256
}
5357
else
5458
{
55-
operationsToDisplay = this.ProcessProviderOperationsWithoutWildCard(ActionString);
59+
operationsToDisplay = this.ProcessProviderOperationsWithoutWildCard(OperationSearchString);
5660
}
5761

5862
this.WriteObject(operationsToDisplay, enumerateCollection: true);
5963
}
6064

65+
private static void ValidateActionSearchString(string actionSearchString)
66+
{
67+
if (actionSearchString.Contains("?"))
68+
{
69+
throw new ArgumentException(ProjectResources.ProviderOperationUnsupportedWildcard);
70+
}
71+
72+
string[] parts = actionSearchString.Split(Separator);
73+
if (parts.Any(p => p.Contains(WildCardCharacter) && p.Length != 1))
74+
{
75+
throw new ArgumentException(ProjectResources.OperationSearchStringInvalidWildcard);
76+
}
77+
78+
if(parts.Length == 1 && parts[0] != WildCardCharacter)
79+
{
80+
throw new ArgumentException(string.Format(ProjectResources.OperationSearchStringInvalidProviderName, parts[0]));
81+
}
82+
}
83+
6184
/// <summary>
6285
/// Get a list of Provider operations in the case that the Actionstring input contains a wildcard
6386
/// </summary>
64-
private List<PSResourceProviderOperation> ProcessProviderOperationsWithWildCard(string actionString)
87+
private List<PSResourceProviderOperation> ProcessProviderOperationsWithWildCard(string actionSearchString)
6588
{
6689
// Filter the list of all operation names to what matches the wildcard
67-
WildcardPattern wildcard = new WildcardPattern(actionString, WildcardOptions.IgnoreCase | WildcardOptions.Compiled);
90+
WildcardPattern wildcard = new WildcardPattern(actionSearchString, WildcardOptions.IgnoreCase | WildcardOptions.Compiled);
6891

6992
List<ProviderOperationsMetadata> providers = new List<ProviderOperationsMetadata>();
70-
71-
string nonWildCardPrefix = GetAzureProviderOperationCommand.GetNonWildcardPrefix(actionString);
72-
if (string.IsNullOrWhiteSpace(nonWildCardPrefix))
93+
string provider = this.OperationSearchString.Split(Separator).First();
94+
if (provider.Equals(WildCardCharacter))
7395
{
7496
// 'Get-AzureRmProviderOperation *' or 'Get-AzureRmProviderOperation */virtualmachines/*'
7597
// get operations for all providers
7698
providers.AddRange(this.ResourcesClient.ListProviderOperationsMetadata());
7799
}
78100
else
79101
{
80-
// Some string exists before the wild card character - potentially the full name of the provider.
81-
string providerFullName = GetAzureProviderOperationCommand.GetResourceProviderFullName(nonWildCardPrefix);
82-
if (!string.IsNullOrWhiteSpace(providerFullName))
83-
{
84-
// we have the full name of the provider. 'Get-AzureRmProviderOperation Microsoft.Sql/servers/*'
85-
// only query for that provider
86-
providers.Add(this.ResourcesClient.GetProviderOperationsMetadata(providerFullName));
87-
}
88-
else
89-
{
90-
// We have only a partial name of the provider, say Microsoft.*/* or Microsoft.*/*/read.
91-
// query for all providers and then do prefix match on the operations
92-
providers.AddRange(this.ResourcesClient.ListProviderOperationsMetadata());
93-
}
102+
// 'Get-AzureRmProviderOperation Microsoft.Compute/virtualmachines/*' or 'Get-AzureRmProviderOperation Microsoft.Sql/*'
103+
providers.Add(this.ResourcesClient.GetProviderOperationsMetadata(provider));
94104
}
95105

96-
return providers.SelectMany(p => GetPSOperationsFromProviderOperationsMetadata(p)).Where(operation => wildcard.IsMatch(operation.Operation)).ToList();
106+
return providers.SelectMany(p => GetPSOperationsFromProviderOperationsMetadata(p)).Where(operation => wildcard.IsMatch(operation.Operation)).ToList();
97107
}
98108

99109
/// <summary>
100110
/// Gets a list of Provider operations in the case that the Actionstring input does not contain a wildcard
101111
/// </summary>
102-
private List<PSResourceProviderOperation> ProcessProviderOperationsWithoutWildCard(string actionString)
112+
private List<PSResourceProviderOperation> ProcessProviderOperationsWithoutWildCard(string operationString)
103113
{
104-
List<PSResourceProviderOperation> operationsToDisplay = new List<PSResourceProviderOperation>();
105-
string providerFullName = GetAzureProviderOperationCommand.GetResourceProviderFullName(actionString);
106-
if (!string.IsNullOrWhiteSpace(providerFullName))
107-
{
108-
// We have the full name of the provider. get operations metadata for this provider
109-
ProviderOperationsMetadata providerOperations = this.ResourcesClient.GetProviderOperationsMetadata(providerFullName);
110-
IEnumerable<PSResourceProviderOperation> flattenedProviderOperations = GetAzureProviderOperationCommand.GetPSOperationsFromProviderOperationsMetadata(providerOperations);
111-
operationsToDisplay.AddRange(flattenedProviderOperations.Where(op => string.Equals(op.Operation, actionString, StringComparison.OrdinalIgnoreCase)));
112-
}
114+
string providerFullName = operationString.Split(Separator).First();
113115

114-
return operationsToDisplay;
116+
ProviderOperationsMetadata providerOperations = this.ResourcesClient.GetProviderOperationsMetadata(providerFullName);
117+
IEnumerable<PSResourceProviderOperation> flattenedProviderOperations = GetAzureProviderOperationCommand.GetPSOperationsFromProviderOperationsMetadata(providerOperations);
118+
return flattenedProviderOperations.Where(op => string.Equals(op.Operation, operationString, StringComparison.OrdinalIgnoreCase)).ToList();
115119
}
116120

117121
private static IEnumerable<PSResourceProviderOperation> GetPSOperationsFromProviderOperationsMetadata(ProviderOperationsMetadata providerOperationsMetadata)
@@ -150,7 +154,7 @@ private static PSResourceProviderOperation ToPSResourceProviderOperation(Operati
150154
/// </summary>
151155
private static string GetResourceProviderFullName(string nonWildCardPrefix)
152156
{
153-
int index = nonWildCardPrefix.IndexOf("/", 0);
157+
int index = nonWildCardPrefix.IndexOf(Separator.ToString(), 0);
154158
return index > 0 ? nonWildCardPrefix.Substring(0, index) : string.Empty;
155159
}
156160

0 commit comments

Comments
 (0)