Skip to content

Commit

Permalink
CosmosClientOptions: Adds validation for ApplicationName (#3455)
Browse files Browse the repository at this point in the history
* IGNORE ME

* IGNORE ME

* Implemented suggested changes, verify that application name does not contain illegal or dangerous characters

* Cleaned up unnecessary code

* Now using built-in NameValueHeaderValueParser

* Clarified Exception message

* Fixed added bug

* Updated Contracts

* Wrapped Format Exception in Argument Exception

* Moved test to unit tests, removed unused variable

* restored ClientTests.cs

* Now checking application name parse with a dummy http request to correctly catch all valid/invalid names

* pushed accidentily unstaged changes

* Use Base HttpRequestMessage

Co-authored-by: Matias Quaranta <ealsur@users.noreply.github.com>

* Changed User Agent String to HttpConstant

* Changed User Agent String to HttpConstant

Co-authored-by: Nalu Tripician <ntripician@microsoft.com>
Co-authored-by: Matias Quaranta <ealsur@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 19, 2022
1 parent 36ee222 commit 5d70017
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 10 deletions.
22 changes: 20 additions & 2 deletions Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ namespace Microsoft.Azure.Cosmos
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Azure.Cosmos.Fluent;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Newtonsoft.Json;
using Telemetry;

/// <summary>
/// Defines all the configurable options that the CosmosClient requires.
Expand Down Expand Up @@ -69,6 +69,7 @@ public class CosmosClientOptions
private PortReuseMode? portReuseMode;
private IWebProxy webProxy;
private Func<HttpClient> httpClientFactory;
private string applicationName;

/// <summary>
/// Creates a new CosmosClientOptions
Expand All @@ -90,7 +91,24 @@ public CosmosClientOptions()
/// <remarks>
/// Setting this property after sending any request won't have any effect.
/// </remarks>
public string ApplicationName { get; set; }
public string ApplicationName
{
get => this.applicationName;
set
{
try
{
HttpRequestMessage dummyMessage = new HttpRequestMessage();
dummyMessage.Headers.Add(HttpConstants.HttpHeaders.UserAgent, value);
}
catch (FormatException fme)
{
throw new ArgumentException($"Application name '{value}' is invalid.", fme);
}

this.applicationName = value;
}
}

/// <summary>
/// Get or set session container for the client
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Results>
<Result>
<Input>
<Description>Null Partition Key Value</Description>
<Query>SELECT * FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>false</ExecuteAsPassThrough>
</Output>
</Result>
<Result>
<Input>
<Description>None Partition Key Value</Description>
<Query>SELECT * FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>false</ExecuteAsPassThrough>
</Output>
</Result>
<Result>
<Input>
<Description>C# Null Partition Key Value</Description>
<Query>SELECT * FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>false</ExecuteAsPassThrough>
</Output>
</Result>
</Results>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Results>
<Result>
<Input>
<Description>Partition Key + Value and Distinct</Description>
<Query>SELECT DISTINCT c.key FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>true</ExecuteAsPassThrough>
</Output>
</Result>
<Result>
<Input>
<Description>Partition Key + Value and Min Aggregate</Description>
<Query>SELECT VALUE MIN(c.key) FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>true</ExecuteAsPassThrough>
</Output>
</Result>
<Result>
<Input>
<Description>Partition Key + Value Fields</Description>
<Query>SELECT c.key FROM c</Query>
<PartitionKeys>
<Key>/pk</Key>
</PartitionKeys>
<PartitionKeyType>Hash</PartitionKeyType>
</Input>
<Output>
<ExecuteAsPassThrough>true</ExecuteAsPassThrough>
</Output>
</Result>
</Results>
Original file line number Diff line number Diff line change
Expand Up @@ -2896,11 +2896,9 @@
"Attributes": [],
"MethodInfo": "System.String ApplicationRegion;CanRead:True;CanWrite:True;System.String get_ApplicationRegion();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ApplicationRegion(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String get_ApplicationName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"System.String get_ApplicationName()": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"Attributes": [],
"MethodInfo": "System.String get_ApplicationName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String get_ApplicationRegion()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
Expand Down Expand Up @@ -2934,11 +2932,9 @@
],
"MethodInfo": "Void set_AllowBulkExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Void set_ApplicationName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Void set_ApplicationName(System.String)": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"Attributes": [],
"MethodInfo": "Void set_ApplicationName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Void set_ApplicationPreferredRegions(System.Collections.Generic.IReadOnlyList`1[System.String])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,33 @@ public void WithQuorumReadWithEventualConsistencyAccount()
Assert.IsTrue(cosmosClientOptions.EnableUpgradeConsistencyToLocalQuorum);
}

[TestMethod]
public void InvalidApplicationNameCatchTest()
{

string[] illegalChars = new string[] { "<", ">", "\"", "{", "}", "\\", "[", "]", ";", ":", "@", "=", "(", ")", "," };
string baseName = "illegal";

foreach (string illegal in illegalChars)
{
Assert.ThrowsException<ArgumentException>(() => new CosmosClientOptions
{
ApplicationName = baseName + illegal
});


Assert.ThrowsException<ArgumentException>(() => new CosmosClientOptions
{
ApplicationName = illegal + baseName
});

Assert.ThrowsException<ArgumentException>(() => new CosmosClientOptions
{
ApplicationName = illegal
});
}
}

private class TestWebProxy : IWebProxy
{
public ICredentials Credentials { get; set; }
Expand Down

0 comments on commit 5d70017

Please sign in to comment.