backend-manager 5.9.14 → 5.9.16
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/package.json
CHANGED
|
@@ -2,16 +2,10 @@ const BaseCommand = require('./base-command');
|
|
|
2
2
|
const chalk = require('chalk').default;
|
|
3
3
|
const powertools = require('node-powertools');
|
|
4
4
|
const attachLogFile = require('../utils/attach-log-file');
|
|
5
|
-
const { execSync } = require('child_process');
|
|
6
5
|
const path = require('path');
|
|
7
6
|
const jetpack = require('fs-jetpack');
|
|
8
7
|
|
|
9
8
|
const DEFAULT_REGION = 'us-central1';
|
|
10
|
-
const PUBLIC_HTTP_FUNCTIONS = [
|
|
11
|
-
'bm_api',
|
|
12
|
-
'bm_authBeforeCreate',
|
|
13
|
-
'bm_authBeforeSignIn',
|
|
14
|
-
];
|
|
15
9
|
|
|
16
10
|
class DeployCommand extends BaseCommand {
|
|
17
11
|
async execute() {
|
|
@@ -49,11 +43,14 @@ class DeployCommand extends BaseCommand {
|
|
|
49
43
|
}
|
|
50
44
|
|
|
51
45
|
/**
|
|
52
|
-
* Ensure HTTP-triggered functions have allUsers as cloudfunctions.invoker.
|
|
46
|
+
* Ensure all HTTP-triggered functions have allUsers as cloudfunctions.invoker.
|
|
53
47
|
*
|
|
54
48
|
* Firebase CLI used to set this automatically but stopped around the Node 10
|
|
55
49
|
* runtime transition. Without it, HTTP requests get a 403 at the IAM level
|
|
56
50
|
* before BEM's application-level auth (backendManagerKey) can run.
|
|
51
|
+
*
|
|
52
|
+
* Dynamically discovers all deployed functions via gcloud and fixes any
|
|
53
|
+
* HTTP-triggered function missing the allUsers invoker binding.
|
|
57
54
|
*/
|
|
58
55
|
async ensurePublicInvoker() {
|
|
59
56
|
const projectId = this.getProjectId();
|
|
@@ -62,10 +59,23 @@ class DeployCommand extends BaseCommand {
|
|
|
62
59
|
return;
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
// Discover all deployed HTTP-triggered functions
|
|
63
|
+
let httpFunctions;
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const output = await powertools.execute(
|
|
67
|
+
`gcloud functions list --project ${projectId} --regions ${DEFAULT_REGION} --format="json(name,httpsTrigger)"`,
|
|
68
|
+
{ log: false },
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
httpFunctions = JSON.parse(output)
|
|
72
|
+
.filter((fn) => fn.httpsTrigger)
|
|
73
|
+
.map((fn) => fn.name.split('/').pop());
|
|
74
|
+
} catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
66
77
|
|
|
67
|
-
if (!
|
|
68
|
-
this.log(chalk.gray('\n Skipping public invoker check (gcloud not found)\n'));
|
|
78
|
+
if (!httpFunctions.length) {
|
|
69
79
|
return;
|
|
70
80
|
}
|
|
71
81
|
|
|
@@ -74,12 +84,11 @@ class DeployCommand extends BaseCommand {
|
|
|
74
84
|
let fixed = 0;
|
|
75
85
|
let ok = 0;
|
|
76
86
|
|
|
77
|
-
for (const fnName of
|
|
87
|
+
for (const fnName of httpFunctions) {
|
|
78
88
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{ encoding: 'utf8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] },
|
|
89
|
+
const policyOutput = await powertools.execute(
|
|
90
|
+
`gcloud functions get-iam-policy ${fnName} --project ${projectId} --region ${DEFAULT_REGION} --format=json`,
|
|
91
|
+
{ log: false },
|
|
83
92
|
);
|
|
84
93
|
|
|
85
94
|
const policy = JSON.parse(policyOutput);
|
|
@@ -93,16 +102,15 @@ class DeployCommand extends BaseCommand {
|
|
|
93
102
|
continue;
|
|
94
103
|
}
|
|
95
104
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{ encoding: 'utf8', timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'] },
|
|
105
|
+
await powertools.execute(
|
|
106
|
+
`gcloud functions add-iam-policy-binding ${fnName} --project ${projectId} --region ${DEFAULT_REGION} --member="allUsers" --role="roles/cloudfunctions.invoker"`,
|
|
107
|
+
{ log: false },
|
|
100
108
|
);
|
|
101
109
|
|
|
102
110
|
this.log(` ${chalk.green('✓')} Set public invoker on ${chalk.cyan(fnName)}`);
|
|
103
111
|
fixed++;
|
|
104
112
|
} catch {
|
|
105
|
-
//
|
|
113
|
+
// Skip silently — function may be in a transient state
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
|
|
@@ -121,23 +129,6 @@ class DeployCommand extends BaseCommand {
|
|
|
121
129
|
return null;
|
|
122
130
|
}
|
|
123
131
|
}
|
|
124
|
-
|
|
125
|
-
findGcloud() {
|
|
126
|
-
const homeDir = require('os').homedir();
|
|
127
|
-
const sdkPath = path.join(homeDir, 'google-cloud-sdk', 'bin', 'gcloud');
|
|
128
|
-
|
|
129
|
-
if (jetpack.exists(sdkPath)) {
|
|
130
|
-
return sdkPath;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Try PATH
|
|
134
|
-
try {
|
|
135
|
-
execSync('which gcloud', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
136
|
-
return 'gcloud';
|
|
137
|
-
} catch {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
132
|
}
|
|
142
133
|
|
|
143
134
|
module.exports = DeployCommand;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const BaseTest = require('./base-test');
|
|
2
|
+
const powertools = require('node-powertools');
|
|
3
|
+
|
|
4
|
+
class GcloudCliTest extends BaseTest {
|
|
5
|
+
getName() {
|
|
6
|
+
return 'gcloud CLI is installed (required by deploy)';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
getWarning() {
|
|
10
|
+
return [
|
|
11
|
+
'gcloud CLI is not installed.',
|
|
12
|
+
'Install with: https://cloud.google.com/sdk/docs/install',
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async run() {
|
|
17
|
+
try {
|
|
18
|
+
await powertools.execute('gcloud --version', { log: false });
|
|
19
|
+
return true;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
return 'warn';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = GcloudCliTest;
|
|
@@ -10,6 +10,7 @@ const NvmrcVersionTest = require('./nvmrc-version');
|
|
|
10
10
|
const FirebaseCLITest = require('./firebase-cli');
|
|
11
11
|
const FirebaseAuthTest = require('./firebase-auth');
|
|
12
12
|
const JavaInstalledTest = require('./java-installed');
|
|
13
|
+
const GcloudCliTest = require('./gcloud-cli');
|
|
13
14
|
const FunctionsPackageTest = require('./functions-package');
|
|
14
15
|
const FirebaseAdminTest = require('./firebase-admin');
|
|
15
16
|
const FirebaseFunctionsTest = require('./firebase-functions');
|
|
@@ -56,6 +57,7 @@ function getTests(context) {
|
|
|
56
57
|
new FirebaseCLITest(context),
|
|
57
58
|
new FirebaseAuthTest(context),
|
|
58
59
|
new JavaInstalledTest(context),
|
|
60
|
+
new GcloudCliTest(context),
|
|
59
61
|
new FunctionsPackageTest(context),
|
|
60
62
|
new FirebaseAdminTest(context),
|
|
61
63
|
new FirebaseFunctionsTest(context),
|