Skip to content

Commit

Permalink
[Fleet Plugin] Use server-side authc.getCurrentUser from core.security (
Browse files Browse the repository at this point in the history
elastic#186932)

Part of elastic#186574

Background: This PR serves as an example of a plugin migrating away from
depending on the Security plugin, which is a high priority effort for
the last release before 9.0.

The Fleet plugin uses the `authc.getCurrentUser` in server-side code,
and they are addressed in this PR. It also uses `authc.apiKeys` in a few
areas, but that isn't ready to be migrated yet.

### Checklist

Delete any items that are not applicable to this PR.

- [x] [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

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
tsullivan and kibanamachine committed Jun 27, 2024
1 parent 3d99878 commit 55bbd76
Show file tree
Hide file tree
Showing 15 changed files with 56 additions and 45 deletions.
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/server/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
loggingSystemMock,
savedObjectsClientMock,
savedObjectsServiceMock,
securityServiceMock,
} from '@kbn/core/server/mocks';
import { dataPluginMock } from '@kbn/data-plugin/server/mocks';
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
Expand Down Expand Up @@ -50,6 +51,7 @@ export interface MockedFleetAppContext extends FleetAppContext {
data: ReturnType<typeof dataPluginMock.createStartContract>;
encryptedSavedObjectsStart?: ReturnType<typeof encryptedSavedObjectsMock.createStart>;
savedObjects: ReturnType<typeof savedObjectsServiceMock.createStartContract>;
securityCoreStart: ReturnType<typeof securityServiceMock.createStart>;
securitySetup: ReturnType<typeof securityMock.createSetup>;
securityStart: ReturnType<typeof securityMock.createStart>;
logger: ReturnType<ReturnType<typeof loggingSystemMock.create>['get']>;
Expand All @@ -74,6 +76,7 @@ export const createAppContextStartContractMock = (
encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(),
encryptedSavedObjectsSetup: encryptedSavedObjectsMock.createSetup({ canEncrypt: true }),
savedObjects: savedObjectsServiceMock.createStartContract(),
securityCoreStart: securityServiceMock.createStart(),
securitySetup: securityMock.createSetup(),
securityStart: securityMock.createStart(),
logger: loggingSystemMock.create().get(),
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
PluginInitializerContext,
SavedObjectsClientContract,
SavedObjectsServiceStart,
SecurityServiceStart,
ServiceStatus,
} from '@kbn/core/server';
import { DEFAULT_APP_CATEGORIES, SavedObjectsClient, ServiceStatusLevels } from '@kbn/core/server';
Expand Down Expand Up @@ -155,6 +156,7 @@ export interface FleetAppContext {
data: DataPluginStart;
encryptedSavedObjectsStart?: EncryptedSavedObjectsPluginStart;
encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup;
securityCoreStart: SecurityServiceStart;
securitySetup: SecurityPluginSetup;
securityStart: SecurityPluginStart;
config$?: Observable<FleetConfigType>;
Expand Down Expand Up @@ -613,6 +615,7 @@ export class FleetPlugin
data: plugins.data,
encryptedSavedObjectsStart: plugins.encryptedSavedObjects,
encryptedSavedObjectsSetup: this.encryptedSavedObjectsSetup,
securityCoreStart: core.security,
securitySetup: this.securitySetup,
securityStart: plugins.security,
configInitialValue: this.configInitialValue,
Expand Down
23 changes: 7 additions & 16 deletions x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export const createAgentPolicyHandler: FleetRequestHandler<
const fleetContext = await context.fleet;
const soClient = fleetContext.internalSoClient;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const withSysMonitoring = request.query.sys_monitoring ?? false;
const monitoringEnabled = request.body.monitoring_enabled;
const { has_fleet_server: hasFleetServer, force, ...newPolicy } = request.body;
Expand Down Expand Up @@ -261,7 +261,7 @@ export const updateAgentPolicyHandler: FleetRequestHandler<
const fleetContext = await context.fleet;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const { force, ...data } = request.body;

const spaceId = fleetContext.spaceId;
Expand All @@ -271,11 +271,7 @@ export const updateAgentPolicyHandler: FleetRequestHandler<
esClient,
request.params.agentPolicyId,
data,
{
force,
user: user || undefined,
spaceId,
}
{ force, user, spaceId }
);
const body: UpdateAgentPolicyResponse = { item: agentPolicy };
return response.ok({
Expand All @@ -300,16 +296,14 @@ export const copyAgentPolicyHandler: RequestHandler<
const coreContext = await context.core;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
try {
const agentPolicy = await agentPolicyService.copy(
soClient,
esClient,
request.params.agentPolicyId,
request.body,
{
user: user || undefined,
}
{ user }
);

const body: CopyAgentPolicyResponse = { item: agentPolicy };
Expand All @@ -329,16 +323,13 @@ export const deleteAgentPoliciesHandler: RequestHandler<
const coreContext = await context.core;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
try {
const body: DeleteAgentPolicyResponse = await agentPolicyService.delete(
soClient,
esClient,
request.body.agentPolicyId,
{
user: user || undefined,
force: request.body.force,
}
{ user, force: request.body.force }
);
return response.ok({
body,
Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/fleet/server/routes/epm/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ export const installPackageFromRegistryHandler: FleetRequestHandler<
const fleetContext = await context.fleet;
const savedObjectsClient = fleetContext.internalSoClient;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;

const { pkgName, pkgVersion } = request.params;

Expand Down Expand Up @@ -350,7 +350,7 @@ export const createCustomIntegrationHandler: FleetRequestHandler<
const fleetContext = await context.fleet;
const savedObjectsClient = fleetContext.internalSoClient;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const kibanaVersion = appContextService.getKibanaVersion();
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username);
const spaceId = fleetContext.spaceId;
Expand Down Expand Up @@ -425,7 +425,7 @@ export const bulkInstallPackagesFromRegistryHandler: FleetRequestHandler<
const savedObjectsClient = fleetContext.internalSoClient;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const spaceId = fleetContext.spaceId;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username);

const bulkInstalledResponses = await bulkInstallPackages({
Expand Down Expand Up @@ -457,7 +457,7 @@ export const installPackageByUploadHandler: FleetRequestHandler<
const contentType = request.headers['content-type'] as string; // from types it could also be string[] or undefined but this is checked later
const archiveBuffer = Buffer.from(request.body);
const spaceId = fleetContext.spaceId;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username);

const res = await installPackage({
Expand Down Expand Up @@ -561,7 +561,7 @@ export const reauthorizeTransformsHandler: FleetRequestHandler<

let username;
try {
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = appContextService.getSecurityCore().authc.getCurrentUser(request);
if (user) {
username = user.username;
}
Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/fleet/server/routes/package_policy/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ export const createPackagePolicyHandler: FleetRequestHandler<
const fleetContext = await context.fleet;
const soClient = fleetContext.internalSoClient;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const { force, id, package: pkg, ...newPolicy } = request.body;
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username);
let wasPackageAlreadyInstalled = false;
Expand Down Expand Up @@ -339,7 +339,7 @@ export const updatePackagePolicyHandler: FleetRequestHandler<
const soClient = fleetContext.internalSoClient;
const limitedToPackages = fleetContext.limitedToPackages;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
const packagePolicy = await packagePolicyService.get(soClient, request.params.packagePolicyId);

if (!packagePolicy) {
Expand Down Expand Up @@ -442,7 +442,7 @@ export const deletePackagePolicyHandler: RequestHandler<
const coreContext = await context.core;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;

try {
const body: PostDeletePackagePoliciesResponse = await packagePolicyService.delete(
Expand Down Expand Up @@ -470,7 +470,7 @@ export const deleteOnePackagePolicyHandler: RequestHandler<
const coreContext = await context.core;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;

try {
const res = await packagePolicyService.delete(
Expand Down Expand Up @@ -509,7 +509,7 @@ export const upgradePackagePolicyHandler: RequestHandler<
const coreContext = await context.core;
const soClient = coreContext.savedObjects.client;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;
try {
const body: UpgradePackagePolicyResponse = await packagePolicyService.upgrade(
soClient,
Expand Down
6 changes: 2 additions & 4 deletions x-pack/plugins/fleet/server/routes/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,11 @@ export const putSettingsHandler: FleetRequestHandler<
> = async (context, request, response) => {
const soClient = (await context.fleet).internalSoClient;
const esClient = (await context.core).elasticsearch.client.asInternalUser;
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined;

try {
const settings = await settingsService.saveSettings(soClient, request.body);
await agentPolicyService.bumpAllAgentPolicies(esClient, {
user: user || undefined,
});
await agentPolicyService.bumpAllAgentPolicies(esClient, { user });
const body = {
item: settings,
};
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/server/services/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { safeDump } from 'js-yaml';
import pMap from 'p-map';
import { lt } from 'semver';
import type {
AuthenticatedUser,
ElasticsearchClient,
SavedObjectsBulkUpdateObject,
SavedObjectsBulkUpdateResponse,
Expand All @@ -20,7 +21,6 @@ import type {
} from '@kbn/core/server';
import { SavedObjectsUtils } from '@kbn/core/server';

import type { AuthenticatedUser } from '@kbn/security-plugin/server';
import type { BulkResponseItem } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';

import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants';
Expand Down
8 changes: 5 additions & 3 deletions x-pack/plugins/fleet/server/services/agent_policy_create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
* 2.0.
*/

import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server';

import type { AuthenticatedUser } from '@kbn/security-plugin/common';
import type {
AuthenticatedUser,
ElasticsearchClient,
SavedObjectsClientContract,
} from '@kbn/core/server';

import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header';

Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/fleet/server/services/app_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
HttpServiceSetup,
Logger,
KibanaRequest,
SecurityServiceStart,
} from '@kbn/core/server';

import { CoreKibanaRequest } from '@kbn/core/server';
Expand Down Expand Up @@ -61,6 +62,7 @@ class AppContextService {
private data: DataPluginStart | undefined;
private esClient: ElasticsearchClient | undefined;
private experimentalFeatures?: ExperimentalFeatures;
private securityCoreStart: SecurityServiceStart | undefined;
private securitySetup: SecurityPluginSetup | undefined;
private securityStart: SecurityPluginStart | undefined;
private config$?: Observable<FleetConfigType>;
Expand All @@ -86,6 +88,7 @@ class AppContextService {
this.encryptedSavedObjectsStart = appContext.encryptedSavedObjectsStart;
this.encryptedSavedObjects = appContext.encryptedSavedObjectsStart?.getClient();
this.encryptedSavedObjectsSetup = appContext.encryptedSavedObjectsSetup;
this.securityCoreStart = appContext.securityCoreStart;
this.securitySetup = appContext.securitySetup;
this.securityStart = appContext.securityStart;
this.savedObjects = appContext.savedObjects;
Expand Down Expand Up @@ -129,6 +132,10 @@ class AppContextService {
return this.encryptedSavedObjects;
}

public getSecurityCore() {
return this.securityCoreStart!;
}

public getSecurity() {
return this.securityStart!;
}
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/fleet/server/services/package_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n';
import semverLt from 'semver/functions/lt';
import { getFlattenedObject } from '@kbn/std';
import type {
AuthenticatedUser,
KibanaRequest,
ElasticsearchClient,
SavedObjectsClientContract,
Expand All @@ -25,8 +26,6 @@ import { safeLoad } from 'js-yaml';

import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants';

import { type AuthenticatedUser } from '@kbn/security-plugin/server';

import pMap from 'p-map';

import type { SavedObjectError } from '@kbn/core-saved-objects-common';
Expand Down
11 changes: 8 additions & 3 deletions x-pack/plugins/fleet/server/services/package_policy_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
* 2.0.
*/

import type { KibanaRequest, Logger, RequestHandlerContext } from '@kbn/core/server';
import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server';
import type { AuthenticatedUser } from '@kbn/security-plugin/server';
import type {
AuthenticatedUser,
KibanaRequest,
Logger,
RequestHandlerContext,
ElasticsearchClient,
SavedObjectsClientContract,
} from '@kbn/core/server';

import type { SavedObjectError } from '@kbn/core-saved-objects-common';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import type {
CheckPrivilegesResponse,
CheckPrivilegesPayload,
} from '@kbn/security-plugin/server';
import type { RequestHandler } from '@kbn/core/server';
import type { AuthenticatedUser, RequestHandler } from '@kbn/core/server';
import type { VersionedRouter } from '@kbn/core-http-server';
import { loggingSystemMock } from '@kbn/core/server/mocks';

import type { AuthenticatedUser } from '@kbn/security-plugin/common';

import { coreMock } from '@kbn/core/server/mocks';

import { API_VERSIONS } from '../../../common/constants';
Expand Down Expand Up @@ -85,7 +83,7 @@ describe('FleetAuthzRouter', () => {
// @ts-expect-error type doesn't properly respect deeply mocked keys
mockContext.securityStart.authz.actions.ui.get.mockImplementation((priv) => `ui:${priv}`);

mockContext.securityStart.authc.getCurrentUser.mockReturnValue({
mockContext.securityCoreStart.authc.getCurrentUser.mockReturnValue({
username: 'foo',
roles,
} as unknown as AuthenticatedUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import { deepFreeze } from '@kbn/std';
import type { SecurityPluginStart, CheckPrivilegesDynamically } from '@kbn/security-plugin/server';

import { securityServiceMock, type SecurityStartMock } from '@kbn/core-security-server-mocks';

import { appContextService } from '../app_context';
import type { FleetAuthz } from '../../../common';

Expand Down Expand Up @@ -554,12 +556,13 @@ describe('When using calculateRouteAuthz()', () => {
});

describe('getAuthzFromRequest', () => {
let mockSecurityCore: SecurityStartMock;
let mockSecurity: jest.MockedObjectDeep<SecurityPluginStart>;
let checkPrivileges: jest.MockedFn<CheckPrivilegesDynamically>;
beforeEach(() => {
checkPrivileges = jest.fn();
mockSecurityCore = securityServiceMock.createStart();
mockSecurity = {
authc: { getCurrentUser: jest.fn() },
authz: {
checkPrivilegesDynamicallyWithRequest: jest.fn().mockReturnValue(checkPrivileges),
actions: {
Expand All @@ -576,6 +579,7 @@ describe('getAuthzFromRequest', () => {
},
} as unknown as jest.MockedObjectDeep<SecurityPluginStart>;

jest.mocked(appContextService.getSecurityCore).mockReturnValue(mockSecurityCore);
jest.mocked(appContextService.getSecurity).mockReturnValue(mockSecurity);
jest.mocked(appContextService.getSecurityLicense).mockReturnValue({
isEnabled: () => true,
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/server/services/security/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function checkSuperuser(req: KibanaRequest) {
return false;
}

const security = appContextService.getSecurity();
const security = appContextService.getSecurityCore();
const user = security.authc.getCurrentUser(req);

if (!user) {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,6 @@
"@kbn/test-jest-helpers",
"@kbn/core-saved-objects-utils-server",
"@kbn/integration-assistant-plugin",
"@kbn/core-security-server-mocks",
]
}

0 comments on commit 55bbd76

Please sign in to comment.