Skip to content

Commit 2a600ff

Browse files
authored
[Storage] Fixed bug where connection string with account name not set in Storage Client (Azure#48636)
* WIP - blobs, datalake is done, not yet shares or queues is done yet * Add fix into Share Files and Queues; Updated Changelog * Added fix to set account name when passed SharedKey * Forgot to commit datalake directory and file * Updated changelog
1 parent 4a91466 commit 2a600ff

35 files changed

+532
-59
lines changed

sdk/storage/Azure.Storage.Blobs/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
### Breaking Changes
99

1010
### Bugs Fixed
11-
11+
- Fixed bug where a `BlobServiceClient`, `BlobContainerClient`, `BlobBaseClient` created with a connection string with an account name specified (e.g. "AccountName=..;"), the account name was not populated on the Storage Clients if the account name was not also specified in the endpoint. (#42925)
12+
- Fixed bug where a `BlobServiceClient`, `BlobContainerClient`, `BlobBaseClient` created with a `StorageSharedKeyCredential`, the account name was not populated on the Storage Clients if the account name was not also specified in the endpoint. (#42925)
1213
### Other Changes
1314

1415
## 12.24.0-beta.1 (2025-02-11)

sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ public BlobBaseClient(string connectionString, string blobContainerName, string
207207
BlobName = blobName
208208
};
209209
_uri = builder.ToUri();
210+
_accountName = conn.AccountName;
211+
_containerName = blobContainerName;
212+
_name = blobName;
210213

211214
_clientConfiguration = new BlobClientConfiguration(
212215
pipeline: options.Build(conn.Credentials),
@@ -278,6 +281,7 @@ public BlobBaseClient(Uri blobUri, StorageSharedKeyCredential credential, BlobCl
278281
sasCredential: null,
279282
tokenCredential: null)
280283
{
284+
_accountName ??= credential?.AccountName;
281285
}
282286

283287
/// <summary>
@@ -605,9 +609,9 @@ private void SetNameFieldsIfNull()
605609
if (_name == null || _containerName == null || _accountName == null)
606610
{
607611
var builder = new BlobUriBuilder(Uri, ClientConfiguration.TrimBlobNameSlashes);
608-
_name = builder.BlobName;
609-
_containerName = builder.BlobContainerName;
610-
_accountName = builder.AccountName;
612+
_name ??= builder.BlobName;
613+
_containerName ??= builder.BlobContainerName;
614+
_accountName ??= builder.AccountName;
611615
}
612616
}
613617

sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public BlobContainerClient(string connectionString, string blobContainerName, Bl
193193
BlobContainerName = blobContainerName
194194
};
195195
_uri = builder.ToUri();
196+
_name = blobContainerName;
197+
_accountName = conn.AccountName;
196198
options ??= new BlobClientOptions();
197199

198200
_clientConfiguration = new BlobClientConfiguration(
@@ -275,6 +277,7 @@ public BlobContainerClient(Uri blobContainerUri, StorageSharedKeyCredential cred
275277
Argument.AssertNotNull(blobContainerUri, nameof(blobContainerUri));
276278
HttpPipelinePolicy authPolicy = credential.AsPolicy();
277279
_uri = blobContainerUri;
280+
_accountName = credential.AccountName;
278281
_authenticationPolicy = authPolicy;
279282
options ??= new BlobClientOptions();
280283

@@ -626,8 +629,8 @@ private void SetNameFieldsIfNull()
626629
if (_name == null || _accountName == null)
627630
{
628631
var builder = new BlobUriBuilder(Uri, ClientConfiguration.TrimBlobNameSlashes);
629-
_name = builder.BlobContainerName;
630-
_accountName = builder.AccountName;
632+
_name ??= builder.BlobContainerName;
633+
_accountName ??= builder.AccountName;
631634
}
632635
}
633636

sdk/storage/Azure.Storage.Blobs/src/BlobServiceClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ public BlobServiceClient(string connectionString, BlobClientOptions options)
149149
_uri = conn.BlobEndpoint;
150150
options ??= new BlobClientOptions();
151151
_authenticationPolicy = StorageClientOptions.GetAuthenticationPolicy(conn.Credentials);
152+
_accountName = conn.AccountName;
152153

153154
_clientConfiguration = new BlobClientConfiguration(
154155
pipeline: options.Build(_authenticationPolicy),
@@ -330,6 +331,7 @@ internal BlobServiceClient(
330331
authentication,
331332
options?._clientSideEncryptionOptions?.Clone())
332333
{
334+
_accountName ??= storageSharedKeyCredential?.AccountName;
333335
}
334336

335337
/// <summary>

sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ public void Ctor_ConnectionString()
7070
Assert.AreEqual("accountName", builder2.AccountName);
7171
}
7272

73+
[Test]
74+
public void Ctor_ConnectionString_CustomUri()
75+
{
76+
var accountName = "accountName";
77+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
78+
79+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
80+
var blobEndpoint = new Uri("http://customdomain/" + accountName);
81+
var blobSecondaryEndpoint = new Uri("http://customdomain/" + accountName + "-secondary");
82+
83+
var connectionString = new StorageConnectionString(credentials, blobStorageUri: (blobEndpoint, blobSecondaryEndpoint));
84+
85+
var containerName = "containername";
86+
var blobName = "blobname";
87+
88+
BlobBaseClient blobClient = new BlobBaseClient(connectionString.ToString(true), containerName, blobName);
89+
90+
Assert.AreEqual(containerName, blobClient.BlobContainerName);
91+
Assert.AreEqual(blobName, blobClient.Name);
92+
Assert.AreEqual(accountName, blobClient.AccountName);
93+
}
94+
7395
[RecordedTest]
7496
public async Task Ctor_ConnectionStringEscapeBlobName()
7597
{
@@ -214,6 +236,24 @@ public void Ctor_CPK_EncryptionScope()
214236
new ArgumentException("CustomerProvidedKey and EncryptionScope cannot both be set"));
215237
}
216238

239+
[Test]
240+
public void Ctor_SharedKey_AccountName()
241+
{
242+
// Arrange
243+
var accountName = "accountName";
244+
var containerName = "containerName";
245+
var blobName = "blobName";
246+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
247+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
248+
var blobEndpoint = new Uri($"https://customdomain/{containerName}/{blobName}");
249+
250+
BlobBaseClient blobClient = new BlobBaseClient(blobEndpoint, credentials);
251+
252+
Assert.AreEqual(accountName, blobClient.AccountName);
253+
Assert.AreEqual(containerName, blobClient.BlobContainerName);
254+
Assert.AreEqual(blobName, blobClient.Name);
255+
}
256+
217257
[RecordedTest]
218258
public async Task Ctor_AzureSasCredential()
219259
{

sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,30 @@ public void Ctor_ConnectionString()
6363
Assert.AreEqual(accountName, builder.AccountName);
6464
}
6565

66+
[Test]
67+
public void Ctor_ConnectionString_CustomUri()
68+
{
69+
var accountName = "accountName";
70+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
71+
72+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
73+
var blobEndpoint = new Uri("http://customdomain/" + accountName);
74+
var blobSecondaryEndpoint = new Uri("http://customdomain/" + accountName + "-secondary");
75+
76+
var connectionString = new StorageConnectionString(credentials, blobStorageUri: (blobEndpoint, blobSecondaryEndpoint));
77+
78+
var containerName = "containername";
79+
80+
BlobContainerClient container = new BlobContainerClient(connectionString.ToString(true), containerName);
81+
82+
var builder = new BlobUriBuilder(container.Uri);
83+
84+
Assert.AreEqual(containerName, builder.BlobContainerName);
85+
Assert.AreEqual("", builder.BlobName);
86+
Assert.AreEqual(containerName, container.Name);
87+
Assert.AreEqual(accountName, container.AccountName);
88+
}
89+
6690
[RecordedTest]
6791
[TestCase(true)] // https://github.com/Azure/azure-sdk-for-net/issues/9110
6892
[TestCase(false)]
@@ -303,6 +327,22 @@ public void Ctor_CPK_EncryptionScope()
303327
new ArgumentException("CustomerProvidedKey and EncryptionScope cannot both be set"));
304328
}
305329

330+
[Test]
331+
public void Ctor_SharedKey_AccountName()
332+
{
333+
// Arrange
334+
var accountName = "accountName";
335+
var containerName = "containerName";
336+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
337+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
338+
var blobEndpoint = new Uri($"https://customdomain/{containerName}");
339+
340+
BlobContainerClient blobClient = new BlobContainerClient(blobEndpoint, credentials);
341+
342+
Assert.AreEqual(accountName, blobClient.AccountName);
343+
Assert.AreEqual(containerName, blobClient.Name);
344+
}
345+
306346
[RecordedTest]
307347
public async Task Ctor_AzureSasCredential()
308348
{

sdk/storage/Azure.Storage.Blobs/tests/ServiceClientTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ public void Ctor_ConnectionString()
5656
Assert.AreEqual(accountName, builder2.AccountName);
5757
}
5858

59+
[Test]
60+
public void Ctor_ConnectionString_CustomUri()
61+
{
62+
var accountName = "accountName";
63+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
64+
65+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
66+
var blobEndpoint = new Uri("http://customdomain/" + accountName);
67+
var blobSecondaryEndpoint = new Uri("http://customdomain/" + accountName + "-secondary");
68+
69+
var connectionString = new StorageConnectionString(credentials, blobStorageUri: (blobEndpoint, blobSecondaryEndpoint));
70+
71+
BlobServiceClient service = new BlobServiceClient(connectionString.ToString(true));
72+
73+
Assert.AreEqual(accountName, service.AccountName);
74+
}
75+
5976
[RecordedTest]
6077
public void Ctor_Uri()
6178
{
@@ -125,6 +142,20 @@ public void Ctor_CPK_EncryptionScope()
125142
new ArgumentException("CustomerProvidedKey and EncryptionScope cannot both be set"));
126143
}
127144

