Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support IPv6 endpoints in IMDS #3853

Merged
merged 21 commits into from
Aug 19, 2021
Merged

Support IPv6 endpoints in IMDS #3853

merged 21 commits into from
Aug 19, 2021

Conversation

trivikr
Copy link
Member

@trivikr trivikr commented Aug 13, 2021

Adds support for IMDS IPv6 endpoints

Manual testing

Testing was done by printing endpoint as follows:

--- a/lib/metadata_service.js
+++ b/lib/metadata_service.js
@@ -60,6 +60,7 @@ AWS.MetadataService = inherit({
    *   retry delay on retryable errors. See AWS.Config for details.
    */
   constructor: function MetadataService(options) {
+    console.log({ endpoint: this.endpoint });
     if (options && options.host) {
       options.endpoint = 'http://' + options.host;
       delete options.host;
test-v2.js
const AWS = require("./aws-sdk-js/index.js");
  
const testCredentials = async () => {
  const region = "us-west-2";
  const client = new AWS.DynamoDB({ region });
  await client.listTables().promise();
};

module.exports = {
  testCredentials,
};
test-v2.shared.js
import { promisify } from "util";
import { exec } from "child_process";

const execPromise = promisify(exec);

const testCredentialsString = `const { testCredentials } = require("./test-v2.js"); (async() => {await testCredentials();})();`;

export const test = async (envKeyValuePair) => {
  console.log(`ENV: ${envKeyValuePair}`);
  const command = `${envKeyValuePair ? envKeyValuePair : ""} node -e '${testCredentialsString}'`;
  try {
    const { stdout } = await execPromise(command);
    console.log(stdout);
  } catch (error) {
    console.log(error.stderr.split("\n").filter(line => line.includes("Error")));
  }
};

Environment variables

test-v2.env.mjs
import { test } from "./test-v2.shared.mjs";

const ENV_ENDPOINT_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT";
const ENV_ENDPOINT_MODE_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE";

await test();
const endpoints = [
  "http://169.254.169.254",
  "http://[fd00:ec2::254]",
  "invalidEndpoint",
];
for (const endpoint of endpoints) {
  await test(`${ENV_ENDPOINT_NAME}=${endpoint}`);
}

await test();
const endpointModes = ["IPv4", "IPv6", "invalidEndpointMode"];
for (const endpointMode of endpointModes) {
  await test(`${ENV_ENDPOINT_MODE_NAME}=${endpointMode}`);
}
Output
ENV: undefined
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT=http://169.254.169.254
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT=http://[fd00:ec2::254]
{ endpoint: 'http://[fd00:ec2::254]' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT=invalidEndpoint
[
  'TypeError [ERR_INVALID_URL]: Invalid URL: invalidEndpoint',
  '    at onParseError (internal/url.js:279:9)'
]
ENV: undefined
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv4
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
{ endpoint: 'http://[fd00:ec2::254]' }

ENV: AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=invalidEndpointMode
[
  "      throw new Error('Unsupported endpoint mode: ' + endpointMode);",
  'Error: Unsupported endpoint mode: invalidEndpointMode'
]

Shared ini configuration

Config
[profile imds_mode_v4]
ec2_metadata_service_endpoint_mode=IPv4

[profile imds_mode_v6]
ec2_metadata_service_endpoint_mode=IPv6

[profile imds_mode_invalid]
ec2_metadata_service_endpoint_mode=invalid

[profile imds_endpoint_v4]
ec2_metadata_service_endpoint=http://169.254.169.254

[profile imds_endpoint_v6]
ec2_metadata_service_endpoint=http://[fd00:ec2::254]

[profile imds_endpoint_invalid]
ec2_metadata_service_endpoint=invalid
test-v2.config.mjs
import { test } from "./test-v2.shared.mjs";
  
await test();
const endpointConfigs = [
  "imds_mode_v4",
  "imds_mode_v6",
  "imds_mode_invalid",
];
for (const endpoint of endpointConfigs) {
  await test(`AWS_PROFILE=${endpoint}`);
}

await test();
const endpointModeConfigs = ["imds_endpoint_v4", "imds_endpoint_v6", "imds_endpoint_invalid"];
for (const endpointMode of endpointModeConfigs) {
  await test(`AWS_PROFILE=${endpointMode}`);
}
Output
ENV: undefined
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_PROFILE=imds_mode_v4
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_PROFILE=imds_mode_v6
{ endpoint: 'http://[fd00:ec2::254]' }

ENV: AWS_PROFILE=imds_mode_invalid
[
  "      throw new Error('Unsupported endpoint mode: ' + endpointMode);",
  'Error: Unsupported endpoint mode: invalid'
]
ENV: undefined
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_PROFILE=imds_endpoint_v4
{ endpoint: 'http://169.254.169.254' }

ENV: AWS_PROFILE=imds_endpoint_v6
{ endpoint: 'http://[fd00:ec2::254]' }

ENV: AWS_PROFILE=imds_endpoint_invalid
[
  'TypeError [ERR_INVALID_URL]: Invalid URL: invalid',
  '    at onParseError (internal/url.js:279:9)'
]
Checklist
  • npm run test passes
  • changelog is added, npm run add-change

@trivikr trivikr changed the title SXupport IMDS for IPv6 endpoints Support IMDS for IPv6 endpoints Aug 13, 2021
@trivikr trivikr marked this pull request as ready for review August 13, 2021 22:41
@trivikr trivikr changed the title Support IMDS for IPv6 endpoints Support IPv6 endpoints in IMDS Aug 16, 2021
@aws-sdk-js-automation
Copy link

AWS CodeBuild CI Report

  • CodeBuild project: sdk-v2-github
  • Commit ID: ea2ff0b
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

Copy link
Contributor

@AllanZhengYP AllanZhengYP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just have a few comments

lib/metadata_service.js Show resolved Hide resolved
lib/node_loader.js Outdated Show resolved Hide resolved
test/metadata_service/endpoint_mode_config_options.spec.js Outdated Show resolved Hide resolved
url.parse does not throw error on invalid URLs.
It also did not return null while testing.

Also URL was introduced in v6.13, infinitisimal number of
AWS SDK for JavaScript (v2) customers are using it and we're
deprecating it on October 30, 2021
This way, we do not have to create substring from received
endpoint and re-add http:// prefix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants