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

[Security Solution] add new GET endpoint metadata list api #118968

Merged
merged 1 commit into from
Nov 18, 2021

Conversation

joeypoon
Copy link
Member

Summary

Creates a new GET endpoint metadata list API. It returns the same data as the existing POST endpoint metadata list API but in a more standardized format. POST API removal and frontend change to use new API will be addressed in separate PRs.

Checklist

For maintainers

@joeypoon joeypoon added v8.0.0 Team:Defend Workflows “EDR Workflows” sub-team of Security Solution auto-backport Deprecated - use backport:version if exact versions are needed v8.1.0 labels Nov 17, 2021
@joeypoon joeypoon requested a review from a team November 17, 2021 23:24
@@ -161,6 +167,83 @@ export const getMetadataListRequestHandler = function (
};
};

export function getMetadataListRequestHandlerV2(
Copy link
Member Author

@joeypoon joeypoon Nov 17, 2021

Choose a reason for hiding this comment

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

will remove the V2 naming across the board when we get rid of the POST API.

Copy link
Member Author

@joeypoon joeypoon Nov 17, 2021

Choose a reason for hiding this comment

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

most of the code is purposely duplicated so that the POST API and associated code can be easily removed in later PR.

endpointAppContextService.start({ ...startContract, packageService: mockPackageService });
mockAgentService = startContract.agentService!;
mockAgentPolicyService = startContract.agentPolicyService!;
describe('POST list endpoints route', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

most of this is actually untouched, I just moved/nested some stuff. also duplicated POST API tests then modified them for the new GET API.

expect(body.request_page_size).to.eql(10);
expect(body.request_page_index).to.eql(0);
});
describe('test metadata apis', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

same as other tests, mostly just nesting/moving tests around followed by duplicating POST API tests and modifying for the new GET API.

@joeypoon joeypoon force-pushed the feature/new-metadata-list-api branch from f396033 to 4096bca Compare November 18, 2021 00:46
@joeypoon joeypoon marked this pull request as ready for review November 18, 2021 00:46
@joeypoon joeypoon requested a review from a team as a code owner November 18, 2021 00:46
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-onboarding-and-lifecycle-mgt (Team:Onboarding and Lifecycle Mgt)

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

  • 💔 Build #7536 failed f3960338804f04ac0f0d7996fc576d5d13df6d1d

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

}

// If no unified Index present, then perform a search using the legacy approach
if (!doesUnitedIndexExist || didUnitedIndexError) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: move this and the next one to another method,. e.g. getMetadataListRequestHandlerLegacy()

@joeypoon joeypoon changed the title [Security Solution] add new GET endpoint metdata list api [Security Solution] add new GET endpoint metadata list api Nov 18, 2021
@joeypoon joeypoon merged commit 293bde0 into elastic:main Nov 18, 2021
@joeypoon joeypoon deleted the feature/new-metadata-list-api branch November 18, 2021 20:11
@kibanamachine
Copy link
Contributor

💚 Backport successful

Status Branch Result
8.0

This backport PR will be merged automatically after passing CI.

Copy link
Contributor

@paul-tavares paul-tavares left a comment

Choose a reason for hiding this comment

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

@joeypoon
Just taking a look at this - thank you for taking this on. I left several comments. Let me know if you have any questions.

