@smithy/credential-provider-imds 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +11 -0
  3. package/dist-cjs/config/Endpoint.js +8 -0
  4. package/dist-cjs/config/EndpointConfigOptions.js +10 -0
  5. package/dist-cjs/config/EndpointMode.js +8 -0
  6. package/dist-cjs/config/EndpointModeConfigOptions.js +11 -0
  7. package/dist-cjs/fromContainerMetadata.js +70 -0
  8. package/dist-cjs/fromInstanceMetadata.js +95 -0
  9. package/dist-cjs/index.js +12 -0
  10. package/dist-cjs/remoteProvider/ImdsCredentials.js +17 -0
  11. package/dist-cjs/remoteProvider/RemoteProviderInit.js +7 -0
  12. package/dist-cjs/remoteProvider/httpRequest.js +41 -0
  13. package/dist-cjs/remoteProvider/index.js +5 -0
  14. package/dist-cjs/remoteProvider/retry.js +11 -0
  15. package/dist-cjs/types.js +2 -0
  16. package/dist-cjs/utils/getExtendedInstanceMetadataCredentials.js +22 -0
  17. package/dist-cjs/utils/getInstanceMetadataEndpoint.js +23 -0
  18. package/dist-cjs/utils/staticStabilityProvider.js +29 -0
  19. package/dist-es/config/Endpoint.js +5 -0
  20. package/dist-es/config/EndpointConfigOptions.js +7 -0
  21. package/dist-es/config/EndpointMode.js +5 -0
  22. package/dist-es/config/EndpointModeConfigOptions.js +8 -0
  23. package/dist-es/fromContainerMetadata.js +66 -0
  24. package/dist-es/fromInstanceMetadata.js +91 -0
  25. package/dist-es/index.js +6 -0
  26. package/dist-es/remoteProvider/ImdsCredentials.js +12 -0
  27. package/dist-es/remoteProvider/RemoteProviderInit.js +3 -0
  28. package/dist-es/remoteProvider/httpRequest.js +36 -0
  29. package/dist-es/remoteProvider/index.js +2 -0
  30. package/dist-es/remoteProvider/retry.js +7 -0
  31. package/dist-es/types.js +1 -0
  32. package/dist-es/utils/getExtendedInstanceMetadataCredentials.js +17 -0
  33. package/dist-es/utils/getInstanceMetadataEndpoint.js +19 -0
  34. package/dist-es/utils/staticStabilityProvider.js +25 -0
  35. package/dist-types/config/Endpoint.d.ts +7 -0
  36. package/dist-types/config/EndpointConfigOptions.d.ts +13 -0
  37. package/dist-types/config/EndpointMode.d.ts +7 -0
  38. package/dist-types/config/EndpointModeConfigOptions.d.ts +13 -0
  39. package/dist-types/fromContainerMetadata.d.ts +21 -0
  40. package/dist-types/fromInstanceMetadata.d.ts +10 -0
  41. package/dist-types/index.d.ts +24 -0
  42. package/dist-types/remoteProvider/ImdsCredentials.d.ts +18 -0
  43. package/dist-types/remoteProvider/RemoteProviderInit.d.ts +32 -0
  44. package/dist-types/remoteProvider/httpRequest.d.ts +7 -0
  45. package/dist-types/remoteProvider/index.d.ts +8 -0
  46. package/dist-types/remoteProvider/retry.d.ts +10 -0
  47. package/dist-types/types.d.ts +7 -0
  48. package/dist-types/utils/getExtendedInstanceMetadataCredentials.d.ts +6 -0
  49. package/dist-types/utils/getInstanceMetadataEndpoint.d.ts +21 -0
  50. package/dist-types/utils/staticStabilityProvider.d.ts +16 -0
  51. package/package.json +69 -0
