add support for multiple spaces
This commit is contained in:
parent
7988853b57
commit
351c4e4ef4
10 changed files with 498 additions and 92 deletions
|
@ -12,32 +12,76 @@ const FILE_NAME = 'elastic_api_service.js';
|
|||
/**
|
||||
* Get Elasticsearch configuration with credentials
|
||||
*
|
||||
* @param {string} spaceId - Optional space ID to get configuration for
|
||||
* @returns {Object} Configuration object with URL and credentials
|
||||
*/
|
||||
const getElasticConfig = () => {
|
||||
return {
|
||||
url: ELASTICSEARCH_CONFIG.apiEndpoint.split('/api/')[0] || process.env.ELASTIC_URL,
|
||||
username: ELASTICSEARCH_CONFIG.credentials.split(':')[0] || process.env.ELASTIC_USERNAME,
|
||||
password: ELASTICSEARCH_CONFIG.credentials.split(':')[1] || process.env.ELASTIC_PASSWORD,
|
||||
const getElasticConfig = (spaceId = null) => {
|
||||
// Default config
|
||||
const config = {
|
||||
protocol: ELASTICSEARCH_CONFIG.protocol || "http",
|
||||
hosts: ELASTICSEARCH_CONFIG.hosts || ["localhost:9200"],
|
||||
username: ELASTICSEARCH_CONFIG.username || process.env.ELASTIC_USERNAME,
|
||||
password: ELASTICSEARCH_CONFIG.password || process.env.ELASTIC_PASSWORD,
|
||||
apiEndpoint: ELASTICSEARCH_CONFIG.apiEndpoint
|
||||
};
|
||||
|
||||
// If space ID provided, find the specific space
|
||||
if (spaceId) {
|
||||
const space = ELASTICSEARCH_CONFIG.spaces.find(s => s.id === spaceId);
|
||||
if (space) {
|
||||
// Apply space-specific configuration overrides if they exist
|
||||
return {
|
||||
...config,
|
||||
space: space
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a rule to Elasticsearch SIEM
|
||||
* Get all configured Elasticsearch spaces
|
||||
*
|
||||
* @returns {Array} List of all configured spaces
|
||||
*/
|
||||
const getAllSpaces = () => {
|
||||
return ELASTICSEARCH_CONFIG.spaces || [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a rule to Elasticsearch SIEM in a specific space
|
||||
*
|
||||
* @param {Object} rulePayload - The rule payload to send to Elasticsearch
|
||||
* @param {string} spaceId - The ID of the space to send the rule to
|
||||
* @returns {Promise<Object>} - Object containing success status and response/error information
|
||||
*/
|
||||
const sendRuleToSiem = async (rulePayload) => {
|
||||
logger.info(`${FILE_NAME}: Sending rule to Elasticsearch SIEM`);
|
||||
const sendRuleToSiem = async (rulePayload, spaceId = 'default') => {
|
||||
logger.info(`${FILE_NAME}: Sending rule to Elasticsearch SIEM in space: ${spaceId}`);
|
||||
|
||||
try {
|
||||
const elasticConfig = getElasticConfig();
|
||||
const apiUrl = elasticConfig.apiEndpoint;
|
||||
const elasticConfig = getElasticConfig(spaceId);
|
||||
const baseApiUrl = elasticConfig.apiEndpoint;
|
||||
|
||||
// Construct space-specific URL if needed
|
||||
let apiUrl = baseApiUrl;
|
||||
if (spaceId && spaceId !== 'default') {
|
||||
// Insert space ID into URL: http://localhost:5601/api/detection_engine/rules
|
||||
// becomes http://localhost:5601/s/space-id/api/detection_engine/rules
|
||||
const urlParts = baseApiUrl.split('/api/');
|
||||
apiUrl = `${urlParts[0]}/s/${spaceId}/api/${urlParts[1]}`;
|
||||
}
|
||||
|
||||
logger.debug(`${FILE_NAME}: Using Elasticsearch API URL: ${apiUrl}`);
|
||||
|
||||
// Add index pattern to rule if provided by space config
|
||||
if (elasticConfig.space && elasticConfig.space.indexPattern && !rulePayload.index) {
|
||||
rulePayload.index = Array.isArray(elasticConfig.space.indexPattern)
|
||||
? elasticConfig.space.indexPattern
|
||||
: [elasticConfig.space.indexPattern];
|
||||
logger.debug(`${FILE_NAME}: Adding index pattern to rule: ${JSON.stringify(rulePayload.index)}`);
|
||||
}
|
||||
|
||||
// Send the request to Elasticsearch
|
||||
const response = await axios({
|
||||
method: 'post',
|
||||
|
@ -55,18 +99,19 @@ const sendRuleToSiem = async (rulePayload) => {
|
|||
|
||||
// Process the response
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
logger.info(`${FILE_NAME}: Successfully sent rule to SIEM`);
|
||||
logger.info(`${FILE_NAME}: Successfully sent rule to SIEM in space: ${spaceId}`);
|
||||
return {
|
||||
success: true,
|
||||
status: response.status,
|
||||
data: response.data
|
||||
data: response.data,
|
||||
space: elasticConfig.space
|
||||
};
|
||||
} else {
|
||||
logger.error(`${FILE_NAME}: Error sending rule to SIEM. Status: ${response.status}, Response: ${JSON.stringify(response.data)}`);
|
||||
return {
|
||||
success: false,
|
||||
status: response.status,
|
||||
message: `Failed to add rule to SIEM. Status: ${response.status}`,
|
||||
message: `Failed to add rule to SIEM in space ${spaceId}. Status: ${response.status}`,
|
||||
data: response.data
|
||||
};
|
||||
}
|
||||
|
@ -92,6 +137,7 @@ const sendRuleToSiem = async (rulePayload) => {
|
|||
* @param {Object} options - Request options
|
||||
* @param {string} options.method - HTTP method (get, post, put, delete)
|
||||
* @param {string} options.endpoint - API endpoint (appended to base URL)
|
||||
* @param {string} options.spaceId - Optional space ID
|
||||
* @param {Object} options.data - Request payload
|
||||
* @param {Object} options.params - URL parameters
|
||||
* @param {Object} options.headers - Additional headers
|
||||
|
@ -99,14 +145,24 @@ const sendRuleToSiem = async (rulePayload) => {
|
|||
*/
|
||||
const makeElasticRequest = async (options) => {
|
||||
try {
|
||||
const elasticConfig = getElasticConfig();
|
||||
const baseUrl = elasticConfig.url;
|
||||
const elasticConfig = getElasticConfig(options.spaceId);
|
||||
const baseUrl = elasticConfig.protocol + '://' + elasticConfig.hosts[0];
|
||||
|
||||
// Build the full URL - use provided endpoint or default API endpoint
|
||||
const url = options.endpoint ?
|
||||
let url = options.endpoint ?
|
||||
`${baseUrl}${options.endpoint.startsWith('/') ? '' : '/'}${options.endpoint}` :
|
||||
elasticConfig.apiEndpoint;
|
||||
|
||||
// Handle space in URL if needed
|
||||
if (options.spaceId && options.spaceId !== 'default') {
|
||||
// Insert space ID into URL: http://localhost:5601/api/detection_engine/rules
|
||||
// becomes http://localhost:5601/s/space-id/api/detection_engine/rules
|
||||
if (url.includes('/api/')) {
|
||||
const urlParts = url.split('/api/');
|
||||
url = `${urlParts[0]}/s/${options.spaceId}/api/${urlParts[1]}`;
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(`${FILE_NAME}: Making ${options.method} request to: ${url}`);
|
||||
|
||||
// Set up default headers
|
||||
|
@ -133,7 +189,8 @@ const makeElasticRequest = async (options) => {
|
|||
return {
|
||||
success: response.status >= 200 && response.status < 300,
|
||||
status: response.status,
|
||||
data: response.data
|
||||
data: response.data,
|
||||
space: elasticConfig.space
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`${FILE_NAME}: Error in Elasticsearch API request: ${error.message}`);
|
||||
|
@ -150,5 +207,6 @@ const makeElasticRequest = async (options) => {
|
|||
module.exports = {
|
||||
sendRuleToSiem,
|
||||
makeElasticRequest,
|
||||
getElasticConfig
|
||||
getElasticConfig,
|
||||
getAllSpaces
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue