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

[Cloud Security] Added filter support to graph API #199048

Merged
merged 12 commits into from
Nov 11, 2024

Conversation

kfirpeled
Copy link
Contributor

@kfirpeled kfirpeled commented Nov 5, 2024

Summary

Enhances the graph API to support filtering by bool query.

Graph API is an internal API that hasn't been released yet to ESS, and is not available yet on serverless (behind a feature-flag in kibana.config) due to the above I don't consider it a breaking change.

Previous API request body:

query: schema.object({
    actorIds: schema.arrayOf(schema.string()),
    eventIds: schema.arrayOf(schema.string()),
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),

New API request body:

  nodesLimit: schema.maybe(schema.number()), // Maximum number of nodes in the graph (currently the graph doesn't handle very well graph with over 100 nodes)
  showUnknownTarget: schema.maybe(schema.boolean()), // Whether or not to return events that miss target.entity.id
  query: schema.object({
    eventIds: schema.arrayOf(schema.string()), // Event ids that triggered the alert, would be marked in red
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),
    esQuery: schema.maybe( // elasticsearch's dsl bool query
      schema.object({
        bool: schema.object({
          filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must_not: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
        }),
      })

New field to the graph API response (pseudo):

messages?: ApiMessageCode[]

enum ApiMessageCode {
  ReachedNodesLimit = 'REACHED_NODES_LIMIT',
}

How to test

Toggle feature flag in kibana.dev.yml

xpack.securitySolution.enableExperimental: ['graphVisualizationInFlyoutEnabled']

To test through the UI you can use the mocked data

node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit \ 
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601

node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/security_alerts \
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601
  1. Go to the alerts page
  2. Change the query time range to show alerts from the 13th of October 2024 (IMPORTANT)
  3. Open the alerts flyout
  4. Scroll to see the graph visualization : D

To test only the API you can use the mocked data

node scripts/es_archiver load x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \ 
--es-url http://elastic:changeme@localhost:9200 \
--kibana-url http://elastic:changeme@localhost:5601

And through dev tools:

POST kbn:/internal/cloud_security_posture/graph?apiVersion=1
{
  "query": {
    "eventIds": [],
    "start": "now-1y/y",
    "end": "now/d",
    "esQuery": {
      "bool": {
        "filter": [
        {
          "match_phrase": {
            "actor.entity.id": "[email protected]"
          }
        }
        ]
      }
    }
  }
}

Related PRs

Checklist

Graph API is an internal API that hasn't been released yet to ESS, and is not available yet on serverless (behind a feature-flag in kibana.config) due to the above I don't consider it as a breaking change
@kfirpeled kfirpeled added backport:prev-minor Backport to (8.x) the previous minor version (i.e. one version back from main) release_note:skip Skip the PR/issue when compiling release notes labels Nov 5, 2024
@kfirpeled kfirpeled marked this pull request as ready for review November 5, 2024 19:48
@kfirpeled kfirpeled requested review from a team as code owners November 5, 2024 19:48
Copy link
Contributor

@opauloh opauloh left a comment

Choose a reason for hiding this comment

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

The code looks good, however, when testing the UI I'm seeing a blank canvas instead of the chart.

Could it be because the actor is missing in the esQuery on the payload?

image

Here's the empty response, also should we think about handling empty response from the chart to not render it for example?

image

import type { FtrProviderContext } from '../../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const roleScopedSupertest = getService('roleScopedSupertest');
let supertestViewer: Pick<Agent, 'post'>;

const postGraph = (agent: Pick<Agent, 'post'>, body: any) => {
const postGraph = (agent: Pick<Agent, 'post'>, body: GraphRequest) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

💯

}

const parseRecords = (logger: Logger, records: GraphEdge[]): GraphContext => {
const ctx: ParseContext = { nodesMap: {}, edgeLabelsNodes: {}, edgesMap: {}, labelEdges: {} };
const parseRecords = (logger: Logger, records: GraphEdge[], nodesLimit?: number): GraphContext => {
Copy link
Contributor

Choose a reason for hiding this comment

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

should the parseRecords also ensure values that we expect to be array are parsed?

the docs suggests that string might be returned from VALUES() when there's a single value, that could cause error when accessing the array.includes method below, i.e ips.includes(actorId)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point,
I'll add tests for these edge cases

Comment on lines +19 to +26
schema.object({
bool: schema.object({
filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
must_not: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
}),
})
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm surprised there wasn't a schema available for esQuery on @kbn/es-query

Copy link
Contributor Author

Choose a reason for hiding this comment

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

likewise, that was the best example I found so far so I used it

@kfirpeled
Copy link
Contributor Author

kfirpeled commented Nov 8, 2024

The code looks good, however, when testing the UI I'm seeing a blank canvas instead of the chart.

Could it be because the actor is missing in the esQuery on the payload?

image

Here's the empty response, also should we think about handling empty response from the chart to not render it for example?

image

Thanks for the review @opauloh

This is due to the fact I changed the range of time to be relative to the alerts time, however the mocked data is not aligned.

Maybe I can check for the original_event time. Ill fix it on the other PR

Copy link
Contributor

@PhilippeOberti PhilippeOberti left a comment

Choose a reason for hiding this comment

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

left a couple of minor comments, but overall the Threat Hunting Investigations code LGTM

const http = useHttp();
const QUERY_KEY = ['useFetchGraphData', eventIds, start, end, esQuery];
Copy link
Contributor

Choose a reason for hiding this comment

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

should we use useMemo here to avoid creating a new array everytime?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @PhilippeOberti, thanks for bringing this up! I've been thinking about the use of useMemo for the react-query key in this context.

From what I've gathered, React Query creates a hash of query keys internally, in a way that even when creating a new array every time, as long as the contents are the same, React Query will recognize it as the same query and avoid unnecessary refetches.

So I thought that using useMemo would not provide a benefit while adding a bit of complexity to the code. But I'm curious, have you noticed any performance improvements or other benefits from memoizing the query key with useMemo in your experience? I'd like to hear your thoughts on this!

Copy link
Contributor

Choose a reason for hiding this comment

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

that is a really good point! I think it has become a reflex now when seeing variables like these that I always think about useMemo but in this case I agree it is not necessary or even useful at all!

Copy link
Contributor

Choose a reason for hiding this comment

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

I know it's not part of this PR, but it would be nice to have a couple of unit tests for this hook. Maybe they can be added as part of a future PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@PhilippeOberti added :)

@kfirpeled kfirpeled enabled auto-merge (squash) November 11, 2024 17:59
@kfirpeled kfirpeled merged commit 160e626 into elastic:main Nov 11, 2024
45 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/11785186607

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 13.4MB 13.4MB +356.0B

History

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Nov 11, 2024
## Summary

Enhances the graph API to support filtering by bool query.

Graph API is an internal API that hasn't been released yet to ESS, and
is not available yet on serverless (behind a feature-flag in
kibana.config) due to the above I don't consider it a breaking change.

Previous API request body:

```js
query: schema.object({
    actorIds: schema.arrayOf(schema.string()),
    eventIds: schema.arrayOf(schema.string()),
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),
```

New API request body:

```js
  nodesLimit: schema.maybe(schema.number()), // Maximum number of nodes in the graph (currently the graph doesn't handle very well graph with over 100 nodes)
  showUnknownTarget: schema.maybe(schema.boolean()), // Whether or not to return events that miss target.entity.id
  query: schema.object({
    eventIds: schema.arrayOf(schema.string()), // Event ids that triggered the alert, would be marked in red
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),
    esQuery: schema.maybe( // elasticsearch's dsl bool query
      schema.object({
        bool: schema.object({
          filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must_not: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
        }),
      })
```

New field to the graph API response (pseudo):

```js
messages?: ApiMessageCode[]

enum ApiMessageCode {
  ReachedNodesLimit = 'REACHED_NODES_LIMIT',
}
```

### How to test

Toggle feature flag in kibana.dev.yml

```yaml
xpack.securitySolution.enableExperimental: ['graphVisualizationInFlyoutEnabled']
```

To test through the UI you can use the mocked data

```bash
node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit \
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601

node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/security_alerts \
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601
```

1. Go to the alerts page
2. Change the query time range to show alerts from the 13th of October
2024 (**IMPORTANT**)
3. Open the alerts flyout
5. Scroll to see the graph visualization : D

To test **only** the API you can use the mocked data

```bash
node scripts/es_archiver load x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \
--es-url http://elastic:changeme@localhost:9200 \
--kibana-url http://elastic:changeme@localhost:5601
```

And through dev tools:

```
POST kbn:/internal/cloud_security_posture/graph?apiVersion=1
{
  "query": {
    "eventIds": [],
    "start": "now-1y/y",
    "end": "now/d",
    "esQuery": {
      "bool": {
        "filter": [
        {
          "match_phrase": {
            "actor.entity.id": "[email protected]"
          }
        }
        ]
      }
    }
  }
}
```

### Related PRs

- elastic#196034
- elastic#195307

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <[email protected]>
(cherry picked from commit 160e626)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Nov 12, 2024
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

tkajtoch pushed a commit to tkajtoch/kibana that referenced this pull request Nov 12, 2024
## Summary

Enhances the graph API to support filtering by bool query.

Graph API is an internal API that hasn't been released yet to ESS, and
is not available yet on serverless (behind a feature-flag in
kibana.config) due to the above I don't consider it a breaking change.

Previous API request body: 

```js
query: schema.object({
    actorIds: schema.arrayOf(schema.string()),
    eventIds: schema.arrayOf(schema.string()),
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),
```

New API request body:

```js
  nodesLimit: schema.maybe(schema.number()), // Maximum number of nodes in the graph (currently the graph doesn't handle very well graph with over 100 nodes)
  showUnknownTarget: schema.maybe(schema.boolean()), // Whether or not to return events that miss target.entity.id
  query: schema.object({
    eventIds: schema.arrayOf(schema.string()), // Event ids that triggered the alert, would be marked in red
    // TODO: use zod for range validation instead of config schema
    start: schema.oneOf([schema.number(), schema.string()]),
    end: schema.oneOf([schema.number(), schema.string()]),
    esQuery: schema.maybe( // elasticsearch's dsl bool query
      schema.object({
        bool: schema.object({
          filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
          must_not: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
        }),
      })
```

New field to the graph API response (pseudo):

```js
messages?: ApiMessageCode[]

enum ApiMessageCode {
  ReachedNodesLimit = 'REACHED_NODES_LIMIT',
}
```

### How to test 

Toggle feature flag in kibana.dev.yml

```yaml
xpack.securitySolution.enableExperimental: ['graphVisualizationInFlyoutEnabled']
```

To test through the UI you can use the mocked data

```bash
node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit \ 
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601

node scripts/es_archiver load x-pack/test/cloud_security_posture_functional/es_archives/security_alerts \
  --es-url http://elastic:changeme@localhost:9200 \
  --kibana-url http://elastic:changeme@localhost:5601
```

1. Go to the alerts page
2. Change the query time range to show alerts from the 13th of October
2024 (**IMPORTANT**)
3. Open the alerts flyout
5. Scroll to see the graph visualization : D


To test **only** the API you can use the mocked data

```bash
node scripts/es_archiver load x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \ 
--es-url http://elastic:changeme@localhost:9200 \
--kibana-url http://elastic:changeme@localhost:5601
```

And through dev tools:

```
POST kbn:/internal/cloud_security_posture/graph?apiVersion=1
{
  "query": {
    "eventIds": [],
    "start": "now-1y/y",
    "end": "now/d",
    "esQuery": {
      "bool": {
        "filter": [
        {
          "match_phrase": {
            "actor.entity.id": "[email protected]"
          }
        }
        ]
      }
    }
  }
}
```

### Related PRs

- elastic#196034
- elastic#195307

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <[email protected]>
kibanamachine added a commit that referenced this pull request Nov 13, 2024
…199702)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Cloud Security] Added filter support to graph API
(#199048)](#199048)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Kfir
Peled","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-11-11T19:47:23Z","message":"[Cloud
Security] Added filter support to graph API (#199048)\n\n##
Summary\r\n\r\nEnhances the graph API to support filtering by bool
query.\r\n\r\nGraph API is an internal API that hasn't been released yet
to ESS, and\r\nis not available yet on serverless (behind a feature-flag
in\r\nkibana.config) due to the above I don't consider it a breaking
change.\r\n\r\nPrevious API request body: \r\n\r\n```js\r\nquery:
schema.object({\r\n actorIds: schema.arrayOf(schema.string()),\r\n
eventIds: schema.arrayOf(schema.string()),\r\n // TODO: use zod for
range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n```\r\n\r\nNew API
request body:\r\n\r\n```js\r\n nodesLimit:
schema.maybe(schema.number()), // Maximum number of nodes in the graph
(currently the graph doesn't handle very well graph with over 100
nodes)\r\n showUnknownTarget: schema.maybe(schema.boolean()), // Whether
or not to return events that miss target.entity.id\r\n query:
schema.object({\r\n eventIds: schema.arrayOf(schema.string()), // Event
ids that triggered the alert, would be marked in red\r\n // TODO: use
zod for range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n esQuery:
schema.maybe( // elasticsearch's dsl bool query\r\n schema.object({\r\n
bool: schema.object({\r\n filter:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n should:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must_not: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n }),\r\n })\r\n```\r\n\r\nNew field to the
graph API response (pseudo):\r\n\r\n```js\r\nmessages?:
ApiMessageCode[]\r\n\r\nenum ApiMessageCode {\r\n ReachedNodesLimit =
'REACHED_NODES_LIMIT',\r\n}\r\n```\r\n\r\n### How to test \r\n\r\nToggle
feature flag in
kibana.dev.yml\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:
['graphVisualizationInFlyoutEnabled']\r\n```\r\n\r\nTo test through the
UI you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit
\\ \r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/security_alerts
\\\r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n```\r\n\r\n1. Go
to the alerts page\r\n2. Change the query time range to show alerts from
the 13th of October\r\n2024 (**IMPORTANT**)\r\n3. Open the alerts
flyout\r\n5. Scroll to see the graph visualization : D\r\n\r\n\r\nTo
test **only** the API you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \\
\r\n--es-url http://elastic:changeme@localhost:9200 \\\r\n--kibana-url
http://elastic:changeme@localhost:5601\r\n```\r\n\r\nAnd through dev
tools:\r\n\r\n```\r\nPOST
kbn:/internal/cloud_security_posture/graph?apiVersion=1\r\n{\r\n
\"query\": {\r\n \"eventIds\": [],\r\n \"start\": \"now-1y/y\",\r\n
\"end\": \"now/d\",\r\n \"esQuery\": {\r\n \"bool\": {\r\n \"filter\":
[\r\n {\r\n \"match_phrase\": {\r\n \"actor.entity.id\":
\"[email protected]\"\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n
}\r\n}\r\n```\r\n\r\n### Related PRs\r\n\r\n-
https://github.com/elastic/kibana/pull/196034\r\n-
https://github.com/elastic/kibana/pull/195307\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"160e626ab58bda7cfe442dbb276744f878eaaf90","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor"],"title":"[Cloud
Security] Added filter support to graph
API","number":199048,"url":"https://github.com/elastic/kibana/pull/199048","mergeCommit":{"message":"[Cloud
Security] Added filter support to graph API (#199048)\n\n##
Summary\r\n\r\nEnhances the graph API to support filtering by bool
query.\r\n\r\nGraph API is an internal API that hasn't been released yet
to ESS, and\r\nis not available yet on serverless (behind a feature-flag
in\r\nkibana.config) due to the above I don't consider it a breaking
change.\r\n\r\nPrevious API request body: \r\n\r\n```js\r\nquery:
schema.object({\r\n actorIds: schema.arrayOf(schema.string()),\r\n
eventIds: schema.arrayOf(schema.string()),\r\n // TODO: use zod for
range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n```\r\n\r\nNew API
request body:\r\n\r\n```js\r\n nodesLimit:
schema.maybe(schema.number()), // Maximum number of nodes in the graph
(currently the graph doesn't handle very well graph with over 100
nodes)\r\n showUnknownTarget: schema.maybe(schema.boolean()), // Whether
or not to return events that miss target.entity.id\r\n query:
schema.object({\r\n eventIds: schema.arrayOf(schema.string()), // Event
ids that triggered the alert, would be marked in red\r\n // TODO: use
zod for range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n esQuery:
schema.maybe( // elasticsearch's dsl bool query\r\n schema.object({\r\n
bool: schema.object({\r\n filter:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n should:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must_not: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n }),\r\n })\r\n```\r\n\r\nNew field to the
graph API response (pseudo):\r\n\r\n```js\r\nmessages?:
ApiMessageCode[]\r\n\r\nenum ApiMessageCode {\r\n ReachedNodesLimit =
'REACHED_NODES_LIMIT',\r\n}\r\n```\r\n\r\n### How to test \r\n\r\nToggle
feature flag in
kibana.dev.yml\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:
['graphVisualizationInFlyoutEnabled']\r\n```\r\n\r\nTo test through the
UI you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit
\\ \r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/security_alerts
\\\r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n```\r\n\r\n1. Go
to the alerts page\r\n2. Change the query time range to show alerts from
the 13th of October\r\n2024 (**IMPORTANT**)\r\n3. Open the alerts
flyout\r\n5. Scroll to see the graph visualization : D\r\n\r\n\r\nTo
test **only** the API you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \\
\r\n--es-url http://elastic:changeme@localhost:9200 \\\r\n--kibana-url
http://elastic:changeme@localhost:5601\r\n```\r\n\r\nAnd through dev
tools:\r\n\r\n```\r\nPOST
kbn:/internal/cloud_security_posture/graph?apiVersion=1\r\n{\r\n
\"query\": {\r\n \"eventIds\": [],\r\n \"start\": \"now-1y/y\",\r\n
\"end\": \"now/d\",\r\n \"esQuery\": {\r\n \"bool\": {\r\n \"filter\":
[\r\n {\r\n \"match_phrase\": {\r\n \"actor.entity.id\":
\"[email protected]\"\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n
}\r\n}\r\n```\r\n\r\n### Related PRs\r\n\r\n-
https://github.com/elastic/kibana/pull/196034\r\n-
https://github.com/elastic/kibana/pull/195307\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"160e626ab58bda7cfe442dbb276744f878eaaf90"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/199048","number":199048,"mergeCommit":{"message":"[Cloud
Security] Added filter support to graph API (#199048)\n\n##
Summary\r\n\r\nEnhances the graph API to support filtering by bool
query.\r\n\r\nGraph API is an internal API that hasn't been released yet
to ESS, and\r\nis not available yet on serverless (behind a feature-flag
in\r\nkibana.config) due to the above I don't consider it a breaking
change.\r\n\r\nPrevious API request body: \r\n\r\n```js\r\nquery:
schema.object({\r\n actorIds: schema.arrayOf(schema.string()),\r\n
eventIds: schema.arrayOf(schema.string()),\r\n // TODO: use zod for
range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n```\r\n\r\nNew API
request body:\r\n\r\n```js\r\n nodesLimit:
schema.maybe(schema.number()), // Maximum number of nodes in the graph
(currently the graph doesn't handle very well graph with over 100
nodes)\r\n showUnknownTarget: schema.maybe(schema.boolean()), // Whether
or not to return events that miss target.entity.id\r\n query:
schema.object({\r\n eventIds: schema.arrayOf(schema.string()), // Event
ids that triggered the alert, would be marked in red\r\n // TODO: use
zod for range validation instead of config schema\r\n start:
schema.oneOf([schema.number(), schema.string()]),\r\n end:
schema.oneOf([schema.number(), schema.string()]),\r\n esQuery:
schema.maybe( // elasticsearch's dsl bool query\r\n schema.object({\r\n
bool: schema.object({\r\n filter:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n should:
schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow'
}))),\r\n must_not: schema.maybe(schema.arrayOf(schema.object({}, {
unknowns: 'allow' }))),\r\n }),\r\n })\r\n```\r\n\r\nNew field to the
graph API response (pseudo):\r\n\r\n```js\r\nmessages?:
ApiMessageCode[]\r\n\r\nenum ApiMessageCode {\r\n ReachedNodesLimit =
'REACHED_NODES_LIMIT',\r\n}\r\n```\r\n\r\n### How to test \r\n\r\nToggle
feature flag in
kibana.dev.yml\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:
['graphVisualizationInFlyoutEnabled']\r\n```\r\n\r\nTo test through the
UI you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/logs_gcp_audit
\\ \r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_functional/es_archives/security_alerts
\\\r\n --es-url http://elastic:changeme@localhost:9200 \\\r\n
--kibana-url http://elastic:changeme@localhost:5601\r\n```\r\n\r\n1. Go
to the alerts page\r\n2. Change the query time range to show alerts from
the 13th of October\r\n2024 (**IMPORTANT**)\r\n3. Open the alerts
flyout\r\n5. Scroll to see the graph visualization : D\r\n\r\n\r\nTo
test **only** the API you can use the mocked data\r\n\r\n```bash\r\nnode
scripts/es_archiver load
x-pack/test/cloud_security_posture_api/es_archives/logs_gcp_audit \\
\r\n--es-url http://elastic:changeme@localhost:9200 \\\r\n--kibana-url
http://elastic:changeme@localhost:5601\r\n```\r\n\r\nAnd through dev
tools:\r\n\r\n```\r\nPOST
kbn:/internal/cloud_security_posture/graph?apiVersion=1\r\n{\r\n
\"query\": {\r\n \"eventIds\": [],\r\n \"start\": \"now-1y/y\",\r\n
\"end\": \"now/d\",\r\n \"esQuery\": {\r\n \"bool\": {\r\n \"filter\":
[\r\n {\r\n \"match_phrase\": {\r\n \"actor.entity.id\":
\"[email protected]\"\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n
}\r\n}\r\n```\r\n\r\n### Related PRs\r\n\r\n-
https://github.com/elastic/kibana/pull/196034\r\n-
https://github.com/elastic/kibana/pull/195307\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"160e626ab58bda7cfe442dbb276744f878eaaf90"}}]}]
BACKPORT-->

Co-authored-by: Kfir Peled <[email protected]>
@kibanamachine kibanamachine added v8.17.0 and removed backport missing Added to PRs automatically when the are determined to be missing a backport. labels Nov 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:prev-minor Backport to (8.x) the previous minor version (i.e. one version back from main) release_note:skip Skip the PR/issue when compiling release notes v8.17.0 v9.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants