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 "Asset Inventory" Kibana Plugin #202291

Merged
merged 30 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
810cd88
Auto-generate asset-inventory plugin
albertoblaz Nov 29, 2024
dec7691
Fix tsconfig.json. Extend from correct base config
albertoblaz Nov 29, 2024
5cf1eec
Enhance package.json based on existing plugins
albertoblaz Nov 29, 2024
58926ec
Delete .scss files.
albertoblaz Nov 29, 2024
1d34c57
Convert kibana.json -> .jsonc. Mimic CSP config
albertoblaz Nov 29, 2024
9fe76f2
Mimic CSP plugin tsconfig.json
albertoblaz Nov 29, 2024
37a5e55
Update references to plugin after building Kibana
albertoblaz Nov 29, 2024
be8e5be
Render "Inventory" on main plugin page
albertoblaz Nov 29, 2024
6866096
Update README.md
albertoblaz Nov 29, 2024
5154d27
Add placeholder code for transforms initialization
albertoblaz Nov 29, 2024
5fe347c
Remove UI boilerplate generated by script
albertoblaz Nov 29, 2024
b20f8e1
Improve phrasing in plugin description
albertoblaz Nov 29, 2024
c084342
Add copyright section above all source files
albertoblaz Nov 29, 2024
211b7a9
Replace # symbol with private keyword
albertoblaz Nov 29, 2024
c6f043c
Remove comment in tsconfig.json
albertoblaz Nov 29, 2024
3f8e548
Remove unnecessary root files
albertoblaz Dec 2, 2024
f107440
Remove scripts from package.json
albertoblaz Dec 2, 2024
b93cc55
Delete translation
albertoblaz Dec 2, 2024
ed9dc25
Enhance plugin description
albertoblaz Dec 2, 2024
9a79958
Delete UI boilerplate generated by script
albertoblaz Dec 2, 2024
bc0b505
[CI] Auto-commit changed files from 'node scripts/build_plugin_list_d…
kibanamachine Dec 2, 2024
b575463
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Dec 2, 2024
d8b7c24
Update plugin description
albertoblaz Dec 2, 2024
b8aee1b
Update bundle limits
albertoblaz Dec 2, 2024
15dcb5a
Fix linting issues
albertoblaz Dec 2, 2024
4c1cf24
Update FTR tests
albertoblaz Dec 2, 2024
1d03d3f
Merge branch 'main' into asset-inventory-empty-plugin
opauloh Dec 3, 2024
2a4bb6a
removing navigation
opauloh Dec 3, 2024
2d45a8e
removing asset inventory from graph
opauloh Dec 3, 2024
08b0be5
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,7 @@ x-pack/plugins/ai_infra/llm_tasks @elastic/appex-ai-infra
x-pack/plugins/ai_infra/product_doc_base @elastic/appex-ai-infra
x-pack/plugins/aiops @elastic/ml-ui
x-pack/plugins/alerting @elastic/response-ops
x-pack/plugins/asset_inventory @elastic/kibana-cloud-security-posture
x-pack/plugins/banners @elastic/appex-sharedux
x-pack/plugins/canvas @elastic/kibana-presentation
x-pack/plugins/cases @elastic/response-ops
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ The plugin exposes the static DefaultEditorController class to consume.
|WARNING: Missing README.


|{kib-repo}blob/{branch}/x-pack/plugins/asset_inventory/README.md[assetInventory]
|Centralized asset inventory experience within the Elastic Security solution. A central place for users to view and manage all their assets from different environments.


|{kib-repo}blob/{branch}/x-pack/plugins/banners/README.md[banners]
|Allow to add a header banner that will be displayed on every page of the Kibana application

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
"@kbn/apm-utils": "link:packages/kbn-apm-utils",
"@kbn/app-link-test-plugin": "link:test/plugin_functional/plugins/app_link_test",
"@kbn/application-usage-test-plugin": "link:x-pack/test/usage_collection/plugins/application_usage_test",
"@kbn/asset-inventory-plugin": "link:x-pack/plugins/asset_inventory",
"@kbn/audit-log-plugin": "link:x-pack/test/security_api_integration/plugins/audit_log",
"@kbn/avc-banner": "link:packages/kbn-avc-banner",
"@kbn/banners-plugin": "link:x-pack/plugins/banners",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pageLoadAssetSize:
aiops: 17680
alerting: 106936
apm: 64385
assetInventory: 18478
banners: 17946
bfetch: 22837
canvas: 29355
Expand Down
2 changes: 2 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@
"@kbn/app-link-test-plugin/*": ["test/plugin_functional/plugins/app_link_test/*"],
"@kbn/application-usage-test-plugin": ["x-pack/test/usage_collection/plugins/application_usage_test"],
"@kbn/application-usage-test-plugin/*": ["x-pack/test/usage_collection/plugins/application_usage_test/*"],
"@kbn/asset-inventory-plugin": ["x-pack/plugins/asset_inventory"],
"@kbn/asset-inventory-plugin/*": ["x-pack/plugins/asset_inventory/*"],
"@kbn/audit-log-plugin": ["x-pack/test/security_api_integration/plugins/audit_log"],
"@kbn/audit-log-plugin/*": ["x-pack/test/security_api_integration/plugins/audit_log/*"],
"@kbn/avc-banner": ["packages/kbn-avc-banner"],
Expand Down
13 changes: 13 additions & 0 deletions x-pack/plugins/asset_inventory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Asset Inventory Kibana Plugin

