-
Notifications
You must be signed in to change notification settings - Fork 105
[Draft] feat: add support for accountId in imds #1621
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
base: main
Are you sure you want to change the base?
Conversation
import { CredentialsProviderError } from "@smithy/property-provider"; | ||
import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; | ||
|
||
import { InstanceMetadataV1FallbackError } from "./error/InstanceMetadataV1FallbackError"; | ||
import { fromInstanceMetadata } from "./fromInstanceMetadata"; | ||
import { checkIfImdsDisabled, fromInstanceMetadata } from "./fromInstanceMetadata"; | ||
import * as fromInstanceMetadataModule from "./fromInstanceMetadata"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use explicit imports instead of *
}); | ||
|
||
beforeEach(() => { | ||
vi.mocked(staticStabilityProvider).mockImplementation((input) => input); | ||
vi.mocked(getInstanceMetadataEndpoint).mockResolvedValue({ hostname } as any); | ||
vi.mocked(loadConfig).mockReturnValue(() => Promise.resolve(false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is hard to understand because the mock is too broad. What config property is being targeted by this mock return value?
Can the mock be made more specific so we can tell what config property it is trying to intercept?
@@ -72,6 +79,65 @@ describe("fromInstanceMetadata", () => { | |||
vi.resetAllMocks(); | |||
}); | |||
|
|||
it("returns no credentials when AWS_EC2_METADATA_DISABLED=true", async () => { | |||
vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(true)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above: mock is too broad
vi.mocked(retry).mockImplementation((fn: any) => fn()); | ||
vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); | ||
|
||
const result = await fromInstanceMetadata({ ec2InstanceProfileName: profileName })(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
variable name too generic
is this "credentials"?
|
||
const provider = fromInstanceMetadata({}); | ||
|
||
const result = await provider(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result should be called credentials
.mockRejectedValueOnce(Object.assign(new Error(), { statusCode: 404 })) | ||
.mockResolvedValueOnce(legacyProfileName as any); | ||
|
||
result = await fromInstanceMetadataModule.getImdsProfileHelper(options, mockMaxRetries, {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename all variables called "result" to be more specific
* @internal | ||
* Gets IMDS profile with proper error handling and retries | ||
*/ | ||
export const getImdsProfileHelper = async ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getImdsProfile
} | ||
} | ||
} catch (err) { | ||
throw err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's no point in catching an error just to throw it, remove the outer try-catch
* @internal | ||
* Checks if IMDS credential fetching is disabled through configuration | ||
*/ | ||
export const checkIfImdsDisabled = async (profile?: string, logger?: any): Promise<void> => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function name should be throwIfImdsTurnedOff
"check" doesn't imply it will do anything
)(); | ||
|
||
// Check runtime config (highest priority) | ||
const name = init.ec2InstanceProfileName || profileName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const name = init.ec2InstanceProfileName || profileName; | |
const name = init.ec2InstanceProfileName ?? profileName; |
|
Issue #, if available:
Internal JS-5966
Description of changes:
This PR adds support for version 2.1 of the IMDS credentials provider. With this update, the provider can now retrieve credentials that include an account ID.
To support this functionality, the credentials provider first attempts to access the extended API endpoint, which ends with
-extended
. If this endpoint returns a 404, the provider falls back to the legacy API endpoint—the same one used in the IMDS credentials provider v2.0.This "try extended API, then fall back to legacy API" pattern is applied to both retrieving the IMDS instance profile name and fetching credentials.
Only the extended API can return credentials that include an account ID.
The PR also made the following IMDS credentials providers options configurable:
Disable IMDS credentials fetching
IMDS instance profile name
Both options can be configured via environment variables or a shared config file, with environment variables taking precedence over the config file.
ToDo:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.