diff --git a/sdk/tables/data-tables/CHANGELOG.md b/sdk/tables/data-tables/CHANGELOG.md index 223f5b6c521e..a7e1239c721b 100644 --- a/sdk/tables/data-tables/CHANGELOG.md +++ b/sdk/tables/data-tables/CHANGELOG.md @@ -1,9 +1,11 @@ # Release History -## 13.2.3 (Unreleased) +## 13.3.0 (Unreleased) ### Features Added +- Added support for Entra ID credentials when targeting a Cosmos endpoint. + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/tables/data-tables/package.json b/sdk/tables/data-tables/package.json index 5d8e74b48832..222ced730cfc 100644 --- a/sdk/tables/data-tables/package.json +++ b/sdk/tables/data-tables/package.json @@ -1,6 +1,6 @@ { "name": "@azure/data-tables", - "version": "13.2.3", + "version": "13.3.0", "description": "An isomorphic client library for the Azure Tables service.", "sdk-type": "client", "main": "dist/index.js", diff --git a/sdk/tables/data-tables/src/TableClient.ts b/sdk/tables/data-tables/src/TableClient.ts index d7a748eb440c..df334c779bbd 100644 --- a/sdk/tables/data-tables/src/TableClient.ts +++ b/sdk/tables/data-tables/src/TableClient.ts @@ -41,7 +41,7 @@ import { isSASCredential, isTokenCredential, } from "@azure/core-auth"; -import { STORAGE_SCOPE, TablesLoggingAllowedHeaderNames } from "./utils/constants"; +import { COSMOS_SCOPE, STORAGE_SCOPE, TablesLoggingAllowedHeaderNames } from "./utils/constants"; import { decodeContinuationToken, encodeContinuationToken } from "./utils/continuationToken"; import { deserialize, @@ -224,6 +224,7 @@ export class TableClient { ) { this.url = url; this.tableName = tableName; + const isCosmos = isCosmosEndpoint(this.url); const credential = isCredential(credentialOrOptions) ? credentialOrOptions : undefined; this.credential = credential; @@ -255,10 +256,11 @@ export class TableClient { } if (isTokenCredential(credential)) { - setTokenChallengeAuthenticationPolicy(generatedClient.pipeline, credential, STORAGE_SCOPE); + const scope = isCosmos ? COSMOS_SCOPE : STORAGE_SCOPE; + setTokenChallengeAuthenticationPolicy(generatedClient.pipeline, credential, scope); } - if (isCosmosEndpoint(this.url)) { + if (isCosmos) { generatedClient.pipeline.addPolicy(cosmosPatchPolicy()); } diff --git a/sdk/tables/data-tables/src/TableServiceClient.ts b/sdk/tables/data-tables/src/TableServiceClient.ts index 872177a0fb83..76bb11cf4dd7 100644 --- a/sdk/tables/data-tables/src/TableServiceClient.ts +++ b/sdk/tables/data-tables/src/TableServiceClient.ts @@ -27,7 +27,7 @@ import { isSASCredential, isTokenCredential, } from "@azure/core-auth"; -import { STORAGE_SCOPE, TablesLoggingAllowedHeaderNames } from "./utils/constants"; +import { COSMOS_SCOPE, STORAGE_SCOPE, TablesLoggingAllowedHeaderNames } from "./utils/constants"; import { Service, Table } from "./generated"; import { injectSecondaryEndpointHeader, @@ -48,6 +48,7 @@ import { setTokenChallengeAuthenticationPolicy } from "./utils/challengeAuthenti import { tablesNamedKeyCredentialPolicy } from "./tablesNamedCredentialPolicy"; import { tablesSASTokenPolicy } from "./tablesSASTokenPolicy"; import { tracingClient } from "./utils/tracing"; +import { isCosmosEndpoint } from "./utils/isCosmosEndpoint"; /** * A TableServiceClient represents a Client to the Azure Tables service allowing you @@ -159,6 +160,7 @@ export class TableServiceClient { options?: TableServiceClientOptions, ) { this.url = url; + const isCosmos = isCosmosEndpoint(this.url); const credential = isCredential(credentialOrOptions) ? credentialOrOptions : undefined; const clientOptions = (!isCredential(credentialOrOptions) ? credentialOrOptions : options) || {}; @@ -187,7 +189,8 @@ export class TableServiceClient { } if (isTokenCredential(credential)) { - setTokenChallengeAuthenticationPolicy(client.pipeline, credential, STORAGE_SCOPE); + const scope = isCosmos ? COSMOS_SCOPE : STORAGE_SCOPE; + setTokenChallengeAuthenticationPolicy(client.pipeline, credential, scope); } if (options?.version) { diff --git a/sdk/tables/data-tables/src/generated/generatedClientContext.ts b/sdk/tables/data-tables/src/generated/generatedClientContext.ts index 0e39252a913a..1452595727f1 100644 --- a/sdk/tables/data-tables/src/generated/generatedClientContext.ts +++ b/sdk/tables/data-tables/src/generated/generatedClientContext.ts @@ -33,7 +33,7 @@ export class GeneratedClientContext extends coreClient.ServiceClient { requestContentType: "application/json; charset=utf-8" }; - const packageDetails = `azsdk-js-data-tables/13.2.3`; + const packageDetails = `azsdk-js-data-tables/13.3.0`; const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}` diff --git a/sdk/tables/data-tables/src/utils/constants.ts b/sdk/tables/data-tables/src/utils/constants.ts index effaf31fe8c5..840234d9d1d5 100644 --- a/sdk/tables/data-tables/src/utils/constants.ts +++ b/sdk/tables/data-tables/src/utils/constants.ts @@ -6,6 +6,7 @@ export const TRANSACTION_HTTP_VERSION_1_1 = "HTTP/1.1"; export const TRANSACTION_HTTP_LINE_ENDING = "\r\n"; export const STORAGE_SCOPE = "https://storage.azure.com/.default"; +export const COSMOS_SCOPE = "https://cosmos.azure.com/.default"; export const HeaderConstants = { AUTHORIZATION: "authorization", diff --git a/sdk/tables/data-tables/src/utils/tracing.ts b/sdk/tables/data-tables/src/utils/tracing.ts index 81a8d8786b2e..9d970bcf63ef 100644 --- a/sdk/tables/data-tables/src/utils/tracing.ts +++ b/sdk/tables/data-tables/src/utils/tracing.ts @@ -10,5 +10,5 @@ import { createTracingClient } from "@azure/core-tracing"; export const tracingClient = createTracingClient({ namespace: "Microsoft.Data.Tables", packageName: "@azure/data-tables", - packageVersion: "13.2.3", + packageVersion: "13.3.0", }); diff --git a/sdk/tables/data-tables/swagger/README.md b/sdk/tables/data-tables/swagger/README.md index 3b42a8a28aaf..6184d00c70de 100644 --- a/sdk/tables/data-tables/swagger/README.md +++ b/sdk/tables/data-tables/swagger/README.md @@ -6,7 +6,7 @@ ```yaml v3: true -package-version: 13.2.3 +package-version: 13.3.0 package-name: "@azure/data-tables" title: TablesClient description: Tables Client diff --git a/sdk/tables/data-tables/test/public/endpoint.spec.ts b/sdk/tables/data-tables/test/public/endpoint.spec.ts new file mode 100644 index 000000000000..030113c8bab5 --- /dev/null +++ b/sdk/tables/data-tables/test/public/endpoint.spec.ts @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { TableClient } from "../../src/TableClient"; +import { TableServiceClient } from "../../src/TableServiceClient"; +import { assert } from "chai"; +import { TokenCredential } from "@azure/core-auth"; +import { COSMOS_SCOPE } from "../../src/utils/constants"; + +export class FakeCredential implements TokenCredential { + public lastScopes?: string | string[]; + + getToken(scopes: string | string[]): Promise { + this.lastScopes = scopes; + return Promise.resolve(null); + } +} + +describe(`Cosmos endpoint tests`, function () { + describe("TableServiceClient", function () { + it("Sets the scope correctly on the auth policy", async function () { + const credential = new FakeCredential(); + const fakeEndpointUrl = "https://localhost/"; + const client = new TableServiceClient(fakeEndpointUrl, credential); + try { + await client.createTable("Test"); + } catch { + // this will throw because the fake credential doesn't return a valid token, + // but we'll still invoke it with the right scope first. + } + assert.deepEqual(credential.lastScopes, [COSMOS_SCOPE]); + }); + }); + + describe("TableClient", function () { + it("Sets the scope correctly on the auth policy", async function () { + const credential = new FakeCredential(); + const fakeEndpointUrl = "https://localhost/"; + const client = new TableClient(fakeEndpointUrl, "Test", credential); + try { + await client.createTable(); + } catch { + // this will throw because the fake credential doesn't return a valid token, + // but we'll still invoke it with the right scope first. + } + assert.deepEqual(credential.lastScopes, [COSMOS_SCOPE]); + }); + }); +}); diff --git a/sdk/tables/data-tables/test/public/utils/recordedClient.ts b/sdk/tables/data-tables/test/public/utils/recordedClient.ts index 22301b065029..babbf662dd53 100644 --- a/sdk/tables/data-tables/test/public/utils/recordedClient.ts +++ b/sdk/tables/data-tables/test/public/utils/recordedClient.ts @@ -35,6 +35,9 @@ const sanitizerOptions: SanitizerOptions = { const recorderOptions: RecorderStartOptions = { envSetupForPlayback: replaceableVariables, sanitizerOptions, + removeCentralSanitizers: [ + "AZSDK3493", // .name in the body is not a secret + ], }; export type CreateClientMode =