claude-aws-mfa 1.4.0 → 1.5.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.
- package/CHANGELOG.md +5 -0
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/config.ts +9 -0
- package/src/sts.ts +2 -1
- package/src/usage.ts +2 -1
- package/test/config.test.ts +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,11 @@ Releases are automated via CI. To create a new release:
|
|
|
22
22
|
Stable versions (e.g. `v1.2.0`) publish to npm `@latest`. Pre-release versions
|
|
23
23
|
(e.g. `v1.2.0-rc.1`) publish to npm `@next` and create a GitHub pre-release.
|
|
24
24
|
|
|
25
|
+
## [v1.5.0] - 2026-10-19
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- `AWS_REGION`, when set, overrides the configured region for STS and `--usage`, so a report can target a region other than the one in the config.
|
|
29
|
+
|
|
25
30
|
## [v1.4.0] - 2026-10-19
|
|
26
31
|
|
|
27
32
|
### Added
|
package/README.md
CHANGED
|
@@ -58,6 +58,8 @@ Add this (plus any addtitional config you prefer) to your Claude Code settings (
|
|
|
58
58
|
6. Saves configuration (including MFA mode and command) to `~/.config/claude-aws-mfa.json` (mode 0600) for subsequent runs
|
|
59
59
|
7. Outputs temporary credentials as JSON to stdout
|
|
60
60
|
|
|
61
|
+
If `AWS_REGION` is set, it overrides the configured region for all AWS calls (STS and `--usage`); the saved config is left unchanged. When Claude Code runs the tool, it sees whatever `AWS_REGION` Claude Code's environment has (including one set in `settings.json`); when you run it yourself from a shell, it only sees your shell's.
|
|
62
|
+
|
|
61
63
|
On subsequent runs, all fields are pre-populated from the saved config — just enter a fresh MFA code and hit OK. If you use the command mode, the TOTP code is fetched automatically so no manual entry is needed at all.
|
|
62
64
|
|
|
63
65
|
### Claude Code profiles
|
|
@@ -119,7 +121,7 @@ claude-aws-mfa --usage='my-role/*' # quote * so the shel
|
|
|
119
121
|
|
|
120
122
|
Only callers that assumed a role are counted; calls made directly with IAM user keys never match.
|
|
121
123
|
|
|
122
|
-
The data comes from Bedrock [model invocation logs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html), so invocation logging to CloudWatch Logs must be enabled in the account and region. The querying credentials need `bedrock:GetModelInvocationLoggingConfiguration`, `logs:StartQuery` and `logs:GetQueryResults`. Without `--profile`, credentials are obtained exactly as for Claude Code (cached session, auto-MFA, or the dialog). Errors go to stderr.
|
|
124
|
+
Only one region is queried: `AWS_REGION` if set, otherwise the configured region. If your Claude Code `settings.json` sets `AWS_REGION` to something other than the configured region, pass the same value when running `--usage` from a shell (`AWS_REGION=eu-west-1 claude-aws-mfa --usage`) to report on the region Claude Code uses. Cross-region inference calls (`us.`/`global.` profiles) are logged in the region they were made from, so they are included. The data comes from Bedrock [model invocation logs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html), so invocation logging to CloudWatch Logs must be enabled in the account and region. The querying credentials need `bedrock:GetModelInvocationLoggingConfiguration`, `logs:StartQuery` and `logs:GetQueryResults`. Without `--profile`, credentials are obtained exactly as for Claude Code (cached session, auto-MFA, or the dialog). Errors go to stderr.
|
|
123
125
|
|
|
124
126
|
Costs are estimated from AWS's public [Price List](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/price-changes.html) for the region (no extra permissions needed), at current base on-demand rates — `us.`/`eu.` cross-region profiles at their geo price, `global.` at the global price. They exclude negotiated discounts and the long-context and 1-hour-cache-write surcharges, which the aggregated logs can't distinguish, so treat them as an estimate rather than your bill. If prices can't be fetched, token counts are still printed.
|
|
125
127
|
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -259,6 +259,15 @@ export function missingConfigFields(cfg: Partial<Config>): string[] {
|
|
|
259
259
|
return missing;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Region for AWS calls: AWS_REGION, when set, overrides the configured one, as
|
|
264
|
+
* it does for the AWS SDK and CLI. Only applied at call time — the config keeps
|
|
265
|
+
* the region entered in the dialog.
|
|
266
|
+
*/
|
|
267
|
+
export function effectiveRegion(configured?: string): string | undefined {
|
|
268
|
+
return process.env.AWS_REGION || configured || undefined;
|
|
269
|
+
}
|
|
270
|
+
|
|
262
271
|
export async function seedDefaults(): Promise<Partial<Config>> {
|
|
263
272
|
const defaults: Partial<Config> = {};
|
|
264
273
|
try {
|
package/src/sts.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { STSClient, AssumeRoleCommand } from "@aws-sdk/client-sts";
|
|
2
|
+
import { effectiveRegion } from "./config";
|
|
2
3
|
|
|
3
4
|
export const DEFAULT_SESSION_NAME = "claude-aws-mfa";
|
|
4
5
|
|
|
@@ -30,7 +31,7 @@ export async function assumeRoleWithMfa(params: {
|
|
|
30
31
|
sessionName?: string;
|
|
31
32
|
}) {
|
|
32
33
|
const client = new STSClient({
|
|
33
|
-
region: params.region,
|
|
34
|
+
region: effectiveRegion(params.region),
|
|
34
35
|
credentials: { accessKeyId: params.accessKeyId, secretAccessKey: params.secretAccessKey },
|
|
35
36
|
});
|
|
36
37
|
|
package/src/usage.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BedrockClient, GetModelInvocationLoggingConfigurationCommand } from "@aws-sdk/client-bedrock";
|
|
2
2
|
import { CloudWatchLogsClient, StartQueryCommand, GetQueryResultsCommand } from "@aws-sdk/client-cloudwatch-logs";
|
|
3
3
|
import { DEFAULT_SESSION_NAME } from "./sts";
|
|
4
|
+
import { effectiveRegion } from "./config";
|
|
4
5
|
|
|
5
6
|
const COLUMNS = ["requests", "inputTokens", "cacheReadTokens", "cacheWriteTokens", "outputTokens"] as const;
|
|
6
7
|
const HEADERS = ["Model", "Requests", "Input", "Cache read", "Cache write", "Output"];
|
|
@@ -190,7 +191,7 @@ export async function printUsage(opts: {
|
|
|
190
191
|
const { start, end } = usageRange(opts.from, opts.to);
|
|
191
192
|
const specText = opts.spec || DEFAULT_SESSION_NAME;
|
|
192
193
|
const spec = parseUsageSpec(specText);
|
|
193
|
-
const clientConfig = { region: opts.region
|
|
194
|
+
const clientConfig = { region: effectiveRegion(opts.region), credentials: opts.credentials, profile: opts.profile };
|
|
194
195
|
|
|
195
196
|
const bedrock = new BedrockClient(clientConfig);
|
|
196
197
|
// Prices are best-effort: token counts are still worth printing without them.
|
package/test/config.test.ts
CHANGED
|
@@ -3,7 +3,25 @@ import { chmodSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync, rmSync,
|
|
|
3
3
|
import { join, resolve } from "path";
|
|
4
4
|
import { tmpdir } from "os";
|
|
5
5
|
import { homedir } from "os";
|
|
6
|
-
import { activeProfile, missingConfigFields, profileSuffix } from "../src/config";
|
|
6
|
+
import { activeProfile, effectiveRegion, missingConfigFields, profileSuffix } from "../src/config";
|
|
7
|
+
|
|
8
|
+
describe("effectiveRegion", () => {
|
|
9
|
+
test("AWS_REGION overrides the configured region", () => {
|
|
10
|
+
const saved = process.env.AWS_REGION;
|
|
11
|
+
try {
|
|
12
|
+
delete process.env.AWS_REGION;
|
|
13
|
+
expect(effectiveRegion("us-west-2")).toBe("us-west-2");
|
|
14
|
+
expect(effectiveRegion(undefined)).toBeUndefined();
|
|
15
|
+
process.env.AWS_REGION = "eu-central-1";
|
|
16
|
+
expect(effectiveRegion("us-west-2")).toBe("eu-central-1");
|
|
17
|
+
process.env.AWS_REGION = "";
|
|
18
|
+
expect(effectiveRegion("us-west-2")).toBe("us-west-2");
|
|
19
|
+
} finally {
|
|
20
|
+
if (saved === undefined) delete process.env.AWS_REGION;
|
|
21
|
+
else process.env.AWS_REGION = saved;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
7
25
|
|
|
8
26
|
describe("profileSuffix", () => {
|
|
9
27
|
test("is empty for no profile and for the default config dir", () => {
|