Centralized asset inventory experience within the Elastic Security solution. A central place for users to view and manage all their assets from different environments.

---

## Development

See the [kibana contributing guide](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md) for instructions setting up your development environment.

## Testing

For general guidelines, read [Kibana Testing Guide](https://www.elastic.co/guide/en/kibana/current/development-tests.html) for more details
8 changes: 8 additions & 0 deletions x-pack/plugins/asset_inventory/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const PLUGIN_ID = 'assetInventory';
export const PLUGIN_NAME = 'assetInventory';
17 changes: 17 additions & 0 deletions x-pack/plugins/asset_inventory/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "plugin",
"id": "@kbn/asset-inventory-plugin",
"owner": ["@elastic/kibana-cloud-security-posture"],
"group": "security",
"visibility": "private",
"description": "Centralized asset inventory experience within the Elastic Security solution. A central place for users to view and manage all their assets from different environments",
"plugin": {
"id": "assetInventory",
"browser": true,
"server": true,
"configPath": ["xpack", "assetInventory"],
"requiredPlugins": [],
"requiredBundles": [],
"optionalPlugins": []
}
}
7 changes: 7 additions & 0 deletions x-pack/plugins/asset_inventory/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"author": "Elastic",
"name": "@kbn/asset-inventory-plugin",
"version": "1.0.0",
"private": true,
"license": "Elastic License 2.0"
}
24 changes: 24 additions & 0 deletions x-pack/plugins/asset_inventory/public/application.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import type { AppMountParameters, CoreStart } from '@kbn/core/public';
import type { AppPluginStartDependencies } from './types';
import { AssetInventoryApp } from './components/app';

export const renderApp = (
{ notifications, http }: CoreStart,
{}: AppPluginStartDependencies,
{ appBasePath, element }: AppMountParameters
) => {
ReactDOM.render(
<AssetInventoryApp basename={appBasePath} notifications={notifications} http={http} />,
element
);

return () => ReactDOM.unmountComponentAtNode(element);
};
38 changes: 38 additions & 0 deletions x-pack/plugins/asset_inventory/public/components/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
import { BrowserRouter as Router } from '@kbn/shared-ux-router';
import { EuiPageTemplate, EuiTitle } from '@elastic/eui';
import type { CoreStart } from '@kbn/core/public';

interface AssetInventoryAppDeps {
basename: string;
notifications: CoreStart['notifications'];
http: CoreStart['http'];
}

export const AssetInventoryApp = ({ basename }: AssetInventoryAppDeps) => {
return (
<Router basename={basename}>
<I18nProvider>
<>
<EuiPageTemplate restrictWidth="1000px">
Copy link
Contributor

@seanrathier seanrathier Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we restricting the width to 1000px?

🤔 Should we use break points here?
https://eui.elastic.co/#/theming/breakpoints/values

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was auto-generated by the script. I agree we should change it but the UI is not relevant at this point. We just wanted to have an empty plugin to start working upon it

<EuiPageTemplate.Header>
<EuiTitle size="l">
<h1>
<FormattedMessage id="assetInventory.helloWorldText" defaultMessage="Inventory" />
</h1>
</EuiTitle>
</EuiPageTemplate.Header>
<EuiPageTemplate.Section />
</EuiPageTemplate>
</>
</I18nProvider>
</Router>
);
};
14 changes: 14 additions & 0 deletions x-pack/plugins/asset_inventory/public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { AssetInventoryPlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export function plugin() {
return new AssetInventoryPlugin();
}
export type { AssetInventoryPluginSetup, AssetInventoryPluginStart } from './types';
35 changes: 35 additions & 0 deletions x-pack/plugins/asset_inventory/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
import type {
AssetInventoryPluginSetup,
AssetInventoryPluginStart,
AppPluginStartDependencies,
} from './types';

export class AssetInventoryPlugin
implements Plugin<AssetInventoryPluginSetup, AssetInventoryPluginStart>
{
public setup(core: CoreSetup): AssetInventoryPluginSetup {
return {};
}
public start(
coreStart: CoreStart,
depsStart: AppPluginStartDependencies
): AssetInventoryPluginStart {
return {
getAssetInventoryPage: async (params: AppMountParameters) => {
// Load application bundle
const { renderApp } = await import('./application');
// Render the application
return renderApp(coreStart, depsStart as AppPluginStartDependencies, params);
},
};
}

public stop() {}
}
15 changes: 15 additions & 0 deletions x-pack/plugins/asset_inventory/public/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AssetInventoryPluginSetup {}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AssetInventoryPluginStart {}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AppPluginStartDependencies {}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was copy-pasted from x-pack/plugins/cloud_security_posture/server/create_transforms/create_transforms.ts. Let me know if we should reuse it somehow instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it would be better to add this when you know you need it so it is not forgotten.

🤔 Asset Inventory likely needs transformers, however, are the changes for asset inventory minimal? Maybe we should consider creating a shared transformer package

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should consider creating a shared transformer package

I think that's a great idea, the transform methods can be adapted to be more general, and we can also leverage our team package where we see fit.

If you prefer that can be done on a follow-up PR, we can keep this file for now and create a follow-up Github issue to move to the shared package.

Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { transformError } from '@kbn/securitysolution-es-utils';
import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import { errors } from '@elastic/elasticsearch';

// TODO: Move transforms to integration package
export const initializeTransforms = async (
esClient: ElasticsearchClient,
logger: Logger
): Promise<void> => {
// Deletes old assets from previous versions as part of upgrade process
await deletePreviousTransformsVersions(esClient, logger);
// TODO initialize transforms here
// await initializeTransform(esClient, <TRANSFORM_HERE>, logger);
Comment on lines +19 to +20
Copy link
Contributor Author

@albertoblaz albertoblaz Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: Placeholder for transforms initialization. Please let me know if this is enough or if I should uncomment the line and add some specific transforms

};

export const initializeTransform = async (
esClient: ElasticsearchClient,
transform: TransformPutTransformRequest,
logger: Logger
) => {
const success = await createTransformIfNotExists(esClient, transform, logger);

if (success) {
await startTransformIfNotStarted(esClient, transform.transform_id, logger);
}
};

/**
* Checks if a transform exists, And if not creates it
*
* @param transform - the transform to create. If a transform with the same transform_id already exists, nothing is created or updated.
*
* @return true if the transform exits or created, false otherwise.
*/
export const createTransformIfNotExists = async (
esClient: ElasticsearchClient,
transform: TransformPutTransformRequest,
logger: Logger
) => {
try {
await esClient.transform.getTransform({
transform_id: transform.transform_id,
});
return true;
} catch (existErr) {
const existError = transformError(existErr);
if (existError.statusCode === 404) {
try {
await esClient.transform.putTransform(transform);
return true;
} catch (createErr) {
const createError = transformError(createErr);
logger.error(
`Failed to create transform ${transform.transform_id}: ${createError.message}`
);
}
} else {
logger.error(
`Failed to check if transform ${transform.transform_id} exists: ${existError.message}`
);
}
}
return false;
};

export const startTransformIfNotStarted = async (
esClient: ElasticsearchClient,
transformId: string,
logger: Logger
) => {
try {
const transformStats = await esClient.transform.getTransformStats({
transform_id: transformId,
});

if (transformStats.count <= 0) {
logger.error(`Failed starting transform ${transformId}: couldn't find transform`);
return;
}

const fetchedTransformStats = transformStats.transforms[0];

// trying to restart the transform in case it comes to a full stop or failure
if (fetchedTransformStats.state === 'stopped' || fetchedTransformStats.state === 'failed') {
try {
return await esClient.transform.startTransform({ transform_id: transformId });
} catch (startErr) {
const startError = transformError(startErr);
logger.error(
`Failed to start transform ${transformId}. Transform State: Transform State: ${fetchedTransformStats.state}. Error: ${startError.message}`
);
}
}

if (fetchedTransformStats.state === 'stopping' || fetchedTransformStats.state === 'aborting') {
logger.error(
`Not starting transform ${transformId} since it's state is: ${fetchedTransformStats.state}`
);
}
} catch (statsErr) {
const statsError = transformError(statsErr);
logger.error(`Failed to check if transform ${transformId} is started: ${statsError.message}`);
}
};

const deletePreviousTransformsVersions = async (esClient: ElasticsearchClient, logger: Logger) => {
// TODO Concat all deprecated transforms versions
const deprecatedTransforms: string[] = [];

for (const transform of deprecatedTransforms) {
const response = await deleteTransformSafe(esClient, logger, transform);
if (response) return;
}
};

const deleteTransformSafe = async (
esClient: ElasticsearchClient,
logger: Logger,
name: string
): Promise<boolean> => {
try {
await esClient.transform.deleteTransform({ transform_id: name, force: true });
logger.info(`Deleted transform successfully [Name: ${name}]`);
return true;
} catch (e) {
if (e instanceof errors.ResponseError && e.statusCode === 404) {
logger.trace(`Transform not exists [Name: ${name}]`);
return false;
} else {
logger.error(`Failed to delete transform [Name: ${name}]`);
logger.error(e);
return false;
}
}
};
17 changes: 17 additions & 0 deletions x-pack/plugins/asset_inventory/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { PluginInitializerContext } from '@kbn/core/server';

// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.

export async function plugin(initializerContext: PluginInitializerContext) {
const { AssetInventoryPlugin } = await import('./plugin');
return new AssetInventoryPlugin(initializerContext);
}

export type { AssetInventoryPluginSetup, AssetInventoryPluginStart } from './types';
Loading
Loading