@riocrypto/common-server 1.0.2480 → 1.0.2481
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.
|
@@ -8,22 +8,34 @@ declare class SecretManagerClient {
|
|
|
8
8
|
private readonly POLL_INTERVAL_MS;
|
|
9
9
|
constructor(env: RioEnv);
|
|
10
10
|
/**
|
|
11
|
-
* Get a secret value from cache or fetch
|
|
12
|
-
* Once fetched,
|
|
11
|
+
* Get a secret value from cache or fetch the entire secret file
|
|
12
|
+
* Once fetched, all secrets are cached and automatically refreshed every hour
|
|
13
13
|
*/
|
|
14
14
|
getSecretValue(secretId: string): Promise<string | null>;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Refresh the entire secret cache by fetching the complete secret file
|
|
17
17
|
*/
|
|
18
|
-
private
|
|
18
|
+
private refreshSecretCache;
|
|
19
19
|
/**
|
|
20
|
-
* Set up cache
|
|
20
|
+
* Set up cache with polling for the entire secret file
|
|
21
21
|
*/
|
|
22
22
|
private setupCacheWithPolling;
|
|
23
23
|
/**
|
|
24
|
-
* Clear the
|
|
24
|
+
* Clear the entire secret cache
|
|
25
25
|
*/
|
|
26
|
-
clearCache(
|
|
26
|
+
clearCache(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get all cached secrets (useful for debugging)
|
|
29
|
+
*/
|
|
30
|
+
getAllSecrets(): Record<string, string> | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get cache status information
|
|
33
|
+
*/
|
|
34
|
+
getCacheStatus(): {
|
|
35
|
+
isLoaded: boolean;
|
|
36
|
+
secretCount: number;
|
|
37
|
+
lastFetched: Date | null;
|
|
38
|
+
};
|
|
27
39
|
}
|
|
28
40
|
export declare const secretManagerClient: SecretManagerClient;
|
|
29
41
|
export {};
|
|
@@ -39,7 +39,7 @@ const fs = __importStar(require("fs"));
|
|
|
39
39
|
class SecretManagerClient {
|
|
40
40
|
constructor(env) {
|
|
41
41
|
this.env = env;
|
|
42
|
-
this.secretCache =
|
|
42
|
+
this.secretCache = null;
|
|
43
43
|
this.POLL_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
|
|
44
44
|
const secretFilePath = "/etc/secrets/secret-manager/secret-manager-service-account-key.json";
|
|
45
45
|
const secretFileContents = fs.readFileSync(secretFilePath, "utf8");
|
|
@@ -56,29 +56,34 @@ class SecretManagerClient {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Get a secret value from cache or fetch
|
|
60
|
-
* Once fetched,
|
|
59
|
+
* Get a secret value from cache or fetch the entire secret file
|
|
60
|
+
* Once fetched, all secrets are cached and automatically refreshed every hour
|
|
61
61
|
*/
|
|
62
62
|
getSecretValue(secretId) {
|
|
63
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
// Check if
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return cachedSecret.value;
|
|
64
|
+
// Check if we have a cache and the secret exists
|
|
65
|
+
if (this.secretCache && this.secretCache.secrets[secretId]) {
|
|
66
|
+
return this.secretCache.secrets[secretId];
|
|
68
67
|
}
|
|
69
|
-
// If not in cache, fetch
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
|
|
68
|
+
// If not in cache or cache doesn't exist, fetch entire secret file
|
|
69
|
+
const success = yield this.refreshSecretCache();
|
|
70
|
+
if (!success) {
|
|
71
|
+
return null;
|
|
73
72
|
}
|
|
74
|
-
|
|
73
|
+
// Check again after refresh
|
|
74
|
+
if (this.secretCache && this.secretCache.secrets[secretId]) {
|
|
75
|
+
return this.secretCache.secrets[secretId];
|
|
76
|
+
}
|
|
77
|
+
// Secret not found even after refresh
|
|
78
|
+
console.error(`Secret ${secretId} not found in secret file`);
|
|
79
|
+
return null;
|
|
75
80
|
});
|
|
76
81
|
}
|
|
77
82
|
/**
|
|
78
|
-
*
|
|
83
|
+
* Refresh the entire secret cache by fetching the complete secret file
|
|
79
84
|
*/
|
|
80
|
-
|
|
81
|
-
var _a, _b;
|
|
85
|
+
refreshSecretCache() {
|
|
86
|
+
var _a, _b, _c;
|
|
82
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
88
|
let file;
|
|
84
89
|
if (this.env === common_1.RioEnv.Development) {
|
|
@@ -105,7 +110,14 @@ class SecretManagerClient {
|
|
|
105
110
|
throw new Error("No payload data");
|
|
106
111
|
}
|
|
107
112
|
const secrets = JSON.parse(version.payload.data.toString());
|
|
108
|
-
|
|
113
|
+
// Clear existing polling if it exists
|
|
114
|
+
if ((_c = this.secretCache) === null || _c === void 0 ? void 0 : _c.pollingInterval) {
|
|
115
|
+
clearInterval(this.secretCache.pollingInterval);
|
|
116
|
+
}
|
|
117
|
+
// Set up new cache with polling
|
|
118
|
+
this.setupCacheWithPolling(secrets);
|
|
119
|
+
console.info(`Refreshed ${Object.keys(secrets).length} secrets from ${file}`);
|
|
120
|
+
return true;
|
|
109
121
|
}
|
|
110
122
|
catch (err) {
|
|
111
123
|
attempt++;
|
|
@@ -117,74 +129,77 @@ class SecretManagerClient {
|
|
|
117
129
|
continue;
|
|
118
130
|
}
|
|
119
131
|
else {
|
|
120
|
-
console.error(`Failed to access secret ${
|
|
121
|
-
return
|
|
132
|
+
console.error(`Failed to access secret file ${file}:`, err);
|
|
133
|
+
return false;
|
|
122
134
|
}
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
|
-
console.error(`Failed to access secret ${
|
|
126
|
-
return
|
|
137
|
+
console.error(`Failed to access secret file ${file} after ${maxRetries} attempts.`);
|
|
138
|
+
return false;
|
|
127
139
|
});
|
|
128
140
|
}
|
|
129
141
|
/**
|
|
130
|
-
* Set up cache
|
|
142
|
+
* Set up cache with polling for the entire secret file
|
|
131
143
|
*/
|
|
132
|
-
setupCacheWithPolling(
|
|
144
|
+
setupCacheWithPolling(secrets) {
|
|
133
145
|
// Only set up polling in non-test environments
|
|
134
146
|
if (process.env.NODE_ENV === "test") {
|
|
135
|
-
// For test environments, just cache the
|
|
136
|
-
this.secretCache
|
|
137
|
-
|
|
147
|
+
// For test environments, just cache the secrets without polling
|
|
148
|
+
this.secretCache = {
|
|
149
|
+
secrets,
|
|
138
150
|
pollingInterval: null,
|
|
139
|
-
|
|
151
|
+
lastFetched: new Date(),
|
|
152
|
+
};
|
|
140
153
|
return;
|
|
141
154
|
}
|
|
142
|
-
// Set up polling interval to refresh
|
|
155
|
+
// Set up polling interval to refresh all secrets
|
|
143
156
|
const pollingInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
144
157
|
try {
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
// Only update and log if the value has changed
|
|
149
|
-
if (currentCached && currentCached.value !== newValue) {
|
|
150
|
-
console.info(`Secret ${secretId} has been updated`);
|
|
151
|
-
this.secretCache.set(secretId, {
|
|
152
|
-
value: newValue,
|
|
153
|
-
pollingInterval: currentCached.pollingInterval,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
158
|
+
const success = yield this.refreshSecretCache();
|
|
159
|
+
if (!success) {
|
|
160
|
+
console.error("Failed to refresh secret cache during polling");
|
|
156
161
|
}
|
|
157
162
|
}
|
|
158
163
|
catch (error) {
|
|
159
|
-
console.error(
|
|
164
|
+
console.error("Error polling secrets:", error);
|
|
160
165
|
}
|
|
161
166
|
}), this.POLL_INTERVAL_MS);
|
|
162
|
-
// Store the
|
|
163
|
-
this.secretCache
|
|
164
|
-
|
|
167
|
+
// Store the cache with polling interval
|
|
168
|
+
this.secretCache = {
|
|
169
|
+
secrets,
|
|
165
170
|
pollingInterval,
|
|
166
|
-
|
|
171
|
+
lastFetched: new Date(),
|
|
172
|
+
};
|
|
167
173
|
}
|
|
168
174
|
/**
|
|
169
|
-
* Clear the
|
|
175
|
+
* Clear the entire secret cache
|
|
170
176
|
*/
|
|
171
|
-
clearCache(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
clearInterval(cached.pollingInterval);
|
|
176
|
-
}
|
|
177
|
-
this.secretCache.delete(secretId);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
// Clear all cached secrets
|
|
181
|
-
this.secretCache.forEach((cached) => {
|
|
182
|
-
if (cached.pollingInterval) {
|
|
183
|
-
clearInterval(cached.pollingInterval);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
this.secretCache.clear();
|
|
177
|
+
clearCache() {
|
|
178
|
+
var _a;
|
|
179
|
+
if ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.pollingInterval) {
|
|
180
|
+
clearInterval(this.secretCache.pollingInterval);
|
|
187
181
|
}
|
|
182
|
+
this.secretCache = null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get all cached secrets (useful for debugging)
|
|
186
|
+
*/
|
|
187
|
+
getAllSecrets() {
|
|
188
|
+
var _a;
|
|
189
|
+
return ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.secrets) || null;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get cache status information
|
|
193
|
+
*/
|
|
194
|
+
getCacheStatus() {
|
|
195
|
+
var _a;
|
|
196
|
+
return {
|
|
197
|
+
isLoaded: !!this.secretCache,
|
|
198
|
+
secretCount: this.secretCache
|
|
199
|
+
? Object.keys(this.secretCache.secrets).length
|
|
200
|
+
: 0,
|
|
201
|
+
lastFetched: ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.lastFetched) || null,
|
|
202
|
+
};
|
|
188
203
|
}
|
|
189
204
|
}
|
|
190
205
|
exports.secretManagerClient = new SecretManagerClient(process.env.RIO_ENV || process.env.NEXT_PUBLIC_RIO_ENV);
|