@vizamodo/aws-sts-core 0.3.3 → 0.3.5

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 +25 -20
  2. package/package.json +1 -1
package/dist/sts/issue.js CHANGED
@@ -8,7 +8,7 @@ const ALGORITHM = "AWS4-X509-ECDSA-SHA256";
8
8
  const SERVICE = "rolesanywhere";
9
9
  const PATH = "/sessions";
10
10
  const PROFILE_TTL = {
11
- Runtime: 90 * 60,
11
+ Runtime: 30 * 60,
12
12
  ConsoleReadOnly: 12 * 60 * 60,
13
13
  ConsoleViewOnlyProd: 12 * 60 * 60,
14
14
  BillingReadOnly: 2 * 60 * 60,
@@ -91,11 +91,15 @@ export async function issueAwsCredentials(input) {
91
91
  const der = base64ToBytes(normalizedCert);
92
92
  let offset = 0;
93
93
  function readLen() {
94
+ if (offset >= der.length)
95
+ throw new Error("DER overflow");
94
96
  const b = der[offset++];
95
97
  if ((b & 0x80) === 0)
96
98
  return b;
97
99
  const n = b & 0x7f;
98
100
  let len = 0;
101
+ if (offset + n > der.length)
102
+ throw new Error("DER overflow");
99
103
  for (let i = 0; i < n; i++) {
100
104
  len = (len << 8) | der[offset++];
101
105
  }
@@ -115,6 +119,8 @@ export async function issueAwsCredentials(input) {
115
119
  if (der[offset++] !== 0x02)
116
120
  throw new Error("bad serial tag");
117
121
  const serialLen = readLen();
122
+ if (offset + serialLen > der.length)
123
+ throw new Error("DER overflow");
118
124
  let serial = der.slice(offset, offset + serialLen);
119
125
  if (serial.length > 1 && serial[0] === 0x00) {
120
126
  serial = serial.slice(1);
@@ -134,17 +140,17 @@ export async function issueAwsCredentials(input) {
134
140
  }
135
141
  }
136
142
  // ---- STS credential cache lookup (using certificate serial) ----
137
- cacheKey = `${region}|${roleArn}|${profileArn}|${certSerialDec}`;
143
+ cacheKey = `${region}|${roleArn}|${profileArn}|${trustAnchorArn}|${certSerialDec}`;
138
144
  const cachedEntry = stsCredentialCache.get(cacheKey);
139
- // Only reuse cached credentials if they still have >1h1m remaining
140
- const MIN_REMAINING_MS = 61 * 60 * 1000;
145
+ // Only reuse cached credentials if they still have >10p remaining
146
+ const MIN_REMAINING_MS = 5 * 60 * 1000;
141
147
  if (cachedEntry) {
142
- // If credentials already resolved and still valid reuse
143
- if (cachedEntry.expiresAt > Date.now() + MIN_REMAINING_MS) {
148
+ // If refresh already in-flight await the same promise
149
+ if (cachedEntry.expiresAt === 0) {
144
150
  return cachedEntry.promise;
145
151
  }
146
- // If a refresh is already in-flight await same promise
147
- if (cachedEntry.expiresAt === 0) {
152
+ // If credentials still valid with safe remaining window reuse
153
+ if (cachedEntry.expiresAt > Date.now() + MIN_REMAINING_MS) {
148
154
  return cachedEntry.promise;
149
155
  }
150
156
  }
@@ -155,9 +161,9 @@ export async function issueAwsCredentials(input) {
155
161
  // 2. Setup constants
156
162
  const host = `${SERVICE}.${region}.amazonaws.com`;
157
163
  const path = PATH;
158
- const now = new Date();
159
- const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
160
- const dateStamp = amzDate.slice(0, 8);
164
+ const iso = new Date().toISOString(); // e.g. 2026-03-07T12:00:00.000Z
165
+ const amzDate = `${iso.slice(0, 4)}${iso.slice(5, 7)}${iso.slice(8, 10)}T${iso.slice(11, 13)}${iso.slice(14, 16)}${iso.slice(17, 19)}Z`;
166
+ const dateStamp = iso.slice(0, 4) + iso.slice(5, 7) + iso.slice(8, 10);
161
167
  const service = SERVICE;
162
168
  // 3. Chuẩn bị Body & Cert
163
169
  const body = JSON.stringify({ trustAnchorArn, profileArn, roleArn, durationSeconds: sessionTtl });
@@ -204,20 +210,17 @@ export async function issueAwsCredentials(input) {
204
210
  body,
205
211
  });
206
212
  if (!res.ok) {
207
- const errorBody = await res.text();
208
- console.error("[aws-rejected] Request details", {
213
+ console.warn("[aws-rejected]", {
209
214
  status: res.status,
210
- response: errorBody,
211
215
  region,
212
- profile,
213
- amzDate
216
+ profile
214
217
  });
215
218
  throw new InternalError("aws_rejected");
216
219
  }
217
220
  const json = await res.json();
218
221
  const creds = json?.credentialSet?.[0]?.credentials;
219
222
  if (!creds?.accessKeyId || !creds?.secretAccessKey || !creds?.sessionToken) {
220
- console.error("[issueAwsCredentials] malformed AWS credential response", { json });
223
+ console.warn("[issueAwsCredentials] malformed AWS credential response");
221
224
  throw new InternalError("aws_malformed_credentials");
222
225
  }
223
226
  const result = {
@@ -226,7 +229,8 @@ export async function issueAwsCredentials(input) {
226
229
  sessionToken: creds.sessionToken,
227
230
  expiration: creds.expiration,
228
231
  };
229
- const exp = new Date(creds.expiration).getTime();
232
+ // subtract small clock‑skew safety window (5s)
233
+ const exp = new Date(creds.expiration).getTime() - 5000;
230
234
  // update cache expiration after success
231
235
  const entry = stsCredentialCache.get(cacheKey);
232
236
  if (entry) {
@@ -254,7 +258,8 @@ function normalizeCert(raw) {
254
258
  if (raw.includes("BEGIN CERTIFICATE")) {
255
259
  throw new InternalError("pem_not_allowed");
256
260
  }
257
- return raw.trim();
261
+ // remove whitespace and newlines to ensure stable cache keys
262
+ return raw.replace(/\s+/g, "");
258
263
  }
259
264
  async function sha256Hex(input) {
260
265
  // Tận dụng textEncoder có sẵn
@@ -274,7 +279,7 @@ async function getPayloadHash(body) {
274
279
  // so caching adds complexity without measurable benefit.
275
280
  return sha256Hex(body);
276
281
  }
277
- // Faster base64 decode → Uint8Array (avoids extra ArrayBuffer wrapping)
282
+ // Faster base64 decode → Uint8Array (V8 optimized path using built‑in vectorized conversion)
278
283
  function base64ToBytes(base64) {
279
284
  const binary = atob(base64);
280
285
  const len = binary.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizamodo/aws-sts-core",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Pure AWS STS + SigV4 (X509 Roles Anywhere) core logic",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",