Skip to content

Commit 978b5df

Browse files
committed
Throw exception if duplicate Systems Manager parameter keys (case insensitive) are detected irrespective of whether the parameter is optional or not.
1 parent 81f5b0b commit 978b5df

File tree

7 files changed

+127
-3
lines changed

7 files changed

+127
-3
lines changed

src/Amazon.Extensions.Configuration.SystemsManager/Amazon.Extensions.Configuration.SystemsManager.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<AssemblyName>Amazon.Extensions.Configuration.SystemsManager</AssemblyName>
77
<RootNamespace>Amazon.Extensions.Configuration.SystemsManager</RootNamespace>
88
<OutputType>Library</OutputType>
9-
<VersionPrefix>6.1.1</VersionPrefix>
9+
<VersionPrefix>6.2.0</VersionPrefix>
1010
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1111
<PackageId>Amazon.Extensions.Configuration.SystemsManager</PackageId>
1212
<Title>.NET Configuration Extensions for AWS Systems Manager</Title>

src/Amazon.Extensions.Configuration.SystemsManager/DefaultParameterProcessor.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,29 @@ public virtual IDictionary<string, string> ProcessParameters(IEnumerable<Paramet
6060
{
6161
if (parameter.Type == ParameterType.StringList)
6262
{
63-
result.AddRange(ParseStringList(parameter, path));
63+
var parameterList = ParseStringList(parameter, path);
64+
65+
// Check for duplicate parameter keys.
66+
var stringListKeys = parameterList.Select(p => p.Key);
67+
var duplicateKeys = result.Where(r => stringListKeys.Contains(r.Key, StringComparer.OrdinalIgnoreCase)).Select(r => r.Key);
68+
if (duplicateKeys.Count() > 0)
69+
{
70+
throw new DuplicateParameterException($"Duplicate parameters '{string.Join(";", duplicateKeys)}' found. Parameter keys are case-insensitive.");
71+
}
72+
73+
result.AddRange(parameterList);
6474
}
6575
else
6676
{
67-
result.Add(new KeyValuePair<string, string>(GetKey(parameter, path), GetValue(parameter, path)));
77+
string parameterKey = GetKey(parameter, path);
78+
79+
// Check for duplicate parameter key.
80+
if (result.Any(r => string.Equals(r.Key, parameterKey, StringComparison.OrdinalIgnoreCase)))
81+
{
82+
throw new DuplicateParameterException($"Duplicate parameter '{parameterKey}' found. Parameter keys are case-insensitive.");
83+
}
84+
85+
result.Add(new KeyValuePair<string, string>(parameterKey, GetValue(parameter, path)));
6886
}
6987
}
7088

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
using System;
17+
18+
namespace Amazon.Extensions.Configuration.SystemsManager
19+
{
20+
/// <summary>
21+
/// This exception is thrown when duplicate Systems Manager parameter keys (case insensitive) are
22+
/// detected irrespective of whether the parameter is optional or not.
23+
/// <para>
24+
/// For example, keys <c>/some-path/some-key</c> and <c>/some-path/SOME-KEY</c> are considered as duplicates.
25+
/// </para>
26+
/// </summary>
27+
public class DuplicateParameterException : ArgumentException
28+
{
29+
/// <summary>
30+
/// Initializes a new instance of DuplicateParameterException.
31+
/// </summary>
32+
public DuplicateParameterException()
33+
{
34+
}
35+
36+
/// <summary>
37+
/// Initializes a new instance of DuplicateParameterException.
38+
/// </summary>
39+
/// <param name="message">The message that describes the error.</param>
40+
public DuplicateParameterException(string message)
41+
: base(message)
42+
{
43+
}
44+
45+
/// <summary>
46+
/// Initializes a new instance of DuplicateParameterException.
47+
/// </summary>
48+
/// <param name="message">The message that describes the error.</param>
49+
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
50+
public DuplicateParameterException(string message, Exception innerException)
51+
: base(message, innerException)
52+
{
53+
}
54+
}
55+
}

src/Amazon.Extensions.Configuration.SystemsManager/JsonParameterProcessor.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ public override IDictionary<string, string> ProcessParameters(IEnumerable<Parame
4040
foreach (var keyValue in parameterDictionary)
4141
{
4242
string key = (!string.IsNullOrEmpty(prefix) ? ConfigurationPath.Combine(prefix, keyValue.Key) : keyValue.Key);
43+
44+
// Check for duplicate parameter key.
45+
if (outputDictionary.ContainsKey(key))
46+
{
47+
throw new DuplicateParameterException($"Duplicate parameter '{key}' found. Parameter keys are case-insensitive.");
48+
}
49+
4350
outputDictionary.Add(key, keyValue.Value);
4451
}
4552
}

src/Amazon.Extensions.Configuration.SystemsManager/SystemsManagerConfigurationProvider.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ private async Task LoadAsync(bool reload)
120120
OnReload();
121121
}
122122
}
123+
catch (DuplicateParameterException) // Throw duplicate parameter exception irrespective of whether parameter is optional or not.
124+
{
125+
throw;
126+
}
123127
catch (Exception ex)
124128
{
125129
if (Source.Optional) return;

test/Amazon.Extensions.Configuration.SystemsManager.Tests/DefaultParameterProcessorTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,31 @@ public void ProcessParametersRootTest()
7171

7272
Assert.All(data, item => Assert.Equal(item.Value, item.Key));
7373
}
74+
75+
[Fact]
76+
public void DuplicateSimpleParametersTest()
77+
{
78+
var parameters = new List<Parameter>
79+
{
80+
new Parameter {Name = "/start/path/p1", Value = "p1:1"},
81+
new Parameter {Name = "/start/path/P1", Value = "p1:2"}
82+
};
83+
84+
const string path = "/start/path";
85+
Assert.Throws<DuplicateParameterException>(() => _parameterProcessor.ProcessParameters(parameters, path));
86+
}
87+
88+
[Fact]
89+
public void DuplicateStringListParametersTest()
90+
{
91+
var parameters = new List<Parameter>
92+
{
93+
new Parameter {Name = "/string-list/multiple", Value = "p1,p2,p3", Type = ParameterType.StringList},
94+
new Parameter {Name = "/string-list/MULTIPLE", Value = "p3,p5,p6", Type = ParameterType.StringList}
95+
};
96+
97+
const string path = "/string-list";
98+
Assert.Throws<DuplicateParameterException>(() => _parameterProcessor.ProcessParameters(parameters, path));
99+
}
74100
}
75101
}

test/Amazon.Extensions.Configuration.SystemsManager.Tests/JsonParameterProcessorTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,19 @@ public void ProcessParametersTest()
4444

4545
Assert.All(expected, item => Assert.Equal(item.Value, data[item.Key]));
4646
}
47+
48+
[Fact]
49+
public void DuplicateParametersTest()
50+
{
51+
var parameters = new List<Parameter>
52+
{
53+
new Parameter {Name = "/p1", Value = "{\"p1\": \"p1\"}"},
54+
new Parameter {Name = "p2", Value = "{\"p2\": \"p2\"}"},
55+
new Parameter {Name = "p1", Value = "{\"P1\": \"p1-1\"}"},
56+
};
57+
58+
const string path = "/";
59+
Assert.Throws<DuplicateParameterException>(() => _parameterProcessor.ProcessParameters(parameters, path));
60+
}
4761
}
4862
}

0 commit comments

Comments
 (0)