Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create the Analysis plugin and implement the new menu app registration method #484

Closed
Tracked by #412
asteriscos opened this issue Jan 14, 2025 · 5 comments · Fixed by wazuh/wazuh-dashboard-plugins#7242
Assignees
Labels
level/task Task issue type/enhancement New feature or request

Comments

@asteriscos
Copy link
Member

asteriscos commented Jan 14, 2025

Description

We have to create the plugin "Analysis" which will include all the applications related to data analysis dashboards. The main goal is to register the Analysis plugin and its applications to create the scaffolding which will be used later on to create the dashboards.

Menu structure

  • Analysis
    • Endpoint security
      • Configuration assessment
      • Malware detection
      • FIM
    • Threat intelligence
      • Threat hunting
      • Vulnerability detection
      • Mitre ATT&CK
    • Security operations
      • Regulatory compliance (unify)
      • IT Hygiene
      • Incident response
    • Cloud Security
      • Docker
      • AWS
      • Google Cloud
      • Github
      • Office365

Functional requirements

  • The applications must be registered in the legacy navigation menu as well as the new navigation menu.

Additional information

The new navigation menu is enabled with the advanced setting useNewHomePage. The OpenSearch native plugin dev_tools already has the new navigation menu implementation.
This can be used as an example:
src/plugins/dev_tools/public/plugin.ts

@guidomodarelli
Copy link

guidomodarelli commented Jan 21, 2025

The dynamically controlled system for hiding/showing subapps

Let me explain how the system for hiding/showing subapplications of an application (for example, "Endpoint Security") works.

Key Concepts

  1. AppUpdater: In the ApplicationService, the appUpdater$ are instances of Subject<AppUpdater> that are associated with a specific appId. This allows updates to be emitted, such as changing the visibility state of navigation links for an application.
  2. NavLinkStatus: Each subapplication within a main application has a navLinkStatus, which can be in one of the following states:
    • Visible: The subapplication's navigation link will be shown.
    • Hidden: The subapplication's navigation link will be hidden.
  3. Application Lifecycle (Mount/Unmount): The lifecycle of an application or subapplication involves two phases: mount (when it is initialized and displayed) and unmount (when it is hidden and cleaned up). The code manages these events through methods like modifyMount and modifySubAppMount.

Subapplication Show/Hide Process Flow

  1. Subapplication Registration:
    • When a subapplication is registered, the modifySubAppMount method is invoked to modify its mounting behavior.
    • In this method, the subapplication's lifecycle is defined, which includes functions like beforeMount and cleanup (before unmounting).
    • These functions modify the navigation link state (visible/hidden) through the appUpdater$.
  2. Visibility Modification:
    • In beforeMount, getAppUpdater is used to obtain the appUpdater$ corresponding to the subapplication. Then, the visibility change to visible.
    • In cleanup, which runs before unmounting the subapplication, the visibility change to hidden.
  3. Navigation Link State Change:
    • setNavLinkVisible and setNavLinkHidden are methods that return objects with the navLinkStatus property set to visible or hidden, respectively. These objects are what is emitted through the appUpdater$ to modify the visibility state of the subapplication's navigation link.

@guidomodarelli
Copy link

guidomodarelli commented Jan 21, 2025

What does getNavGroupEnabled() do?

The core.chrome.navGroup.getNavGroupEnabled() method verifies if navigation groups are enabled in the system configuration.


The NavGroupEnabled acts as a mechanism to verify if navigation groups (or Nav Groups) are enabled in the OpenSearch Dashboards user interface.


What is a Nav Group?

A Nav Group (navigation group) is a set of links or apps grouped under a common category in the OpenSearch Dashboards sidebar. For example:

  • "Endpoint Security" can contain subapps like "Configuration Assessment" or "Malware Detection".

Why is NavGroupEnabled relevant?

  1. Conditional for certain actions: In the code, getNavGroupEnabled() acts as a condition before executing group actions, such as:

    • Changing the current group:

      if (core.chrome.navGroup.getNavGroupEnabled()) {
        core.chrome.navGroup.setCurrentNavGroup(navGroupId);
      }
  2. When groups are disabled, the plugin avoids unnecessary operations such as:

    • Subscribing to group changes (getCurrentNavGroup).
    • Updating subapps that won't be visible.

getNavGroupEnabled() ensures that navigation group functionalities are executed only when enabled, providing compatibility with both the legacy menu system and newer configurations.

@guidomodarelli
Copy link

showInAllNavGroup

    core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [
      {
        id: this.ENDPOINT_SECURITY_ID,
        title: this.translationMessages.ENDPOINT_SECURITY,
        order: 0,
        category: this.CATEGORY,
      },
      {
        id: this.THREAT_INTELLIGENCE_ID,
        title: this.translationMessages.THREAT_INTELLIGENCE,
        order: 1,
        category: this.CATEGORY,
      },
      {
        id: this.SECURITY_OPERATIONS_ID,
        title: this.translationMessages.SECURITY_OPERATIONS,
        order: 2,
        category: this.CATEGORY,
      },
      {
        id: this.CLOUD_SECURITY_ID,
        title: this.translationMessages.CLOUD_SECURITY,
        order: 3,
        category: this.CATEGORY,
      },
    ]);

Image

Explanation

  1. core.chrome.navGroup.addNavLinksToGroup:
    • This method adds navigation links to a specific navigation group.
    • DEFAULT_NAV_GROUPS.all indicates that the links are being added to a general navigation group containing all categories.
  2. Links array ([ ... ]):
    • Each object in the array represents a link that will appear in the side navigation menu, as shown in the image.
    • Each link has the following properties:
      • id: Unique link identifier.
      • title: Text displayed in the interface.
      • order: Determines the link display order. Lower values appear first.
      • category: Groups links under a specific category, such as "Analysis" (visible in the image).
  3. Interface result:
    • The added links appear under the "Analysis" header in the left sidebar, with titles including:
      • Endpoint Security
      • Threat Intelligence
      • Security Operations
      • Cloud Security
    • The links are ordered according to their order property.
    core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [
      {
        id: this.ENDPOINT_SECURITY_ID,
        title: this.translationMessages.ENDPOINT_SECURITY,
        order: 0,
        category: this.CATEGORY,
+       showInAllNavGroup: true,
      },
      {
        id: this.THREAT_INTELLIGENCE_ID,
        title: this.translationMessages.THREAT_INTELLIGENCE,
        order: 1,
        category: this.CATEGORY,
+       showInAllNavGroup: true,
      },
      {
        id: this.SECURITY_OPERATIONS_ID,
        title: this.translationMessages.SECURITY_OPERATIONS,
        order: 2,
        category: this.CATEGORY,
+       showInAllNavGroup: true,
      },
      {
        id: this.CLOUD_SECURITY_ID,
        title: this.translationMessages.CLOUD_SECURITY,
        order: 3,
        category: this.CATEGORY,
+       showInAllNavGroup: true,
      },
    ]);

Image

In this new code, an additional property (showInAllNavGroup) is added to each navigation group link. Below is an explanation of what's happening and how it affects the interface:

Original vs. Modified Code

In the original code, each link had properties like id, title, order, and category. The modified code introduces a new property:

+ showInAllNavGroup: true,

This enables the visibility of these links in the navigation group "Analytics".


Effect of the showInAllNavGroup Property

  • Purpose: The showInAllNavGroup: true property indicates that the associated links will display in the "Analytics" navigation group (DEFAULT_NAV_GROUPS.all), even if they belong to another category or section.
  • Visual Result:
    • Before: Links only appeared under a specific section, such as Analysis.
    • Now: The same links appear in multiple locations within the navigation menu.
      • For example, links such as Endpoint Security, Threat Intelligence, Security Operations, and Cloud Security now appear under both Analytics and Analysis, as shown in the provided image.

@guidomodarelli
Copy link

guidomodarelli commented Jan 22, 2025

Global SearchBar

Peek.2025-01-22.11-54.mp4

A SearchCommand is registered using the core.chrome.globalSearch.registerSearchCommand function. This function allows adding custom searches to the OpenSearch Dashboards navigation system.


1. Search Command Registration

if (this.coreSetup.chrome.navGroup.getNavGroupEnabled()) {
  this.coreSetup.chrome.globalSearch.registerSearchCommand({
    id,
    type: 'PAGES',
    run: async (query: string, done?: () => void) =>
      searchPages(query, applicationIds, getCore(), done),
  });
}

Registration Components:

  • id: Unique identifier for the command, in this case 'wz-analysis'.
  • type: Defines the type of element to search for. Here it's 'PAGES', indicating that the search will be performed on pages within applications.
  • run: Function that executes when performing a search. It receives:
    • query: The search term entered by the user.
    • done: (Optional) Function that is called when execution is complete.

2. Logic of the run Function

The run property executes the searchPages function, which performs the search:

searchPages(query, applicationIds, getCore(), done)

Parameters:

  1. The term entered by the user for the search (query).
  2. An array of registered application IDs (applicationIds) to search in their navigation links (navLinks).
  3. The getCore() instance to interact with the OpenSearch Dashboards API.
  4. The optional done function that executes when the search is complete.

3. Search in Detail: searchPages

The searchPages function performs these operations:

  1. Gets the navigation groups through:

    core.chrome.navGroup.getCurrentNavGroup$().pipe(first()).toPromise()
  2. Filters relevant links using:

    links.filter(link => {
        const titleMatch = match(title, query);
        return !link.disabled && titleMatch;
    });
  3. Transforms the filtered results into React components (<GlobalSearchPageItem />) for visualization.

@wazuhci wazuhci moved this from Backlog to In progress in XDR+SIEM/Release 5.0.0 Feb 5, 2025
@guidomodarelli
Copy link

guidomodarelli commented Feb 7, 2025

Below is a simple explanation of each relevant method in the ApplicationService class, and how they’re used in the sample plugin.


Methods

modifyAppGroupMount(app: App)

It prepares and registers the mounting process for an application group, ensuring that navigation links become visible and a startup event is triggered when the group mounts.


modifySubAppMount(app: App)

It adjusts the lifecycle of sub-applications so that their navigation links are properly shown when the app is mounted and hidden when unmounted.


onAppStartup(core: CoreStart)

This method is typically called during the plugin’s start phase to ensure that, when an application or group starts, the UI reflects the correct navigation state and the user is redirected accordingly.


registerSearchCommand({ id, navGroups }: SetupParams)

This command integrates global search functionality so that users can search within the pages provided by the registered app groups.


setup({ id, navGroups }: SetupParams)

This method is invoked by the plugin’s setup routine (as seen in the sample AnalysisPlugin), initializing the navigation groups, their associated applications, and the search command.


How It’s Used in a Plugin

The sample AnalysisPlugin demonstrates how ApplicationService integrates into the plugin lifecycle:

  • In the setup method:

    • The plugin defines an array of navigation groups (e.g., EndpointSecurityNavGroup, ThreatIntelligenceNavGroup, etc.).
    • It calls plugins.wazuhCore.applicationService.setup({ ... }) to register all navigation groups and their sub-applications with the core system.
  • In the onAppStartup method:

    • The plugin calls plugins.wazuhCore.applicationService.onAppStartup(core) to subscribe to startup events. This ensures that when an app group is started, the UI will update the active navigation group and automatically navigate to the first available app in that group.

The ApplicationService class centralizes the registration and lifecycle management of navigation groups and their associated applications. It provides mechanisms to:

  • Modify Mount/Unmount Behavior:
    By injecting beforeMount and cleanup operations into the app’s lifecycle, it ensures the UI is updated correctly when apps are mounted or unmounted.

  • Register Navigation Groups and Apps:
    It organizes both app groups and sub-applications, ensuring they are properly integrated into the Chrome navigation and application registry.

  • Handle Navigation Startup:
    It listens for startup events and automatically navigates the user to the first available application in the active navigation group.

  • Integrate Global Search:
    It registers a search command that allows users to search within the pages of the registered app groups.

@wazuhci wazuhci moved this from In progress to Pending review in XDR+SIEM/Release 5.0.0 Feb 11, 2025
@wazuhci wazuhci moved this from Pending review to Pending final review in XDR+SIEM/Release 5.0.0 Feb 17, 2025
@wazuhci wazuhci moved this from Pending final review to Done in XDR+SIEM/Release 5.0.0 Feb 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
level/task Task issue type/enhancement New feature or request
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants