fix: 🐛 Fix client daemon usage on windows (#2115)

* fix: 🐛 Fix client daemon usage on windows

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12365

* refactor: 💡 Fix error handling

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12365

---------

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
This commit is contained in:
Zhihe LiandCameron Perera authored and GitHub committed 2024-01-26 16:57:15 -06:00
1 parent 8f34d83c15
commit 3721f63edf
4 files changed
+102 -16

No files matched your search

@@ -106,10 +106,12 @@ export default class ClientDaemonHandler {
}
const sessionData = this.session.data?.authenticated;
const auth_token_id = sessionData?.id;
const token = sessionData?.token;
remainingQuery = {
...remainingQuery,
query: searchQuery,
auth_token_id,
token,
resource: pluralize(type),
};
@@ -125,7 +127,7 @@ export default class ClientDaemonHandler {
if (e.statusCode === 403 || e.statusCode === 401) {
await this.ipc.invoke('addTokenToClientDaemon', {
tokenId: auth_token_id,
token: sessionData?.token,
token,
});
try {
clientDaemonResults = await this.ipc.invoke(
+3 -3
View File
@@ -13,9 +13,9 @@ module.exports = {
// Returns JSON-formatted version information from the CLI
version: () => {
const command = ['-v'];
const rawOutput = spawnSync(command);
let gitRevision = /Git Revision:\s*(?<rev>.*)\n/.exec(rawOutput);
let versionNumber = /Version Number:\s*(?<ver>.*)\n/.exec(rawOutput);
const { stdout } = spawnSync(command);
let gitRevision = /Git Revision:\s*(?<rev>.*)\n/.exec(stdout);
let versionNumber = /Version Number:\s*(?<ver>.*)\n/.exec(stdout);
if (gitRevision) gitRevision = gitRevision.groups.rev;
if (versionNumber) versionNumber = versionNumber.groups.ver;
const formatted = versionNumber
@@ -74,12 +74,19 @@ module.exports = {
* Spawn child process and return output immediately.
* This function is intended for non-connection related tasks.
* @param {string} command
* @return {string}
*/
spawnSync(command) {
const childProcess = spawnSync(path(), command);
const rawOutput = childProcess.stdout.toString();
return rawOutput;
* @param {object} envVars
* @returns {{stdout: string | undefined, stderr: string | undefined}} */
spawnSync(command, envVars = {}) {
const childProcess = spawnSync(path(), command, {
env: {
...process.env,
...envVars,
},
});
const { stdout, stderr } = childProcess;
return { stdout: stdout?.toString(), stderr: stderr?.toString() };
},
/**
@@ -3,10 +3,16 @@
* SPDX-License-Identifier: MPL-2.0
*/
const { spawnSync, spawn } = require('../helpers/spawn-promise');
const {
spawnSync,
spawn,
spawnAsyncJSONPromise,
} = require('../helpers/spawn-promise');
const jsonify = require('../utils/jsonify.js');
const { unixSocketRequest } = require('../helpers/request-promise');
const runtimeSettings = require('./runtime-settings');
const sanitizer = require('../utils/sanitizer.js');
const { isWindows } = require('../helpers/platform.js');
class ClientDaemonManager {
#socketPath;
@@ -22,9 +28,9 @@ class ClientDaemonManager {
*/
status() {
const daemonStatusCommand = ['daemon', 'status', '-format=json'];
const data = spawnSync(daemonStatusCommand);
const { stdout } = spawnSync(daemonStatusCommand);
const status = jsonify(data);
const status = jsonify(stdout);
this.#socketPath = status?.item?.socket_address;
return status;
}
@@ -35,6 +41,7 @@ class ClientDaemonManager {
*/
async start() {
const startDaemonCommand = ['daemon', 'start'];
// We use spawn here because we want to check the stderr for specific logs
const { stderr } = await spawn(startDaemonCommand);
// If we get a null/undefined, err on safe side and don't stop daemon when
@@ -65,11 +72,16 @@ class ClientDaemonManager {
* @param tokenId
* @returns {Promise}
*/
addToken({ token, tokenId }) {
async addToken({ token, tokenId }) {
// TODO: Should this and search just always call CLI even for non-Windows?
if (isWindows()) {
return addTokenCliCommand(token);
}
const postBody = {
auth_token_id: tokenId,
auth_token_id: sanitizer.base62EscapeAndValidate(tokenId),
boundary_addr: runtimeSettings.clusterUrl,
auth_token: token,
auth_token: sanitizer.base62EscapeAndValidate(token),
};
const request = {
method: 'POST',
@@ -80,6 +92,11 @@ class ClientDaemonManager {
}
search(requestData) {
if (isWindows()) {
return searchCliCommand(requestData);
}
delete requestData.token;
const queryString = new URLSearchParams(requestData);
const request = {
@@ -91,5 +108,65 @@ class ClientDaemonManager {
}
}
const addTokenCliCommand = (token) => {
const addTokenCommand = [
'daemon',
'add-token',
'-format=json',
'-token=env://BOUNDARY_TOKEN',
'-keyring-type=none',
];
const sanitizedToken = sanitizer.base62EscapeAndValidate(token);
// TODO: Is setting an env var for the address the only way? I'm surprised to not see an -addr flag
const { stdout, stderr } = spawnSync(addTokenCommand, {
BOUNDARY_TOKEN: sanitizedToken,
BOUNDARY_ADDR: runtimeSettings.clusterUrl,
});
let parsedResponse = jsonify(stdout);
if (parsedResponse?.status_code === 204) {
// 204 has no response body
return;
}
parsedResponse = jsonify(stderr);
return Promise.reject({
statusCode: parsedResponse?.status_code,
...parsedResponse?.api_error,
});
};
const searchCliCommand = (requestData) => {
const searchCommand = [
'search',
'-format=json',
'-token=env://BOUNDARY_TOKEN',
`-resource=${requestData.resource}`,
];
if (requestData.query) {
searchCommand.push(`-query=${requestData.query}`);
}
if (requestData.filter) {
searchCommand.push(`-filter=${requestData.filter}`);
}
const sanitizedToken = sanitizer.base62EscapeAndValidate(requestData.token);
const { stdout, stderr } = spawnSync(searchCommand, {
BOUNDARY_TOKEN: sanitizedToken,
});
let parsedResponse = jsonify(stdout);
if (parsedResponse?.status_code === 200) {
return parsedResponse?.item;
}
parsedResponse = jsonify(stderr);
return Promise.reject({
statusCode: parsedResponse?.status_code,
...parsedResponse?.api_error,
});
};
// Export an instance so we get a singleton
module.exports = new ClientDaemonManager();