Skip to content

Commit c2ce947

Browse files
committed
fix(ec2-metadata-service): custom port configuration for IMDS requests
1 parent dbc6519 commit c2ce947

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

packages/ec2-metadata-service/src/MetadataService.spec.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,95 @@ describe("MetadataService Socket Leak Checks", () => {
253253
});
254254
});
255255
});
256+
257+
describe("MetadataService Custom Ports", () => {
258+
let metadataService: MetadataService;
259+
260+
beforeEach(() => {
261+
vi.clearAllMocks();
262+
});
263+
264+
const createMockResponse = (statusCode: number, body: string) => {
265+
const stream = Readable.from([body]);
266+
return {
267+
response: {
268+
statusCode,
269+
body: stream,
270+
headers: {},
271+
},
272+
};
273+
};
274+
275+
it("should use custom port from endpoint URL in request()", async () => {
276+
metadataService = new MetadataService({
277+
endpoint: "http://localhost:1338",
278+
httpOptions: { timeout: 1000 },
279+
});
280+
281+
const mockResponse = createMockResponse(200, "i-1234567890abcdef0");
282+
const mockHandle = vi.fn().mockResolvedValue(mockResponse);
283+
284+
vi.mocked(NodeHttpHandler).mockImplementation(() => ({ handle: mockHandle } as any));
285+
286+
await metadataService.request("/latest/meta-data/instance-id", {});
287+
288+
const requestArg = mockHandle.mock.calls[0][0];
289+
expect(requestArg.port).toBe(1338);
290+
expect(requestArg.hostname).toBe("localhost");
291+
});
292+
293+
it("should use custom port from endpoint URL in fetchMetadataToken()", async () => {
294+
metadataService = new MetadataService({
295+
endpoint: "http://localhost:1338",
296+
httpOptions: { timeout: 1000 },
297+
});
298+
299+
const mockResponse = createMockResponse(200, "test-token-123");
300+
const mockHandle = vi.fn().mockResolvedValue(mockResponse);
301+
302+
vi.mocked(NodeHttpHandler).mockImplementation(() => ({ handle: mockHandle } as any));
303+
304+
await metadataService.fetchMetadataToken();
305+
306+
const requestArg = mockHandle.mock.calls[0][0];
307+
expect(requestArg.port).toBe(1338);
308+
expect(requestArg.hostname).toBe("localhost");
309+
});
310+
311+
it("should use undefined port for standard HTTP endpoint (port 80)", async () => {
312+
metadataService = new MetadataService({
313+
endpoint: "http://169.254.169.254",
314+
httpOptions: { timeout: 1000 },
315+
});
316+
317+
const mockResponse = createMockResponse(200, "test-token-123");
318+
const mockHandle = vi.fn().mockResolvedValue(mockResponse);
319+
320+
vi.mocked(NodeHttpHandler).mockImplementation(() => ({ handle: mockHandle } as any));
321+
322+
await metadataService.fetchMetadataToken();
323+
324+
const requestArg = mockHandle.mock.calls[0][0];
325+
expect(requestArg.port).toBeUndefined();
326+
expect(requestArg.hostname).toBe("169.254.169.254");
327+
});
328+
329+
it("should use custom HTTPS port from endpoint URL", async () => {
330+
metadataService = new MetadataService({
331+
endpoint: "https://localhost:8443",
332+
httpOptions: { timeout: 1000 },
333+
});
334+
335+
const mockResponse = createMockResponse(200, "test-token-123");
336+
const mockHandle = vi.fn().mockResolvedValue(mockResponse);
337+
338+
vi.mocked(NodeHttpHandler).mockImplementation(() => ({ handle: mockHandle } as any));
339+
340+
await metadataService.fetchMetadataToken();
341+
342+
const requestArg = mockHandle.mock.calls[0][0];
343+
expect(requestArg.port).toBe(8443);
344+
expect(requestArg.hostname).toBe("localhost");
345+
expect(requestArg.protocol).toBe("https:");
346+
});
347+
});

packages/ec2-metadata-service/src/MetadataService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export class MetadataService {
6969
hostname: endpointUrl.hostname,
7070
path: endpointUrl.pathname + path,
7171
protocol: endpointUrl.protocol,
72+
port: endpointUrl.port ? parseInt(endpointUrl.port) : undefined,
7273
});
7374
try {
7475
const { response } = await handler.handle(request, {} as HttpHandlerOptions);
@@ -102,6 +103,7 @@ export class MetadataService {
102103
hostname: endpointUrl.hostname,
103104
path: "/latest/api/token",
104105
protocol: endpointUrl.protocol,
106+
port: endpointUrl.port ? parseInt(endpointUrl.port) : undefined,
105107
});
106108
try {
107109
const { response } = await handler.handle(tokenRequest, {} as HttpHandlerOptions);

0 commit comments

Comments
 (0)