@azure/identity 4.13.0-alpha.20251103.1 → 4.14.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/constants.d.ts +1 -1
- package/dist/browser/constants.d.ts.map +1 -1
- package/dist/browser/constants.js +1 -1
- package/dist/browser/constants.js.map +1 -1
- package/dist/browser/credentials/workloadIdentityCredentialOptions.d.ts +4 -0
- package/dist/browser/credentials/workloadIdentityCredentialOptions.d.ts.map +1 -1
- package/dist/browser/credentials/workloadIdentityCredentialOptions.js.map +1 -1
- package/dist/browser/util/certificatesUtils.d.ts +13 -0
- package/dist/browser/util/certificatesUtils.d.ts.map +1 -0
- package/dist/browser/util/certificatesUtils.js +47 -0
- package/dist/browser/util/certificatesUtils.js.map +1 -0
- package/dist/commonjs/constants.d.ts +1 -1
- package/dist/commonjs/constants.d.ts.map +1 -1
- package/dist/commonjs/constants.js +1 -1
- package/dist/commonjs/constants.js.map +1 -1
- package/dist/commonjs/credentials/clientCertificateCredential.d.ts.map +1 -1
- package/dist/commonjs/credentials/clientCertificateCredential.js +2 -13
- package/dist/commonjs/credentials/clientCertificateCredential.js.map +1 -1
- package/dist/commonjs/credentials/workloadIdentityCredential.d.ts +20 -0
- package/dist/commonjs/credentials/workloadIdentityCredential.d.ts.map +1 -1
- package/dist/commonjs/credentials/workloadIdentityCredential.js +192 -14
- package/dist/commonjs/credentials/workloadIdentityCredential.js.map +1 -1
- package/dist/commonjs/credentials/workloadIdentityCredentialOptions.d.ts +4 -0
- package/dist/commonjs/credentials/workloadIdentityCredentialOptions.d.ts.map +1 -1
- package/dist/commonjs/credentials/workloadIdentityCredentialOptions.js.map +1 -1
- package/dist/commonjs/util/certificatesUtils.d.ts +13 -0
- package/dist/commonjs/util/certificatesUtils.d.ts.map +1 -0
- package/dist/commonjs/util/certificatesUtils.js +51 -0
- package/dist/commonjs/util/certificatesUtils.js.map +1 -0
- package/dist/esm/constants.d.ts +1 -1
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/credentials/clientCertificateCredential.d.ts.map +1 -1
- package/dist/esm/credentials/clientCertificateCredential.js +2 -13
- package/dist/esm/credentials/clientCertificateCredential.js.map +1 -1
- package/dist/esm/credentials/workloadIdentityCredential.d.ts +20 -0
- package/dist/esm/credentials/workloadIdentityCredential.d.ts.map +1 -1
- package/dist/esm/credentials/workloadIdentityCredential.js +191 -14
- package/dist/esm/credentials/workloadIdentityCredential.js.map +1 -1
- package/dist/esm/credentials/workloadIdentityCredentialOptions.d.ts +4 -0
- package/dist/esm/credentials/workloadIdentityCredentialOptions.d.ts.map +1 -1
- package/dist/esm/credentials/workloadIdentityCredentialOptions.js.map +1 -1
- package/dist/esm/util/certificatesUtils.d.ts +13 -0
- package/dist/esm/util/certificatesUtils.d.ts.map +1 -0
- package/dist/esm/util/certificatesUtils.js +47 -0
- package/dist/esm/util/certificatesUtils.js.map +1 -0
- package/dist/workerd/constants.d.ts +1 -1
- package/dist/workerd/constants.d.ts.map +1 -1
- package/dist/workerd/constants.js +1 -1
- package/dist/workerd/constants.js.map +1 -1
- package/dist/workerd/credentials/clientCertificateCredential.d.ts.map +1 -1
- package/dist/workerd/credentials/clientCertificateCredential.js +2 -13
- package/dist/workerd/credentials/clientCertificateCredential.js.map +1 -1
- package/dist/workerd/credentials/workloadIdentityCredential.d.ts +20 -0
- package/dist/workerd/credentials/workloadIdentityCredential.d.ts.map +1 -1
- package/dist/workerd/credentials/workloadIdentityCredential.js +191 -14
- package/dist/workerd/credentials/workloadIdentityCredential.js.map +1 -1
- package/dist/workerd/credentials/workloadIdentityCredentialOptions.d.ts +4 -0
- package/dist/workerd/credentials/workloadIdentityCredentialOptions.d.ts.map +1 -1
- package/dist/workerd/credentials/workloadIdentityCredentialOptions.js.map +1 -1
- package/dist/workerd/util/certificatesUtils.d.ts +13 -0
- package/dist/workerd/util/certificatesUtils.d.ts.map +1 -0
- package/dist/workerd/util/certificatesUtils.js +47 -0
- package/dist/workerd/util/certificatesUtils.js.map +1 -0
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,WAAW,kBAAkB,CAAC;AAE3C;;;GAGG;AAIH,eAAO,MAAM,uBAAuB,yCAAyC,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,eAAe,WAAW,CAAC;AAExC;;GAEG;AACH,oBAAY,mBAAmB;IAC7B;;OAEG;IACH,UAAU,mCAAmC;IAC7C;;;;;SAKK;IACL,YAAY,qCAAqC;IACjD;;OAEG;IACH,eAAe,qCAAqC;IACpD;;OAEG;IACH,gBAAgB,sCAAsC;CACvD;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uCAAuC,CAAC;AAEzE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,EAAU,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,eAAe,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAE3C;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,MAAM,CAAN,IAAY,mBAoBX;AApBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;;;;SAKK;IACL,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EApBW,mBAAmB,KAAnB,mBAAmB,QAoB9B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAE5D;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAa,CAAC,GAAG,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * Current version of the `@azure/identity` package.\n */\nexport const SDK_VERSION = `4.14.0-beta.1`;\n\n/**\n * The default client ID for authentication\n * @internal\n */\n// TODO: temporary - this is the Azure CLI clientID - we'll replace it when\n// Developer Sign On application is available\n// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9\nexport const DeveloperSignOnClientId = \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\";\n\n/**\n * The default tenant for authentication\n * @internal\n */\nexport const DefaultTenantId = \"common\";\n\n/**\n * A list of known Azure authority hosts\n */\nexport enum AzureAuthorityHosts {\n /**\n * China-based Azure Authority Host\n */\n AzureChina = \"https://login.chinacloudapi.cn\",\n /**\n * Germany-based Azure Authority Host\n *\n * @deprecated Microsoft Cloud Germany was closed on October 29th, 2021.\n *\n * */\n AzureGermany = \"https://login.microsoftonline.de\",\n /**\n * US Government Azure Authority Host\n */\n AzureGovernment = \"https://login.microsoftonline.us\",\n /**\n * Public Cloud Azure Authority Host\n */\n AzurePublicCloud = \"https://login.microsoftonline.com\",\n}\n\n/**\n * @internal\n * The default authority host.\n */\nexport const DefaultAuthorityHost = AzureAuthorityHosts.AzurePublicCloud;\n\n/**\n * @internal\n * The default environment host for Azure Public Cloud\n */\nexport const DefaultAuthority = \"login.microsoftonline.com\";\n\n/**\n * @internal\n * Allow acquiring tokens for any tenant for multi-tentant auth.\n */\nexport const ALL_TENANTS: string[] = [\"*\"];\n\n/**\n * @internal\n */\nexport const CACHE_CAE_SUFFIX = \"cae\";\n\n/**\n * @internal\n */\nexport const CACHE_NON_CAE_SUFFIX = \"nocae\";\n\n/**\n * @internal\n *\n * The default name for the cache persistence plugin.\n * Matches the constant defined in the cache persistence package.\n */\nexport const DEFAULT_TOKEN_CACHE_NAME = \"msal.cache\";\n"]}
|
|
@@ -16,5 +16,9 @@ export interface WorkloadIdentityCredentialOptions extends MultiTenantTokenCrede
|
|
|
16
16
|
* The path to a file containing a Kubernetes service account token that authenticates the identity.
|
|
17
17
|
*/
|
|
18
18
|
tokenFilePath?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Enables the identity binding feature.
|
|
21
|
+
*/
|
|
22
|
+
enableAzureKubernetesTokenProxy?: boolean;
|
|
19
23
|
}
|
|
20
24
|
//# sourceMappingURL=workloadIdentityCredentialOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workloadIdentityCredentialOptions.d.ts","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredentialOptions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAEhG;;GAEG;AACH,MAAM,WAAW,iCACf,SAAQ,iCAAiC,EACvC,0BAA0B;IAC5B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"workloadIdentityCredentialOptions.d.ts","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredentialOptions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAEhG;;GAEG;AACH,MAAM,WAAW,iCACf,SAAQ,iCAAiC,EACvC,0BAA0B;IAC5B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,+BAA+B,CAAC,EAAE,OAAO,CAAC;CAC3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workloadIdentityCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AuthorityValidationOptions } from \"./authorityValidationOptions.js\";\nimport type { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions.js\";\n\n/**\n * Options for the {@link WorkloadIdentityCredential}\n */\nexport interface WorkloadIdentityCredentialOptions\n extends MultiTenantTokenCredentialOptions,\n AuthorityValidationOptions {\n /**\n * ID of the application's Microsoft Entra tenant. Also called its directory ID.\n */\n tenantId?: string;\n /**\n * The client ID of a Microsoft Entra app registration.\n */\n clientId?: string;\n /**\n * The path to a file containing a Kubernetes service account token that authenticates the identity.\n */\n tokenFilePath?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workloadIdentityCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AuthorityValidationOptions } from \"./authorityValidationOptions.js\";\nimport type { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions.js\";\n\n/**\n * Options for the {@link WorkloadIdentityCredential}\n */\nexport interface WorkloadIdentityCredentialOptions\n extends MultiTenantTokenCredentialOptions,\n AuthorityValidationOptions {\n /**\n * ID of the application's Microsoft Entra tenant. Also called its directory ID.\n */\n tenantId?: string;\n /**\n * The client ID of a Microsoft Entra app registration.\n */\n clientId?: string;\n /**\n * The path to a file containing a Kubernetes service account token that authenticates the identity.\n */\n tokenFilePath?: string;\n /**\n * Enables the identity binding feature.\n */\n enableAzureKubernetesTokenProxy?: boolean;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts public keys from PEM certificate content
|
|
3
|
+
* @param pemData - The PEM certificate data to parse
|
|
4
|
+
* @returns Array of base64-encoded public key strings
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractPemCertificateKeys(pemContent: string): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Checks if PEM certificate content can be parsed as X509Certificate
|
|
9
|
+
* @param pemCert - The PEM certificate
|
|
10
|
+
* @returns true if all certificates in the PEM content can be parsed without error
|
|
11
|
+
*/
|
|
12
|
+
export declare function canParseAsX509Certificate(pemCert: string): boolean;
|
|
13
|
+
//# sourceMappingURL=certificatesUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificatesUtils.d.ts","sourceRoot":"","sources":["../../../src/util/certificatesUtils.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBtE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgBlE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
import { X509Certificate } from "crypto";
|
|
4
|
+
/**
|
|
5
|
+
* Extracts public keys from PEM certificate content
|
|
6
|
+
* @param pemData - The PEM certificate data to parse
|
|
7
|
+
* @returns Array of base64-encoded public key strings
|
|
8
|
+
*/
|
|
9
|
+
export function extractPemCertificateKeys(pemContent) {
|
|
10
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
|
|
11
|
+
const publicKeys = [];
|
|
12
|
+
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
|
13
|
+
let match;
|
|
14
|
+
do {
|
|
15
|
+
match = certificatePattern.exec(pemContent);
|
|
16
|
+
if (match) {
|
|
17
|
+
publicKeys.push(match[3]);
|
|
18
|
+
}
|
|
19
|
+
} while (match);
|
|
20
|
+
if (publicKeys.length === 0) {
|
|
21
|
+
throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
|
22
|
+
}
|
|
23
|
+
return publicKeys;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks if PEM certificate content can be parsed as X509Certificate
|
|
27
|
+
* @param pemCert - The PEM certificate
|
|
28
|
+
* @returns true if all certificates in the PEM content can be parsed without error
|
|
29
|
+
*/
|
|
30
|
+
export function canParseAsX509Certificate(pemCert) {
|
|
31
|
+
try {
|
|
32
|
+
const pemContents = extractPemCertificateKeys(pemCert);
|
|
33
|
+
for (let i = 0; i < pemContents.length; i++) {
|
|
34
|
+
const pemContent = pemContents[i];
|
|
35
|
+
// Reconstruct the full PEM format for X509Certificate constructor
|
|
36
|
+
const fullPemCertificate = `-----BEGIN CERTIFICATE-----\n${pemContent}\n-----END CERTIFICATE-----`;
|
|
37
|
+
// Attempt to parse as X.509 certificate
|
|
38
|
+
new X509Certificate(fullPemCertificate);
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (extractError) {
|
|
43
|
+
// Return false for any error (extraction or parsing)
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=certificatesUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificatesUtils.js","sourceRoot":"","sources":["../../../src/util/certificatesUtils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,kBAAkB,GACtB,+FAA+F,CAAC;IAClG,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,qHAAqH;IACrH,IAAI,KAAK,CAAC;IACV,GAAG,CAAC;QACF,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,QAAQ,KAAK,EAAE;IAEhB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAEvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAClC,kEAAkE;YAClE,MAAM,kBAAkB,GAAG,gCAAgC,UAAU,6BAA6B,CAAC;YACnG,wCAAwC;YACxC,IAAI,eAAe,CAAC,kBAAkB,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,YAAY,EAAE,CAAC;QACtB,qDAAqD;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { X509Certificate } from \"crypto\";\n\n/**\n * Extracts public keys from PEM certificate content\n * @param pemData - The PEM certificate data to parse\n * @returns Array of base64-encoded public key strings\n */\nexport function extractPemCertificateKeys(pemContent: string): string[] {\n const certificatePattern =\n /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(pemContent);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n return publicKeys;\n}\n\n/**\n * Checks if PEM certificate content can be parsed as X509Certificate\n * @param pemCert - The PEM certificate\n * @returns true if all certificates in the PEM content can be parsed without error\n */\nexport function canParseAsX509Certificate(pemCert: string): boolean {\n try {\n const pemContents = extractPemCertificateKeys(pemCert);\n\n for (let i = 0; i < pemContents.length; i++) {\n const pemContent = pemContents[i];\n // Reconstruct the full PEM format for X509Certificate constructor\n const fullPemCertificate = `-----BEGIN CERTIFICATE-----\\n${pemContent}\\n-----END CERTIFICATE-----`;\n // Attempt to parse as X.509 certificate\n new X509Certificate(fullPemCertificate);\n }\n return true;\n } catch (extractError) {\n // Return false for any error (extraction or parsing)\n return false;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,WAAW,kBAAkB,CAAC;AAE3C;;;GAGG;AAIH,eAAO,MAAM,uBAAuB,yCAAyC,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,eAAe,WAAW,CAAC;AAExC;;GAEG;AACH,oBAAY,mBAAmB;IAC7B;;OAEG;IACH,UAAU,mCAAmC;IAC7C;;;;;SAKK;IACL,YAAY,qCAAqC;IACjD;;OAEG;IACH,eAAe,qCAAqC;IACpD;;OAEG;IACH,gBAAgB,sCAAsC;CACvD;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uCAAuC,CAAC;AAEzE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,EAAU,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,eAAe,CAAC"}
|
|
@@ -6,7 +6,7 @@ exports.DEFAULT_TOKEN_CACHE_NAME = exports.CACHE_NON_CAE_SUFFIX = exports.CACHE_
|
|
|
6
6
|
/**
|
|
7
7
|
* Current version of the `@azure/identity` package.
|
|
8
8
|
*/
|
|
9
|
-
exports.SDK_VERSION = `4.
|
|
9
|
+
exports.SDK_VERSION = `4.14.0-beta.1`;
|
|
10
10
|
/**
|
|
11
11
|
* The default client ID for authentication
|
|
12
12
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAElC;;GAEG;AACU,QAAA,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAElC;;GAEG;AACU,QAAA,WAAW,GAAG,eAAe,CAAC;AAE3C;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AAC1F,QAAA,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACU,QAAA,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,IAAY,mBAoBX;AApBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;;;;SAKK;IACL,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EApBW,mBAAmB,mCAAnB,mBAAmB,QAoB9B;AAED;;;GAGG;AACU,QAAA,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC;AAEzE;;;GAGG;AACU,QAAA,gBAAgB,GAAG,2BAA2B,CAAC;AAE5D;;;GAGG;AACU,QAAA,WAAW,GAAa,CAAC,GAAG,CAAC,CAAC;AAE3C;;GAEG;AACU,QAAA,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACU,QAAA,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;;;GAKG;AACU,QAAA,wBAAwB,GAAG,YAAY,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * Current version of the `@azure/identity` package.\n */\nexport const SDK_VERSION = `4.14.0-beta.1`;\n\n/**\n * The default client ID for authentication\n * @internal\n */\n// TODO: temporary - this is the Azure CLI clientID - we'll replace it when\n// Developer Sign On application is available\n// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9\nexport const DeveloperSignOnClientId = \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\";\n\n/**\n * The default tenant for authentication\n * @internal\n */\nexport const DefaultTenantId = \"common\";\n\n/**\n * A list of known Azure authority hosts\n */\nexport enum AzureAuthorityHosts {\n /**\n * China-based Azure Authority Host\n */\n AzureChina = \"https://login.chinacloudapi.cn\",\n /**\n * Germany-based Azure Authority Host\n *\n * @deprecated Microsoft Cloud Germany was closed on October 29th, 2021.\n *\n * */\n AzureGermany = \"https://login.microsoftonline.de\",\n /**\n * US Government Azure Authority Host\n */\n AzureGovernment = \"https://login.microsoftonline.us\",\n /**\n * Public Cloud Azure Authority Host\n */\n AzurePublicCloud = \"https://login.microsoftonline.com\",\n}\n\n/**\n * @internal\n * The default authority host.\n */\nexport const DefaultAuthorityHost = AzureAuthorityHosts.AzurePublicCloud;\n\n/**\n * @internal\n * The default environment host for Azure Public Cloud\n */\nexport const DefaultAuthority = \"login.microsoftonline.com\";\n\n/**\n * @internal\n * Allow acquiring tokens for any tenant for multi-tentant auth.\n */\nexport const ALL_TENANTS: string[] = [\"*\"];\n\n/**\n * @internal\n */\nexport const CACHE_CAE_SUFFIX = \"cae\";\n\n/**\n * @internal\n */\nexport const CACHE_NON_CAE_SUFFIX = \"nocae\";\n\n/**\n * @internal\n *\n * The default name for the cache persistence plugin.\n * Matches the constant defined in the cache persistence package.\n */\nexport const DEFAULT_TOKEN_CACHE_NAME = \"msal.cache\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientCertificateCredential.d.ts","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAStF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAC;AAIlG,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAC/B,mCAAmC,EACpC,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"clientCertificateCredential.d.ts","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAStF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAC;AAIlG,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAC/B,mCAAmC,EACpC,MAAM,wCAAwC,CAAC;AAMhD;;;;;;;GAOG;AACH,qBAAa,2BAA4B,YAAW,eAAe;IACjE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,4BAA4B,CAAW;IAC/C,OAAO,CAAC,wBAAwB,CAA8C;IAC9E,OAAO,CAAC,oBAAoB,CAAC,CAAU;IACvC,OAAO,CAAC,UAAU,CAAa;IAE/B;;;;;;;;;OASG;gBAED,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE,kCAAkC;IAE9C;;;;;;;;;OASG;gBAED,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,mCAAmC,EAClD,OAAO,CAAC,EAAE,kCAAkC;IAE9C;;;;;;;;;OASG;gBAED,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,+BAA+B,EAC9C,OAAO,CAAC,EAAE,kCAAkC;IA+C9C;;;;;;;OAOG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;YAehF,sBAAsB;CA6BrC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,wBAAwB,EAAE,2CAA2C,EACrE,oBAAoB,EAAE,OAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,GAAG;IAAE,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBjF"}
|
|
@@ -10,6 +10,7 @@ const tenantIdUtils_js_1 = require("../util/tenantIdUtils.js");
|
|
|
10
10
|
const logging_js_1 = require("../util/logging.js");
|
|
11
11
|
const promises_1 = require("node:fs/promises");
|
|
12
12
|
const tracing_js_1 = require("../util/tracing.js");
|
|
13
|
+
const certificatesUtils_js_1 = require("../util/certificatesUtils.js");
|
|
13
14
|
const credentialName = "ClientCertificateCredential";
|
|
14
15
|
const logger = (0, logging_js_1.credentialLogger)(credentialName);
|
|
15
16
|
/**
|
|
@@ -112,19 +113,7 @@ async function parseCertificate(certificateConfiguration, sendCertificateChain)
|
|
|
112
113
|
.certificatePath;
|
|
113
114
|
const certificateContents = certificate || (await (0, promises_1.readFile)(certificatePath, "utf8"));
|
|
114
115
|
const x5c = sendCertificateChain ? certificateContents : undefined;
|
|
115
|
-
const
|
|
116
|
-
const publicKeys = [];
|
|
117
|
-
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
|
118
|
-
let match;
|
|
119
|
-
do {
|
|
120
|
-
match = certificatePattern.exec(certificateContents);
|
|
121
|
-
if (match) {
|
|
122
|
-
publicKeys.push(match[3]);
|
|
123
|
-
}
|
|
124
|
-
} while (match);
|
|
125
|
-
if (publicKeys.length === 0) {
|
|
126
|
-
throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
|
127
|
-
}
|
|
116
|
+
const publicKeys = (0, certificatesUtils_js_1.extractPemCertificateKeys)(certificateContents);
|
|
128
117
|
const thumbprint = (0, node_crypto_1.createHash)("sha1") // CodeQL [SM04514] Needed for backward compatibility reason
|
|
129
118
|
.update(Buffer.from(publicKeys[0], "base64"))
|
|
130
119
|
.digest("hex")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport type { MsalClient } from \"../msal/nodeFlows/msalClient.js\";\nimport { createMsalClient } from \"../msal/nodeFlows/msalClient.js\";\nimport { createHash, createPrivateKey } from \"node:crypto\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils.js\";\n\nimport type { CertificateParts } from \"../msal/types.js\";\nimport type { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions.js\";\nimport { credentialLogger } from \"../util/logging.js\";\nimport { readFile } from \"node:fs/promises\";\nimport { tracingClient } from \"../util/tracing.js\";\nimport type {\n ClientCertificateCredentialPEMConfiguration,\n ClientCertificatePEMCertificate,\n ClientCertificatePEMCertificatePath,\n} from \"./clientCertificateCredentialModels.js\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private certificateConfiguration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n private msalClient: MsalClient;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * Ensure that certificate is in PEM format and contains both the public and private keys.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.sendCertificateChain = options.sendCertificateChain;\n\n this.certificateConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate = (this.certificateConfiguration as ClientCertificatePEMCertificate)\n .certificate;\n const certificatePath = (this.certificateConfiguration as ClientCertificatePEMCertificatePath)\n .certificatePath;\n if (!this.certificateConfiguration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n const certificate = await this.buildClientCertificate();\n return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);\n });\n }\n\n private async buildClientCertificate(): Promise<CertificateParts> {\n const parts = await parseCertificate(\n this.certificateConfiguration,\n this.sendCertificateChain ?? false,\n );\n\n let privateKey: string;\n if (this.certificateConfiguration.certificatePassword !== undefined) {\n privateKey = createPrivateKey({\n key: parts.certificateContents,\n passphrase: this.certificateConfiguration.certificatePassword,\n format: \"pem\",\n })\n .export({\n format: \"pem\",\n type: \"pkcs8\",\n })\n .toString();\n } else {\n privateKey = parts.certificateContents;\n }\n\n return {\n thumbprint: parts.thumbprint,\n thumbprintSha256: parts.thumbprintSha256,\n privateKey,\n x5c: parts.x5c,\n };\n }\n}\n\n/**\n * Parses a certificate into its relevant parts\n *\n * @param certificateConfiguration - The certificate contents or path to the certificate\n * @param sendCertificateChain - true if the entire certificate chain should be sent for SNI, false otherwise\n * @returns The parsed certificate parts and the certificate contents\n */\nexport async function parseCertificate(\n certificateConfiguration: ClientCertificateCredentialPEMConfiguration,\n sendCertificateChain: boolean,\n): Promise<Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }> {\n const certificate = (certificateConfiguration as ClientCertificatePEMCertificate).certificate;\n const certificatePath = (certificateConfiguration as ClientCertificatePEMCertificatePath)\n .certificatePath;\n const certificateContents = certificate || (await readFile(certificatePath!, \"utf8\"));\n const x5c = sendCertificateChain ? certificateContents : undefined;\n\n const certificatePattern =\n /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(certificateContents);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n const thumbprint = createHash(\"sha1\") // CodeQL [SM04514] Needed for backward compatibility reason\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n const thumbprintSha256 = createHash(\"sha256\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return {\n certificateContents,\n thumbprintSha256,\n thumbprint,\n x5c,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAmMlC,4CA4BC;AA3ND,mEAAmE;AACnE,6CAA2D;AAC3D,+DAGkC;AAIlC,mDAAsD;AACtD,+CAA4C;AAC5C,mDAAmD;AAMnD,uEAAyE;AAEzE,MAAM,cAAc,GAAG,6BAA6B,CAAC;AACrD,MAAM,MAAM,GAAG,IAAA,6BAAgB,EAAC,cAAc,CAAC,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAa,2BAA2B;IAC9B,QAAQ,CAAS;IACjB,4BAA4B,CAAW;IACvC,wBAAwB,CAA8C;IACtE,oBAAoB,CAAW;IAC/B,UAAU,CAAa;IAkD/B,YACE,QAAgB,EAChB,QAAgB,EAChB,8BAAoF,EACpF,UAA8C,EAAE;QAEhD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,cAAc,kDAAkD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,4BAA4B,GAAG,IAAA,sDAAmC,EACrE,OAAO,EAAE,0BAA0B,CACpC,CAAC;QAEF,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QAEzD,IAAI,CAAC,wBAAwB,GAAG;YAC9B,GAAG,CAAC,OAAO,8BAA8B,KAAK,QAAQ;gBACpD,CAAC,CAAC;oBACE,eAAe,EAAE,8BAA8B;iBAChD;gBACH,CAAC,CAAC,8BAA8B,CAAC;SACpC,CAAC;QACF,MAAM,WAAW,GAAI,IAAI,CAAC,wBAA4D;aACnF,WAAW,CAAC;QACf,MAAM,eAAe,GAAI,IAAI,CAAC,wBAAgE;aAC3F,eAAe,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,CAAC,WAAW,IAAI,eAAe,CAAC,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,4MAA4M,CAC9N,CAAC;QACJ,CAAC;QACD,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,wOAAwO,CAC1P,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAA,gCAAgB,EAAC,QAAQ,EAAE,QAAQ,EAAE;YACrD,GAAG,OAAO;YACV,MAAM;YACN,sBAAsB,EAAE,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,0BAAa,CAAC,QAAQ,CAAC,GAAG,cAAc,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YACxF,UAAU,CAAC,QAAQ,GAAG,IAAA,4CAAyB,EAC7C,IAAI,CAAC,QAAQ,EACb,UAAU,EACV,IAAI,CAAC,4BAA4B,EACjC,MAAM,CACP,CAAC;YAEF,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC,UAAU,CAAC,2BAA2B,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,sBAAsB;QAClC,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAClC,IAAI,CAAC,wBAAwB,EAC7B,IAAI,CAAC,oBAAoB,IAAI,KAAK,CACnC,CAAC;QAEF,IAAI,UAAkB,CAAC;QACvB,IAAI,IAAI,CAAC,wBAAwB,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YACpE,UAAU,GAAG,IAAA,8BAAgB,EAAC;gBAC5B,GAAG,EAAE,KAAK,CAAC,mBAAmB;gBAC9B,UAAU,EAAE,IAAI,CAAC,wBAAwB,CAAC,mBAAmB;gBAC7D,MAAM,EAAE,KAAK;aACd,CAAC;iBACC,MAAM,CAAC;gBACN,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,OAAO;aACd,CAAC;iBACD,QAAQ,EAAE,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,KAAK,CAAC,mBAAmB,CAAC;QACzC,CAAC;QAED,OAAO;YACL,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,UAAU;YACV,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAC;IACJ,CAAC;CACF;AAxJD,kEAwJC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,gBAAgB,CACpC,wBAAqE,EACrE,oBAA6B;IAE7B,MAAM,WAAW,GAAI,wBAA4D,CAAC,WAAW,CAAC;IAC9F,MAAM,eAAe,GAAI,wBAAgE;SACtF,eAAe,CAAC;IACnB,MAAM,mBAAmB,GAAG,WAAW,IAAI,CAAC,MAAM,IAAA,mBAAQ,EAAC,eAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IACtF,MAAM,GAAG,GAAG,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnE,MAAM,UAAU,GAAG,IAAA,gDAAyB,EAAC,mBAAmB,CAAC,CAAC;IAElE,MAAM,UAAU,GAAG,IAAA,wBAAU,EAAC,MAAM,CAAC,CAAC,4DAA4D;SAC/F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;SAC5C,MAAM,CAAC,KAAK,CAAC;SACb,WAAW,EAAE,CAAC;IAEjB,MAAM,gBAAgB,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC;SAC1C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;SAC5C,MAAM,CAAC,KAAK,CAAC;SACb,WAAW,EAAE,CAAC;IAEjB,OAAO;QACL,mBAAmB;QACnB,gBAAgB;QAChB,UAAU;QACV,GAAG;KACJ,CAAC;AACJ,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport type { MsalClient } from \"../msal/nodeFlows/msalClient.js\";\nimport { createMsalClient } from \"../msal/nodeFlows/msalClient.js\";\nimport { createHash, createPrivateKey } from \"node:crypto\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils.js\";\n\nimport type { CertificateParts } from \"../msal/types.js\";\nimport type { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions.js\";\nimport { credentialLogger } from \"../util/logging.js\";\nimport { readFile } from \"node:fs/promises\";\nimport { tracingClient } from \"../util/tracing.js\";\nimport type {\n ClientCertificateCredentialPEMConfiguration,\n ClientCertificatePEMCertificate,\n ClientCertificatePEMCertificatePath,\n} from \"./clientCertificateCredentialModels.js\";\nimport { extractPemCertificateKeys } from \"../util/certificatesUtils.js\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private certificateConfiguration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n private msalClient: MsalClient;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * Ensure that certificate is in PEM format and contains both the public and private keys.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.sendCertificateChain = options.sendCertificateChain;\n\n this.certificateConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate = (this.certificateConfiguration as ClientCertificatePEMCertificate)\n .certificate;\n const certificatePath = (this.certificateConfiguration as ClientCertificatePEMCertificatePath)\n .certificatePath;\n if (!this.certificateConfiguration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n const certificate = await this.buildClientCertificate();\n return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);\n });\n }\n\n private async buildClientCertificate(): Promise<CertificateParts> {\n const parts = await parseCertificate(\n this.certificateConfiguration,\n this.sendCertificateChain ?? false,\n );\n\n let privateKey: string;\n if (this.certificateConfiguration.certificatePassword !== undefined) {\n privateKey = createPrivateKey({\n key: parts.certificateContents,\n passphrase: this.certificateConfiguration.certificatePassword,\n format: \"pem\",\n })\n .export({\n format: \"pem\",\n type: \"pkcs8\",\n })\n .toString();\n } else {\n privateKey = parts.certificateContents;\n }\n\n return {\n thumbprint: parts.thumbprint,\n thumbprintSha256: parts.thumbprintSha256,\n privateKey,\n x5c: parts.x5c,\n };\n }\n}\n\n/**\n * Parses a certificate into its relevant parts\n *\n * @param certificateConfiguration - The certificate contents or path to the certificate\n * @param sendCertificateChain - true if the entire certificate chain should be sent for SNI, false otherwise\n * @returns The parsed certificate parts and the certificate contents\n */\nexport async function parseCertificate(\n certificateConfiguration: ClientCertificateCredentialPEMConfiguration,\n sendCertificateChain: boolean,\n): Promise<Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }> {\n const certificate = (certificateConfiguration as ClientCertificatePEMCertificate).certificate;\n const certificatePath = (certificateConfiguration as ClientCertificatePEMCertificatePath)\n .certificatePath;\n const certificateContents = certificate || (await readFile(certificatePath!, \"utf8\"));\n const x5c = sendCertificateChain ? certificateContents : undefined;\n\n const publicKeys = extractPemCertificateKeys(certificateContents);\n\n const thumbprint = createHash(\"sha1\") // CodeQL [SM04514] Needed for backward compatibility reason\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n const thumbprintSha256 = createHash(\"sha256\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return {\n certificateContents,\n thumbprintSha256,\n thumbprint,\n x5c,\n };\n}\n"]}
|
|
@@ -8,6 +8,11 @@ import type { WorkloadIdentityCredentialOptions } from "./workloadIdentityCreden
|
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
10
|
export declare const SupportedWorkloadEnvironmentVariables: string[];
|
|
11
|
+
/**
|
|
12
|
+
* @internal
|
|
13
|
+
* Parses and validates the custom token proxy endpoint URL
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseAndValidateCustomTokenProxy(endpoint: string): string;
|
|
11
16
|
/**
|
|
12
17
|
* Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)
|
|
13
18
|
* to access other Azure resources without the need for a service principal or managed identity. With Workload Identity
|
|
@@ -27,12 +32,27 @@ export declare class WorkloadIdentityCredential implements TokenCredential {
|
|
|
27
32
|
private azureFederatedTokenFileContent;
|
|
28
33
|
private cacheDate;
|
|
29
34
|
private federatedTokenFilePath;
|
|
35
|
+
private cachedTlsSettings;
|
|
36
|
+
private cachedCaData;
|
|
37
|
+
private caData;
|
|
38
|
+
private caFile;
|
|
39
|
+
private sniName;
|
|
30
40
|
/**
|
|
31
41
|
* WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.
|
|
32
42
|
*
|
|
33
43
|
* @param options - The identity client options to use for authentication.
|
|
34
44
|
*/
|
|
35
45
|
constructor(options?: WorkloadIdentityCredentialOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Creates a proxy HttpClient that intercepts token requests and redirects them to the Kubernetes endpoint
|
|
48
|
+
* Caching is handled at the credential level to persist across token requests
|
|
49
|
+
*/
|
|
50
|
+
private createAksProxyClient;
|
|
51
|
+
/**
|
|
52
|
+
* Gets TLS settings for the request.
|
|
53
|
+
* Handles a few scenarios with CA data or CA file provided.
|
|
54
|
+
*/
|
|
55
|
+
private getTlsSettings;
|
|
36
56
|
/**
|
|
37
57
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
38
58
|
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workloadIdentityCredential.d.ts","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKtF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"workloadIdentityCredential.d.ts","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKtF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAUhG;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,UAIjD,CAAC;AAwCF;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwCzE;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,0BAA2B,YAAW,eAAe;IAChE,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,8BAA8B,CAAiC;IACvE,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,sBAAsB,CAAqB;IAGnD,OAAO,CAAC,iBAAiB,CAAsD;IAC/E,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAqB;IAEpC;;;;OAIG;gBACS,OAAO,CAAC,EAAE,iCAAiC;IAoFvD;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqC5B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAiEtB;;;;;;;OAOG;IACU,QAAQ,CACnB,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,WAAW,CAAC;YAUT,gBAAgB;CAwB/B"}
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
// Licensed under the MIT License.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.WorkloadIdentityCredential = exports.SupportedWorkloadEnvironmentVariables = void 0;
|
|
6
|
+
exports.parseAndValidateCustomTokenProxy = parseAndValidateCustomTokenProxy;
|
|
6
7
|
const logging_js_1 = require("../util/logging.js");
|
|
7
8
|
const clientAssertionCredential_js_1 = require("./clientAssertionCredential.js");
|
|
8
9
|
const errors_js_1 = require("../errors.js");
|
|
9
10
|
const tenantIdUtils_js_1 = require("../util/tenantIdUtils.js");
|
|
10
11
|
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const core_rest_pipeline_1 = require("@azure/core-rest-pipeline");
|
|
13
|
+
const certificatesUtils_js_1 = require("../util/certificatesUtils.js");
|
|
14
|
+
const node_fs_1 = require("node:fs");
|
|
11
15
|
const credentialName = "WorkloadIdentityCredential";
|
|
12
16
|
/**
|
|
13
17
|
* Contains the list of all supported environment variable names so that an
|
|
@@ -22,6 +26,65 @@ exports.SupportedWorkloadEnvironmentVariables = [
|
|
|
22
26
|
"AZURE_FEDERATED_TOKEN_FILE",
|
|
23
27
|
];
|
|
24
28
|
const logger = (0, logging_js_1.credentialLogger)(credentialName);
|
|
29
|
+
/**
|
|
30
|
+
* Error messages for WorkloadIdentityCredential
|
|
31
|
+
*/
|
|
32
|
+
const ErrorMessages = {
|
|
33
|
+
FAILED_TO_PARSE_TOKEN_PROXY: (endpoint, error) => `Failed to parse custom token proxy URL "${endpoint}": ${error}`,
|
|
34
|
+
INVALID_HTTPS_SCHEME: (protocol) => `Custom token endpoint must use https scheme, got "${protocol}"`,
|
|
35
|
+
TOKEN_ENDPOINT_NO_USER_INFO: (url) => `Custom token endpoint URL "${url}" must not contain user info`,
|
|
36
|
+
TOKEN_ENDPOINT_NO_QUERY: (url) => `Custom token endpoint URL "${url}" must not contain a query`,
|
|
37
|
+
TOKEN_ENDPOINT_NO_FRAGMENT: (url) => `Custom token endpoint URL "${url}" must not contain a fragment`,
|
|
38
|
+
CA_FILE_EMPTY: (file) => `CA certificate file is empty: ${file}`,
|
|
39
|
+
FAILED_TO_READ_CA_FILE: (file, error) => `Failed to read CA certificate file: ${file}. ${error}`,
|
|
40
|
+
INVALID_CA_CERTIFICATES: `Invalid CA certificate data: no valid PEM certificates found`,
|
|
41
|
+
INVALID_FILE_PATH: (path) => `Invalid file path provided ${path}.`,
|
|
42
|
+
NO_FILE_CONTENT: (path) => `No content on the file ${path}.`,
|
|
43
|
+
NO_CA_SOURCE: `No CA certificate source specified.`,
|
|
44
|
+
CLIENT_ID_REQUIRED: `clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_CLIENT_ID".
|
|
45
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
46
|
+
TENANT_ID_REQUIRED: `tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_TENANT_ID".
|
|
47
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
48
|
+
TOKEN_FILE_PATH_REQUIRED: `federatedTokenFilePath is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_FEDERATED_TOKEN_FILE".
|
|
49
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
50
|
+
TOKEN_PROXY_NOT_SET: `AZURE_KUBERNETES_TOKEN_PROXY is not set but other custom endpoint-related environment variables are present`,
|
|
51
|
+
CA_FILE_AND_DATA_EXCLUSIVE: `AZURE_KUBERNETES_CA_FILE and AZURE_KUBERNETES_CA_DATA are mutually exclusive. Specify only one.`,
|
|
52
|
+
MISSING_ENV_VARS: `tenantId, clientId, and federatedTokenFilePath are required parameters.
|
|
53
|
+
In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables -
|
|
54
|
+
"AZURE_TENANT_ID",
|
|
55
|
+
"AZURE_CLIENT_ID",
|
|
56
|
+
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* @internal
|
|
60
|
+
* Parses and validates the custom token proxy endpoint URL
|
|
61
|
+
*/
|
|
62
|
+
function parseAndValidateCustomTokenProxy(endpoint) {
|
|
63
|
+
let tokenProxy;
|
|
64
|
+
try {
|
|
65
|
+
tokenProxy = new URL(endpoint);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_PARSE_TOKEN_PROXY(endpoint, error)}`);
|
|
69
|
+
}
|
|
70
|
+
if (tokenProxy.protocol !== "https:") {
|
|
71
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_HTTPS_SCHEME(tokenProxy.protocol)}`);
|
|
72
|
+
}
|
|
73
|
+
if (tokenProxy.username || tokenProxy.password) {
|
|
74
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_USER_INFO(tokenProxy.toString())}`);
|
|
75
|
+
}
|
|
76
|
+
if (tokenProxy.search) {
|
|
77
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_QUERY(tokenProxy.toString())}`);
|
|
78
|
+
}
|
|
79
|
+
if (tokenProxy.hash) {
|
|
80
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_FRAGMENT(tokenProxy.toString())}`);
|
|
81
|
+
}
|
|
82
|
+
if (!tokenProxy.pathname || tokenProxy.pathname === "") {
|
|
83
|
+
// if the path is empty, set it to "/" to avoid stripping the path from req.URL
|
|
84
|
+
tokenProxy.pathname = "/";
|
|
85
|
+
}
|
|
86
|
+
return tokenProxy.toString();
|
|
87
|
+
}
|
|
25
88
|
/**
|
|
26
89
|
* Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)
|
|
27
90
|
* to access other Azure resources without the need for a service principal or managed identity. With Workload Identity
|
|
@@ -41,6 +104,12 @@ class WorkloadIdentityCredential {
|
|
|
41
104
|
azureFederatedTokenFileContent = undefined;
|
|
42
105
|
cacheDate = undefined;
|
|
43
106
|
federatedTokenFilePath;
|
|
107
|
+
// AKS proxy CA caching - persists across token requests
|
|
108
|
+
cachedTlsSettings;
|
|
109
|
+
cachedCaData;
|
|
110
|
+
caData;
|
|
111
|
+
caFile;
|
|
112
|
+
sniName;
|
|
44
113
|
/**
|
|
45
114
|
* WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.
|
|
46
115
|
*
|
|
@@ -59,19 +128,132 @@ class WorkloadIdentityCredential {
|
|
|
59
128
|
(0, tenantIdUtils_js_1.checkTenantId)(logger, tenantId);
|
|
60
129
|
}
|
|
61
130
|
if (!clientId) {
|
|
62
|
-
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
63
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
|
131
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CLIENT_ID_REQUIRED}`);
|
|
64
132
|
}
|
|
65
133
|
if (!tenantId) {
|
|
66
|
-
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
67
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
|
134
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TENANT_ID_REQUIRED}`);
|
|
68
135
|
}
|
|
69
136
|
if (!this.federatedTokenFilePath) {
|
|
70
|
-
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
71
|
-
|
|
137
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_FILE_PATH_REQUIRED}`);
|
|
138
|
+
}
|
|
139
|
+
// Use identity binding mode only when enableAzureKubernetesTokenProxy is set
|
|
140
|
+
if (workloadIdentityCredentialOptions.enableAzureKubernetesTokenProxy) {
|
|
141
|
+
const kubernetesTokenProxy = process.env.AZURE_KUBERNETES_TOKEN_PROXY;
|
|
142
|
+
const kubernetesSNIName = process.env.AZURE_KUBERNETES_SNI_NAME;
|
|
143
|
+
const kubernetesCAFile = process.env.AZURE_KUBERNETES_CA_FILE;
|
|
144
|
+
const kubernetesCAData = process.env.AZURE_KUBERNETES_CA_DATA;
|
|
145
|
+
if (!kubernetesTokenProxy) {
|
|
146
|
+
// Custom token proxy is not set, while other Kubernetes-related environment variables are present,
|
|
147
|
+
// this is likely a configuration issue so erroring out to avoid misconfiguration
|
|
148
|
+
if (kubernetesSNIName || kubernetesCAFile || kubernetesCAData) {
|
|
149
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_PROXY_NOT_SET}`);
|
|
150
|
+
}
|
|
151
|
+
logger.info(`enableAzureKubernetesTokenProxy is true but AZURE_KUBERNETES_TOKEN_PROXY is not set, using normal authentication flow`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const tokenProxy = parseAndValidateCustomTokenProxy(kubernetesTokenProxy);
|
|
155
|
+
// CAFile and CAData are mutually exclusive, at most one can be set.
|
|
156
|
+
// If none of CAFile or CAData are set, the default system CA pool will be used.
|
|
157
|
+
if (kubernetesCAFile && kubernetesCAData) {
|
|
158
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_AND_DATA_EXCLUSIVE}`);
|
|
159
|
+
}
|
|
160
|
+
this.caData = kubernetesCAData;
|
|
161
|
+
this.caFile = kubernetesCAFile;
|
|
162
|
+
this.sniName = kubernetesSNIName;
|
|
163
|
+
// Configure client options with AKS proxy client
|
|
164
|
+
const proxyClient = this.createAksProxyClient(tokenProxy);
|
|
165
|
+
workloadIdentityCredentialOptions.httpClient = proxyClient;
|
|
166
|
+
logger.info(`${credentialName}: Using proxy client for token requests`);
|
|
167
|
+
}
|
|
72
168
|
}
|
|
73
169
|
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
|
|
74
|
-
this.client = new clientAssertionCredential_js_1.ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this),
|
|
170
|
+
this.client = new clientAssertionCredential_js_1.ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), workloadIdentityCredentialOptions);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Creates a proxy HttpClient that intercepts token requests and redirects them to the Kubernetes endpoint
|
|
174
|
+
* Caching is handled at the credential level to persist across token requests
|
|
175
|
+
*/
|
|
176
|
+
createAksProxyClient(tokenEndpoint) {
|
|
177
|
+
const defaultClient = (0, core_rest_pipeline_1.createDefaultHttpClient)();
|
|
178
|
+
// Init cached TLS settings at construction time to fail fast on misconfiguration
|
|
179
|
+
this.cachedTlsSettings = this.getTlsSettings();
|
|
180
|
+
return {
|
|
181
|
+
sendRequest: async (request) => {
|
|
182
|
+
const requestUrl = new URL(request.url);
|
|
183
|
+
logger.info(`${credentialName}: Redirecting request to Kubernetes endpoint: ${tokenEndpoint}`);
|
|
184
|
+
const proxyUrl = new URL(tokenEndpoint);
|
|
185
|
+
// Remove leading slash from request path and join with proxy path
|
|
186
|
+
const requestPath = requestUrl.pathname.replace(/^\//, "");
|
|
187
|
+
const combinedPath = proxyUrl.pathname.endsWith("/")
|
|
188
|
+
? proxyUrl.pathname + requestPath
|
|
189
|
+
: proxyUrl.pathname + "/" + requestPath;
|
|
190
|
+
// Create new URL preserving query and fragment from original request
|
|
191
|
+
const newUrl = new URL(proxyUrl.origin);
|
|
192
|
+
newUrl.pathname = combinedPath;
|
|
193
|
+
newUrl.search = requestUrl.search;
|
|
194
|
+
newUrl.hash = requestUrl.hash;
|
|
195
|
+
request.url = newUrl.toString();
|
|
196
|
+
request.tlsSettings = this.getTlsSettings();
|
|
197
|
+
logger.info(`${credentialName}: Sending request to ${request.url}`);
|
|
198
|
+
// Forward the modified request with custom TLS settings
|
|
199
|
+
return defaultClient.sendRequest(request);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Gets TLS settings for the request.
|
|
205
|
+
* Handles a few scenarios with CA data or CA file provided.
|
|
206
|
+
*/
|
|
207
|
+
getTlsSettings() {
|
|
208
|
+
// No CA overrides, use default transport
|
|
209
|
+
if (!this.caData && !this.caFile) {
|
|
210
|
+
if (!this.cachedTlsSettings) {
|
|
211
|
+
this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};
|
|
212
|
+
}
|
|
213
|
+
return this.cachedTlsSettings;
|
|
214
|
+
}
|
|
215
|
+
// Host provided CA bytes in AZURE_KUBERNETES_CA_DATA and can't change now
|
|
216
|
+
if (!this.caFile) {
|
|
217
|
+
if (!this.cachedTlsSettings) {
|
|
218
|
+
if (!(0, certificatesUtils_js_1.canParseAsX509Certificate)(this.caData)) {
|
|
219
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`);
|
|
220
|
+
}
|
|
221
|
+
this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};
|
|
222
|
+
this.cachedTlsSettings.ca = this.caData;
|
|
223
|
+
}
|
|
224
|
+
return this.cachedTlsSettings;
|
|
225
|
+
}
|
|
226
|
+
// Host provided the CA bytes in a file whose contents it can change,
|
|
227
|
+
let fileContent;
|
|
228
|
+
try {
|
|
229
|
+
fileContent = (0, node_fs_1.readFileSync)(this.caFile);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_READ_CA_FILE(this.caFile, error)}`);
|
|
233
|
+
}
|
|
234
|
+
// This can happen in the middle of CA rotation
|
|
235
|
+
if (fileContent.length === 0) {
|
|
236
|
+
if (!this.cachedTlsSettings) {
|
|
237
|
+
// If the transport was never created, error out here to force retrying the call later
|
|
238
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_EMPTY(this.caFile)}`);
|
|
239
|
+
}
|
|
240
|
+
// If the transport was already created, just keep using it
|
|
241
|
+
return this.cachedTlsSettings;
|
|
242
|
+
}
|
|
243
|
+
// Check if CA has changed
|
|
244
|
+
if (!this.cachedCaData || !fileContent.equals(this.cachedCaData)) {
|
|
245
|
+
const caDataString = fileContent.toString("utf8");
|
|
246
|
+
if (!(0, certificatesUtils_js_1.canParseAsX509Certificate)(caDataString)) {
|
|
247
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`);
|
|
248
|
+
}
|
|
249
|
+
// CA has changed, rebuild the TLS settings with new CA pool
|
|
250
|
+
this.cachedTlsSettings = {
|
|
251
|
+
ca: caDataString,
|
|
252
|
+
...(this.sniName && { servername: this.sniName }),
|
|
253
|
+
};
|
|
254
|
+
this.cachedCaData = fileContent;
|
|
255
|
+
}
|
|
256
|
+
return this.cachedTlsSettings;
|
|
75
257
|
}
|
|
76
258
|
/**
|
|
77
259
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -83,11 +265,7 @@ class WorkloadIdentityCredential {
|
|
|
83
265
|
*/
|
|
84
266
|
async getToken(scopes, options) {
|
|
85
267
|
if (!this.client) {
|
|
86
|
-
const errorMessage = `${credentialName}: is unavailable.
|
|
87
|
-
In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables -
|
|
88
|
-
"AZURE_TENANT_ID",
|
|
89
|
-
"AZURE_CLIENT_ID",
|
|
90
|
-
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`;
|
|
268
|
+
const errorMessage = `${credentialName}: is unavailable. ${ErrorMessages.MISSING_ENV_VARS}`;
|
|
91
269
|
logger.info(errorMessage);
|
|
92
270
|
throw new errors_js_1.CredentialUnavailableError(errorMessage);
|
|
93
271
|
}
|
|
@@ -100,13 +278,13 @@ class WorkloadIdentityCredential {
|
|
|
100
278
|
this.azureFederatedTokenFileContent = undefined;
|
|
101
279
|
}
|
|
102
280
|
if (!this.federatedTokenFilePath) {
|
|
103
|
-
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
281
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_FILE_PATH(this.federatedTokenFilePath)}`);
|
|
104
282
|
}
|
|
105
283
|
if (!this.azureFederatedTokenFileContent) {
|
|
106
284
|
const file = await (0, promises_1.readFile)(this.federatedTokenFilePath, "utf8");
|
|
107
285
|
const value = file.trim();
|
|
108
286
|
if (!value) {
|
|
109
|
-
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
287
|
+
throw new errors_js_1.CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.NO_FILE_CONTENT(this.federatedTokenFilePath)}`);
|
|
110
288
|
}
|
|
111
289
|
else {
|
|
112
290
|
this.azureFederatedTokenFileContent = value;
|