diff --git a/packages/ec2-metadata-service/jest.config.js b/packages/ec2-metadata-service/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/ec2-metadata-service/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/ec2-metadata-service/package.json b/packages/ec2-metadata-service/package.json index bd65473fcfbde..faac7a962f923 100644 --- a/packages/ec2-metadata-service/package.json +++ b/packages/ec2-metadata-service/package.json @@ -25,9 +25,9 @@ "tslib": "^2.5.0", "@smithy/node-http-handler": "^2.3.1", "@smithy/util-stream": "^2.1.1", - "@aws-sdk/types": "3.515.0", + "@aws-sdk/types": "*", "@aws-sdk/protocol-http": "3.374.0", - "@smithy/node-config-provider": "2.2.5" + "@smithy/node-config-provider": "^2.2.1" }, "devDependencies": { "@tsconfig/recommended": "1.0.1", diff --git a/packages/ec2-metadata-service/src/ConfigLoaders.ts b/packages/ec2-metadata-service/src/ConfigLoaders.ts index 9fab33cdf0d28..a1cbc1c0e7821 100644 --- a/packages/ec2-metadata-service/src/ConfigLoaders.ts +++ b/packages/ec2-metadata-service/src/ConfigLoaders.ts @@ -1,4 +1,6 @@ import { LoadedConfigSelectors } from "@smithy/node-config-provider"; + +import { Endpoint } from "./Endpoint"; import { EndpointMode } from "./EndpointMode"; /** @@ -16,7 +18,7 @@ export const CONFIG_ENDPOINT_NAME = "ec2_metadata_service_endpoint"; export const ENDPOINT_SELECTORS: LoadedConfigSelectors = { environmentVariableSelector: (env) => env[ENV_ENDPOINT_NAME], configFileSelector: (profile) => profile[CONFIG_ENDPOINT_NAME], - default: undefined, + default: Endpoint.IPv4, }; /** @@ -50,10 +52,10 @@ export const PROFILE_AWS_EC2_METADATA_V1_DISABLED = "ec2_metadata_v1_disabled"; */ export const IMDSv1_DISABLED_SELECTORS: LoadedConfigSelectors = { environmentVariableSelector: (env) => - env[AWS_EC2_METADATA_V1_DISABLED] ? env[AWS_EC2_METADATA_V1_DISABLED].toLowerCase() !== "false" : undefined, + env[AWS_EC2_METADATA_V1_DISABLED] ? env[AWS_EC2_METADATA_V1_DISABLED] !== "false" : undefined, configFileSelector: (profile) => profile[PROFILE_AWS_EC2_METADATA_V1_DISABLED] - ? profile[PROFILE_AWS_EC2_METADATA_V1_DISABLED].toLowerCase() !== "false" + ? profile[PROFILE_AWS_EC2_METADATA_V1_DISABLED] !== "false" : undefined, default: false, }; diff --git a/packages/ec2-metadata-service/src/MetadataService.ts b/packages/ec2-metadata-service/src/MetadataService.ts index 81a09901f77a9..fb17a0637d77e 100644 --- a/packages/ec2-metadata-service/src/MetadataService.ts +++ b/packages/ec2-metadata-service/src/MetadataService.ts @@ -1,8 +1,9 @@ import { HttpRequest } from "@aws-sdk/protocol-http"; import { HttpHandlerOptions } from "@aws-sdk/types"; +import { loadConfig } from "@smithy/node-config-provider"; import { NodeHttpHandler } from "@smithy/node-http-handler"; import { sdkStreamMixin } from "@smithy/util-stream"; -import { loadConfig } from "@smithy/node-config-provider"; + import { ENDPOINT_SELECTORS, IMDSv1_DISABLED_SELECTORS } from "./ConfigLoaders"; import { MetadataServiceOptions } from "./MetadataServiceOptions"; @@ -33,23 +34,37 @@ export class MetadataService { async request( path: string, options: { method?: string; headers?: Record }, - withToken?: boolean + withToken?: boolean // withToken should be set to true, if the request is to be made in accordance with IMDSv2 ): Promise { const { endpoint, ec2MetadataV1Disabled } = await this.config; - if (this.disableFetchToken && !withToken && ec2MetadataV1Disabled) { - throw new Error( - "In IMDSv1 fallback mode and ec2MetadataV1Disabled option is set to true, no request can be made." - ); - } const handler = new NodeHttpHandler(); const endpointUrl = new URL(endpoint); - const headers = options.headers || {}; // Using provided headers or default to an empty object + const headers = options.headers || {}; + + if (this.disableFetchToken && withToken) { + throw new Error("The disableFetchToken option and the withToken argument are both set to true."); + } /** - * Make request with token. + * If IMDSv1 is disabled and disableFetchToken is true, throw an error + * Refer: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html + */ + if (this.disableFetchToken && ec2MetadataV1Disabled) { + throw new Error("IMDSv1 is disabled and fetching token is disabled, cannot make the request."); + } + /** + * Make request with token if disableFetchToken is not true and withToken is true. * Note that making the request call with token will result in an additional request to fetch the token. */ - if (withToken) { - headers["x-aws-ec2-metadata-token"] = await this.fetchMetadataToken(); + if (withToken && !this.disableFetchToken) { + try { + headers["x-aws-ec2-metadata-token"] = await this.fetchMetadataToken(); + } catch (err) { + if (ec2MetadataV1Disabled) { + // If IMDSv1 is disabled and token fetch fails (IMDSv2 fails), rethrow the error + throw err; + } + // If token fetch fails and IMDSv1 is not disabled, proceed without token (IMDSv1 fallback) + } } const request = new HttpRequest({ method: options.method || "GET", // Default to GET if no method is specified @@ -75,8 +90,6 @@ export class MetadataService { /** * Refer: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html */ - - // Define the request to fetch the metadata token const { endpoint } = await this.config; const handler = new NodeHttpHandler(); const endpointUrl = new URL(endpoint);