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] Intercept individual package installation via Fleet #161859

Merged
merged 3 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,57 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()

describe('Installation of prebuilt rules package via Fleet', () => {
beforeEach(() => {
cy.intercept('POST', '/api/fleet/epm/packages/_bulk*').as('installPackage');
cy.intercept('POST', '/api/fleet/epm/packages/_bulk*').as('installPackageBulk');
cy.intercept('POST', '/api/fleet/epm/packages/security_detection_engine/*').as(
'installPackage'
);
waitForRulesTableToBeLoaded();
});

it('should install package from Fleet in the background', () => {
/* Assert that the package in installed from Fleet by checking that
/* the installSource is "registry", as opposed to "bundle" */
cy.wait('@installPackage', {
cy.wait('@installPackageBulk', {
timeout: 60000,
}).then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);

const packages = response?.body.items.map(({ name, result }: BulkInstallPackageInfo) => ({
name,
installSource: result.installSource,
}));

expect(packages.length).to.have.greaterThan(0);
expect(packages).to.deep.include.members([
{ name: 'security_detection_engine', installSource: 'registry' },
]);
}).then(({ response: bulkResponse }) => {
cy.wrap(bulkResponse?.statusCode).should('eql', 200);

const packages = bulkResponse?.body.items.map(
({ name, result }: BulkInstallPackageInfo) => ({
name,
installSource: result.installSource,
})
);

const packagesBulkInstalled = packages.map(({ name }: { name: string }) => name);

// Under normal flow the package is installed via the Fleet bulk install API.
// However, for testing purposes the package can be installed via the Fleet individual install API,
// so we need to intercept and wait for that request as well.
if (!packagesBulkInstalled.includes('security_detection_engine')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's okay to leave the logic here for now, but for a more robust solution, we should consider introducing an API endpoint on the detection engine side. This endpoint would handle all the complexities of package installation logic internally. We currently have duplication of this logic on both the frontend and backend. That could be part of Serverless: #150587.

// Should happen only during testing when the `xpack.securitySolution.prebuiltRulesPackageVersion` flag is set
cy.wait('@installPackage').then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);
cy.wrap(response?.body)
.should('have.property', 'items')
.should('have.length.greaterThan', 0);
cy.wrap(response?.body)
.should('have.property', '_meta')
.should('have.property', 'install_source')
.should('eql', 'registry');
});
} else {
// Normal flow, install via the Fleet bulk install API
expect(packages.length).to.have.greaterThan(0);
expect(packages).to.deep.include.members([
{ name: 'security_detection_engine', installSource: 'registry' },
]);
}
});
});

it('should install rules from the Fleet package when user clicks on CTA', () => {
/* Retrieve how many rules were installed from the Fleet package */
cy.wait('@installPackage', {
timeout: 60000,
}).then(() => {
const getRulesAndAssertNumberInstalled = () => {
getRuleAssets().then((response) => {
const ruleIds = response.body.hits.hits.map(
(hit: { _source: { ['security-rule']: Rule } }) => hit._source['security-rule'].rule_id
Expand All @@ -87,6 +109,25 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
.should('be.visible')
.should('have.text', `${numberOfRulesToInstall} rules installed successfully.`);
});
};
/* Retrieve how many rules were installed from the Fleet package */
/* See comments in test above for more details */
cy.wait('@installPackageBulk', {
timeout: 60000,
}).then(({ response: bulkResponse }) => {
cy.wrap(bulkResponse?.statusCode).should('eql', 200);

const packagesBulkInstalled = bulkResponse?.body.items.map(
({ name }: { name: string }) => name
);

if (!packagesBulkInstalled.includes('security_detection_engine')) {
cy.wait('@installPackage').then(() => {
getRulesAndAssertNumberInstalled();
});
} else {
getRulesAndAssertNumberInstalled();
}
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export const getRuleAssets = (index: string | undefined = '.kibana_security_solu
/* during e2e tests, and allow for manual installation of mock rules instead. */
export const preventPrebuiltRulesPackageInstallation = () => {
cy.intercept('POST', '/api/fleet/epm/packages/_bulk*', {});
cy.intercept('POST', '/api/fleet/epm/packages/security_detection_engine/*', {});
};

/**
Expand Down