145+
[Test]
146+
public void Ctor_SharedKey_AccountName()
147+
{
148+
// Arrange
149+
var accountName = "accountName";
150+
var accountKey = Convert.ToBase64String(new byte[] { 0, 1, 2, 3, 4, 5 });
151+
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
152+
var blobEndpoint = new Uri($"https://customdomain/");
153+
154+
BlobServiceClient blobClient = new BlobServiceClient(blobEndpoint, credentials);
155+
156+
Assert.AreEqual(accountName, blobClient.AccountName);
157+
}
158+
128159
[RecordedTest]
129160
public async Task Ctor_AzureSasCredential()
130161
{

sdk/storage/Azure.Storage.Common/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Fixed bug to ensure that the accumulated disposables within the internal `StorageWriteStream` are disposed properly in the event that an exception is thrown during the disposal process. (#47781)
1212
- Fixed bug to Redact SAS credentials from Error.SasCredentialRequiresUriWithoutSas message.
1313
- Fixed bug where LazyLoadingReadOnlyStream overprovisions the default buffer memory for OpenRead
14+
- Fixed bug where a client created with a connection string with an account name specified (e.g. "AccountName=..;"), the account name was not populated on the Storage Clients if the account name was not also specified in the endpoint. (#42925)
1415

1516
### Other Changes
1617
- Implemented IAsyncDisposable in StorageWriteStream

sdk/storage/Azure.Storage.Common/src/Shared/StorageConnectionString.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ public static StorageConnectionString DevelopmentStorageAccount
222222
public object Credentials { get; set; }
223223

224224
/// <summary>
225-
/// Private record of the account name for use in ToString(bool).
225+
/// Gets the account name.
226226
/// </summary>
227-
internal string _accountName;
227+
public string AccountName;
228228

229229
/// <summary>
230230
/// Parses a connection string and returns a <see cref="StorageConnectionString"/> created
@@ -516,7 +516,7 @@ static Uri CreateUri(string endpoint, string sasToken)
516516
Settings = s_validCredentials(settings)
517517
};
518518

519-
accountInformation._accountName = settingOrDefault(Constants.ConnectionStrings.AccountNameSetting);
519+
accountInformation.AccountName = settingOrDefault(Constants.ConnectionStrings.AccountNameSetting);
520520

521521
return true;
522522
}

sdk/storage/Azure.Storage.Common/tests/Shared/TestExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ internal static StorageConnectionString CreateStorageConnectionString(
126126
throw Errors.ArgumentNull(nameof(accountName));
127127
}
128128

129-
conn._accountName = accountName;
129+
conn.AccountName = accountName;
130130
var sasToken = (storageCredentials is SharedAccessSignatureCredentials sasCredentials) ? sasCredentials.SasToken : default;
131131

132132
var scheme = useHttps ? Constants.Https : Constants.Http;
@@ -205,9 +205,9 @@ internal static string ToString(this StorageConnectionString conn, bool exportSe
205205
listOfSettings.Add(ToString(conn.Credentials, exportSecrets));
206206
}
207207

208-
if (!string.IsNullOrWhiteSpace(conn._accountName) && (conn.Credentials is StorageSharedKeyCredential sharedKeyCredentials ? string.IsNullOrWhiteSpace(sharedKeyCredentials.AccountName) : true))
208+
if (!string.IsNullOrWhiteSpace(conn.AccountName) && (conn.Credentials is StorageSharedKeyCredential sharedKeyCredentials ? string.IsNullOrWhiteSpace(sharedKeyCredentials.AccountName) : true))
209209
{
210-
listOfSettings.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", Constants.ConnectionStrings.AccountNameSetting, conn._accountName));
210+
listOfSettings.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", Constants.ConnectionStrings.AccountNameSetting, conn.AccountName));
211211
}
212212

213213
return string.Join(";", listOfSettings);

0 commit comments

Comments
 (0)