gcs-google-mcp-server 0.1.10 → 0.1.11
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/build/healthcheck.js +20 -10
- package/build/index.js +4 -2
- package/package.json +1 -1
package/build/healthcheck.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { logInfo } from '../shared/logging.js';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown when a constrained bucket cannot be reached (does not exist or the
|
|
4
|
-
* service account lacks access to it).
|
|
4
|
+
* service account lacks object-read access to it).
|
|
5
5
|
*/
|
|
6
6
|
export class BucketNotAccessibleError extends Error {
|
|
7
|
-
constructor(bucket) {
|
|
8
|
-
|
|
7
|
+
constructor(bucket, cause) {
|
|
8
|
+
const causeMessage = cause instanceof Error ? cause.message : cause !== undefined ? String(cause) : undefined;
|
|
9
|
+
super(`Constrained bucket "${bucket}" does not exist or is not accessible` +
|
|
10
|
+
(causeMessage ? `: ${causeMessage}` : ''));
|
|
9
11
|
this.name = 'BucketNotAccessibleError';
|
|
10
12
|
}
|
|
11
13
|
}
|
|
@@ -13,10 +15,13 @@ export class BucketNotAccessibleError extends Error {
|
|
|
13
15
|
* Validate GCS credentials and connectivity.
|
|
14
16
|
*
|
|
15
17
|
* - When constrained to a single bucket (`GCS_BUCKET`), probe ONLY that bucket
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* with an object-scoped list (`storage.objects.list`). This is the exact
|
|
19
|
+
* permission the server actually exercises for the constrained bucket, and a
|
|
20
|
+
* least-privilege, bucket-scoped service account is granted it. This path must
|
|
21
|
+
* NOT call `listBuckets()` (project-level `storage.buckets.list`) NOR a
|
|
22
|
+
* bucket-metadata probe like `headBucket`/`getMetadata` (bucket-level
|
|
23
|
+
* `storage.buckets.get`): a correctly scoped read-only SA can be denied BOTH
|
|
24
|
+
* of those while still being able to read objects in the bucket.
|
|
20
25
|
* - Without a constraint, validate by listing buckets, which legitimately
|
|
21
26
|
* requires project-level access.
|
|
22
27
|
*
|
|
@@ -24,9 +29,14 @@ export class BucketNotAccessibleError extends Error {
|
|
|
24
29
|
*/
|
|
25
30
|
export async function validateGcsCredentials(client, constrainedBucket) {
|
|
26
31
|
if (constrainedBucket) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
try {
|
|
33
|
+
// A single object-list request validates `storage.objects.list` on the
|
|
34
|
+
// bucket without requiring any project- or bucket-level metadata
|
|
35
|
+
// permission. maxResults:1 keeps the probe cheap.
|
|
36
|
+
await client.listObjects(constrainedBucket, { maxResults: 1 });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new BucketNotAccessibleError(constrainedBucket, error);
|
|
30
40
|
}
|
|
31
41
|
logInfo('healthcheck', `Constrained bucket "${constrainedBucket}" verified`);
|
|
32
42
|
}
|
package/build/index.js
CHANGED
|
@@ -110,8 +110,10 @@ async function performHealthChecks() {
|
|
|
110
110
|
keyFileContents,
|
|
111
111
|
});
|
|
112
112
|
// Validate credentials. When constrained to a single bucket, this probes
|
|
113
|
-
// only that bucket
|
|
114
|
-
//
|
|
113
|
+
// only that bucket via an object-scoped list (storage.objects.list) and
|
|
114
|
+
// never touches project-level (storage.buckets.list) or bucket-metadata
|
|
115
|
+
// (storage.buckets.get) permissions, so a least-privilege, bucket-scoped
|
|
116
|
+
// read-only service account can start.
|
|
115
117
|
await validateGcsCredentials(client, constrainedBucket);
|
|
116
118
|
}
|
|
117
119
|
catch (error) {
|
package/package.json
CHANGED