-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Cloud Posture] Create concrete csp rules post create package (#130120)
- Loading branch information
Showing
8 changed files
with
240 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* 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 { loggingSystemMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; | ||
import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; | ||
import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; | ||
import { CIS_KUBERNETES_PACKAGE_NAME } from '../../common/constants'; | ||
import { onPackagePolicyPostCreateCallback } from './fleet_integration'; | ||
|
||
describe('create CSP rules with post package create callback', () => { | ||
let logger: ReturnType<typeof loggingSystemMock.createLogger>; | ||
let mockSoClient: jest.Mocked<SavedObjectsClientContract>; | ||
const ruleAttributes = { | ||
id: '41308bcdaaf665761478bb6f0d745a5c', | ||
name: 'Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)', | ||
tags: ['CIS', 'Kubernetes', 'CIS 1.1.1', 'Master Node Configuration Files'], | ||
description: | ||
'Ensure that the API server pod specification file has permissions of `644` or more restrictive.\n', | ||
rationale: | ||
'The API server pod specification file controls various parameters that set the behavior of the API server. You should restrict its file permissions to maintain the integrity of the file. The file should be writable by only the administrators on the system.\n', | ||
default_value: 'By default, the `kube-apiserver.yaml` file has permissions of `640`.\n', | ||
impact: 'None\n', | ||
remediation: | ||
'Run the below command (based on the file location on your system) on the\nmaster node.\nFor example,\n```\nchmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n```\n', | ||
benchmark: { | ||
name: 'CIS Kubernetes V1.20', | ||
version: 'v1.0.0', | ||
}, | ||
enabled: true, | ||
rego_rule_id: 'cis_1_2_2', | ||
}; | ||
|
||
beforeEach(() => { | ||
logger = loggingSystemMock.createLogger(); | ||
mockSoClient = savedObjectsClientMock.create(); | ||
}); | ||
it('should create stateful rules based on rule template', async () => { | ||
const mockPackagePolicy = createPackagePolicyMock(); | ||
mockPackagePolicy.package!.name = CIS_KUBERNETES_PACKAGE_NAME; | ||
mockSoClient.find.mockResolvedValueOnce({ | ||
saved_objects: [ | ||
{ | ||
type: 'csp-rule-template', | ||
id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', | ||
attributes: { ...ruleAttributes }, | ||
}, | ||
], | ||
pit_id: undefined, | ||
} as unknown as SavedObjectsFindResponse); | ||
|
||
await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); | ||
|
||
expect(mockSoClient.bulkCreate.mock.calls[0][0]).toMatchObject([ | ||
{ | ||
type: 'csp_rule', | ||
attributes: { | ||
...ruleAttributes, | ||
package_policy_id: mockPackagePolicy.id, | ||
policy_id: mockPackagePolicy.policy_id, | ||
}, | ||
}, | ||
]); | ||
}); | ||
|
||
it('should not create rules when the package policy is not csp package', async () => { | ||
const mockPackagePolicy = createPackagePolicyMock(); | ||
mockPackagePolicy.package!.name = 'not_csp_package'; | ||
|
||
await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); | ||
expect(mockSoClient.find).toHaveBeenCalledTimes(0); | ||
expect(mockSoClient.bulkCreate).toHaveBeenCalledTimes(0); | ||
}); | ||
}); |
105 changes: 105 additions & 0 deletions
105
x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* 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 { | ||
SavedObjectsBulkCreateObject, | ||
SavedObjectsFindResponse, | ||
SavedObjectsFindResult, | ||
ISavedObjectsRepository, | ||
SavedObjectsClientContract, | ||
Logger, | ||
} from '@kbn/core/server'; | ||
import { PackagePolicy, DeletePackagePoliciesResponse } from '@kbn/fleet-plugin/common'; | ||
import { | ||
cloudSecurityPostureRuleTemplateSavedObjectType, | ||
CloudSecurityPostureRuleTemplateSchema, | ||
} from '../../common/schemas/csp_rule_template'; | ||
import { CIS_KUBERNETES_PACKAGE_NAME } from '../../common/constants'; | ||
import { CspRuleSchema, cspRuleAssetSavedObjectType } from '../../common/schemas/csp_rule'; | ||
|
||
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends ReadonlyArray< | ||
infer ElementType | ||
> | ||
? ElementType | ||
: never; | ||
|
||
const isCspPackagePolicy = <T extends { package?: { name: string } }>( | ||
packagePolicy: T | ||
): boolean => { | ||
return packagePolicy.package?.name === CIS_KUBERNETES_PACKAGE_NAME; | ||
}; | ||
|
||
/** | ||
* Callback to handle creation of PackagePolicies in Fleet | ||
*/ | ||
export const onPackagePolicyPostCreateCallback = async ( | ||
logger: Logger, | ||
packagePolicy: PackagePolicy, | ||
savedObjectsClient: SavedObjectsClientContract | ||
): Promise<void> => { | ||
// We only care about Cloud Security Posture package policies | ||
if (!isCspPackagePolicy(packagePolicy)) { | ||
return; | ||
} | ||
// Create csp-rules from the generic asset | ||
const existingRuleTemplates: SavedObjectsFindResponse<CloudSecurityPostureRuleTemplateSchema> = | ||
await savedObjectsClient.find({ type: cloudSecurityPostureRuleTemplateSavedObjectType }); | ||
|
||
if (existingRuleTemplates.total === 0) { | ||
return; | ||
} | ||
|
||
const cspRules = generateRulesFromTemplates( | ||
packagePolicy.id, | ||
packagePolicy.policy_id, | ||
existingRuleTemplates.saved_objects | ||
); | ||
|
||
try { | ||
await savedObjectsClient.bulkCreate(cspRules); | ||
logger.info(`Generated CSP rules for package ${packagePolicy.policy_id}`); | ||
} catch (e) { | ||
logger.error('failed to generate rules out of template'); | ||
logger.error(e); | ||
} | ||
}; | ||
|
||
/** | ||
* Callback to handle deletion of PackagePolicies in Fleet | ||
*/ | ||
export const onPackagePolicyDeleteCallback = async ( | ||
logger: Logger, | ||
deletedPackagePolicy: ArrayElement<DeletePackagePoliciesResponse>, | ||
soClient: ISavedObjectsRepository | ||
): Promise<void> => { | ||
try { | ||
const { saved_objects: cspRules }: SavedObjectsFindResponse<CspRuleSchema> = | ||
await soClient.find({ | ||
type: cspRuleAssetSavedObjectType, | ||
filter: `csp_rule.attributes.package_policy_id: ${deletedPackagePolicy.id} AND csp_rule.attributes.policy_id: ${deletedPackagePolicy.policy_id}`, | ||
}); | ||
await Promise.all( | ||
cspRules.map((rule) => soClient.delete(cspRuleAssetSavedObjectType, rule.id)) | ||
); | ||
} catch (e) { | ||
logger.error(`Failed to delete CSP rules after delete package ${deletedPackagePolicy.id}`); | ||
logger.error(e); | ||
} | ||
}; | ||
|
||
const generateRulesFromTemplates = ( | ||
packagePolicyId: string, | ||
policyId: string, | ||
cspRuleTemplates: Array<SavedObjectsFindResult<CloudSecurityPostureRuleTemplateSchema>> | ||
): Array<SavedObjectsBulkCreateObject<CspRuleSchema>> => | ||
cspRuleTemplates.map((template) => ({ | ||
type: cspRuleAssetSavedObjectType, | ||
attributes: { | ||
...template.attributes, | ||
package_policy_id: packagePolicyId, | ||
policy_id: policyId, | ||
}, | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 0 additions & 53 deletions
53
x-pack/plugins/cloud_security_posture/server/saved_objects/cis_1_4_1/rules.ts
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 0 additions & 24 deletions
24
x-pack/plugins/cloud_security_posture/server/saved_objects/initialize_rules.ts
This file was deleted.
Oops, something went wrong.