@azure/identity 4.13.0 → 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/README.md +1 -1
- 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/chainedTokenCredential.d.ts +1 -1
- package/dist/browser/credentials/chainedTokenCredential.js +1 -1
- package/dist/browser/credentials/chainedTokenCredential.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/chainedTokenCredential.d.ts +1 -1
- package/dist/commonjs/credentials/chainedTokenCredential.js +1 -1
- package/dist/commonjs/credentials/chainedTokenCredential.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/defaultAzureCredential.d.ts +1 -1
- package/dist/commonjs/credentials/defaultAzureCredential.js +1 -1
- package/dist/commonjs/credentials/defaultAzureCredential.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/tsdoc-metadata.json +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/chainedTokenCredential.d.ts +1 -1
- package/dist/esm/credentials/chainedTokenCredential.js +1 -1
- package/dist/esm/credentials/chainedTokenCredential.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/defaultAzureCredential.d.ts +1 -1
- package/dist/esm/credentials/defaultAzureCredential.js +1 -1
- package/dist/esm/credentials/defaultAzureCredential.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/chainedTokenCredential.d.ts +1 -1
- package/dist/workerd/credentials/chainedTokenCredential.js +1 -1
- package/dist/workerd/credentials/chainedTokenCredential.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/defaultAzureCredential.d.ts +1 -1
- package/dist/workerd/credentials/defaultAzureCredential.js +1 -1
- package/dist/workerd/credentials/defaultAzureCredential.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 -9
|
@@ -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":"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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\";\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"]}
|
|
@@ -14,7 +14,7 @@ export declare class UnavailableDefaultCredential implements TokenCredential {
|
|
|
14
14
|
/**
|
|
15
15
|
* Provides a default {@link ChainedTokenCredential} configuration that works for most
|
|
16
16
|
* applications that use Azure SDK client libraries. For more information, see
|
|
17
|
-
* [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#
|
|
17
|
+
* [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview).
|
|
18
18
|
*
|
|
19
19
|
* The following credential types will be tried, in order:
|
|
20
20
|
*
|
|
@@ -23,7 +23,7 @@ export class UnavailableDefaultCredential {
|
|
|
23
23
|
/**
|
|
24
24
|
* Provides a default {@link ChainedTokenCredential} configuration that works for most
|
|
25
25
|
* applications that use Azure SDK client libraries. For more information, see
|
|
26
|
-
* [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#
|
|
26
|
+
* [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview).
|
|
27
27
|
*
|
|
28
28
|
* The following credential types will be tried, in order:
|
|
29
29
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultAzureCredential.js","sourceRoot":"","sources":["../../../src/credentials/defaultAzureCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n DefaultAzureCredentialClientIdOptions,\n DefaultAzureCredentialOptions,\n DefaultAzureCredentialResourceIdOptions,\n} from \"./defaultAzureCredentialOptions.js\";\n\nimport { ManagedIdentityCredential } from \"./managedIdentityCredential/index.js\";\nimport { VisualStudioCodeCredential } from \"./visualStudioCodeCredential.js\";\nimport { AzureCliCredential } from \"./azureCliCredential.js\";\nimport { AzureDeveloperCliCredential } from \"./azureDeveloperCliCredential.js\";\nimport { AzurePowerShellCredential } from \"./azurePowerShellCredential.js\";\nimport { ChainedTokenCredential } from \"./chainedTokenCredential.js\";\nimport { EnvironmentCredential } from \"./environmentCredential.js\";\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { WorkloadIdentityCredential } from \"./workloadIdentityCredential.js\";\nimport { credentialLogger } from \"../util/logging.js\";\nimport {\n createDefaultAzureCliCredential,\n createDefaultAzureDeveloperCliCredential,\n createDefaultAzurePowershellCredential,\n createDefaultBrokerCredential,\n createDefaultManagedIdentityCredential,\n createDefaultVisualStudioCodeCredential,\n createDefaultWorkloadIdentityCredential,\n createDefaultEnvironmentCredential,\n} from \"./defaultAzureCredentialFunctions.js\";\n\nconst logger = credentialLogger(\"DefaultAzureCredential\");\n\n/**\n * A no-op credential that logs the reason it was skipped if getToken is called.\n * @internal\n */\nexport class UnavailableDefaultCredential implements TokenCredential {\n credentialUnavailableErrorMessage: string;\n credentialName: string;\n\n constructor(credentialName: string, message: string) {\n this.credentialName = credentialName;\n this.credentialUnavailableErrorMessage = message;\n }\n\n getToken(): Promise<null> {\n logger.getToken.info(\n `Skipping ${this.credentialName}, reason: ${this.credentialUnavailableErrorMessage}`,\n );\n return Promise.resolve(null);\n }\n}\n\n/**\n * Provides a default {@link ChainedTokenCredential} configuration that works for most\n * applications that use Azure SDK client libraries. For more information, see\n * [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#use-defaultazurecredential-for-flexibility).\n *\n * The following credential types will be tried, in order:\n *\n * - {@link EnvironmentCredential}\n * - {@link WorkloadIdentityCredential}\n * - {@link ManagedIdentityCredential}\n * - {@link VisualStudioCodeCredential}\n * - {@link AzureCliCredential}\n * - {@link AzurePowerShellCredential}\n * - {@link AzureDeveloperCliCredential}\n * - BrokerCredential (a broker-enabled credential that requires \\@azure/identity-broker is installed)\n *\n * Consult the documentation of these credential types for more information\n * on how they attempt authentication.\n *\n * The following example demonstrates how to use the `requiredEnvVars` option to ensure that certain environment variables are set before the `DefaultAzureCredential` is instantiated.\n * If any of the specified environment variables are missing or empty, an error will be thrown, preventing the application from continuing execution without the necessary configuration.\n * It also demonstrates how to set the `AZURE_TOKEN_CREDENTIALS` environment variable to control which credentials are included in the chain.\n \n * ```ts snippet:defaultazurecredential_requiredEnvVars\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const credential = new DefaultAzureCredential({\n * requiredEnvVars: [\n * \"AZURE_CLIENT_ID\",\n * \"AZURE_TENANT_ID\",\n * \"AZURE_CLIENT_SECRET\",\n * \"AZURE_TOKEN_CREDENTIALS\",\n * ],\n * });\n * ```\n */\nexport class DefaultAzureCredential extends ChainedTokenCredential {\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialClientIdOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialClientIdOptions}.\n */\n constructor(options?: DefaultAzureCredentialClientIdOptions);\n\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialResourceIdOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialResourceIdOptions}.\n */\n constructor(options?: DefaultAzureCredentialResourceIdOptions);\n\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialOptions}.\n */\n constructor(options?: DefaultAzureCredentialOptions);\n\n constructor(options?: DefaultAzureCredentialOptions) {\n validateRequiredEnvVars(options);\n // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain.\n const azureTokenCredentials = process.env.AZURE_TOKEN_CREDENTIALS\n ? process.env.AZURE_TOKEN_CREDENTIALS.trim().toLowerCase()\n : undefined;\n const devCredentialFunctions = [\n createDefaultVisualStudioCodeCredential,\n createDefaultAzureCliCredential,\n createDefaultAzurePowershellCredential,\n createDefaultAzureDeveloperCliCredential,\n createDefaultBrokerCredential,\n ];\n const prodCredentialFunctions = [\n createDefaultEnvironmentCredential,\n createDefaultWorkloadIdentityCredential,\n createDefaultManagedIdentityCredential,\n ];\n let credentialFunctions = [];\n const validCredentialNames =\n \"EnvironmentCredential, WorkloadIdentityCredential, ManagedIdentityCredential, VisualStudioCodeCredential, AzureCliCredential, AzurePowerShellCredential, AzureDeveloperCliCredential\";\n // If AZURE_TOKEN_CREDENTIALS is set, use it to determine which credentials to use.\n // The value of AZURE_TOKEN_CREDENTIALS should be either \"dev\" or \"prod\" or any one of these credentials - {validCredentialNames}.\n if (azureTokenCredentials) {\n switch (azureTokenCredentials) {\n case \"dev\":\n credentialFunctions = devCredentialFunctions;\n break;\n case \"prod\":\n credentialFunctions = prodCredentialFunctions;\n break;\n case \"environmentcredential\":\n credentialFunctions = [createDefaultEnvironmentCredential];\n break;\n case \"workloadidentitycredential\":\n credentialFunctions = [createDefaultWorkloadIdentityCredential];\n break;\n case \"managedidentitycredential\":\n // Setting `sendProbeRequest` to false to ensure ManagedIdentityCredential behavior\n // is consistent when used standalone in DAC chain or used directly.\n credentialFunctions = [\n () => createDefaultManagedIdentityCredential({ sendProbeRequest: false }),\n ];\n break;\n case \"visualstudiocodecredential\":\n credentialFunctions = [createDefaultVisualStudioCodeCredential];\n break;\n case \"azureclicredential\":\n credentialFunctions = [createDefaultAzureCliCredential];\n break;\n case \"azurepowershellcredential\":\n credentialFunctions = [createDefaultAzurePowershellCredential];\n break;\n case \"azuredeveloperclicredential\":\n credentialFunctions = [createDefaultAzureDeveloperCliCredential];\n break;\n default: {\n // If AZURE_TOKEN_CREDENTIALS is set to an unsupported value, throw an error.\n // This will prevent the creation of the DefaultAzureCredential.\n const errorMessage = `Invalid value for AZURE_TOKEN_CREDENTIALS = ${process.env.AZURE_TOKEN_CREDENTIALS}. Valid values are 'prod' or 'dev' or any of these credentials - ${validCredentialNames}.`;\n logger.warning(errorMessage);\n throw new Error(errorMessage);\n }\n }\n } else {\n // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain.\n credentialFunctions = [...prodCredentialFunctions, ...devCredentialFunctions];\n }\n\n // Errors from individual credentials should not be thrown in the DefaultAzureCredential constructor, instead throwing on getToken() which is handled by ChainedTokenCredential.\n // When adding new credentials to the default chain, consider:\n // 1. Making the constructor parameters required and explicit\n // 2. Validating any required parameters in the factory function\n // 3. Returning a UnavailableDefaultCredential from the factory function if a credential is unavailable for any reason\n const credentials: TokenCredential[] = credentialFunctions.map((createCredentialFn) => {\n try {\n return createCredentialFn(options ?? {});\n } catch (err: any) {\n logger.warning(\n `Skipped ${createCredentialFn.name} because of an error creating the credential: ${err}`,\n );\n return new UnavailableDefaultCredential(createCredentialFn.name, err.message);\n }\n });\n\n super(...credentials);\n }\n}\n\n/**\n * This function checks that all environment variables in `options.requiredEnvVars` are set and non-empty.\n * If any are missing or empty, it throws an error.\n */\nfunction validateRequiredEnvVars(options?: DefaultAzureCredentialOptions) {\n if (options?.requiredEnvVars) {\n const requiredVars = Array.isArray(options.requiredEnvVars)\n ? options.requiredEnvVars\n : [options.requiredEnvVars];\n const missing = requiredVars.filter((envVar) => !process.env[envVar]);\n if (missing.length > 0) {\n const errorMessage = `Required environment ${missing.length === 1 ? \"variable\" : \"variables\"} '${missing.join(\", \")}' for DefaultAzureCredential ${missing.length === 1 ? \"is\" : \"are\"} not set or empty.`;\n logger.warning(errorMessage);\n throw new Error(errorMessage);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"defaultAzureCredential.js","sourceRoot":"","sources":["../../../src/credentials/defaultAzureCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n DefaultAzureCredentialClientIdOptions,\n DefaultAzureCredentialOptions,\n DefaultAzureCredentialResourceIdOptions,\n} from \"./defaultAzureCredentialOptions.js\";\n\nimport { ManagedIdentityCredential } from \"./managedIdentityCredential/index.js\";\nimport { VisualStudioCodeCredential } from \"./visualStudioCodeCredential.js\";\nimport { AzureCliCredential } from \"./azureCliCredential.js\";\nimport { AzureDeveloperCliCredential } from \"./azureDeveloperCliCredential.js\";\nimport { AzurePowerShellCredential } from \"./azurePowerShellCredential.js\";\nimport { ChainedTokenCredential } from \"./chainedTokenCredential.js\";\nimport { EnvironmentCredential } from \"./environmentCredential.js\";\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { WorkloadIdentityCredential } from \"./workloadIdentityCredential.js\";\nimport { credentialLogger } from \"../util/logging.js\";\nimport {\n createDefaultAzureCliCredential,\n createDefaultAzureDeveloperCliCredential,\n createDefaultAzurePowershellCredential,\n createDefaultBrokerCredential,\n createDefaultManagedIdentityCredential,\n createDefaultVisualStudioCodeCredential,\n createDefaultWorkloadIdentityCredential,\n createDefaultEnvironmentCredential,\n} from \"./defaultAzureCredentialFunctions.js\";\n\nconst logger = credentialLogger(\"DefaultAzureCredential\");\n\n/**\n * A no-op credential that logs the reason it was skipped if getToken is called.\n * @internal\n */\nexport class UnavailableDefaultCredential implements TokenCredential {\n credentialUnavailableErrorMessage: string;\n credentialName: string;\n\n constructor(credentialName: string, message: string) {\n this.credentialName = credentialName;\n this.credentialUnavailableErrorMessage = message;\n }\n\n getToken(): Promise<null> {\n logger.getToken.info(\n `Skipping ${this.credentialName}, reason: ${this.credentialUnavailableErrorMessage}`,\n );\n return Promise.resolve(null);\n }\n}\n\n/**\n * Provides a default {@link ChainedTokenCredential} configuration that works for most\n * applications that use Azure SDK client libraries. For more information, see\n * [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview).\n *\n * The following credential types will be tried, in order:\n *\n * - {@link EnvironmentCredential}\n * - {@link WorkloadIdentityCredential}\n * - {@link ManagedIdentityCredential}\n * - {@link VisualStudioCodeCredential}\n * - {@link AzureCliCredential}\n * - {@link AzurePowerShellCredential}\n * - {@link AzureDeveloperCliCredential}\n * - BrokerCredential (a broker-enabled credential that requires \\@azure/identity-broker is installed)\n *\n * Consult the documentation of these credential types for more information\n * on how they attempt authentication.\n *\n * The following example demonstrates how to use the `requiredEnvVars` option to ensure that certain environment variables are set before the `DefaultAzureCredential` is instantiated.\n * If any of the specified environment variables are missing or empty, an error will be thrown, preventing the application from continuing execution without the necessary configuration.\n * It also demonstrates how to set the `AZURE_TOKEN_CREDENTIALS` environment variable to control which credentials are included in the chain.\n \n * ```ts snippet:defaultazurecredential_requiredEnvVars\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const credential = new DefaultAzureCredential({\n * requiredEnvVars: [\n * \"AZURE_CLIENT_ID\",\n * \"AZURE_TENANT_ID\",\n * \"AZURE_CLIENT_SECRET\",\n * \"AZURE_TOKEN_CREDENTIALS\",\n * ],\n * });\n * ```\n */\nexport class DefaultAzureCredential extends ChainedTokenCredential {\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialClientIdOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialClientIdOptions}.\n */\n constructor(options?: DefaultAzureCredentialClientIdOptions);\n\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialResourceIdOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialResourceIdOptions}.\n */\n constructor(options?: DefaultAzureCredentialResourceIdOptions);\n\n /**\n * Creates an instance of the DefaultAzureCredential class with {@link DefaultAzureCredentialOptions}.\n *\n * @param options - Optional parameters. See {@link DefaultAzureCredentialOptions}.\n */\n constructor(options?: DefaultAzureCredentialOptions);\n\n constructor(options?: DefaultAzureCredentialOptions) {\n validateRequiredEnvVars(options);\n // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain.\n const azureTokenCredentials = process.env.AZURE_TOKEN_CREDENTIALS\n ? process.env.AZURE_TOKEN_CREDENTIALS.trim().toLowerCase()\n : undefined;\n const devCredentialFunctions = [\n createDefaultVisualStudioCodeCredential,\n createDefaultAzureCliCredential,\n createDefaultAzurePowershellCredential,\n createDefaultAzureDeveloperCliCredential,\n createDefaultBrokerCredential,\n ];\n const prodCredentialFunctions = [\n createDefaultEnvironmentCredential,\n createDefaultWorkloadIdentityCredential,\n createDefaultManagedIdentityCredential,\n ];\n let credentialFunctions = [];\n const validCredentialNames =\n \"EnvironmentCredential, WorkloadIdentityCredential, ManagedIdentityCredential, VisualStudioCodeCredential, AzureCliCredential, AzurePowerShellCredential, AzureDeveloperCliCredential\";\n // If AZURE_TOKEN_CREDENTIALS is set, use it to determine which credentials to use.\n // The value of AZURE_TOKEN_CREDENTIALS should be either \"dev\" or \"prod\" or any one of these credentials - {validCredentialNames}.\n if (azureTokenCredentials) {\n switch (azureTokenCredentials) {\n case \"dev\":\n credentialFunctions = devCredentialFunctions;\n break;\n case \"prod\":\n credentialFunctions = prodCredentialFunctions;\n break;\n case \"environmentcredential\":\n credentialFunctions = [createDefaultEnvironmentCredential];\n break;\n case \"workloadidentitycredential\":\n credentialFunctions = [createDefaultWorkloadIdentityCredential];\n break;\n case \"managedidentitycredential\":\n // Setting `sendProbeRequest` to false to ensure ManagedIdentityCredential behavior\n // is consistent when used standalone in DAC chain or used directly.\n credentialFunctions = [\n () => createDefaultManagedIdentityCredential({ sendProbeRequest: false }),\n ];\n break;\n case \"visualstudiocodecredential\":\n credentialFunctions = [createDefaultVisualStudioCodeCredential];\n break;\n case \"azureclicredential\":\n credentialFunctions = [createDefaultAzureCliCredential];\n break;\n case \"azurepowershellcredential\":\n credentialFunctions = [createDefaultAzurePowershellCredential];\n break;\n case \"azuredeveloperclicredential\":\n credentialFunctions = [createDefaultAzureDeveloperCliCredential];\n break;\n default: {\n // If AZURE_TOKEN_CREDENTIALS is set to an unsupported value, throw an error.\n // This will prevent the creation of the DefaultAzureCredential.\n const errorMessage = `Invalid value for AZURE_TOKEN_CREDENTIALS = ${process.env.AZURE_TOKEN_CREDENTIALS}. Valid values are 'prod' or 'dev' or any of these credentials - ${validCredentialNames}.`;\n logger.warning(errorMessage);\n throw new Error(errorMessage);\n }\n }\n } else {\n // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain.\n credentialFunctions = [...prodCredentialFunctions, ...devCredentialFunctions];\n }\n\n // Errors from individual credentials should not be thrown in the DefaultAzureCredential constructor, instead throwing on getToken() which is handled by ChainedTokenCredential.\n // When adding new credentials to the default chain, consider:\n // 1. Making the constructor parameters required and explicit\n // 2. Validating any required parameters in the factory function\n // 3. Returning a UnavailableDefaultCredential from the factory function if a credential is unavailable for any reason\n const credentials: TokenCredential[] = credentialFunctions.map((createCredentialFn) => {\n try {\n return createCredentialFn(options ?? {});\n } catch (err: any) {\n logger.warning(\n `Skipped ${createCredentialFn.name} because of an error creating the credential: ${err}`,\n );\n return new UnavailableDefaultCredential(createCredentialFn.name, err.message);\n }\n });\n\n super(...credentials);\n }\n}\n\n/**\n * This function checks that all environment variables in `options.requiredEnvVars` are set and non-empty.\n * If any are missing or empty, it throws an error.\n */\nfunction validateRequiredEnvVars(options?: DefaultAzureCredentialOptions) {\n if (options?.requiredEnvVars) {\n const requiredVars = Array.isArray(options.requiredEnvVars)\n ? options.requiredEnvVars\n : [options.requiredEnvVars];\n const missing = requiredVars.filter((envVar) => !process.env[envVar]);\n if (missing.length > 0) {\n const errorMessage = `Required environment ${missing.length === 1 ? \"variable\" : \"variables\"} '${missing.join(\", \")}' for DefaultAzureCredential ${missing.length === 1 ? \"is\" : \"are\"} not set or empty.`;\n logger.warning(errorMessage);\n throw new Error(errorMessage);\n }\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"}
|
|
@@ -5,6 +5,9 @@ import { ClientAssertionCredential } from "./clientAssertionCredential.js";
|
|
|
5
5
|
import { CredentialUnavailableError } from "../errors.js";
|
|
6
6
|
import { checkTenantId } from "../util/tenantIdUtils.js";
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
|
+
import { createDefaultHttpClient } from "@azure/core-rest-pipeline";
|
|
9
|
+
import { canParseAsX509Certificate } from "../util/certificatesUtils.js";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
8
11
|
const credentialName = "WorkloadIdentityCredential";
|
|
9
12
|
/**
|
|
10
13
|
* Contains the list of all supported environment variable names so that an
|
|
@@ -19,6 +22,65 @@ export const SupportedWorkloadEnvironmentVariables = [
|
|
|
19
22
|
"AZURE_FEDERATED_TOKEN_FILE",
|
|
20
23
|
];
|
|
21
24
|
const logger = credentialLogger(credentialName);
|
|
25
|
+
/**
|
|
26
|
+
* Error messages for WorkloadIdentityCredential
|
|
27
|
+
*/
|
|
28
|
+
const ErrorMessages = {
|
|
29
|
+
FAILED_TO_PARSE_TOKEN_PROXY: (endpoint, error) => `Failed to parse custom token proxy URL "${endpoint}": ${error}`,
|
|
30
|
+
INVALID_HTTPS_SCHEME: (protocol) => `Custom token endpoint must use https scheme, got "${protocol}"`,
|
|
31
|
+
TOKEN_ENDPOINT_NO_USER_INFO: (url) => `Custom token endpoint URL "${url}" must not contain user info`,
|
|
32
|
+
TOKEN_ENDPOINT_NO_QUERY: (url) => `Custom token endpoint URL "${url}" must not contain a query`,
|
|
33
|
+
TOKEN_ENDPOINT_NO_FRAGMENT: (url) => `Custom token endpoint URL "${url}" must not contain a fragment`,
|
|
34
|
+
CA_FILE_EMPTY: (file) => `CA certificate file is empty: ${file}`,
|
|
35
|
+
FAILED_TO_READ_CA_FILE: (file, error) => `Failed to read CA certificate file: ${file}. ${error}`,
|
|
36
|
+
INVALID_CA_CERTIFICATES: `Invalid CA certificate data: no valid PEM certificates found`,
|
|
37
|
+
INVALID_FILE_PATH: (path) => `Invalid file path provided ${path}.`,
|
|
38
|
+
NO_FILE_CONTENT: (path) => `No content on the file ${path}.`,
|
|
39
|
+
NO_CA_SOURCE: `No CA certificate source specified.`,
|
|
40
|
+
CLIENT_ID_REQUIRED: `clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_CLIENT_ID".
|
|
41
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
42
|
+
TENANT_ID_REQUIRED: `tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_TENANT_ID".
|
|
43
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
44
|
+
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".
|
|
45
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
46
|
+
TOKEN_PROXY_NOT_SET: `AZURE_KUBERNETES_TOKEN_PROXY is not set but other custom endpoint-related environment variables are present`,
|
|
47
|
+
CA_FILE_AND_DATA_EXCLUSIVE: `AZURE_KUBERNETES_CA_FILE and AZURE_KUBERNETES_CA_DATA are mutually exclusive. Specify only one.`,
|
|
48
|
+
MISSING_ENV_VARS: `tenantId, clientId, and federatedTokenFilePath are required parameters.
|
|
49
|
+
In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables -
|
|
50
|
+
"AZURE_TENANT_ID",
|
|
51
|
+
"AZURE_CLIENT_ID",
|
|
52
|
+
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* @internal
|
|
56
|
+
* Parses and validates the custom token proxy endpoint URL
|
|
57
|
+
*/
|
|
58
|
+
export function parseAndValidateCustomTokenProxy(endpoint) {
|
|
59
|
+
let tokenProxy;
|
|
60
|
+
try {
|
|
61
|
+
tokenProxy = new URL(endpoint);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_PARSE_TOKEN_PROXY(endpoint, error)}`);
|
|
65
|
+
}
|
|
66
|
+
if (tokenProxy.protocol !== "https:") {
|
|
67
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_HTTPS_SCHEME(tokenProxy.protocol)}`);
|
|
68
|
+
}
|
|
69
|
+
if (tokenProxy.username || tokenProxy.password) {
|
|
70
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_USER_INFO(tokenProxy.toString())}`);
|
|
71
|
+
}
|
|
72
|
+
if (tokenProxy.search) {
|
|
73
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_QUERY(tokenProxy.toString())}`);
|
|
74
|
+
}
|
|
75
|
+
if (tokenProxy.hash) {
|
|
76
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_FRAGMENT(tokenProxy.toString())}`);
|
|
77
|
+
}
|
|
78
|
+
if (!tokenProxy.pathname || tokenProxy.pathname === "") {
|
|
79
|
+
// if the path is empty, set it to "/" to avoid stripping the path from req.URL
|
|
80
|
+
tokenProxy.pathname = "/";
|
|
81
|
+
}
|
|
82
|
+
return tokenProxy.toString();
|
|
83
|
+
}
|
|
22
84
|
/**
|
|
23
85
|
* Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)
|
|
24
86
|
* to access other Azure resources without the need for a service principal or managed identity. With Workload Identity
|
|
@@ -38,6 +100,12 @@ export class WorkloadIdentityCredential {
|
|
|
38
100
|
azureFederatedTokenFileContent = undefined;
|
|
39
101
|
cacheDate = undefined;
|
|
40
102
|
federatedTokenFilePath;
|
|
103
|
+
// AKS proxy CA caching - persists across token requests
|
|
104
|
+
cachedTlsSettings;
|
|
105
|
+
cachedCaData;
|
|
106
|
+
caData;
|
|
107
|
+
caFile;
|
|
108
|
+
sniName;
|
|
41
109
|
/**
|
|
42
110
|
* WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.
|
|
43
111
|
*
|
|
@@ -56,19 +124,132 @@ export class WorkloadIdentityCredential {
|
|
|
56
124
|
checkTenantId(logger, tenantId);
|
|
57
125
|
}
|
|
58
126
|
if (!clientId) {
|
|
59
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
60
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
|
127
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CLIENT_ID_REQUIRED}`);
|
|
61
128
|
}
|
|
62
129
|
if (!tenantId) {
|
|
63
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
64
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
|
130
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TENANT_ID_REQUIRED}`);
|
|
65
131
|
}
|
|
66
132
|
if (!this.federatedTokenFilePath) {
|
|
67
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
68
|
-
|
|
133
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_FILE_PATH_REQUIRED}`);
|
|
134
|
+
}
|
|
135
|
+
// Use identity binding mode only when enableAzureKubernetesTokenProxy is set
|
|
136
|
+
if (workloadIdentityCredentialOptions.enableAzureKubernetesTokenProxy) {
|
|
137
|
+
const kubernetesTokenProxy = process.env.AZURE_KUBERNETES_TOKEN_PROXY;
|
|
138
|
+
const kubernetesSNIName = process.env.AZURE_KUBERNETES_SNI_NAME;
|
|
139
|
+
const kubernetesCAFile = process.env.AZURE_KUBERNETES_CA_FILE;
|
|
140
|
+
const kubernetesCAData = process.env.AZURE_KUBERNETES_CA_DATA;
|
|
141
|
+
if (!kubernetesTokenProxy) {
|
|
142
|
+
// Custom token proxy is not set, while other Kubernetes-related environment variables are present,
|
|
143
|
+
// this is likely a configuration issue so erroring out to avoid misconfiguration
|
|
144
|
+
if (kubernetesSNIName || kubernetesCAFile || kubernetesCAData) {
|
|
145
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.TOKEN_PROXY_NOT_SET}`);
|
|
146
|
+
}
|
|
147
|
+
logger.info(`enableAzureKubernetesTokenProxy is true but AZURE_KUBERNETES_TOKEN_PROXY is not set, using normal authentication flow`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const tokenProxy = parseAndValidateCustomTokenProxy(kubernetesTokenProxy);
|
|
151
|
+
// CAFile and CAData are mutually exclusive, at most one can be set.
|
|
152
|
+
// If none of CAFile or CAData are set, the default system CA pool will be used.
|
|
153
|
+
if (kubernetesCAFile && kubernetesCAData) {
|
|
154
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_AND_DATA_EXCLUSIVE}`);
|
|
155
|
+
}
|
|
156
|
+
this.caData = kubernetesCAData;
|
|
157
|
+
this.caFile = kubernetesCAFile;
|
|
158
|
+
this.sniName = kubernetesSNIName;
|
|
159
|
+
// Configure client options with AKS proxy client
|
|
160
|
+
const proxyClient = this.createAksProxyClient(tokenProxy);
|
|
161
|
+
workloadIdentityCredentialOptions.httpClient = proxyClient;
|
|
162
|
+
logger.info(`${credentialName}: Using proxy client for token requests`);
|
|
163
|
+
}
|
|
69
164
|
}
|
|
70
165
|
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
|
|
71
|
-
this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this),
|
|
166
|
+
this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), workloadIdentityCredentialOptions);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Creates a proxy HttpClient that intercepts token requests and redirects them to the Kubernetes endpoint
|
|
170
|
+
* Caching is handled at the credential level to persist across token requests
|
|
171
|
+
*/
|
|
172
|
+
createAksProxyClient(tokenEndpoint) {
|
|
173
|
+
const defaultClient = createDefaultHttpClient();
|
|
174
|
+
// Init cached TLS settings at construction time to fail fast on misconfiguration
|
|
175
|
+
this.cachedTlsSettings = this.getTlsSettings();
|
|
176
|
+
return {
|
|
177
|
+
sendRequest: async (request) => {
|
|
178
|
+
const requestUrl = new URL(request.url);
|
|
179
|
+
logger.info(`${credentialName}: Redirecting request to Kubernetes endpoint: ${tokenEndpoint}`);
|
|
180
|
+
const proxyUrl = new URL(tokenEndpoint);
|
|
181
|
+
// Remove leading slash from request path and join with proxy path
|
|
182
|
+
const requestPath = requestUrl.pathname.replace(/^\//, "");
|
|
183
|
+
const combinedPath = proxyUrl.pathname.endsWith("/")
|
|
184
|
+
? proxyUrl.pathname + requestPath
|
|
185
|
+
: proxyUrl.pathname + "/" + requestPath;
|
|
186
|
+
// Create new URL preserving query and fragment from original request
|
|
187
|
+
const newUrl = new URL(proxyUrl.origin);
|
|
188
|
+
newUrl.pathname = combinedPath;
|
|
189
|
+
newUrl.search = requestUrl.search;
|
|
190
|
+
newUrl.hash = requestUrl.hash;
|
|
191
|
+
request.url = newUrl.toString();
|
|
192
|
+
request.tlsSettings = this.getTlsSettings();
|
|
193
|
+
logger.info(`${credentialName}: Sending request to ${request.url}`);
|
|
194
|
+
// Forward the modified request with custom TLS settings
|
|
195
|
+
return defaultClient.sendRequest(request);
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Gets TLS settings for the request.
|
|
201
|
+
* Handles a few scenarios with CA data or CA file provided.
|
|
202
|
+
*/
|
|
203
|
+
getTlsSettings() {
|
|
204
|
+
// No CA overrides, use default transport
|
|
205
|
+
if (!this.caData && !this.caFile) {
|
|
206
|
+
if (!this.cachedTlsSettings) {
|
|
207
|
+
this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};
|
|
208
|
+
}
|
|
209
|
+
return this.cachedTlsSettings;
|
|
210
|
+
}
|
|
211
|
+
// Host provided CA bytes in AZURE_KUBERNETES_CA_DATA and can't change now
|
|
212
|
+
if (!this.caFile) {
|
|
213
|
+
if (!this.cachedTlsSettings) {
|
|
214
|
+
if (!canParseAsX509Certificate(this.caData)) {
|
|
215
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`);
|
|
216
|
+
}
|
|
217
|
+
this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};
|
|
218
|
+
this.cachedTlsSettings.ca = this.caData;
|
|
219
|
+
}
|
|
220
|
+
return this.cachedTlsSettings;
|
|
221
|
+
}
|
|
222
|
+
// Host provided the CA bytes in a file whose contents it can change,
|
|
223
|
+
let fileContent;
|
|
224
|
+
try {
|
|
225
|
+
fileContent = readFileSync(this.caFile);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_READ_CA_FILE(this.caFile, error)}`);
|
|
229
|
+
}
|
|
230
|
+
// This can happen in the middle of CA rotation
|
|
231
|
+
if (fileContent.length === 0) {
|
|
232
|
+
if (!this.cachedTlsSettings) {
|
|
233
|
+
// If the transport was never created, error out here to force retrying the call later
|
|
234
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_EMPTY(this.caFile)}`);
|
|
235
|
+
}
|
|
236
|
+
// If the transport was already created, just keep using it
|
|
237
|
+
return this.cachedTlsSettings;
|
|
238
|
+
}
|
|
239
|
+
// Check if CA has changed
|
|
240
|
+
if (!this.cachedCaData || !fileContent.equals(this.cachedCaData)) {
|
|
241
|
+
const caDataString = fileContent.toString("utf8");
|
|
242
|
+
if (!canParseAsX509Certificate(caDataString)) {
|
|
243
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`);
|
|
244
|
+
}
|
|
245
|
+
// CA has changed, rebuild the TLS settings with new CA pool
|
|
246
|
+
this.cachedTlsSettings = {
|
|
247
|
+
ca: caDataString,
|
|
248
|
+
...(this.sniName && { servername: this.sniName }),
|
|
249
|
+
};
|
|
250
|
+
this.cachedCaData = fileContent;
|
|
251
|
+
}
|
|
252
|
+
return this.cachedTlsSettings;
|
|
72
253
|
}
|
|
73
254
|
/**
|
|
74
255
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -80,11 +261,7 @@ export class WorkloadIdentityCredential {
|
|
|
80
261
|
*/
|
|
81
262
|
async getToken(scopes, options) {
|
|
82
263
|
if (!this.client) {
|
|
83
|
-
const errorMessage = `${credentialName}: is unavailable.
|
|
84
|
-
In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables -
|
|
85
|
-
"AZURE_TENANT_ID",
|
|
86
|
-
"AZURE_CLIENT_ID",
|
|
87
|
-
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`;
|
|
264
|
+
const errorMessage = `${credentialName}: is unavailable. ${ErrorMessages.MISSING_ENV_VARS}`;
|
|
88
265
|
logger.info(errorMessage);
|
|
89
266
|
throw new CredentialUnavailableError(errorMessage);
|
|
90
267
|
}
|
|
@@ -97,13 +274,13 @@ export class WorkloadIdentityCredential {
|
|
|
97
274
|
this.azureFederatedTokenFileContent = undefined;
|
|
98
275
|
}
|
|
99
276
|
if (!this.federatedTokenFilePath) {
|
|
100
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
277
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.INVALID_FILE_PATH(this.federatedTokenFilePath)}`);
|
|
101
278
|
}
|
|
102
279
|
if (!this.azureFederatedTokenFileContent) {
|
|
103
280
|
const file = await readFile(this.federatedTokenFilePath, "utf8");
|
|
104
281
|
const value = file.trim();
|
|
105
282
|
if (!value) {
|
|
106
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
|
283
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. ${ErrorMessages.NO_FILE_CONTENT(this.federatedTokenFilePath)}`);
|
|
107
284
|
}
|
|
108
285
|
else {
|
|
109
286
|
this.azureFederatedTokenFileContent = value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workloadIdentityCredential.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.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 { credentialLogger, processEnvVars } from \"../util/logging.js\";\n\nimport { ClientAssertionCredential } from \"./clientAssertionCredential.js\";\nimport { CredentialUnavailableError } from \"../errors.js\";\nimport type { WorkloadIdentityCredentialOptions } from \"./workloadIdentityCredentialOptions.js\";\nimport { checkTenantId } from \"../util/tenantIdUtils.js\";\nimport { readFile } from \"node:fs/promises\";\n\nconst credentialName = \"WorkloadIdentityCredential\";\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const SupportedWorkloadEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\",\n];\nconst logger = credentialLogger(credentialName);\n/**\n * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)\n * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity\n * authentication, applications authenticate themselves using their own identity, rather than using a shared service\n * principal or managed identity. Under the hood, Workload Identity authentication uses the concept of Service Account\n * Credentials (SACs), which are automatically created by Azure and stored securely in the VM. By using Workload\n * Identity authentication, you can avoid the need to manage and rotate service principals or managed identities for\n * each application on each VM. Additionally, because SACs are created automatically and managed by Azure, you don't\n * need to worry about storing and securing sensitive credentials themselves.\n * The WorkloadIdentityCredential supports Microsoft Entra Workload ID authentication on Azure Kubernetes and acquires\n * a token using the SACs available in the Azure Kubernetes environment.\n * Refer to <a href=\"https://learn.microsoft.com/azure/aks/workload-identity-overview\">Microsoft Entra\n * Workload ID</a> for more information.\n */\nexport class WorkloadIdentityCredential implements TokenCredential {\n private client: ClientAssertionCredential | undefined;\n private azureFederatedTokenFileContent: string | undefined = undefined;\n private cacheDate: number | undefined = undefined;\n private federatedTokenFilePath: string | undefined;\n\n /**\n * WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.\n *\n * @param options - The identity client options to use for authentication.\n */\n constructor(options?: WorkloadIdentityCredentialOptions) {\n // Logging environment variables for error details\n const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assignedEnv}`);\n\n const workloadIdentityCredentialOptions = options ?? {};\n const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;\n const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;\n this.federatedTokenFilePath =\n workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n if (!clientId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_CLIENT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_TENANT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. federatedTokenFilePath is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_FEDERATED_TOKEN_FILE\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`,\n );\n this.client = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.readFileContents.bind(this),\n 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 public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions,\n ): Promise<AccessToken> {\n if (!this.client) {\n const errorMessage = `${credentialName}: is unavailable. tenantId, clientId, and federatedTokenFilePath are required parameters. \n In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables - \n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`;\n logger.info(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.client.getToken(scopes, options);\n }\n\n private async readFileContents(): Promise<string> {\n // Cached assertions expire after 5 minutes\n if (this.cacheDate !== undefined && Date.now() - this.cacheDate >= 1000 * 60 * 5) {\n this.azureFederatedTokenFileContent = undefined;\n }\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Invalid file path provided ${this.federatedTokenFilePath}.`,\n );\n }\n if (!this.azureFederatedTokenFileContent) {\n const file = await readFile(this.federatedTokenFilePath, \"utf8\");\n const value = file.trim();\n if (!value) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. No content on the file ${this.federatedTokenFilePath}.`,\n );\n } else {\n this.azureFederatedTokenFileContent = value;\n this.cacheDate = Date.now();\n }\n }\n return this.azureFederatedTokenFileContent;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workloadIdentityCredential.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.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 { credentialLogger, processEnvVars } from \"../util/logging.js\";\n\nimport { ClientAssertionCredential } from \"./clientAssertionCredential.js\";\nimport { CredentialUnavailableError } from \"../errors.js\";\nimport type { WorkloadIdentityCredentialOptions } from \"./workloadIdentityCredentialOptions.js\";\nimport { checkTenantId } from \"../util/tenantIdUtils.js\";\nimport { readFile } from \"node:fs/promises\";\nimport type { PipelineRequest, PipelineResponse, HttpClient } from \"@azure/core-rest-pipeline\";\nimport { createDefaultHttpClient } from \"@azure/core-rest-pipeline\";\nimport type { TlsSettings } from \"@azure/core-rest-pipeline\";\nimport { canParseAsX509Certificate } from \"../util/certificatesUtils.js\";\nimport { readFileSync } from \"node:fs\";\n\nconst credentialName = \"WorkloadIdentityCredential\";\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const SupportedWorkloadEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\",\n];\n\nconst logger = credentialLogger(credentialName);\n\n/**\n * Error messages for WorkloadIdentityCredential\n */\nconst ErrorMessages = {\n FAILED_TO_PARSE_TOKEN_PROXY: (endpoint: string, error: unknown) =>\n `Failed to parse custom token proxy URL \"${endpoint}\": ${error}`,\n INVALID_HTTPS_SCHEME: (protocol: string) =>\n `Custom token endpoint must use https scheme, got \"${protocol}\"`,\n TOKEN_ENDPOINT_NO_USER_INFO: (url: string) =>\n `Custom token endpoint URL \"${url}\" must not contain user info`,\n TOKEN_ENDPOINT_NO_QUERY: (url: string) =>\n `Custom token endpoint URL \"${url}\" must not contain a query`,\n TOKEN_ENDPOINT_NO_FRAGMENT: (url: string) =>\n `Custom token endpoint URL \"${url}\" must not contain a fragment`,\n CA_FILE_EMPTY: (file: string) => `CA certificate file is empty: ${file}`,\n FAILED_TO_READ_CA_FILE: (file: string, error: unknown) =>\n `Failed to read CA certificate file: ${file}. ${error}`,\n INVALID_CA_CERTIFICATES: `Invalid CA certificate data: no valid PEM certificates found`,\n INVALID_FILE_PATH: (path: string | undefined) => `Invalid file path provided ${path}.`,\n NO_FILE_CONTENT: (path: string) => `No content on the file ${path}.`,\n NO_CA_SOURCE: `No CA certificate source specified.`,\n CLIENT_ID_REQUIRED: `clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_CLIENT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n TENANT_ID_REQUIRED: `tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_TENANT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n 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\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n TOKEN_PROXY_NOT_SET: `AZURE_KUBERNETES_TOKEN_PROXY is not set but other custom endpoint-related environment variables are present`,\n CA_FILE_AND_DATA_EXCLUSIVE: `AZURE_KUBERNETES_CA_FILE and AZURE_KUBERNETES_CA_DATA are mutually exclusive. Specify only one.`,\n MISSING_ENV_VARS: `tenantId, clientId, and federatedTokenFilePath are required parameters. \n In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables - \n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n};\n\n/**\n * @internal\n * Parses and validates the custom token proxy endpoint URL\n */\nexport function parseAndValidateCustomTokenProxy(endpoint: string): string {\n let tokenProxy: URL;\n try {\n tokenProxy = new URL(endpoint);\n } catch (error) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_PARSE_TOKEN_PROXY(endpoint, error)}`,\n );\n }\n\n if (tokenProxy.protocol !== \"https:\") {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.INVALID_HTTPS_SCHEME(tokenProxy.protocol)}`,\n );\n }\n\n if (tokenProxy.username || tokenProxy.password) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_USER_INFO(tokenProxy.toString())}`,\n );\n }\n\n if (tokenProxy.search) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_QUERY(tokenProxy.toString())}`,\n );\n }\n\n if (tokenProxy.hash) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TOKEN_ENDPOINT_NO_FRAGMENT(tokenProxy.toString())}`,\n );\n }\n\n if (!tokenProxy.pathname || tokenProxy.pathname === \"\") {\n // if the path is empty, set it to \"/\" to avoid stripping the path from req.URL\n tokenProxy.pathname = \"/\";\n }\n\n return tokenProxy.toString();\n}\n\n/**\n * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)\n * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity\n * authentication, applications authenticate themselves using their own identity, rather than using a shared service\n * principal or managed identity. Under the hood, Workload Identity authentication uses the concept of Service Account\n * Credentials (SACs), which are automatically created by Azure and stored securely in the VM. By using Workload\n * Identity authentication, you can avoid the need to manage and rotate service principals or managed identities for\n * each application on each VM. Additionally, because SACs are created automatically and managed by Azure, you don't\n * need to worry about storing and securing sensitive credentials themselves.\n * The WorkloadIdentityCredential supports Microsoft Entra Workload ID authentication on Azure Kubernetes and acquires\n * a token using the SACs available in the Azure Kubernetes environment.\n * Refer to <a href=\"https://learn.microsoft.com/azure/aks/workload-identity-overview\">Microsoft Entra\n * Workload ID</a> for more information.\n */\nexport class WorkloadIdentityCredential implements TokenCredential {\n private client: ClientAssertionCredential | undefined;\n private azureFederatedTokenFileContent: string | undefined = undefined;\n private cacheDate: number | undefined = undefined;\n private federatedTokenFilePath: string | undefined;\n\n // AKS proxy CA caching - persists across token requests\n private cachedTlsSettings: (TlsSettings & { servername?: string }) | undefined;\n private cachedCaData: Buffer | undefined;\n private caData: string | undefined;\n private caFile: string | undefined;\n private sniName: string | undefined;\n\n /**\n * WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.\n *\n * @param options - The identity client options to use for authentication.\n */\n constructor(options?: WorkloadIdentityCredentialOptions) {\n // Logging environment variables for error details\n const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assignedEnv}`);\n\n const workloadIdentityCredentialOptions = options ?? {};\n const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;\n const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;\n this.federatedTokenFilePath =\n workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;\n\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n if (!clientId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.CLIENT_ID_REQUIRED}`,\n );\n }\n\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TENANT_ID_REQUIRED}`,\n );\n }\n\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TOKEN_FILE_PATH_REQUIRED}`,\n );\n }\n\n // Use identity binding mode only when enableAzureKubernetesTokenProxy is set\n if (workloadIdentityCredentialOptions.enableAzureKubernetesTokenProxy) {\n const kubernetesTokenProxy = process.env.AZURE_KUBERNETES_TOKEN_PROXY;\n const kubernetesSNIName = process.env.AZURE_KUBERNETES_SNI_NAME;\n const kubernetesCAFile = process.env.AZURE_KUBERNETES_CA_FILE;\n const kubernetesCAData = process.env.AZURE_KUBERNETES_CA_DATA;\n\n if (!kubernetesTokenProxy) {\n // Custom token proxy is not set, while other Kubernetes-related environment variables are present,\n // this is likely a configuration issue so erroring out to avoid misconfiguration\n if (kubernetesSNIName || kubernetesCAFile || kubernetesCAData) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.TOKEN_PROXY_NOT_SET}`,\n );\n }\n logger.info(\n `enableAzureKubernetesTokenProxy is true but AZURE_KUBERNETES_TOKEN_PROXY is not set, using normal authentication flow`,\n );\n } else {\n const tokenProxy = parseAndValidateCustomTokenProxy(kubernetesTokenProxy);\n\n // CAFile and CAData are mutually exclusive, at most one can be set.\n // If none of CAFile or CAData are set, the default system CA pool will be used.\n if (kubernetesCAFile && kubernetesCAData) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_AND_DATA_EXCLUSIVE}`,\n );\n }\n\n this.caData = kubernetesCAData;\n this.caFile = kubernetesCAFile;\n this.sniName = kubernetesSNIName;\n\n // Configure client options with AKS proxy client\n const proxyClient = this.createAksProxyClient(tokenProxy);\n workloadIdentityCredentialOptions.httpClient = proxyClient;\n logger.info(`${credentialName}: Using proxy client for token requests`);\n }\n }\n\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`,\n );\n\n this.client = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.readFileContents.bind(this),\n workloadIdentityCredentialOptions,\n );\n }\n\n /**\n * Creates a proxy HttpClient that intercepts token requests and redirects them to the Kubernetes endpoint\n * Caching is handled at the credential level to persist across token requests\n */\n private createAksProxyClient(tokenEndpoint: string): HttpClient {\n const defaultClient = createDefaultHttpClient();\n // Init cached TLS settings at construction time to fail fast on misconfiguration\n this.cachedTlsSettings = this.getTlsSettings();\n\n return {\n sendRequest: async (request: PipelineRequest): Promise<PipelineResponse> => {\n const requestUrl = new URL(request.url);\n\n logger.info(\n `${credentialName}: Redirecting request to Kubernetes endpoint: ${tokenEndpoint}`,\n );\n\n const proxyUrl = new URL(tokenEndpoint);\n\n // Remove leading slash from request path and join with proxy path\n const requestPath = requestUrl.pathname.replace(/^\\//, \"\");\n const combinedPath = proxyUrl.pathname.endsWith(\"/\")\n ? proxyUrl.pathname + requestPath\n : proxyUrl.pathname + \"/\" + requestPath;\n\n // Create new URL preserving query and fragment from original request\n const newUrl = new URL(proxyUrl.origin);\n newUrl.pathname = combinedPath;\n newUrl.search = requestUrl.search;\n newUrl.hash = requestUrl.hash;\n\n request.url = newUrl.toString();\n request.tlsSettings = this.getTlsSettings();\n\n logger.info(`${credentialName}: Sending request to ${request.url}`);\n // Forward the modified request with custom TLS settings\n return defaultClient.sendRequest(request);\n },\n };\n }\n\n /**\n * Gets TLS settings for the request.\n * Handles a few scenarios with CA data or CA file provided.\n */\n private getTlsSettings(): TlsSettings & { servername?: string } {\n // No CA overrides, use default transport\n if (!this.caData && !this.caFile) {\n if (!this.cachedTlsSettings) {\n this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};\n }\n return this.cachedTlsSettings;\n }\n\n // Host provided CA bytes in AZURE_KUBERNETES_CA_DATA and can't change now\n if (!this.caFile) {\n if (!this.cachedTlsSettings) {\n if (!canParseAsX509Certificate(this.caData!)) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`,\n );\n }\n this.cachedTlsSettings = this.sniName ? { servername: this.sniName } : {};\n this.cachedTlsSettings.ca = this.caData;\n }\n return this.cachedTlsSettings;\n }\n\n // Host provided the CA bytes in a file whose contents it can change,\n let fileContent: Buffer;\n try {\n fileContent = readFileSync(this.caFile);\n } catch (error) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.FAILED_TO_READ_CA_FILE(this.caFile!, error)}`,\n );\n }\n // This can happen in the middle of CA rotation\n if (fileContent.length === 0) {\n if (!this.cachedTlsSettings) {\n // If the transport was never created, error out here to force retrying the call later\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.CA_FILE_EMPTY(this.caFile)}`,\n );\n }\n // If the transport was already created, just keep using it\n return this.cachedTlsSettings;\n }\n\n // Check if CA has changed\n if (!this.cachedCaData || !fileContent.equals(this.cachedCaData)) {\n const caDataString = fileContent.toString(\"utf8\");\n\n if (!canParseAsX509Certificate(caDataString)) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.INVALID_CA_CERTIFICATES}`,\n );\n }\n\n // CA has changed, rebuild the TLS settings with new CA pool\n this.cachedTlsSettings = {\n ca: caDataString,\n ...(this.sniName && { servername: this.sniName }),\n };\n this.cachedCaData = fileContent;\n }\n\n return this.cachedTlsSettings!;\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 public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions,\n ): Promise<AccessToken> {\n if (!this.client) {\n const errorMessage = `${credentialName}: is unavailable. ${ErrorMessages.MISSING_ENV_VARS}`;\n logger.info(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.client.getToken(scopes, options);\n }\n\n private async readFileContents(): Promise<string> {\n // Cached assertions expire after 5 minutes\n if (this.cacheDate !== undefined && Date.now() - this.cacheDate >= 1000 * 60 * 5) {\n this.azureFederatedTokenFileContent = undefined;\n }\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.INVALID_FILE_PATH(this.federatedTokenFilePath)}`,\n );\n }\n if (!this.azureFederatedTokenFileContent) {\n const file = await readFile(this.federatedTokenFilePath, \"utf8\");\n const value = file.trim();\n if (!value) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. ${ErrorMessages.NO_FILE_CONTENT(this.federatedTokenFilePath)}`,\n );\n } else {\n this.azureFederatedTokenFileContent = value;\n this.cacheDate = Date.now();\n }\n }\n return this.azureFederatedTokenFileContent;\n }\n}\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"}
|