runcloud 0.1.117 → 0.1.118
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/diagnose.js +29 -21
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/runcloud-0.1.118.tgz +0 -0
- package/runcloud-0.1.117.tgz +0 -0
package/dist/diagnose.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
|
-
import { GoogleAuth
|
|
3
|
+
import { GoogleAuth } from 'google-auth-library';
|
|
4
4
|
import { renderSessionDiagnosticTerminal, writeSessionDiagnosticBundle, } from './sessionDiagnostics.js';
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
6
|
const AUTH_ATTEMPT_TIMEOUT_MS = 10_000;
|
|
@@ -87,10 +87,8 @@ function extractAuthorization(headers) {
|
|
|
87
87
|
const h = headers;
|
|
88
88
|
return h?.Authorization ?? h?.authorization;
|
|
89
89
|
}
|
|
90
|
-
async function gcloudIdentityToken(audience
|
|
91
|
-
const args = ['auth', 'print-identity-token',
|
|
92
|
-
if (serviceAccount)
|
|
93
|
-
args.push(`--impersonate-service-account=${serviceAccount}`);
|
|
90
|
+
async function gcloudIdentityToken(audience) {
|
|
91
|
+
const args = ['auth', 'print-identity-token', '--audiences=' + audience];
|
|
94
92
|
const { stdout } = await execFileAsync('gcloud', args, { timeout: 15_000, maxBuffer: 1024 * 1024 });
|
|
95
93
|
const token = stdout.trim();
|
|
96
94
|
if (!token)
|
|
@@ -123,22 +121,32 @@ function exactAudienceAuthorization(authorization, audience) {
|
|
|
123
121
|
}
|
|
124
122
|
return authorization;
|
|
125
123
|
}
|
|
126
|
-
async function
|
|
127
|
-
return withDeadline('service-account
|
|
124
|
+
async function serviceAccountIdentityToken(audience, serviceAccount) {
|
|
125
|
+
return withDeadline('service-account ID-token minting', async (signal) => {
|
|
128
126
|
const sourceClient = await new GoogleAuth({
|
|
129
127
|
projectId: AUTH_DISCOVERY_PROJECT_ID,
|
|
130
128
|
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
|
|
131
129
|
clientOptions: { transporterOptions: { signal, timeout: AUTH_ATTEMPT_TIMEOUT_MS } },
|
|
132
130
|
}).getClient();
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
131
|
+
const sourceToken = await sourceClient.getAccessToken();
|
|
132
|
+
const authorization = typeof sourceToken === 'string' ? sourceToken : sourceToken.token;
|
|
133
|
+
if (!authorization)
|
|
134
|
+
throw new Error('ADC returned an empty source access token');
|
|
135
|
+
const response = await fetch('https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/' +
|
|
136
|
+
encodeURIComponent(serviceAccount) + ':generateIdToken', {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: {
|
|
139
|
+
Authorization: 'Bearer ' + authorization,
|
|
140
|
+
'Content-Type': 'application/json',
|
|
141
|
+
},
|
|
142
|
+
body: JSON.stringify({ audience, includeEmail: true }),
|
|
143
|
+
signal,
|
|
139
144
|
});
|
|
140
|
-
const
|
|
141
|
-
|
|
145
|
+
const body = await response.json().catch(() => ({}));
|
|
146
|
+
if (!response.ok || typeof body.token !== 'string') {
|
|
147
|
+
throw new Error("generateIdToken failed (" + response.status + "): " + JSON.stringify(body.error ?? body));
|
|
148
|
+
}
|
|
149
|
+
return exactAudienceAuthorization('Bearer ' + body.token, audience);
|
|
142
150
|
});
|
|
143
151
|
}
|
|
144
152
|
export async function resolveOpsAuthHeader(env = process.env, requestedAudience, requestedServiceAccount) {
|
|
@@ -158,13 +166,13 @@ export async function resolveOpsAuthHeader(env = process.env, requestedAudience,
|
|
|
158
166
|
catch (error) {
|
|
159
167
|
adcError = error instanceof Error ? error.message : String(error);
|
|
160
168
|
}
|
|
161
|
-
let
|
|
169
|
+
let serviceAccountError = 'not configured';
|
|
162
170
|
if (serviceAccount && env.DIAGNOSE_DISABLE_IMPERSONATION !== '1') {
|
|
163
171
|
try {
|
|
164
|
-
return await
|
|
172
|
+
return await serviceAccountIdentityToken(audience, serviceAccount);
|
|
165
173
|
}
|
|
166
174
|
catch (error) {
|
|
167
|
-
|
|
175
|
+
serviceAccountError = error instanceof Error ? error.message : String(error);
|
|
168
176
|
}
|
|
169
177
|
}
|
|
170
178
|
const token = env.DIAGNOSE_OPS_TOKEN;
|
|
@@ -173,13 +181,13 @@ export async function resolveOpsAuthHeader(env = process.env, requestedAudience,
|
|
|
173
181
|
}
|
|
174
182
|
if (env.DIAGNOSE_DISABLE_GCLOUD !== '1') {
|
|
175
183
|
try {
|
|
176
|
-
return exactAudienceAuthorization(`Bearer ${await gcloudIdentityToken(audience
|
|
184
|
+
return exactAudienceAuthorization(`Bearer ${await gcloudIdentityToken(audience)}`, audience);
|
|
177
185
|
}
|
|
178
186
|
catch (error) {
|
|
179
187
|
const gcloudError = error instanceof Error ? error.message : String(error);
|
|
180
188
|
throw new Error(`No usable ops credential for audience ${audience}.\n` +
|
|
181
189
|
`ADC failed: ${truncate(adcError, 500)}\n` +
|
|
182
|
-
`Service-account
|
|
190
|
+
`Service-account ID-token minting failed: ${truncate(serviceAccountError, 500)}\n` +
|
|
183
191
|
`gcloud failed: ${truncate(gcloudError, 500)}\n\n` +
|
|
184
192
|
'Repair access by adding the Google identity to control-plane `operators`, applying Terraform, ' +
|
|
185
193
|
'and running `gcloud auth application-default login`, then rerun. ' +
|
|
@@ -188,7 +196,7 @@ export async function resolveOpsAuthHeader(env = process.env, requestedAudience,
|
|
|
188
196
|
}
|
|
189
197
|
throw new Error(`No ops credential available for audience ${audience}. ` +
|
|
190
198
|
`ADC failed: ${truncate(adcError, 300)}. ` +
|
|
191
|
-
`Service-account
|
|
199
|
+
`Service-account ID-token minting failed: ${truncate(serviceAccountError, 300)}. ` +
|
|
192
200
|
'Run `gcloud auth application-default login` after the operator Terraform has been applied, or export DIAGNOSE_OPS_TOKEN.');
|
|
193
201
|
}
|
|
194
202
|
function truncate(value, max = 200) {
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = '0.1.
|
|
1
|
+
export const CLI_VERSION = '0.1.118';
|
package/package.json
CHANGED
|
Binary file
|
package/runcloud-0.1.117.tgz
DELETED
|
Binary file
|