@usebruno/cli
Version:
With Bruno CLI, you can now run your API collections with ease using simple command line commands.
158 lines (148 loc) • 4.69 kB
JavaScript
const debug = require('debug');
const nodeVaultDebug = debug('node-vault');
const axios = require('axios');
const { getOptions } = require('./bru');
const options = getOptions();
const verbose = options?.['verbose'];
if (verbose) {
debug.enable('node-vault');
}
const getExternalSecretsData = async ({ type, config, paths, debug }) => {
var vault = require('node-vault')({ apiVersion: 'v1', debug: debug ? nodeVaultDebug : null });
let secretsData;
if (type == 'vault') {
if (config?.type == 'vault-server') {
if (config?.vaultServerConfig?.auth?.method == 'token') {
vault.endpoint = config?.vaultServerConfig?.url;
if (config?.vaultServerConfig?.namespace?.length) {
vault.namespace = config?.vaultServerConfig?.namespace;
}
vault.token = config?.vaultServerConfig?.auth?.token;
secretsData = await fetchExternalSecrets({
vault,
paths
});
} else if (config?.vaultServerConfig?.auth?.method == 'app_role') {
vault.endpoint = config?.vaultServerConfig?.url;
if (config?.vaultServerConfig?.namespace?.length) {
vault.namespace = config?.vaultServerConfig?.namespace;
}
const accessToken = await getVaultServerApproleToken({
vault,
options: config?.vaultServerConfig?.auth?.appRole
});
vault.token = accessToken;
secretsData = await fetchExternalSecrets({
vault,
paths
});
}
} else if (config?.type == 'vault-cloud') {
if (
config?.vaultCloudConfig?.auth?.method == 'client_credentials' &&
config?.vaultCloudConfig?.auth?.clientCredentials &&
config?.vaultCloudConfig?.project
) {
const accessToken = await getVaultCloudToken({ options: config?.vaultCloudConfig?.auth?.clientCredentials });
secretsData = await Promise.all(
paths.map((path) =>
getVaultCloudSecrets({
options: { ...config?.vaultCloudConfig?.auth?.clientCredentials, ...config?.vaultCloudConfig?.project },
accessToken,
path
})
)
);
}
}
}
return secretsData;
};
const fetchExternalSecrets = async ({ paths, vault }) => {
return Promise.all(
paths.map(
(path) =>
new Promise(async (resolve, reject) => {
let data, error;
await vault
.read(path)
.then((res) => {
let data = res?.data?.data || res?.data || data;
resolve({ path, data });
})
.catch((e) => {
let error = e?.response?.body;
resolve({ path, error });
});
})
)
);
};
const getVaultCloudToken = async ({ options }) => {
const { tokenEndpoint, clientId, clientSecret } = options;
return await axios
.post(
tokenEndpoint,
{
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
audience: 'https://api.hashicorp.cloud'
},
{
headers: { check: 'again', 'Content-Type': 'application/x-www-form-urlencoded' }
}
)
.then((response) => {
return response?.data?.access_token;
})
.catch((error) => {
throw new Error(error?.response?.data?.error);
});
};
const getVaultCloudSecrets = async ({ options, accessToken, path }) => {
const { secretsEndpoint, organizationId, projectId } = options;
if (!organizationId || !projectId) {
return {
path,
data: {}
};
}
const appName = path.split('/')?.[0];
const secrets = await axios
.get(`${secretsEndpoint}/organizations/${organizationId}/projects/${projectId}/apps/${appName}/open`, {
headers: { check: 'again', Authorization: `Bearer ${accessToken}` }
})
.then((response) => {
return response.data.secrets;
})
.catch((error) => {
return null;
});
return {
path,
data: secrets?.reduce((acc, s) => {
return { ...acc, [s?.name]: s?.version?.value };
}, {})
};
};
const getVaultServerApproleToken = async ({ vault, options }) => {
const { role, roleId, secretId } = options;
return await vault
.approleLogin({ role, role_id: roleId, secret_id: secretId })
.then((res) => {
return res?.auth?.client_token;
})
.catch((e) => {
throw new Error(
JSON.stringify(e?.response?.body || e?.message || 'Error while getting token from approle login')
);
});
};
module.exports = {
getExternalSecretsData,
fetchExternalSecrets,
getVaultCloudToken,
getVaultCloudSecrets,
getVaultServerApproleToken
};