Skip to content

Commit

Permalink
cliv2 compatible provider
Browse files Browse the repository at this point in the history
  • Loading branch information
smilkuri committed Feb 4, 2025
1 parent 2b3d1df commit 050bdcb
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 5 deletions.
21 changes: 18 additions & 3 deletions clients/client-accessanalyzer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
"description": "AWS SDK for JavaScript Accessanalyzer Client for Node.js, Browser and React Native",
"version": "3.741.0",
"scripts": {
"build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
"build": "concurrently 'yarn generate:version' 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types' ",
"build:webpack": "webpack",
"build:cjs": "node ../../scripts/compilation/inline client-accessanalyzer",
"build:es": "tsc -p tsconfig.es.json",
"build:include:deps": "lerna run --scope $npm_package_name --include-dependencies build",
"build:types": "tsc -p tsconfig.types.json",
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo",
"extract:docs": "api-extractor run --local",
"generate:client": "node ../../scripts/generate-clients/single-service --solo accessanalyzer"
"generate:client": "node ../../scripts/generate-clients/single-service --solo accessanalyzer",
"generate:version": "node src/scripts/generate-version.js"
},
"main": "./dist-cjs/index.js",
"types": "./dist-types/index.d.ts",
Expand Down Expand Up @@ -63,10 +65,23 @@
"devDependencies": {
"@tsconfig/node18": "18.2.4",
"@types/node": "^18.19.69",
"@types/path-browserify": "^1",
"@types/webpack-bundle-analyzer": "^4",
"assert": "^2.1.0",
"browserify-zlib": "^0.2.0",
"concurrently": "7.0.0",
"downlevel-dts": "0.10.1",
"http2-wrapper": "^2.2.1",
"https-browserify": "^1.0.0",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
"rimraf": "3.0.2",
"typescript": "~5.2.2"
"stream-http": "^3.2.0",
"typescript": "~5.2.2",
"url": "^0.11.4",
"webpack": "^5.97.1",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "^6.0.1"
},
"engines": {
"node": ">=18.0.0"
Expand Down
3 changes: 3 additions & 0 deletions clients/client-accessanalyzer/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// smithy-typescript generated code
/* eslint-disable */
import { version } from "../version.json";
/**
* <p>Identity and Access Management Access Analyzer helps you to set, verify, and refine your IAM policies by providing
* a suite of capabilities. Its features include findings for external and unused access,
Expand Down Expand Up @@ -28,6 +29,8 @@
*
* @packageDocumentation
*/

export const VERSION = version;
export * from "./AccessAnalyzerClient";
export * from "./AccessAnalyzer";
export { ClientInputEndpointParameters } from "./endpoint/EndpointParameters";
Expand Down
2 changes: 1 addition & 1 deletion clients/client-accessanalyzer/src/runtimeConfig.browser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// smithy-typescript generated code
// @ts-ignore: package.json will be imported from dist folders
import packageInfo from "../package.json"; // eslint-disable-line
import packageInfo from "../version.json"; // eslint-disable-line

import { Sha256 } from "@aws-crypto/sha256-browser";
import { createDefaultUserAgentProvider } from "@aws-sdk/util-user-agent-browser";
Expand Down
2 changes: 1 addition & 1 deletion clients/client-accessanalyzer/src/runtimeConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// smithy-typescript generated code
// @ts-ignore: package.json will be imported from dist folders
import packageInfo from "../package.json"; // eslint-disable-line
import packageInfo from "../version.json"; // eslint-disable-line

import { emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { fromEnv } from "@aws-sdk/credential-provider-env";
import { fromIni } from "@aws-sdk/credential-provider-ini";
import { defaultProvider } from "@aws-sdk/credential-provider-node";
import type { CredentialProviderOptions, Provider } from "@aws-sdk/types";
import { chain, memoize } from "@smithy/property-provider";
import type { AwsCredentialIdentity } from "@smithy/types";

interface AwsCliV2CompatibleProviderOptions extends CredentialProviderOptions {
profile?: string;
accessKeyId?: string;
secretAccessKey?: string;
sessionToken?: string;
}

/**
* AWS CLI V2 Compatible Credential Provider Chain
* If profile is explicitly provided, uses fromIni with that profile.
* Otherwise, uses a chain of fromEnv and fromNodeProviderChain.
*/
export const fromAwsCliV2CompatibleProviderChain = (
options: AwsCliV2CompatibleProviderOptions = {}
): Provider<AwsCredentialIdentity> => {
const { profile, accessKeyId, secretAccessKey, sessionToken } = options;

return memoize(
async (): Promise<AwsCredentialIdentity> => {
// If explicit credentials are provided in the constructor, use them.
if (accessKeyId && secretAccessKey) {
return {
accessKeyId,
secretAccessKey,
sessionToken, // Optional
};
}
// If profile is explicitly provided, use fromIni directly
if (profile) {
return fromIni({ profile })();
}

// Otherwise, use the chain of providers
const credentials = await chain(fromEnv(), async () => {
return defaultProvider()();
})();

if (!credentials) {
throw new Error("Failed to retrieve valid AWS credentials");
}

return credentials;
},
credentialsTreatedAsExpired,
credentialsWillNeedRefresh
);
};

export const credentialsTreatedAsExpired = (credentials: AwsCredentialIdentity) =>
credentials?.expiration !== undefined && credentials.expiration.getTime() - Date.now() < 300000;

export const credentialsWillNeedRefresh = (credentials: AwsCredentialIdentity) => credentials?.expiration !== undefined;
51 changes: 51 additions & 0 deletions packages/credential-providers/src/resolveAwsCliV2Region.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { MetadataService } from "@aws-sdk/ec2-metadata-service";
import { logger } from "@aws-sdk/smithy-client/dist-types";
import { loadSharedConfigFiles } from "@smithy/shared-ini-file-loader";

/**
* Resolves the AWS region following AWS CLI V2 precedence order.
*/
export const resolveAwsCliV2Region = async (defaultRegion?: string, maybeProfile?: string): Promise<string> => {
const profile = maybeProfile ?? process.env.AWS_PROFILE ?? process.env.AWS_DEFAULT_PROFILE ?? "default";

const region =
process.env.AWS_REGION ||
process.env.AWS_DEFAULT_REGION ||
(await getRegionFromIni(profile)) ||
(await regionFromMetadataService());

if (!region) {
const usedProfile = !profile ? "" : ` (profile: "${profile}")`;
if (defaultRegion) {
logger.warn(
`Unable to determine AWS region from environment or AWS configuration${usedProfile}, defaulting to '${defaultRegion}'`
);
return defaultRegion;
}
throw new Error(
`Unable to determine AWS region from environment or AWS configuration${usedProfile}. Please specify a region.`
);
}
return region;
};

/**
* Fetches the region from the AWS shared config files.
*/
export async function getRegionFromIni(profile: string): Promise<string | undefined> {
const sharedFiles = await loadSharedConfigFiles({ ignoreCache: true });
return sharedFiles.configFile?.[profile]?.region || sharedFiles.credentialsFile?.[profile]?.region;
}

/**
* Retrieves the AWS region from the EC2 Instance Metadata Service (IMDS).
*/
export async function regionFromMetadataService(): Promise<string | undefined> {
try {
const metadataService = new MetadataService();
const document = await metadataService.request("/latest/dynamic/instance-identity/document", {});
return JSON.parse(document).region;
} catch (e) {
return undefined;
}
}

0 comments on commit 050bdcb

Please sign in to comment.