From 5470410b97d8269532de18db367844fa23650478 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 08:45:14 +0000 Subject: [PATCH] [copilot-finds] Bug: Connection string parser uses case-sensitive key lookup Azure connection string keys should be case-insensitive per Azure SDK conventions. The parser stored keys as-is but looked them up by exact case, causing failures when keys used lowercase or mixed casing (e.g. 'endpoint=...' instead of 'Endpoint=...'). Fix: normalize keys to lowercase during parsing and lookup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/connection-string.ts | 4 +- .../test/unit/connection-string.spec.ts | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/durabletask-js-azuremanaged/src/connection-string.ts b/packages/durabletask-js-azuremanaged/src/connection-string.ts index e2877e73..a436643e 100644 --- a/packages/durabletask-js-azuremanaged/src/connection-string.ts +++ b/packages/durabletask-js-azuremanaged/src/connection-string.ts @@ -87,7 +87,7 @@ export class DurableTaskAzureManagedConnectionString { } private getValue(name: string): string | undefined { - return this.properties.get(name); + return this.properties.get(name.toLowerCase()); } private getRequiredValue(name: string): string { @@ -108,7 +108,7 @@ export class DurableTaskAzureManagedConnectionString { if (equalsIndex > 0) { const key = pair.substring(0, equalsIndex).trim(); const value = pair.substring(equalsIndex + 1).trim(); - properties.set(key, value); + properties.set(key.toLowerCase(), value); } } diff --git a/packages/durabletask-js-azuremanaged/test/unit/connection-string.spec.ts b/packages/durabletask-js-azuremanaged/test/unit/connection-string.spec.ts index 00767dbe..ca4eed13 100644 --- a/packages/durabletask-js-azuremanaged/test/unit/connection-string.spec.ts +++ b/packages/durabletask-js-azuremanaged/test/unit/connection-string.spec.ts @@ -67,6 +67,46 @@ describe("DurableTaskAzureManagedConnectionString", () => { "The connection string must contain a TaskHub property", ); }); + + it("should parse connection string with all-lowercase keys", () => { + const connectionString = new DurableTaskAzureManagedConnectionString( + "endpoint=https://example.com;authentication=ManagedIdentity;taskhub=myTaskHub", + ); + + expect(connectionString.getEndpoint()).toBe("https://example.com"); + expect(connectionString.getAuthentication()).toBe("ManagedIdentity"); + expect(connectionString.getTaskHubName()).toBe("myTaskHub"); + }); + + it("should parse connection string with all-uppercase keys", () => { + const connectionString = new DurableTaskAzureManagedConnectionString( + "ENDPOINT=https://example.com;AUTHENTICATION=ManagedIdentity;TASKHUB=myTaskHub", + ); + + expect(connectionString.getEndpoint()).toBe("https://example.com"); + expect(connectionString.getAuthentication()).toBe("ManagedIdentity"); + expect(connectionString.getTaskHubName()).toBe("myTaskHub"); + }); + + it("should parse connection string with mixed-case keys", () => { + const connectionString = new DurableTaskAzureManagedConnectionString( + "endPoint=https://example.com;AUTHENTICATION=ManagedIdentity;taskHub=myTaskHub", + ); + + expect(connectionString.getEndpoint()).toBe("https://example.com"); + expect(connectionString.getAuthentication()).toBe("ManagedIdentity"); + expect(connectionString.getTaskHubName()).toBe("myTaskHub"); + }); + + it("should preserve value casing with case-insensitive keys", () => { + const connectionString = new DurableTaskAzureManagedConnectionString( + "endpoint=https://MyHost.example.com;authentication=ManagedIdentity;taskhub=MyTaskHub;clientid=My-Client-ID", + ); + + expect(connectionString.getEndpoint()).toBe("https://MyHost.example.com"); + expect(connectionString.getTaskHubName()).toBe("MyTaskHub"); + expect(connectionString.getClientId()).toBe("My-Client-ID"); + }); }); describe("getAdditionallyAllowedTenants", () => { @@ -87,6 +127,16 @@ describe("DurableTaskAzureManagedConnectionString", () => { expect(connectionString.getAdditionallyAllowedTenants()).toBeUndefined(); }); + + it("should match property name case-insensitively", () => { + const connectionStringWithTenants = + VALID_CONNECTION_STRING + ";additionallyallowedtenants=tenant1,tenant2"; + + const connectionString = new DurableTaskAzureManagedConnectionString(connectionStringWithTenants); + const tenants = connectionString.getAdditionallyAllowedTenants(); + + expect(tenants).toEqual(["tenant1", "tenant2"]); + }); }); describe("getClientId", () => {