@vizamodo/aws-sts-core 0.3.11 → 0.3.13
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/dist/sts/cache.d.ts +3 -0
- package/dist/sts/cache.js +40 -0
- package/dist/sts/issue.js +25 -1
- package/package.json +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const CACHE_KEY_PREFIX = "https://sts-cache.internal/";
|
|
2
|
+
const CACHE_TTL_BUFFER_SEC = 5 * 60; // 5 minutes safety buffer
|
|
3
|
+
export async function getCachedCredentials(cacheKey) {
|
|
4
|
+
const cache = caches.default;
|
|
5
|
+
const req = new Request(CACHE_KEY_PREFIX + cacheKey);
|
|
6
|
+
const res = await cache.match(req);
|
|
7
|
+
if (!res)
|
|
8
|
+
return null;
|
|
9
|
+
try {
|
|
10
|
+
return (await res.json());
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// corrupted cache entry → ignore
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export async function setCachedCredentials(cacheKey, result) {
|
|
18
|
+
if (!result.expiration) {
|
|
19
|
+
// cache is optional; skip caching if expiration missing
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const expiresAt = Date.parse(result.expiration);
|
|
23
|
+
if (!Number.isFinite(expiresAt)) {
|
|
24
|
+
// invalid expiration → skip caching
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const ttlSec = Math.floor((expiresAt - Date.now()) / 1000) - CACHE_TTL_BUFFER_SEC;
|
|
28
|
+
if (ttlSec <= 0)
|
|
29
|
+
return;
|
|
30
|
+
const cache = caches.default;
|
|
31
|
+
const req = new Request(CACHE_KEY_PREFIX + cacheKey);
|
|
32
|
+
const body = JSON.stringify(result);
|
|
33
|
+
const res = new Response(body, {
|
|
34
|
+
headers: {
|
|
35
|
+
"Content-Type": "application/json",
|
|
36
|
+
"Cache-Control": `max-age=${ttlSec}`,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
await cache.put(req, res);
|
|
40
|
+
}
|
package/dist/sts/issue.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCachedCredentials, setCachedCredentials } from "./cache";
|
|
1
2
|
import { canonicalizeHeaders } from "../sigv4/headers";
|
|
2
3
|
import { buildCanonicalRequest } from "../sigv4/canonical";
|
|
3
4
|
import { buildStringToSign } from "../sigv4/string-to-sign";
|
|
@@ -133,18 +134,39 @@ export async function issueAwsCredentials(input) {
|
|
|
133
134
|
throw new InternalError("invalid_cert_der");
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
|
-
// ----
|
|
137
|
+
// ---- cross-request cache lookup (Cloudflare Cache API) ----
|
|
137
138
|
cacheKey = `${region}|${roleArn}|${profileArn}|${trustAnchorArn}|${certSerialDec}`;
|
|
139
|
+
const externalCached = await getCachedCredentials(cacheKey);
|
|
140
|
+
if (externalCached) {
|
|
141
|
+
console.log("[sts-cache] edge-hit", { cacheKey });
|
|
142
|
+
return externalCached;
|
|
143
|
+
}
|
|
144
|
+
// ---- isolate-level cache lookup (dedupe concurrent refresh within isolate) ----
|
|
138
145
|
const cachedEntry = stsCredentialCache.get(cacheKey);
|
|
146
|
+
if (cachedEntry) {
|
|
147
|
+
console.log("[sts-cache] isolate-hit", {
|
|
148
|
+
cacheKey,
|
|
149
|
+
expiresAt: cachedEntry.expiresAt,
|
|
150
|
+
now: Date.now(),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
console.log("[sts-cache] isolate-miss", { cacheKey });
|
|
155
|
+
}
|
|
139
156
|
// Only reuse cached credentials if they still have >10p remaining
|
|
140
157
|
const MIN_REMAINING_MS = 5 * 60 * 1000;
|
|
141
158
|
if (cachedEntry) {
|
|
142
159
|
// If refresh already in-flight → await the same promise
|
|
143
160
|
if (cachedEntry.expiresAt === 0) {
|
|
161
|
+
console.log("[sts-cache] reuse-inflight-refresh", { cacheKey });
|
|
144
162
|
return cachedEntry.promise;
|
|
145
163
|
}
|
|
146
164
|
// If credentials still valid with safe remaining window → reuse
|
|
147
165
|
if (cachedEntry.expiresAt > Date.now() + MIN_REMAINING_MS) {
|
|
166
|
+
console.log("[sts-cache] reuse-valid-credentials", {
|
|
167
|
+
cacheKey,
|
|
168
|
+
expiresAt: cachedEntry.expiresAt,
|
|
169
|
+
});
|
|
148
170
|
return cachedEntry.promise;
|
|
149
171
|
}
|
|
150
172
|
}
|
|
@@ -223,6 +245,8 @@ export async function issueAwsCredentials(input) {
|
|
|
223
245
|
sessionToken: creds.sessionToken,
|
|
224
246
|
expiration: creds.expiration,
|
|
225
247
|
};
|
|
248
|
+
// persist credential in edge cache (best effort)
|
|
249
|
+
setCachedCredentials(cacheKey, result).catch(() => { });
|
|
226
250
|
// subtract small clock‑skew safety window (5s)
|
|
227
251
|
const exp = new Date(creds.expiration).getTime() - 5000;
|
|
228
252
|
// update cache expiration after success
|