Skip to content

Commit

Permalink
[7.10] [Fleet] Enforce superuser role for all fleet APIs (#85136) (#8…
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored Dec 10, 2020
1 parent 0ff038d commit ba8de93
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 136 deletions.
28 changes: 17 additions & 11 deletions x-pack/plugins/ingest_manager/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ import {
registerDataStreamRoutes,
registerAgentPolicyRoutes,
registerSetupRoutes,
registerAgentRoutes,
registerAgentAPIRoutes,
registerElasticAgentRoutes,
registerEnrollmentApiKeyRoutes,
registerInstallScriptRoutes,
registerOutputRoutes,
Expand All @@ -69,6 +70,7 @@ import { CloudSetup } from '../../cloud/server';
import { agentCheckinState } from './services/agents/checkin/state';
import { registerIngestManagerUsageCollector } from './collectors/register';
import { getInstallation } from './services/epm/packages';
import { makeRouterEnforcingSuperuser } from './routes/security';

export interface IngestManagerSetupDeps {
licensing: LicensingPluginSetup;
Expand Down Expand Up @@ -219,16 +221,18 @@ export class IngestManagerPlugin

// Always register app routes for permissions checking
registerAppRoutes(router);
// For all the routes we enforce the user to have role superuser
const routerSuperuserOnly = makeRouterEnforcingSuperuser(router);

// Register rest of routes only if security is enabled
if (this.security) {
registerSetupRoutes(router, config);
registerAgentPolicyRoutes(router);
registerPackagePolicyRoutes(router);
registerOutputRoutes(router);
registerSettingsRoutes(router);
registerDataStreamRoutes(router);
registerEPMRoutes(router);
registerSetupRoutes(routerSuperuserOnly, config);
registerAgentPolicyRoutes(routerSuperuserOnly);
registerPackagePolicyRoutes(routerSuperuserOnly);
registerOutputRoutes(routerSuperuserOnly);
registerSettingsRoutes(routerSuperuserOnly);
registerDataStreamRoutes(routerSuperuserOnly);
registerEPMRoutes(routerSuperuserOnly);

// Conditional config routes
if (config.agents.enabled) {
Expand All @@ -244,12 +248,14 @@ export class IngestManagerPlugin
// we currently only use this global interceptor if fleet is enabled
// since it would run this func on *every* req (other plugins, CSS, etc)
registerLimitedConcurrencyRoutes(core, config);
registerAgentRoutes(router, config);
registerEnrollmentApiKeyRoutes(router);
registerAgentAPIRoutes(routerSuperuserOnly, config);
registerEnrollmentApiKeyRoutes(routerSuperuserOnly);
registerInstallScriptRoutes({
router,
router: routerSuperuserOnly,
basePath: core.http.basePath,
});
// Do not enforce superuser role for Elastic Agent routes
registerElasticAgentRoutes(router, config);
}
}
}
Expand Down
180 changes: 91 additions & 89 deletions x-pack/plugins/ingest_manager/server/routes/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function makeValidator(jsonSchema: any) {
};
}

export const registerRoutes = (router: IRouter, config: IngestManagerConfigType) => {
export const registerAPIRoutes = (router: IRouter, config: IngestManagerConfigType) => {
// Get one
router.get(
{
Expand Down Expand Up @@ -119,6 +119,96 @@ export const registerRoutes = (router: IRouter, config: IngestManagerConfigType)
getAgentsHandler
);

// Agent actions
router.post(
{
path: AGENT_API_ROUTES.ACTIONS_PATTERN,
validate: PostNewAgentActionRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postNewAgentActionHandlerBuilder({
getAgent: AgentService.getAgent,
createAgentAction: AgentService.createAgentAction,
})
);

router.post(
{
path: AGENT_API_ROUTES.UNENROLL_PATTERN,
validate: PostAgentUnenrollRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postAgentUnenrollHandler
);

router.put(
{
path: AGENT_API_ROUTES.REASSIGN_PATTERN,
validate: PutAgentReassignRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
putAgentsReassignHandler
);

// Get agent events
router.get(
{
path: AGENT_API_ROUTES.EVENTS_PATTERN,
validate: GetOneAgentEventsRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentEventsHandler
);

// Get agent status for policy
router.get(
{
path: AGENT_API_ROUTES.STATUS_PATTERN,
validate: GetAgentStatusRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentStatusForAgentPolicyHandler
);
// upgrade agent
router.post(
{
path: AGENT_API_ROUTES.UPGRADE_PATTERN,
validate: PostAgentUpgradeRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postAgentUpgradeHandler
);
// bulk upgrade
router.post(
{
path: AGENT_API_ROUTES.BULK_UPGRADE_PATTERN,
validate: PostBulkAgentUpgradeRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsUpgradeHandler
);
// Bulk reassign
router.post(
{
path: AGENT_API_ROUTES.BULK_REASSIGN_PATTERN,
validate: PostBulkAgentReassignRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsReassignHandler
);

// Bulk unenroll
router.post(
{
path: AGENT_API_ROUTES.BULK_UNENROLL_PATTERN,
validate: PostBulkAgentUnenrollRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsUnenrollHandler
);
};

export const registerElasticAgentRoutes = (router: IRouter, config: IngestManagerConfigType) => {
const pollingRequestTimeout = config.agents.pollingRequestTimeout;
// Agent checkin
router.post(
Expand Down Expand Up @@ -226,92 +316,4 @@ export const registerRoutes = (router: IRouter, config: IngestManagerConfigType)
saveAgentEvents: AgentService.saveAgentEvents,
})
);

// Agent actions
router.post(
{
path: AGENT_API_ROUTES.ACTIONS_PATTERN,
validate: PostNewAgentActionRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postNewAgentActionHandlerBuilder({
getAgent: AgentService.getAgent,
createAgentAction: AgentService.createAgentAction,
})
);

router.post(
{
path: AGENT_API_ROUTES.UNENROLL_PATTERN,
validate: PostAgentUnenrollRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postAgentUnenrollHandler
);

router.put(
{
path: AGENT_API_ROUTES.REASSIGN_PATTERN,
validate: PutAgentReassignRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
putAgentsReassignHandler
);

// Get agent events
router.get(
{
path: AGENT_API_ROUTES.EVENTS_PATTERN,
validate: GetOneAgentEventsRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentEventsHandler
);

// Get agent status for policy
router.get(
{
path: AGENT_API_ROUTES.STATUS_PATTERN,
validate: GetAgentStatusRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentStatusForAgentPolicyHandler
);
// upgrade agent
router.post(
{
path: AGENT_API_ROUTES.UPGRADE_PATTERN,
validate: PostAgentUpgradeRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postAgentUpgradeHandler
);
// bulk upgrade
router.post(
{
path: AGENT_API_ROUTES.BULK_UPGRADE_PATTERN,
validate: PostBulkAgentUpgradeRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsUpgradeHandler
);
// Bulk reassign
router.post(
{
path: AGENT_API_ROUTES.BULK_REASSIGN_PATTERN,
validate: PostBulkAgentReassignRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsReassignHandler
);

// Bulk unenroll
router.post(
{
path: AGENT_API_ROUTES.BULK_UNENROLL_PATTERN,
validate: PostBulkAgentUnenrollRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postBulkAgentsUnenrollHandler
);
};
2 changes: 1 addition & 1 deletion x-pack/plugins/ingest_manager/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export { registerRoutes as registerPackagePolicyRoutes } from './package_policy'
export { registerRoutes as registerDataStreamRoutes } from './data_streams';
export { registerRoutes as registerEPMRoutes } from './epm';
export { registerRoutes as registerSetupRoutes } from './setup';
export { registerRoutes as registerAgentRoutes } from './agent';
export { registerAPIRoutes as registerAgentAPIRoutes, registerElasticAgentRoutes } from './agent';
export { registerRoutes as registerEnrollmentApiKeyRoutes } from './enrollment_api_key';
export { registerRoutes as registerInstallScriptRoutes } from './install_script';
export { registerRoutes as registerOutputRoutes } from './output';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const registerRoutes = ({
{
path: INSTALL_SCRIPT_API_ROUTES,
validate: InstallScriptRequestSchema,
options: { tags: [], authRequired: false },
options: { tags: [], authRequired: true },
},
async function getInstallScriptHandler(
context,
Expand Down
43 changes: 43 additions & 0 deletions x-pack/plugins/ingest_manager/server/routes/security.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { IRouter, RequestHandler } from 'src/core/server';
import { appContextService } from '../services';

export function enforceSuperUser<T1, T2, T3>(
handler: RequestHandler<T1, T2, T3>
): RequestHandler<T1, T2, T3> {
return function enforceSuperHandler(context, req, res) {
const security = appContextService.getSecurity();
const user = security.authc.getCurrentUser(req);
if (!user) {
return res.unauthorized();
}

const userRoles = user.roles || [];
if (!userRoles.includes('superuser')) {
return res.forbidden({
body: {
message: 'Access to Fleet API require the superuser role.',
},
});
}
return handler(context, req, res);
};
}

export function makeRouterEnforcingSuperuser(router: IRouter): IRouter {
return {
get: (options, handler) => router.get(options, enforceSuperUser(handler)),
delete: (options, handler) => router.delete(options, enforceSuperUser(handler)),
post: (options, handler) => router.post(options, enforceSuperUser(handler)),
put: (options, handler) => router.put(options, enforceSuperUser(handler)),
patch: (options, handler) => router.patch(options, enforceSuperUser(handler)),
handleLegacyErrors: (handler) => router.handleLegacyErrors(handler),
getRoutes: () => router.getRoutes(),
routerPath: router.routerPath,
};
}
Loading

0 comments on commit ba8de93

Please sign in to comment.