@vizamodo/aws-sts-core 0.3.1 → 0.3.2

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 (2) hide show
  1. package/dist/sts/issue.js +20 -49
  2. package/package.json +7 -2
package/dist/sts/issue.js CHANGED
@@ -17,6 +17,8 @@ const PROFILE_TTL = {
17
17
  };
18
18
  const DEFAULT_TTL = 2 * 60 * 60;
19
19
  // ---- isolate-level cached signing material ----
20
+ // Promise-based cache to avoid cold-start race during concurrent imports
21
+ let signingKeyPromise = null;
20
22
  let cachedSigningKey = null;
21
23
  let cachedCertBase64 = null;
22
24
  let cachedPrivateKeyBase64 = null;
@@ -34,18 +36,32 @@ async function getSigningMaterial(input) {
34
36
  if (cachedSigningKey &&
35
37
  cachedCertBase64 === input.certBase64 &&
36
38
  cachedPrivateKeyBase64 === input.privateKeyPkcs8Base64) {
37
- console.debug("[sts-cache] signingKey HIT");
38
39
  return { signingKey: cachedSigningKey, certBase64: cachedCertBase64 };
39
40
  }
40
- console.debug("[sts-cache] signingKey MISS importing key");
41
+ // Reset cache only after a signing key has been resolved and material actually changed
42
+ if (cachedSigningKey &&
43
+ (cachedCertBase64 !== input.certBase64 ||
44
+ cachedPrivateKeyBase64 !== input.privateKeyPkcs8Base64)) {
45
+ signingKeyPromise = null;
46
+ cachedSigningKey = null;
47
+ }
48
+ if (!signingKeyPromise) {
49
+ try {
50
+ const keyBuffer = base64ToBytes(input.privateKeyPkcs8Base64);
51
+ signingKeyPromise = crypto.subtle.importKey("pkcs8", keyBuffer, { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
52
+ }
53
+ catch {
54
+ throw new InternalError("invalid_signing_material");
55
+ }
56
+ }
41
57
  try {
42
- const keyBuffer = base64ToBytes(input.privateKeyPkcs8Base64);
43
- cachedSigningKey = await crypto.subtle.importKey("pkcs8", keyBuffer, { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
58
+ cachedSigningKey = await signingKeyPromise;
44
59
  cachedCertBase64 = input.certBase64;
45
60
  cachedPrivateKeyBase64 = input.privateKeyPkcs8Base64;
46
61
  return { signingKey: cachedSigningKey, certBase64: cachedCertBase64 };
47
62
  }
48
63
  catch {
64
+ signingKeyPromise = null; // allow retry after failure
49
65
  throw new InternalError("invalid_signing_material");
50
66
  }
51
67
  }
@@ -82,11 +98,9 @@ export async function issueAwsCredentials(input) {
82
98
  // --- MINIMAL DER WALK: extract serial number ---
83
99
  let certSerialDec;
84
100
  if (cachedCertSerialDec && cachedCertSerialSource === normalizedCert) {
85
- console.debug("[sts-cache] certSerial HIT");
86
101
  certSerialDec = cachedCertSerialDec;
87
102
  }
88
103
  else {
89
- console.debug("[sts-cache] certSerial MISS → parsing DER");
90
104
  try {
91
105
  const der = base64ToBytes(normalizedCert);
92
106
  let offset = 0;
@@ -149,30 +163,14 @@ export async function issueAwsCredentials(input) {
149
163
  signedHeaders,
150
164
  payloadHash,
151
165
  });
152
- console.debug("[sts-debug] canonicalRequest", {
153
- amzDate,
154
- signedHeaders,
155
- payloadHash,
156
- canonicalHeadersPreview: canonicalHeaders.slice(0, 120),
157
- canonicalRequestPreview: canonicalRequest.slice(0, 200)
158
- });
159
166
  const canonicalRequestHash = await getCanonicalRequestHash(canonicalRequest);
160
- console.debug("[sts-debug] canonicalRequestHash", canonicalRequestHash);
161
167
  const stringToSign = buildStringToSign({
162
168
  algorithm: ALGORITHM,
163
169
  amzDate,
164
170
  credentialScope,
165
171
  canonicalRequestHash,
166
172
  });
167
- console.debug("[sts-debug] stringToSign", {
168
- credentialScope,
169
- stringPreview: stringToSign.slice(0, 200)
170
- });
171
173
  const signatureHex = await signStringToSign(stringToSign, signingKey);
172
- console.debug("[sts-debug] signature", {
173
- length: signatureHex.length,
174
- prefix: signatureHex.slice(0, 32)
175
- });
176
174
  // 5. Build Authorization Header với số Serial (DECIMAL)
177
175
  const finalHeaders = new Headers({
178
176
  "Content-Type": "application/json",
@@ -180,25 +178,6 @@ export async function issueAwsCredentials(input) {
180
178
  "X-Amz-X509": normalizedCert,
181
179
  "Authorization": `AWS4-X509-ECDSA-SHA256 Credential=${certSerialDec}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signatureHex}`
182
180
  });
183
- console.debug("[sts-debug] requestHeaders", {
184
- host,
185
- amzDate,
186
- signedHeaders,
187
- certLen: normalizedCert.length
188
- });
189
- console.debug("[sts-request] issuing rolesanywhere session", {
190
- region,
191
- profile,
192
- roleArn,
193
- profileArn,
194
- trustAnchorArn,
195
- amzDate,
196
- cacheState: {
197
- hasSigningKey: !!cachedSigningKey,
198
- cachedCertMatch: cachedCertBase64 === normalizedCert,
199
- }
200
- });
201
- // 6. Execution
202
181
  try {
203
182
  const res = await fetch(`https://${host}${path}`, {
204
183
  method: "POST",
@@ -231,14 +210,6 @@ export async function issueAwsCredentials(input) {
231
210
  };
232
211
  }
233
212
  catch (e) {
234
- console.error("[sts-debug] fetch failure", {
235
- error: String(e),
236
- region,
237
- roleArn,
238
- profileArn,
239
- trustAnchorArn,
240
- amzDate
241
- });
242
213
  if (e instanceof InternalError)
243
214
  throw e;
244
215
  throw new InternalError("aws_unreachable");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizamodo/aws-sts-core",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Pure AWS STS + SigV4 (X509 Roles Anywhere) core logic",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,7 @@
13
13
  ],
14
14
  "scripts": {
15
15
  "build": "tsc",
16
+ "test": "vitest run",
16
17
  "clean": "rm -rf dist",
17
18
  "prepublishOnly": "npm run build",
18
19
  "dev": "ts-node bin/viza.ts",
@@ -20,6 +21,10 @@
20
21
  "release:full": "rm -rf dist && npx npm-check-updates -u && npm install && git add package.json package-lock.json && git commit -m 'chore(deps): auto update dependencies before release' || echo 'No changes' && node versioning.js && npm login && npm publish --tag latest --access public && git push"
21
22
  },
22
23
  "devDependencies": {
23
- "typescript": "^5.9.3"
24
+ "@aws-crypto/sha256-js": "^5.2.0",
25
+ "@aws-sdk/signature-v4": "^3.374.0",
26
+ "@vitest/coverage-v8": "^4.0.18",
27
+ "typescript": "^5.9.3",
28
+ "vitest": "^4.0.18"
24
29
  }
25
30
  }