@@ -0,0 +1,66 @@
1
+ import { CredentialsProviderError } from "@smithy/property-provider";
2
+ import { parse } from "url";
3
+ import { httpRequest } from "./remoteProvider/httpRequest";
4
+ import { fromImdsCredentials, isImdsCredentials } from "./remoteProvider/ImdsCredentials";
5
+ import { providerConfigFromInit } from "./remoteProvider/RemoteProviderInit";
6
+ import { retry } from "./remoteProvider/retry";
7
+ export const ENV_CMDS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
8
+ export const ENV_CMDS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
9
+ export const ENV_CMDS_AUTH_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN";
10
+ export const fromContainerMetadata = (init = {}) => {
11
+ const { timeout, maxRetries } = providerConfigFromInit(init);
12
+ return () => retry(async () => {
13
+ const requestOptions = await getCmdsUri();
14
+ const credsResponse = JSON.parse(await requestFromEcsImds(timeout, requestOptions));
15
+ if (!isImdsCredentials(credsResponse)) {
16
+ throw new CredentialsProviderError("Invalid response received from instance metadata service.");
17
+ }
18
+ return fromImdsCredentials(credsResponse);
19
+ }, maxRetries);
20
+ };
21
+ const requestFromEcsImds = async (timeout, options) => {
22
+ if (process.env[ENV_CMDS_AUTH_TOKEN]) {
23
+ options.headers = {
24
+ ...options.headers,
25
+ Authorization: process.env[ENV_CMDS_AUTH_TOKEN],
26
+ };
27
+ }
28
+ const buffer = await httpRequest({
29
+ ...options,
30
+ timeout,
31
+ });
32
+ return buffer.toString();
33
+ };
34
+ const CMDS_IP = "169.254.170.2";
35
+ const GREENGRASS_HOSTS = {
36
+ localhost: true,
37
+ "127.0.0.1": true,
38
+ };
39
+ const GREENGRASS_PROTOCOLS = {
40
+ "http:": true,
41
+ "https:": true,
42
+ };
43
+ const getCmdsUri = async () => {
44
+ if (process.env[ENV_CMDS_RELATIVE_URI]) {
45
+ return {
46
+ hostname: CMDS_IP,
47
+ path: process.env[ENV_CMDS_RELATIVE_URI],
48
+ };
49
+ }
50
+ if (process.env[ENV_CMDS_FULL_URI]) {
51
+ const parsed = parse(process.env[ENV_CMDS_FULL_URI]);
52
+ if (!parsed.hostname || !(parsed.hostname in GREENGRASS_HOSTS)) {
53
+ throw new CredentialsProviderError(`${parsed.hostname} is not a valid container metadata service hostname`, false);
54
+ }
55
+ if (!parsed.protocol || !(parsed.protocol in GREENGRASS_PROTOCOLS)) {
56
+ throw new CredentialsProviderError(`${parsed.protocol} is not a valid container metadata service protocol`, false);
57
+ }
58
+ return {
59
+ ...parsed,
60
+ port: parsed.port ? parseInt(parsed.port, 10) : undefined,
61
+ };
62
+ }
63
+ throw new CredentialsProviderError("The container metadata credential provider cannot be used unless" +
64
+ ` the ${ENV_CMDS_RELATIVE_URI} or ${ENV_CMDS_FULL_URI} environment` +
65
+ " variable is set", false);
66
+ };
@@ -0,0 +1,91 @@
1
+ import { CredentialsProviderError } from "@smithy/property-provider";
2
+ import { httpRequest } from "./remoteProvider/httpRequest";
3
+ import { fromImdsCredentials, isImdsCredentials } from "./remoteProvider/ImdsCredentials";
4
+ import { providerConfigFromInit } from "./remoteProvider/RemoteProviderInit";
5
+ import { retry } from "./remoteProvider/retry";
6
+ import { getInstanceMetadataEndpoint } from "./utils/getInstanceMetadataEndpoint";
7
+ import { staticStabilityProvider } from "./utils/staticStabilityProvider";
8
+ const IMDS_PATH = "/latest/meta-data/iam/security-credentials/";
9
+ const IMDS_TOKEN_PATH = "/latest/api/token";
10
+ export const fromInstanceMetadata = (init = {}) => staticStabilityProvider(getInstanceImdsProvider(init), { logger: init.logger });
11
+ const getInstanceImdsProvider = (init) => {
12
+ let disableFetchToken = false;
13
+ const { timeout, maxRetries } = providerConfigFromInit(init);
14
+ const getCredentials = async (maxRetries, options) => {
15
+ const profile = (await retry(async () => {
16
+ let profile;
17
+ try {
18
+ profile = await getProfile(options);
19
+ }
20
+ catch (err) {
21
+ if (err.statusCode === 401) {
22
+ disableFetchToken = false;
23
+ }
24
+ throw err;
25
+ }
26
+ return profile;
27
+ }, maxRetries)).trim();
28
+ return retry(async () => {
29
+ let creds;
30
+ try {
31
+ creds = await getCredentialsFromProfile(profile, options);
32
+ }
33
+ catch (err) {
34
+ if (err.statusCode === 401) {
35
+ disableFetchToken = false;
36
+ }
37
+ throw err;
38
+ }
39
+ return creds;
40
+ }, maxRetries);
41
+ };
42
+ return async () => {
43
+ const endpoint = await getInstanceMetadataEndpoint();
44
+ if (disableFetchToken) {
45
+ return getCredentials(maxRetries, { ...endpoint, timeout });
46
+ }
47
+ else {
48
+ let token;
49
+ try {
50
+ token = (await getMetadataToken({ ...endpoint, timeout })).toString();
51
+ }
52
+ catch (error) {
53
+ if (error?.statusCode === 400) {
54
+ throw Object.assign(error, {
55
+ message: "EC2 Metadata token request returned error",
56
+ });
57
+ }
58
+ else if (error.message === "TimeoutError" || [403, 404, 405].includes(error.statusCode)) {
59
+ disableFetchToken = true;
60
+ }
61
+ return getCredentials(maxRetries, { ...endpoint, timeout });
62
+ }
63
+ return getCredentials(maxRetries, {
64
+ ...endpoint,
65
+ headers: {
66
+ "x-aws-ec2-metadata-token": token,
67
+ },
68
+ timeout,
69
+ });
70
+ }
71
+ };
72
+ };
73
+ const getMetadataToken = async (options) => httpRequest({
74
+ ...options,
75
+ path: IMDS_TOKEN_PATH,
76
+ method: "PUT",
77
+ headers: {
78
+ "x-aws-ec2-metadata-token-ttl-seconds": "21600",
79
+ },
80
+ });
81
+ const getProfile = async (options) => (await httpRequest({ ...options, path: IMDS_PATH })).toString();
82
+ const getCredentialsFromProfile = async (profile, options) => {
83
+ const credsResponse = JSON.parse((await httpRequest({
84
+ ...options,
85
+ path: IMDS_PATH + profile,
86
+ })).toString());
87
+ if (!isImdsCredentials(credsResponse)) {
88
+ throw new CredentialsProviderError("Invalid response received from instance metadata service.");
89
+ }
90
+ return fromImdsCredentials(credsResponse);
91
+ };
@@ -0,0 +1,6 @@
1
+ export * from "./fromContainerMetadata";
2
+ export * from "./fromInstanceMetadata";
3
+ export * from "./remoteProvider/RemoteProviderInit";
4
+ export * from "./types";
5
+ export { httpRequest } from "./remoteProvider/httpRequest";
6
+ export { getInstanceMetadataEndpoint } from "./utils/getInstanceMetadataEndpoint";
@@ -0,0 +1,12 @@
1
+ export const isImdsCredentials = (arg) => Boolean(arg) &&
2
+ typeof arg === "object" &&
3
+ typeof arg.AccessKeyId === "string" &&
4
+ typeof arg.SecretAccessKey === "string" &&
5
+ typeof arg.Token === "string" &&
6
+ typeof arg.Expiration === "string";
7
+ export const fromImdsCredentials = (creds) => ({
8
+ accessKeyId: creds.AccessKeyId,
9
+ secretAccessKey: creds.SecretAccessKey,
10
+ sessionToken: creds.Token,
11
+ expiration: new Date(creds.Expiration),
12
+ });
@@ -0,0 +1,3 @@
1
+ export const DEFAULT_TIMEOUT = 1000;
2
+ export const DEFAULT_MAX_RETRIES = 0;
3
+ export const providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT, }) => ({ maxRetries, timeout });
@@ -0,0 +1,36 @@
1
+ import { ProviderError } from "@smithy/property-provider";
2
+ import { Buffer } from "buffer";
3
+ import { request } from "http";
4
+ export function httpRequest(options) {
5
+ return new Promise((resolve, reject) => {
6
+ const req = request({
7
+ method: "GET",
8
+ ...options,
9
+ hostname: options.hostname?.replace(/^\[(.+)\]$/, "$1"),
10
+ });
11
+ req.on("error", (err) => {
12
+ reject(Object.assign(new ProviderError("Unable to connect to instance metadata service"), err));
13
+ req.destroy();
14
+ });
15
+ req.on("timeout", () => {
16
+ reject(new ProviderError("TimeoutError from instance metadata service"));
17
+ req.destroy();
18
+ });
19
+ req.on("response", (res) => {
20
+ const { statusCode = 400 } = res;
21
+ if (statusCode < 200 || 300 <= statusCode) {
22
+ reject(Object.assign(new ProviderError("Error response received from instance metadata service"), { statusCode }));
23
+ req.destroy();
24
+ }
25
+ const chunks = [];
26
+ res.on("data", (chunk) => {
27
+ chunks.push(chunk);
28
+ });
29
+ res.on("end", () => {
30
+ resolve(Buffer.concat(chunks));
31
+ req.destroy();
32
+ });
33
+ });
34
+ req.end();
35
+ });
36
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./ImdsCredentials";
2
+ export * from "./RemoteProviderInit";
@@ -0,0 +1,7 @@
1
+ export const retry = (toRetry, maxRetries) => {
2
+ let promise = toRetry();
3
+ for (let i = 0; i < maxRetries; i++) {
4
+ promise = promise.catch(toRetry);
5
+ }
6
+ return promise;
7
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ const STATIC_STABILITY_REFRESH_INTERVAL_SECONDS = 5 * 60;
2
+ const STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS = 5 * 60;
3
+ const STATIC_STABILITY_DOC_URL = "https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html";
4
+ export const getExtendedInstanceMetadataCredentials = (credentials, logger) => {
5
+ const refreshInterval = STATIC_STABILITY_REFRESH_INTERVAL_SECONDS +
6
+ Math.floor(Math.random() * STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS);
7
+ const newExpiration = new Date(Date.now() + refreshInterval * 1000);
8
+ logger.warn("Attempting credential expiration extension due to a credential service availability issue. A refresh of these " +
9
+ "credentials will be attempted after ${new Date(newExpiration)}.\nFor more information, please visit: " +
10
+ STATIC_STABILITY_DOC_URL);
11
+ const originalExpiration = credentials.originalExpiration ?? credentials.expiration;
12
+ return {
13
+ ...credentials,
14
+ ...(originalExpiration ? { originalExpiration } : {}),
15
+ expiration: newExpiration,
16
+ };
17
+ };
@@ -0,0 +1,19 @@
1
+ import { loadConfig } from "@smithy/node-config-provider";
2
+ import { parseUrl } from "@smithy/url-parser";
3
+ import { Endpoint as InstanceMetadataEndpoint } from "../config/Endpoint";
4
+ import { ENDPOINT_CONFIG_OPTIONS } from "../config/EndpointConfigOptions";
5
+ import { EndpointMode } from "../config/EndpointMode";
6
+ import { ENDPOINT_MODE_CONFIG_OPTIONS, } from "../config/EndpointModeConfigOptions";
7
+ export const getInstanceMetadataEndpoint = async () => parseUrl((await getFromEndpointConfig()) || (await getFromEndpointModeConfig()));
8
+ const getFromEndpointConfig = async () => loadConfig(ENDPOINT_CONFIG_OPTIONS)();
9
+ const getFromEndpointModeConfig = async () => {
10
+ const endpointMode = await loadConfig(ENDPOINT_MODE_CONFIG_OPTIONS)();
11
+ switch (endpointMode) {
12
+ case EndpointMode.IPv4:
13
+ return InstanceMetadataEndpoint.IPv4;
14
+ case EndpointMode.IPv6:
15
+ return InstanceMetadataEndpoint.IPv6;
16
+ default:
17
+ throw new Error(`Unsupported endpoint mode: ${endpointMode}.` + ` Select from ${Object.values(EndpointMode)}`);
18
+ }
19
+ };
@@ -0,0 +1,25 @@
1
+ import { getExtendedInstanceMetadataCredentials } from "./getExtendedInstanceMetadataCredentials";
2
+ export const staticStabilityProvider = (provider, options = {}) => {
3
+ const logger = options?.logger || console;
4
+ let pastCredentials;
5
+ return async () => {
6
+ let credentials;
7
+ try {
8
+ credentials = await provider();
9
+ if (credentials.expiration && credentials.expiration.getTime() < Date.now()) {
10
+ credentials = getExtendedInstanceMetadataCredentials(credentials, logger);
11
+ }
12
+ }
13
+ catch (e) {
14
+ if (pastCredentials) {
15
+ logger.warn("Credential renew failed: ", e);
16
+ credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger);
17
+ }
18
+ else {
19
+ throw e;
20
+ }
21
+ }
22
+ pastCredentials = credentials;
23
+ return credentials;
24
+ };
25
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export declare enum Endpoint {
5
+ IPv4 = "http://169.254.169.254",
6
+ IPv6 = "http://[fd00:ec2::254]"
7
+ }
@@ -0,0 +1,13 @@
1
+ import { LoadedConfigSelectors } from "@smithy/node-config-provider";
2
+ /**
3
+ * @internal
4
+ */
5
+ export declare const ENV_ENDPOINT_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT";
6
+ /**
7
+ * @internal
8
+ */
9
+ export declare const CONFIG_ENDPOINT_NAME = "ec2_metadata_service_endpoint";
10
+ /**
11
+ * @internal
12
+ */
13
+ export declare const ENDPOINT_CONFIG_OPTIONS: LoadedConfigSelectors<string | undefined>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export declare enum EndpointMode {
5
+ IPv4 = "IPv4",
6
+ IPv6 = "IPv6"
7
+ }
@@ -0,0 +1,13 @@
1
+ import { LoadedConfigSelectors } from "@smithy/node-config-provider";
2
+ /**
3
+ * @internal
4
+ */
5
+ export declare const ENV_ENDPOINT_MODE_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE";
6
+ /**
7
+ * @internal
8
+ */
9
+ export declare const CONFIG_ENDPOINT_MODE_NAME = "ec2_metadata_service_endpoint_mode";
10
+ /**
11
+ * @internal
12
+ */
13
+ export declare const ENDPOINT_MODE_CONFIG_OPTIONS: LoadedConfigSelectors<string | undefined>;
@@ -0,0 +1,21 @@
1
+ import { AwsCredentialIdentityProvider } from "@smithy/types";
2
+ import { RemoteProviderInit } from "./remoteProvider/RemoteProviderInit";
3
+ /**
4
+ * @internal
5
+ */
6
+ export declare const ENV_CMDS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
7
+ /**
8
+ * @internal
9
+ */
10
+ export declare const ENV_CMDS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
11
+ /**
12
+ * @internal
13
+ */
14
+ export declare const ENV_CMDS_AUTH_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN";
15
+ /**
16
+ * @internal
17
+ *
18
+ * Creates a credential provider that will source credentials from the ECS
19
+ * Container Metadata Service
20
+ */
21
+ export declare const fromContainerMetadata: (init?: RemoteProviderInit) => AwsCredentialIdentityProvider;
@@ -0,0 +1,10 @@
1
+ import { Provider } from "@smithy/types";
2
+ import { RemoteProviderInit } from "./remoteProvider/RemoteProviderInit";
3
+ import { InstanceMetadataCredentials } from "./types";
4
+ /**
5
+ * @internal
6
+ *
7
+ * Creates a credential provider that will source credentials from the EC2
8
+ * Instance Metadata Service
9
+ */
10
+ export declare const fromInstanceMetadata: (init?: RemoteProviderInit) => Provider<InstanceMetadataCredentials>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export * from "./fromContainerMetadata";
5
+ /**
6
+ * @internal
7
+ */
8
+ export * from "./fromInstanceMetadata";
9
+ /**
10
+ * @internal
11
+ */
12
+ export * from "./remoteProvider/RemoteProviderInit";
13
+ /**
14
+ * @internal
15
+ */
16
+ export * from "./types";
17
+ /**
18
+ * @internal
19
+ */
20
+ export { httpRequest } from "./remoteProvider/httpRequest";
21
+ /**
22
+ * @internal
23
+ */
24
+ export { getInstanceMetadataEndpoint } from "./utils/getInstanceMetadataEndpoint";
@@ -0,0 +1,18 @@
1
+ import { AwsCredentialIdentity } from "@smithy/types";
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface ImdsCredentials {
6
+ AccessKeyId: string;
7
+ SecretAccessKey: string;
8
+ Token: string;
9
+ Expiration: string;
10
+ }
11
+ /**
12
+ * @internal
13
+ */
14
+ export declare const isImdsCredentials: (arg: any) => arg is ImdsCredentials;
15
+ /**
16
+ * @internal
17
+ */
18
+ export declare const fromImdsCredentials: (creds: ImdsCredentials) => AwsCredentialIdentity;
@@ -0,0 +1,32 @@
1
+ import { Logger } from "@smithy/types";
2
+ /**
3
+ * @internal
4
+ */
5
+ export declare const DEFAULT_TIMEOUT = 1000;
6
+ /**
7
+ * @internal
8
+ */
9
+ export declare const DEFAULT_MAX_RETRIES = 0;
10
+ /**
11
+ * @internal
12
+ */
13
+ export interface RemoteProviderConfig {
14
+ /**
15
+ * The connection timeout (in milliseconds)
16
+ */
17
+ timeout: number;
18
+ /**
19
+ * The maximum number of times the HTTP connection should be retried
20
+ */
21
+ maxRetries: number;
22
+ }
23
+ /**
24
+ * @internal
25
+ */
26
+ export interface RemoteProviderInit extends Partial<RemoteProviderConfig> {
27
+ logger?: Logger;
28
+ }
29
+ /**
30
+ * @internal
31
+ */
32
+ export declare const providerConfigFromInit: ({ maxRetries, timeout, }: RemoteProviderInit) => RemoteProviderConfig;
@@ -0,0 +1,7 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { RequestOptions } from "http";
4
+ /**
5
+ * @internal
6
+ */
7
+ export declare function httpRequest(options: RequestOptions): Promise<Buffer>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export * from "./ImdsCredentials";
5
+ /**
6
+ * @internal
7
+ */
8
+ export * from "./RemoteProviderInit";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export interface RetryableProvider<T> {
5
+ (): Promise<T>;
6
+ }
7
+ /**
8
+ * @internal
9
+ */
10
+ export declare const retry: <T>(toRetry: RetryableProvider<T>, maxRetries: number) => Promise<T>;
@@ -0,0 +1,7 @@
1
+ import { AwsCredentialIdentity } from "@smithy/types";
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface InstanceMetadataCredentials extends AwsCredentialIdentity {
6
+ readonly originalExpiration?: Date;
7
+ }
@@ -0,0 +1,6 @@
1
+ import { Logger } from "@smithy/types";
2
+ import { InstanceMetadataCredentials } from "../types";
3
+ /**
4
+ * @internal
5
+ */
6
+ export declare const getExtendedInstanceMetadataCredentials: (credentials: InstanceMetadataCredentials, logger: Logger) => InstanceMetadataCredentials;
@@ -0,0 +1,21 @@
1
+ import { Endpoint } from "@smithy/types";
2
+ /**
3
+ * Returns the host to use for instance metadata service call.
4
+ *
5
+ * The host is read from endpoint which can be set either in
6
+ * {@link ENV_ENDPOINT_NAME} environment variable or {@link CONFIG_ENDPOINT_NAME}
7
+ * configuration property.
8
+ *
9
+ * If endpoint is not set, then endpoint mode is read either from
10
+ * {@link ENV_ENDPOINT_MODE_NAME} environment variable or {@link CONFIG_ENDPOINT_MODE_NAME}
11
+ * configuration property. If endpoint mode is not set, then default endpoint mode
12
+ * {@link EndpointMode.IPv4} is used.
13
+ *
14
+ * If endpoint mode is set to {@link EndpointMode.IPv4}, then the host is {@link Endpoint.IPv4}.
15
+ * If endpoint mode is set to {@link EndpointMode.IPv6}, then the host is {@link Endpoint.IPv6}.
16
+ *
17
+ * @returns Host to use for instance metadata service call.
18
+ *
19
+ * @internal
20
+ */
21
+ export declare const getInstanceMetadataEndpoint: () => Promise<Endpoint>;
@@ -0,0 +1,16 @@
1
+ import { Logger, Provider } from "@smithy/types";
2
+ import { InstanceMetadataCredentials } from "../types";
3
+ /**
4
+ * @internal
5
+ *
6
+ * IMDS credential supports static stability feature. When used, the expiration
7
+ * of recently issued credentials is extended. The server side allows using
8
+ * the recently expired credentials. This mitigates impact when clients using
9
+ * refreshable credentials are unable to retrieve updates.
10
+ *
11
+ * @param provider Credential provider
12
+ * @returns A credential provider that supports static stability
13
+ */
14
+ export declare const staticStabilityProvider: (provider: Provider<InstanceMetadataCredentials>, options?: {
15
+ logger?: Logger | undefined;
16
+ }) => Provider<InstanceMetadataCredentials>;
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@smithy/credential-provider-imds",
3
+ "version": "1.0.0",
4
+ "description": "AWS credential provider that sources credentials from the EC2 instance metadata service and ECS container metadata service",
5
+ "main": "./dist-cjs/index.js",
6
+ "module": "./dist-es/index.js",
7
+ "scripts": {
8
+ "build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
9
+ "build:cjs": "tsc -p tsconfig.cjs.json",
10
+ "build:es": "tsc -p tsconfig.es.json",
11
+ "build:types": "tsc -p tsconfig.types.json",
12
+ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
13
+ "stage-release": "rimraf ./.release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz",
14
+ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo",
15
+ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"",
16
+ "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"",
17
+ "test": "jest"
18
+ },
19
+ "keywords": [
20
+ "aws",
21
+ "credentials"
22
+ ],
23
+ "author": {
24
+ "name": "AWS SDK for JavaScript Team",
25
+ "url": "https://aws.amazon.com/javascript/"
26
+ },
27
+ "license": "Apache-2.0",
28
+ "dependencies": {
29
+ "@smithy/node-config-provider": "workspace:^",
30
+ "@smithy/property-provider": "workspace:^",
31
+ "@smithy/types": "workspace:^",
32
+ "@smithy/url-parser": "workspace:^",
33
+ "tslib": "^2.5.0"
34
+ },
35
+ "devDependencies": {
36
+ "@tsconfig/recommended": "1.0.1",
37
+ "@types/node": "^14.14.31",
38
+ "concurrently": "7.0.0",
39
+ "downlevel-dts": "0.10.1",
40
+ "jest": "28.1.1",
41
+ "nock": "^13.0.2",
42
+ "rimraf": "3.0.2",
43
+ "typedoc": "0.23.23",
44
+ "typescript": "~4.9.5"
45
+ },
46
+ "types": "./dist-types/index.d.ts",
47
+ "engines": {
48
+ "node": ">=14.0.0"
49
+ },
50
+ "typesVersions": {
51
+ "<4.0": {
52
+ "dist-types/*": [
53
+ "dist-types/ts3.4/*"
54
+ ]
55
+ }
56
+ },
57
+ "files": [
58
+ "dist-*/**"
59
+ ],
60
+ "homepage": "https://github.com/awslabs/smithy-typescript/tree/main/packages/credential-provider-imds",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/awslabs/smithy-typescript.git",
64
+ "directory": "packages/credential-provider-imds"
65
+ },
66
+ "typedoc": {
67
+ "entryPoint": "src/index.ts"
68
+ }
69
+ }