/**
* Returned by the server via GET /api/endpoint/metadata
*/
export interface MetadataListResponse extends BaseListResponse {
Copy link
Contributor

Choose a reason for hiding this comment

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

You could hve also made BaseListResonse a generic, like:

export interface BaseListResponse<D = unknown> {
  data: D[];
  page: number;
  pageSize: number;
  total: number;
  sort?: string;
  sortOrder?: 'asc' | 'desc';
}

Which would make it easier to defined more domain specific types:

export type MetadataListResponse = BaseListResponse<HostInfo>

pageSize: number;
total: number;
sort?: string;
sortOrder?: 'asc' | 'desc';
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ Q. Do we support sort/sort order on the metadata API currently? (or maybe this new API does?)

Copy link
Member Author

Choose a reason for hiding this comment

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

no to both :(. this was just preemptive.

Copy link
Contributor

Choose a reason for hiding this comment

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

cool. best to remove it for now (don't forget to adjust the schema

pageSize: pagingProperties.pageSize,
filters: request.body?.filters || {},
hostStatuses: request.body?.filters.host_status || [],
Copy link
Contributor

Choose a reason for hiding this comment

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

oh crap - was this a bug I introduced during the refactor?

Copy link
Member Author

Choose a reason for hiding this comment

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

nah, I'm just flatting things here for the new route so had to change some of the methods.

total,
request_page_size: pageSize,
request_page_index: pagingProperties.pageIndex * pagingProperties.pageSize,
Copy link
Contributor

Choose a reason for hiding this comment

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

is this correct?

request_page_index is suppose to be the page index that the user requested, correct? This does not look right to me.

Copy link
Member Author

@joeypoon joeypoon Nov 19, 2021

Choose a reason for hiding this comment

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

the naming here is a bit confusing, this was actually the index of the document since it was being pulled directly from the esQuery.from. I changed everything to be index of the page so this is the last place where we're using index of doc (for endpoint list apis at least), which we can then delete together with the route.

Copy link
Contributor

Choose a reason for hiding this comment

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

😱 🙀 - So happy we are deleting this API.

> {
return async (context, request, response) => {
const endpointMetadataService = endpointAppContext.service.getEndpointMetadataService();
if (!endpointMetadataService) {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this needed?
I would move it to the service.getEndpointMetadataService() instead if you see that it is actually needed

Copy link
Member Author

Choose a reason for hiding this comment

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

this is needed here but I hesitate to move the exception up since isn't there a possibility that this might not be a required service for a consumer?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think so. I think that EndpointAppContext is always initialized "fully" so this service will (?should?) be available always

Copy link
Member Author

Choose a reason for hiding this comment

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

misunderstood you here. will just remove the null check.

body = {
data,
total,
page: request.query.page,
Copy link
Contributor

Choose a reason for hiding this comment

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

you could just use the return value from getHostMetadataList() method right (I think it has the same signature as far as the data structure.

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed to this because I removed page and pageSize from getHostMetadataList since it just returns those directly from the received params anyways.

endpointAppContext: EndpointAppContext,
logger: Logger,
endpointPolicies: PackagePolicy[]
endpointPolicies: PackagePolicy[],
queryOptions: TypeOf<typeof GetMetadataListRequestSchemaV2.query>
Copy link
Contributor

Choose a reason for hiding this comment

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

We probably should create a type for this in security_solution/common/ because the UI will need it as well.

@@ -60,27 +65,54 @@ export const GetMetadataListRequestSchema = {
),
};

export const GetMetadataListRequestSchemaV2 = {
query: schema.object({
Copy link
Contributor

Choose a reason for hiding this comment

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

can we make all of this optional? A consumer of the list api should not be required to define all of this. It should be optional and schema assign defaults.

Also - I suggest you move it to security_solution/common/endpoint/schema, so that the Types that we create from it can be re-used on the UI side. You should also add some tests against the schema (case we ever change to io-ts we have tests in place to ensure it still works as we expected it)

service: new EndpointAppContextService(),
config: () => Promise.resolve(createMockConfig()),
experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental),
const query = await kibanaRequestToMetadataListESQuery({
Copy link
Contributor

Choose a reason for hiding this comment

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

If you make the query optional, please a test for it.

@@ -36,7 +36,7 @@ export function buildStatusesKuery(statusesToFilter: string[]): string | undefin
export async function findAgentIdsByStatus(
agentService: AgentService,
esClient: ElasticsearchClient,
statuses: string[],
statuses: string[] = [],
Copy link
Contributor

Choose a reason for hiding this comment

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

why make it optional? the method's purpose is to get agents by statuses, so the consumer of this method must define them on input.

(I see below there is not much harm, as it exits if it finds an empty array, but still I think we should not be invoking this method without statuses)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed release_note:enhancement Team:Defend Workflows “EDR Workflows” sub-team of Security Solution v8.0.0 v8.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants