Skip to content

Commit 9a2afdf

Browse files
authored
[identity] Prep for release (#29981)
1 parent 3caf203 commit 9a2afdf

File tree

8 files changed

+280
-165
lines changed

8 files changed

+280
-165
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 84 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/identity/identity/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Release History
22

3+
## 4.2.1 (2024-06-10)
4+
5+
### Bugs Fixed
6+
7+
- Managed identity bug fixes
8+
39
## 4.2.0 (2024-04-30)
410

511
### Features Added

sdk/identity/identity/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@azure/identity",
33
"sdk-type": "client",
4-
"version": "4.2.0",
4+
"version": "4.2.1",
55
"description": "Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID",
66
"main": "dist/index.js",
77
"module": "dist-esm/src/index.js",
@@ -115,7 +115,7 @@
115115
"@azure/core-util": "^1.3.0",
116116
"@azure/logger": "^1.0.0",
117117
"@azure/msal-browser": "^3.11.1",
118-
"@azure/msal-node": "^2.6.6",
118+
"@azure/msal-node": "^2.9.2",
119119
"events": "^3.0.0",
120120
"jws": "^4.0.0",
121121
"open": "^8.0.0",

sdk/identity/identity/src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/**
55
* Current version of the `@azure/identity` package.
66
*/
7-
export const SDK_VERSION = `4.2.0`;
7+
export const SDK_VERSION = `4.2.1`;
88

99
/**
1010
* The default client ID for authentication

sdk/identity/identity/src/credentials/managedIdentityCredential/arcMsi.ts

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT license.
33

4+
import { MSI, MSIConfiguration, MSIToken } from "./models";
45
import {
56
PipelineRequestOptions,
67
createHttpHeaders,
78
createPipelineRequest,
89
} from "@azure/core-rest-pipeline";
9-
import { GetTokenOptions } from "@azure/core-auth";
10-
import { readFile } from "fs";
10+
1111
import { AuthenticationError } from "../../errors";
12-
import { credentialLogger } from "../../util/logging";
12+
import { GetTokenOptions } from "@azure/core-auth";
1313
import { IdentityClient } from "../../client/identityClient";
14-
import { mapScopesToResource } from "./utils";
15-
import { MSI, MSIConfiguration, MSIToken } from "./models";
1614
import { azureArcAPIVersion } from "./constants";
15+
import { credentialLogger } from "../../util/logging";
16+
import fs from "node:fs";
17+
import { mapScopesToResource } from "./utils";
1718

1819
const msiName = "ManagedIdentityCredential - Azure Arc MSI";
1920
const logger = credentialLogger(msiName);
@@ -60,21 +61,6 @@ function prepareRequestOptions(
6061
});
6162
}
6263

63-
/**
64-
* Retrieves the file contents at the given path using promises.
65-
* Useful since `fs`'s readFileSync locks the thread, and to avoid extra dependencies.
66-
*/
67-
function readFileAsync(path: string, options: { encoding: BufferEncoding }): Promise<string> {
68-
return new Promise((resolve, reject) =>
69-
readFile(path, options, (err, data) => {
70-
if (err) {
71-
reject(err);
72-
}
73-
resolve(data);
74-
}),
75-
);
76-
}
77-
7864
/**
7965
* Does a request to the authentication provider that results in a file path.
8066
*/
@@ -103,6 +89,50 @@ async function filePathRequest(
10389
}
10490
}
10591

92+
export function platformToFilePath(): string {
93+
switch (process.platform) {
94+
case "win32":
95+
if (!process.env.PROGRAMDATA) {
96+
throw new Error(`${msiName}: PROGRAMDATA environment variable has no value.`);
97+
}
98+
return `${process.env.PROGRAMDATA}\\AzureConnectedMachineAgent\\Tokens`;
99+
case "linux":
100+
return "/var/opt/azcmagent/tokens";
101+
default:
102+
throw new Error(`${msiName}: Unsupported platform ${process.platform}.`);
103+
}
104+
}
105+
106+
/**
107+
* Validates that a given Azure Arc MSI file path is valid for use.
108+
*
109+
* A valid file will:
110+
* 1. Be in the expected path for the current platform.
111+
* 2. Have a `.key` extension.
112+
* 3. Be at most 4096 bytes in size.
113+
*/
114+
export function validateKeyFile(filePath?: string): asserts filePath is string {
115+
if (!filePath) {
116+
throw new Error(`${msiName}: Failed to find the token file.`);
117+
}
118+
119+
if (!filePath.endsWith(".key")) {
120+
throw new Error(`${msiName}: unexpected file path from HIMDS service: ${filePath}.`);
121+
}
122+
123+
const expectedPath = platformToFilePath();
124+
if (!filePath.startsWith(expectedPath)) {
125+
throw new Error(`${msiName}: unexpected file path from HIMDS service: ${filePath}.`);
126+
}
127+
128+
const stats = fs.statSync(filePath);
129+
if (stats.size > 4096) {
130+
throw new Error(
131+
`${msiName}: The file at ${filePath} is larger than expected at ${stats.size} bytes.`,
132+
);
133+
}
134+
}
135+
106136
/**
107137
* Defines how to determine whether the Azure Arc MSI is available, and also how to retrieve a token from the Azure Arc MSI.
108138
*/
@@ -150,12 +180,9 @@ export const arcMsi: MSI = {
150180
};
151181

152182
const filePath = await filePathRequest(identityClient, requestOptions);
183+
validateKeyFile(filePath);
153184

154-
if (!filePath) {
155-
throw new Error(`${msiName}: Failed to find the token file.`);
156-
}
157-
158-
const key = await readFileAsync(filePath, { encoding: "utf-8" });
185+
const key = await fs.promises.readFile(filePath, { encoding: "utf-8" });
159186
requestOptions.headers?.set("Authorization", `Basic ${key}`);
160187

161188
const request = createPipelineRequest({

0 commit comments

Comments
 (0)