@azure/identity
Version:
Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID
272 lines (271 loc) • 10.8 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var managedIdentityCredential_exports = {};
__export(managedIdentityCredential_exports, {
ManagedIdentityCredential: () => ManagedIdentityCredential
});
module.exports = __toCommonJS(managedIdentityCredential_exports);
var import_logger = require("@azure/logger");
var import_msal_node = require("@azure/msal-node");
var import_identityClient = require("../../client/identityClient.js");
var import_errors = require("../../errors.js");
var import_utils = require("../../msal/utils.js");
var import_imdsRetryPolicy = require("./imdsRetryPolicy.js");
var import_logging = require("../../util/logging.js");
var import_tracing = require("../../util/tracing.js");
var import_imdsMsi = require("./imdsMsi.js");
var import_tokenExchangeMsi = require("./tokenExchangeMsi.js");
var import_utils2 = require("./utils.js");
const logger = (0, import_logging.credentialLogger)("ManagedIdentityCredential");
class ManagedIdentityCredential {
managedIdentityApp;
identityClient;
clientId;
resourceId;
objectId;
msiRetryConfig = {
maxRetries: 5,
startDelayInMs: 800,
intervalIncrement: 2
};
isAvailableIdentityClient;
sendProbeRequest;
/**
* @internal
* @hidden
*/
constructor(clientIdOrOptions, options) {
let _options;
if (typeof clientIdOrOptions === "string") {
this.clientId = clientIdOrOptions;
_options = options ?? {};
} else {
this.clientId = clientIdOrOptions?.clientId;
_options = clientIdOrOptions ?? {};
}
this.resourceId = _options?.resourceId;
this.objectId = _options?.objectId;
this.sendProbeRequest = _options?.sendProbeRequest ?? false;
const providedIds = [
{ key: "clientId", value: this.clientId },
{ key: "resourceId", value: this.resourceId },
{ key: "objectId", value: this.objectId }
].filter((id) => id.value);
if (providedIds.length > 1) {
throw new Error(
`ManagedIdentityCredential: only one of 'clientId', 'resourceId', or 'objectId' can be provided. Received values: ${JSON.stringify(
{ clientId: this.clientId, resourceId: this.resourceId, objectId: this.objectId }
)}`
);
}
_options.allowInsecureConnection = true;
if (_options.retryOptions?.maxRetries !== void 0) {
this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;
}
this.identityClient = new import_identityClient.IdentityClient({
..._options,
additionalPolicies: [{ policy: (0, import_imdsRetryPolicy.imdsRetryPolicy)(this.msiRetryConfig), position: "perCall" }]
});
this.managedIdentityApp = new import_msal_node.ManagedIdentityApplication({
managedIdentityIdParams: {
userAssignedClientId: this.clientId,
userAssignedResourceId: this.resourceId,
userAssignedObjectId: this.objectId
},
system: {
disableInternalRetries: true,
networkClient: this.identityClient,
loggerOptions: {
logLevel: (0, import_utils.getMSALLogLevel)((0, import_logger.getLogLevel)()),
piiLoggingEnabled: _options.loggingOptions?.enableUnsafeSupportLogging,
loggerCallback: (0, import_utils.defaultLoggerCallback)(logger)
}
}
});
this.isAvailableIdentityClient = new import_identityClient.IdentityClient({
..._options,
retryOptions: {
maxRetries: 0
}
});
const managedIdentitySource = this.managedIdentityApp.getManagedIdentitySource();
if (managedIdentitySource === "CloudShell") {
if (this.clientId || this.resourceId || this.objectId) {
logger.warning(
`CloudShell MSI detected with user-provided IDs - throwing. Received values: ${JSON.stringify(
{
clientId: this.clientId,
resourceId: this.resourceId,
objectId: this.objectId
}
)}.`
);
throw new import_errors.CredentialUnavailableError(
"ManagedIdentityCredential: Specifying a user-assigned managed identity is not supported for CloudShell at runtime. When using Managed Identity in CloudShell, omit the clientId, resourceId, and objectId parameters."
);
}
}
if (managedIdentitySource === "ServiceFabric") {
if (this.clientId || this.resourceId || this.objectId) {
logger.warning(
`Service Fabric detected with user-provided IDs - throwing. Received values: ${JSON.stringify(
{
clientId: this.clientId,
resourceId: this.resourceId,
objectId: this.objectId
}
)}.`
);
throw new import_errors.CredentialUnavailableError(
`ManagedIdentityCredential: ${import_utils2.serviceFabricErrorMessage}`
);
}
}
logger.info(`Using ${managedIdentitySource} managed identity.`);
if (providedIds.length === 1) {
const { key, value } = providedIds[0];
logger.info(`${managedIdentitySource} with ${key}: ${value}`);
}
}
/**
* Authenticates with Microsoft Entra ID and returns an access token if successful.
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
* If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.
*
* @param scopes - The list of scopes for which the token will have access.
* @param options - The options used to configure any requests this
* TokenCredential implementation might make.
*/
async getToken(scopes, options = {}) {
logger.getToken.info("Using the MSAL provider for Managed Identity.");
const resource = (0, import_utils2.mapScopesToResource)(scopes);
if (!resource) {
throw new import_errors.CredentialUnavailableError(
`ManagedIdentityCredential: Multiple scopes are not supported. Scopes: ${JSON.stringify(
scopes
)}`
);
}
return import_tracing.tracingClient.withSpan("ManagedIdentityCredential.getToken", options, async () => {
try {
const isTokenExchangeMsi = await import_tokenExchangeMsi.tokenExchangeMsi.isAvailable(this.clientId);
const identitySource = this.managedIdentityApp.getManagedIdentitySource();
const isImdsMsi = identitySource === "DefaultToImds" || identitySource === "Imds";
logger.getToken.info(`MSAL Identity source: ${identitySource}`);
if (isTokenExchangeMsi) {
logger.getToken.info("Using the token exchange managed identity.");
const result = await import_tokenExchangeMsi.tokenExchangeMsi.getToken({
scopes,
clientId: this.clientId,
identityClient: this.identityClient,
retryConfig: this.msiRetryConfig,
resourceId: this.resourceId
});
if (result === null) {
throw new import_errors.CredentialUnavailableError(
"Attempted to use the token exchange managed identity, but received a null response."
);
}
return result;
} else if (isImdsMsi && this.sendProbeRequest) {
logger.getToken.info("Using the IMDS endpoint to probe for availability.");
const isAvailable = await import_imdsMsi.imdsMsi.isAvailable({
scopes,
clientId: this.clientId,
getTokenOptions: options,
identityClient: this.isAvailableIdentityClient,
resourceId: this.resourceId
});
if (!isAvailable) {
throw new import_errors.CredentialUnavailableError(
`Attempted to use the IMDS endpoint, but it is not available.`
);
}
}
logger.getToken.info("Calling into MSAL for managed identity token.");
const token = await this.managedIdentityApp.acquireToken({
resource
});
this.ensureValidMsalToken(scopes, token, options);
logger.getToken.info((0, import_logging.formatSuccess)(scopes));
return {
expiresOnTimestamp: token.expiresOn.getTime(),
token: token.accessToken,
refreshAfterTimestamp: token.refreshOn?.getTime(),
tokenType: "Bearer"
};
} catch (err) {
logger.getToken.error((0, import_logging.formatError)(scopes, err));
if (err.name === "AuthenticationRequiredError") {
throw err;
}
if (isNetworkError(err)) {
throw new import_errors.CredentialUnavailableError(
`ManagedIdentityCredential: Network unreachable. Message: ${err.message}`,
{ cause: err }
);
}
throw new import_errors.CredentialUnavailableError(
`ManagedIdentityCredential: Authentication failed. Message ${err.message}`,
{ cause: err }
);
}
});
}
/**
* Ensures the validity of the MSAL token
*/
ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
const createError = (message) => {
logger.getToken.info(message);
return new import_errors.AuthenticationRequiredError({
scopes: Array.isArray(scopes) ? scopes : [scopes],
getTokenOptions,
message
});
};
if (!msalToken) {
throw createError("No response.");
}
if (!msalToken.expiresOn) {
throw createError(`Response had no "expiresOn" property.`);
}
if (!msalToken.accessToken) {
throw createError(`Response had no "accessToken" property.`);
}
}
}
function isNetworkError(err) {
if (err.errorCode === "network_error") {
return true;
}
if (err.code === "ENETUNREACH" || err.code === "EHOSTUNREACH") {
return true;
}
if (err.statusCode === 403 || err.code === 403) {
if (err.message.includes("unreachable")) {
return true;
}
}
return false;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ManagedIdentityCredential
});
//# sourceMappingURL=index.js.map