Skip to content

Commit

Permalink
Allow elastic/fleet-server to call appropriate Fleet APIs (#113932)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover authored Oct 19, 2021
1 parent f9afe67 commit 5974fcf
Show file tree
Hide file tree
Showing 20 changed files with 651 additions and 131 deletions.
12 changes: 11 additions & 1 deletion x-pack/plugins/fleet/server/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ import type { FleetAppContext } from '../plugin';
// Export all mocks from artifacts
export * from '../services/artifacts/mocks';

export const createAppContextStartContractMock = (): FleetAppContext => {
export interface MockedFleetAppContext extends FleetAppContext {
elasticsearch: ReturnType<typeof elasticsearchServiceMock.createStart>;
data: ReturnType<typeof dataPluginMock.createStartContract>;
encryptedSavedObjectsStart?: ReturnType<typeof encryptedSavedObjectsMock.createStart>;
savedObjects: ReturnType<typeof savedObjectsServiceMock.createStartContract>;
securitySetup?: ReturnType<typeof securityMock.createSetup>;
securityStart?: ReturnType<typeof securityMock.createStart>;
logger: ReturnType<ReturnType<typeof loggingSystemMock.create>['get']>;
}

export const createAppContextStartContractMock = (): MockedFleetAppContext => {
const config = {
agents: { enabled: true, elasticsearch: {} },
enabled: true,
Expand Down
55 changes: 42 additions & 13 deletions x-pack/plugins/fleet/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ import {
} from './services/agents';
import { registerFleetUsageCollector } from './collectors/register';
import { getInstallation, ensureInstalledPackage } from './services/epm/packages';
import { makeRouterEnforcingSuperuser } from './routes/security';
import { RouterWrappers } from './routes/security';
import { startFleetServerSetup } from './services/fleet_server';
import { FleetArtifactsClient } from './services/artifacts';
import type { FleetRouter } from './types/request_context';

export interface FleetSetupDeps {
licensing: LicensingPluginSetup;
Expand Down Expand Up @@ -206,6 +207,24 @@ export class FleetPlugin
category: DEFAULT_APP_CATEGORIES.management,
app: [PLUGIN_ID, INTEGRATIONS_PLUGIN_ID, 'kibana'],
catalogue: ['fleet'],
reserved: {
description:
'Privilege to setup Fleet packages and configured policies. Intended for use by the elastic/fleet-server service account only.',
privileges: [
{
id: 'fleet-setup',
privilege: {
excludeFromBasePrivileges: true,
api: ['fleet-setup'],
savedObject: {
all: [],
read: [],
},
ui: [],
},
},
],
},
privileges: {
all: {
api: [`${PLUGIN_ID}-read`, `${PLUGIN_ID}-all`],
Expand Down Expand Up @@ -245,7 +264,7 @@ export class FleetPlugin
})
);

const router = core.http.createRouter<FleetRequestHandlerContext>();
const router: FleetRouter = core.http.createRouter<FleetRequestHandlerContext>();

// Register usage collection
registerFleetUsageCollector(core, config, deps.usageCollection);
Expand All @@ -254,24 +273,34 @@ export class FleetPlugin
registerAppRoutes(router);
// Allow read-only users access to endpoints necessary for Integrations UI
// Only some endpoints require superuser so we pass a raw IRouter here
registerEPMRoutes(router);

// For all the routes we enforce the user to have role superuser
const routerSuperuserOnly = makeRouterEnforcingSuperuser(router);
const superuserRouter = RouterWrappers.require.superuser(router);
const fleetSetupRouter = RouterWrappers.require.fleetSetupPrivilege(router);

// Some EPM routes use regular rbac to support integrations app
registerEPMRoutes({ rbac: router, superuser: superuserRouter });

// Register rest of routes only if security is enabled
if (deps.security) {
registerSetupRoutes(routerSuperuserOnly, config);
registerAgentPolicyRoutes(routerSuperuserOnly);
registerPackagePolicyRoutes(routerSuperuserOnly);
registerOutputRoutes(routerSuperuserOnly);
registerSettingsRoutes(routerSuperuserOnly);
registerDataStreamRoutes(routerSuperuserOnly);
registerPreconfigurationRoutes(routerSuperuserOnly);
registerSetupRoutes(fleetSetupRouter, config);
registerAgentPolicyRoutes({
fleetSetup: fleetSetupRouter,
superuser: superuserRouter,
});
registerPackagePolicyRoutes(superuserRouter);
registerOutputRoutes(superuserRouter);
registerSettingsRoutes(superuserRouter);
registerDataStreamRoutes(superuserRouter);
registerPreconfigurationRoutes(superuserRouter);

// Conditional config routes
if (config.agents.enabled) {
registerAgentAPIRoutes(routerSuperuserOnly, config);
registerEnrollmentApiKeyRoutes(routerSuperuserOnly);
registerAgentAPIRoutes(superuserRouter, config);
registerEnrollmentApiKeyRoutes({
fleetSetup: fleetSetupRouter,
superuser: superuserRouter,
});
}
}
}
Expand Down
27 changes: 14 additions & 13 deletions x-pack/plugins/fleet/server/routes/agent_policy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* 2.0.
*/

import type { IRouter } from 'src/core/server';

import { PLUGIN_ID, AGENT_POLICY_API_ROUTES } from '../../constants';
import {
GetAgentPoliciesRequestSchema,
Expand All @@ -17,6 +15,7 @@ import {
DeleteAgentPolicyRequestSchema,
GetFullAgentPolicyRequestSchema,
} from '../../types';
import type { FleetRouter } from '../../types/request_context';

import {
getAgentPoliciesHandler,
Expand All @@ -29,19 +28,21 @@ import {
downloadFullAgentPolicy,
} from './handlers';

export const registerRoutes = (router: IRouter) => {
// List
router.get(
export const registerRoutes = (routers: { superuser: FleetRouter; fleetSetup: FleetRouter }) => {
// List - Fleet Server needs access to run setup
routers.fleetSetup.get(
{
path: AGENT_POLICY_API_ROUTES.LIST_PATTERN,
validate: GetAgentPoliciesRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
// Disable this tag and the automatic RBAC support until elastic/fleet-server access is removed in 8.0
// Required to allow elastic/fleet-server to access this API.
// options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentPoliciesHandler
);

// Get one
router.get(
routers.superuser.get(
{
path: AGENT_POLICY_API_ROUTES.INFO_PATTERN,
validate: GetOneAgentPolicyRequestSchema,
Expand All @@ -51,7 +52,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Create
router.post(
routers.superuser.post(
{
path: AGENT_POLICY_API_ROUTES.CREATE_PATTERN,
validate: CreateAgentPolicyRequestSchema,
Expand All @@ -61,7 +62,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Update
router.put(
routers.superuser.put(
{
path: AGENT_POLICY_API_ROUTES.UPDATE_PATTERN,
validate: UpdateAgentPolicyRequestSchema,
Expand All @@ -71,7 +72,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Copy
router.post(
routers.superuser.post(
{
path: AGENT_POLICY_API_ROUTES.COPY_PATTERN,
validate: CopyAgentPolicyRequestSchema,
Expand All @@ -81,7 +82,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Delete
router.post(
routers.superuser.post(
{
path: AGENT_POLICY_API_ROUTES.DELETE_PATTERN,
validate: DeleteAgentPolicyRequestSchema,
Expand All @@ -91,7 +92,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Get one full agent policy
router.get(
routers.superuser.get(
{
path: AGENT_POLICY_API_ROUTES.FULL_INFO_PATTERN,
validate: GetFullAgentPolicyRequestSchema,
Expand All @@ -101,7 +102,7 @@ export const registerRoutes = (router: IRouter) => {
);

// Download one full agent policy
router.get(
routers.superuser.get(
{
path: AGENT_POLICY_API_ROUTES.FULL_INFO_DOWNLOAD_PATTERN,
validate: GetFullAgentPolicyRequestSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export const getEnrollmentApiKeysHandler: RequestHandler<
undefined,
TypeOf<typeof GetEnrollmentAPIKeysRequestSchema.query>
> = async (context, request, response) => {
const esClient = context.core.elasticsearch.client.asCurrentUser;
// Use kibana_system and depend on authz checks on HTTP layer to prevent abuse
const esClient = context.core.elasticsearch.client.asInternalUser;

try {
const { items, total, page, perPage } = await APIKeyService.listEnrollmentApiKeys(esClient, {
Expand Down Expand Up @@ -87,7 +88,8 @@ export const deleteEnrollmentApiKeyHandler: RequestHandler<
export const getOneEnrollmentApiKeyHandler: RequestHandler<
TypeOf<typeof GetOneEnrollmentAPIKeyRequestSchema.params>
> = async (context, request, response) => {
const esClient = context.core.elasticsearch.client.asCurrentUser;
// Use kibana_system and depend on authz checks on HTTP layer to prevent abuse
const esClient = context.core.elasticsearch.client.asInternalUser;
try {
const apiKey = await APIKeyService.getEnrollmentAPIKey(esClient, request.params.keyId);
const body: GetOneEnrollmentAPIKeyResponse = { item: apiKey };
Expand Down
21 changes: 12 additions & 9 deletions x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
* 2.0.
*/

import type { IRouter } from 'src/core/server';

import { PLUGIN_ID, ENROLLMENT_API_KEY_ROUTES } from '../../constants';
import {
GetEnrollmentAPIKeysRequestSchema,
GetOneEnrollmentAPIKeyRequestSchema,
DeleteEnrollmentAPIKeyRequestSchema,
PostEnrollmentAPIKeyRequestSchema,
} from '../../types';
import type { FleetRouter } from '../../types/request_context';

import {
getEnrollmentApiKeysHandler,
Expand All @@ -22,17 +21,19 @@ import {
postEnrollmentApiKeyHandler,
} from './handler';

export const registerRoutes = (router: IRouter) => {
router.get(
export const registerRoutes = (routers: { superuser: FleetRouter; fleetSetup: FleetRouter }) => {
routers.fleetSetup.get(
{
path: ENROLLMENT_API_KEY_ROUTES.INFO_PATTERN,
validate: GetOneEnrollmentAPIKeyRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
// Disable this tag and the automatic RBAC support until elastic/fleet-server access is removed in 8.0
// Required to allow elastic/fleet-server to access this API.
// options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getOneEnrollmentApiKeyHandler
);

router.delete(
routers.superuser.delete(
{
path: ENROLLMENT_API_KEY_ROUTES.DELETE_PATTERN,
validate: DeleteEnrollmentAPIKeyRequestSchema,
Expand All @@ -41,16 +42,18 @@ export const registerRoutes = (router: IRouter) => {
deleteEnrollmentApiKeyHandler
);

router.get(
routers.fleetSetup.get(
{
path: ENROLLMENT_API_KEY_ROUTES.LIST_PATTERN,
validate: GetEnrollmentAPIKeysRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
// Disable this tag and the automatic RBAC support until elastic/fleet-server access is removed in 8.0
// Required to allow elastic/fleet-server to access this API.
// options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getEnrollmentApiKeysHandler
);

router.post(
routers.superuser.post(
{
path: ENROLLMENT_API_KEY_ROUTES.CREATE_PATTERN,
validate: PostEnrollmentAPIKeyRequestSchema,
Expand Down
Loading

0 comments on commit 5974fcf

Please sign in to comment.