Skip to content

Commit

Permalink
[Security Solution][Detections] Implement endpoint for fetching insta…
Browse files Browse the repository at this point in the history
…lled Fleet integrations (#132667)

**Addresses partially:** elastic/security-team#2856, elastic/security-team#3624 (internal tickets)

## Summary

Adds a new detections endpoint that returns installed Fleet integrations. It is to be used on the Rule Management and Rule Details pages (see #131475 for context and screenshots). This endpoint is `internal` - no need to document it.

```
GET /internal/detection_engine/fleet/integrations/installed
```

```json
{
  "installed_integrations": [
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "billing",
      "integration_title": "AWS Billing",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "cloudtrail",
      "integration_title": "AWS CloudTrail",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "cloudwatch",
      "integration_title": "AWS CloudWatch",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "dynamodb",
      "integration_title": "Amazon DynamoDB",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "ebs",
      "integration_title": "Amazon EBS",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "ec2",
      "integration_title": "Amazon EC2",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "elb",
      "integration_title": "AWS ELB",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "lambda",
      "integration_title": "AWS Lambda",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "natgateway",
      "integration_title": "Amazon NAT Gateway",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "firewall",
      "integration_title": "AWS Network Firewall",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "rds",
      "integration_title": "Amazon RDS",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "s3",
      "integration_title": "Amazon S3",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "s3_storage_lens",
      "integration_title": "Amazon S3 Storage Lens",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "sns",
      "integration_title": "Amazon SNS",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "sqs",
      "integration_title": "Amazon SQS",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "transitgateway",
      "integration_title": "AWS Transit Gateway",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "usage",
      "integration_title": "AWS Usage",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "vpcflow",
      "integration_title": "Amazon VPC",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "vpn",
      "integration_title": "Amazon VPN",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "waf",
      "integration_title": "AWS WAF",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "route53",
      "integration_title": "AWS Route 53",
      "is_enabled": false
    },
    {
      "package_name": "aws",
      "package_title": "AWS",
      "package_version": "1.16.1",
      "integration_name": "cloudfront",
      "integration_title": "Amazon CloudFront",
      "is_enabled": true
    },
    {
      "package_name": "system",
      "package_title": "System",
      "package_version": "1.13.0",
      "is_enabled": true
    }
  ]
}
```

## Next steps

- Test with users with different privileges (non-superusers). Fleet privileges: none, read, all. Security Solution privileges. SO privileges.
- Add filtering by `package_name` and `is_enabled` (will be done in a separate PR).
- Add test coverage (will be done in a separate PR).


### Checklist

Delete any items that are not applicable to this PR.

- [ ] [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
  • Loading branch information
banderror authored May 23, 2022
1 parent 93de448 commit dcf83f9
Show file tree
Hide file tree
Showing 10 changed files with 508 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

export * from './installed_integrations';
export * from './rule_monitoring';
export * from './rule_params';
export * from './schemas';
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/*
* 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.
*/

// -------------------------------------------------------------------------------------------------
// Installed package

/**
* Basic information about an installed Fleet package.
*/
export interface InstalledPackageBasicInfo {
/**
* Name is a unique package id within a given cluster.
* There can't be 2 or more different packages with the same name.
* @example 'aws'
*/
package_name: string;

/**
* Title is a user-friendly name of the package that we show in the UI.
* @example 'AWS'
*/
package_title: string;

/**
* Version of the package. Semver-compatible.
* @example '1.2.3'
*/
package_version: string;
}

/**
* Information about an installed Fleet package including its integrations.
*
* @example
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integrations: [
* {
* integration_name: 'billing',
* integration_title: 'AWS Billing',
* is_enabled: false
* },
* {
* integration_name: 'cloudtrail',
* integration_title: 'AWS CloudTrail',
* is_enabled: false
* },
* {
* integration_name: 'cloudwatch',
* integration_title: 'AWS CloudWatch',
* is_enabled: false
* },
* {
* integration_name: 'cloudfront',
* integration_title: 'Amazon CloudFront',
* is_enabled: true
* }
* ]
* }
*/
export interface InstalledPackage extends InstalledPackageBasicInfo {
integrations: InstalledIntegrationBasicInfo[];
}

// -------------------------------------------------------------------------------------------------
// Installed integration

/**
* Basic information about an installed Fleet integration.
* An integration belongs to a package. A package can contain one or many integrations.
*/
export interface InstalledIntegrationBasicInfo {
/**
* Name identifies an integration within its package.
* @example 'cloudtrail'
*/
integration_name: string;

/**
* Title is a user-friendly name of the integration that we show in the UI.
* @example 'AWS CloudTrail'
*/
integration_title: string;

/**
* Whether this integration is enabled or not in at least one package policy in Fleet.
*/
is_enabled: boolean;
}

/**
* Information about an installed Fleet integration including info about its package.
*
* @example
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integration_name: 'cloudtrail',
* integration_title: 'AWS CloudTrail',
* is_enabled: false
* }
*
* @example
* {
* package_name: 'system',
* package_title: 'System',
* package_version: '1.13.0',
* is_enabled: true
* }
*/
export interface InstalledIntegration extends InstalledPackageBasicInfo {
/**
* Name identifies an integration within its package.
* Undefined when package name === integration name. This indicates that it's the only integration
* within this package.
* @example 'cloudtrail'
* @example undefined
*/
integration_name?: string;

/**
* Title is a user-friendly name of the integration that we show in the UI.
* Undefined when package name === integration name. This indicates that it's the only integration
* within this package.
* @example 'AWS CloudTrail'
* @example undefined
*/
integration_title?: string;

/**
* Whether this integration is enabled or not in at least one package policy in Fleet.
*/
is_enabled: boolean;
}

// -------------------------------------------------------------------------------------------------
// Arrays of installed packages and integrations

/**
* An array of installed packages with their integrations.
* This is a hierarchical way of representing installed integrations.
*
* @example
* [
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integrations: [
* {
* integration_name: 'billing',
* integration_title: 'AWS Billing',
* is_enabled: false
* },
* {
* integration_name: 'cloudtrail',
* integration_title: 'AWS CloudTrail',
* is_enabled: false
* },
* {
* integration_name: 'cloudwatch',
* integration_title: 'AWS CloudWatch',
* is_enabled: false
* },
* {
* integration_name: 'cloudfront',
* integration_title: 'Amazon CloudFront',
* is_enabled: true
* }
* ]
* },
* {
* package_name: 'system',
* package_title: 'System',
* package_version: '1.13.0',
* integrations: [
* {
* integration_name: 'system',
* integration_title: 'System logs and metrics',
* is_enabled: true
* }
* ]
* }
* ]
*/
export type InstalledPackageArray = InstalledPackage[];

/**
* An array of installed integrations with info about their packages.
* This is a flattened way of representing installed integrations.
*
* @example
* [
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integration_name: 'billing',
* integration_title: 'AWS Billing',
* is_enabled: false
* },
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integration_name: 'cloudtrail',
* integration_title: 'AWS CloudTrail',
* is_enabled: false
* },
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integration_name: 'cloudwatch',
* integration_title: 'AWS CloudWatch',
* is_enabled: false
* },
* {
* package_name: 'aws',
* package_title: 'AWS',
* package_version: '1.16.1',
* integration_name: 'cloudfront',
* integration_title: 'Amazon CloudFront',
* is_enabled: true
* },
* {
* package_name: 'system',
* package_title: 'System',
* package_version: '1.13.0',
* is_enabled: true
* }
* ]
*/
export type InstalledIntegrationArray = InstalledIntegration[];
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 { InstalledIntegrationArray } from '../common';

export interface GetInstalledIntegrationsResponse {
installed_integrations: InstalledIntegrationArray;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type { MockedKeys } from '@kbn/utility-types/jest';
import type { AwaitedProperties } from '@kbn/utility-types';
import type { KibanaRequest } from '@kbn/core/server';
import { coreMock } from '@kbn/core/server/mocks';

import { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server';
Expand All @@ -31,6 +32,7 @@ import type {
SecuritySolutionApiRequestHandlerContext,
SecuritySolutionRequestHandlerContext,
} from '../../../../types';

import { getEndpointAuthzInitialStateMock } from '../../../../../common/endpoint/service/authz';
import { EndpointAuthz } from '../../../../../common/endpoint/types/authz';

Expand Down Expand Up @@ -125,6 +127,14 @@ const createSecuritySolutionRequestContextMock = (
getRuleDataService: jest.fn(() => clients.ruleDataService),
getRuleExecutionLog: jest.fn(() => clients.ruleExecutionLog),
getExceptionListClient: jest.fn(() => clients.lists.exceptionListClient),
getInternalFleetServices: jest.fn(() => {
// TODO: Mock EndpointInternalFleetServicesInterface and return the mocked object.
throw new Error('Not implemented');
}),
getScopedFleetServices: jest.fn((req: KibanaRequest) => {
// TODO: Mock EndpointScopedFleetServicesInterface and return the mocked object.
throw new Error('Not implemented');
}),
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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 type { SecuritySolutionPluginRouter } from '../../../../../types';
import { DETECTION_ENGINE_INSTALLED_INTEGRATIONS_URL } from '../../../../../../common/constants';
import { GetInstalledIntegrationsResponse } from '../../../../../../common/detection_engine/schemas/response/get_installed_integrations_response_schema';
import { buildSiemResponse } from '../../utils';
import { createInstalledIntegrationSet } from './installed_integration_set';

/**
* Returns an array of installed Fleet integrations and their packages.
*/
export const getInstalledIntegrationsRoute = (router: SecuritySolutionPluginRouter) => {
router.get(
{
path: DETECTION_ENGINE_INSTALLED_INTEGRATIONS_URL,
validate: {},
options: {
tags: ['access:securitySolution'],
},
},
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);

try {
const ctx = await context.resolve(['core', 'securitySolution']);
const fleet = ctx.securitySolution.getInternalFleetServices();
const soClient = ctx.core.savedObjects.client;
const set = createInstalledIntegrationSet();

const packagePolicies = await fleet.packagePolicy.list(soClient, {});

packagePolicies.items.forEach((policy) => {
set.addPackagePolicy(policy);
});

const registryPackages = await Promise.all(
set.getPackages().map((packageInfo) => {
return fleet.packages.getRegistryPackage(
packageInfo.package_name,
packageInfo.package_version
);
})
);

registryPackages.forEach((registryPackage) => {
set.addRegistryPackage(registryPackage.packageInfo);
});

const installedIntegrations = set.getIntegrations();

const body: GetInstalledIntegrationsResponse = {
installed_integrations: installedIntegrations,
};

return response.ok({ body });
} catch (err) {
const error = transformError(err);
return siemResponse.error({
body: error.message,
statusCode: error.statusCode,
});
}
}
);
};
Loading

0 comments on commit dcf83f9

Please sign in to comment.