Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Update file data visualizer permissions #101169

Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
22b84ab
[ML] Update file data visualizer permissions
jgowdyelastic Jun 2, 2021
15df2e6
adding home bundle
jgowdyelastic Jun 2, 2021
2473bcf
fixing translations
jgowdyelastic Jun 2, 2021
1e199bd
Merge branch 'master' into update-file-data-visualizer-permissions
kibanamachine Jun 8, 2021
5fd67e8
Merge remote-tracking branch 'origin/master' into update-file-data-vi…
jgowdyelastic Jun 17, 2021
8cdff37
removing home from bundles
jgowdyelastic Jun 17, 2021
988a9fa
Merge branch 'master' into update-file-data-visualizer-permissions
kibanamachine Jun 18, 2021
ef820e5
switching to current user for analysis
jgowdyelastic Jun 18, 2021
62a7868
adding find structure permission check
jgowdyelastic Jun 18, 2021
d542bf8
clean up
jgowdyelastic Jun 18, 2021
8ff3b12
updating text
jgowdyelastic Jun 18, 2021
a11b0f8
Merge branch 'master' into update-file-data-visualizer-permissions
kibanamachine Jun 21, 2021
d19e738
updating maps
jgowdyelastic Jun 21, 2021
db90076
Merge branch 'master' into update-file-data-visualizer-permissions
kibanamachine Jun 22, 2021
34518bf
Merge branch 'master' into update-file-data-visualizer-permissions
kibanamachine Jun 29, 2021
8e7c537
removing has_find_file_structure_permission endpoint
jgowdyelastic Jun 29, 2021
df2b11b
removing more code
jgowdyelastic Jun 29, 2021
d77e042
adding permission error message
jgowdyelastic Jun 29, 2021
fc9949f
renaming variable
jgowdyelastic Jun 29, 2021
3d3c2c0
adding fileUpload:analyzeFile back into ML
jgowdyelastic Jun 29, 2021
6e49678
updating error text
jgowdyelastic Jun 29, 2021
940f7b1
updating snapshots
jgowdyelastic Jun 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import {
import { WelcomeContent } from './welcome_content';

interface Props {
disabled: boolean;
onFilePickerChange(files: FileList | null): void;
}

export const AboutPanel: FC<Props> = ({ onFilePickerChange }) => {
export const AboutPanel: FC<Props> = ({ disabled, onFilePickerChange }) => {
return (
<EuiPage restrictWidth={1000} data-test-subj="dataVisualizerPageFileUpload">
<EuiPageBody>
Expand All @@ -41,6 +42,7 @@ export const AboutPanel: FC<Props> = ({ onFilePickerChange }) => {

<div style={{ textAlign: 'center' }}>
<EuiFilePicker
disabled={disabled}
id="filePicker"
initialPromptText={i18n.translate(
'xpack.dataVisualizer.file.aboutPanel.selectOrDragAndDropFileDescription',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import { isEqual } from 'lodash';
import { AboutPanel, LoadingPanel } from '../about_panel';
import { BottomBar } from '../bottom_bar';
import { ResultsView } from '../results_view';
import { FileCouldNotBeRead, FileTooLarge } from './file_error_callouts';
import {
FileCouldNotBeRead,
FileTooLarge,
FindFileStructurePermissionDenied,
} from './file_error_callouts';
import { EditFlyout } from '../edit_flyout';
import { ExplanationFlyout } from '../explanation_flyout';
import { ImportView } from '../import_view';
Expand Down Expand Up @@ -50,6 +54,7 @@ export class FileDataVisualizerView extends Component {
isExplanationFlyoutVisible: false,
bottomBarVisible: false,
hasPermissionToImport: false,
hasFindFileStructurePermission: undefined,
};

this.overrides = {};
Expand All @@ -66,11 +71,16 @@ export class FileDataVisualizerView extends Component {
// check the user has the correct permission to import data.
// note, calling hasImportPermission with no arguments just checks the
// cluster privileges, the user will still need index privileges to create and ingest
const hasPermissionToImport = await this.props.fileUpload.hasImportPermission({
checkCreateIndexPattern: false,
checkHasManagePipeline: true,
});
this.setState({ hasPermissionToImport });

const [hasPermissionToImport, hasFindFileStructurePermission] = await Promise.all([
this.props.fileUpload.hasImportPermission({
checkCreateIndexPattern: false,
checkHasManagePipeline: true,
}),
this.props.fileUpload.hasFindFileStructurePermission(),
]);

this.setState({ hasPermissionToImport, hasFindFileStructurePermission });
}

onFilePickerChange = (files) => {
Expand Down Expand Up @@ -275,6 +285,7 @@ export class FileDataVisualizerView extends Component {
isExplanationFlyoutVisible,
bottomBarVisible,
hasPermissionToImport,
hasFindFileStructurePermission,
} = this.state;

const fields =
Expand All @@ -286,10 +297,17 @@ export class FileDataVisualizerView extends Component {
<div>
{mode === MODE.READ && (
<>
{!loading && !loaded && <AboutPanel onFilePickerChange={this.onFilePickerChange} />}
{!loading && !loaded && (
<AboutPanel
onFilePickerChange={this.onFilePickerChange}
disabled={!hasFindFileStructurePermission}
/>
)}

{loading && <LoadingPanel />}

{hasFindFileStructurePermission === false && <FindFileStructurePermissionDenied />}

{fileTooLarge && (
<FileTooLarge fileSize={fileSize} maxFileSize={this.maxFileUploadBytes} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,26 @@ export const Explanation: FC<{ error: FindFileStructureErrorResponse }> = ({ err
</>
);
};

export const FindFileStructurePermissionDenied: FC = () => {
return (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.dataVisualizer.file.fileErrorCallouts.findFileStructurePermissionDenied.title"
defaultMessage="Permission denied"
/>
}
color="danger"
iconType="cross"
data-test-subj="dataVisualizerFileStructurePermissionDeniedErrorCallout"
>
<FormattedMessage
id="xpack.dataVisualizer.file.fileErrorCallouts.findFileStructurePermissionDenied.description"
defaultMessage="monitor_text_structure or monitor cluster privileges are required to use this feature"
jgowdyelastic marked this conversation as resolved.
Show resolved Hide resolved
/>
</EuiCallOut>
</>
);
};
4 changes: 4 additions & 0 deletions x-pack/plugins/file_upload/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export interface HasImportPermission {
hasImportPermission: boolean;
}

export interface HasFindFileStructurePermission {
hasFindFileStructurePermission: boolean;
}

export type InputData = any[];

export interface ImportResponse {
Expand Down
20 changes: 19 additions & 1 deletion x-pack/plugins/file_upload/public/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@

import { lazyLoadModules } from '../lazy_load_bundle';
import type { IImporter, ImportFactoryOptions } from '../importer';
import type { HasImportPermission, FindFileStructureResponse } from '../../common';
import type {
HasImportPermission,
HasFindFileStructurePermission,
FindFileStructureResponse,
} from '../../common';
import type { getMaxBytes, getMaxBytesFormatted } from '../importer/get_max_bytes';
import { JsonUploadAndParseAsyncWrapper } from './json_upload_and_parse_async_wrapper';
import { IndexNameFormAsyncWrapper } from './index_name_form_async_wrapper';
Expand All @@ -19,6 +23,7 @@ export interface FileUploadStartApi {
getMaxBytes: typeof getMaxBytes;
getMaxBytesFormatted: typeof getMaxBytesFormatted;
hasImportPermission: typeof hasImportPermission;
hasFindFileStructurePermission: typeof hasFindFileStructurePermission;
checkIndexExists: typeof checkIndexExists;
getTimeFieldRange: typeof getTimeFieldRange;
analyzeFile: typeof analyzeFile;
Expand Down Expand Up @@ -61,6 +66,19 @@ export async function analyzeFile(
});
}

export async function hasFindFileStructurePermission(): Promise<boolean> {
const fileUploadModules = await lazyLoadModules();
try {
const resp = await fileUploadModules.getHttp().fetch<HasFindFileStructurePermission>({
path: `/internal/file_data_visualizer/has_find_file_structure_permission`,
method: 'GET',
});
return resp.hasFindFileStructurePermission;
} catch (error) {
return false;
}
}

export async function hasImportPermission(params: HasImportPermissionParams): Promise<boolean> {
const fileUploadModules = await lazyLoadModules();
try {
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/file_upload/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
FileUploadComponent,
importerFactory,
hasImportPermission,
hasFindFileStructurePermission,
IndexNameFormComponent,
checkIndexExists,
getTimeFieldRange,
Expand Down Expand Up @@ -48,6 +49,7 @@ export class FileUploadPlugin
getMaxBytes,
getMaxBytesFormatted,
hasImportPermission,
hasFindFileStructurePermission,
checkIndexExists,
getTimeFieldRange,
analyzeFile,
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/file_upload/server/analyze_file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function analyzeFile(
overrides: InputOverrides
): Promise<AnalysisResult> {
overrides.explain = overrides.explain === undefined ? 'true' : overrides.explain;
const { body } = await client.asInternalUser.textStructure.findStructure({
const { body } = await client.asCurrentUser.textStructure.findStructure({
body: data,
...overrides,
});
Expand Down
35 changes: 33 additions & 2 deletions x-pack/plugins/file_upload/server/check_privileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import { KibanaRequest } from 'kibana/server';
import { AuthorizationServiceSetup, CheckPrivilegesPayload } from '../../security/server';

interface Deps {
interface BasicDeps {
request: KibanaRequest;
authorization?: Pick<
AuthorizationServiceSetup,
'mode' | 'actions' | 'checkPrivilegesDynamicallyWithRequest'
>;
}

interface FileUploadDeps extends BasicDeps {
checkHasManagePipeline: boolean;
checkCreateIndexPattern: boolean;
indexName?: string;
Expand All @@ -25,7 +28,7 @@ export const checkFileUploadPrivileges = async ({
checkHasManagePipeline,
checkCreateIndexPattern,
indexName,
}: Deps) => {
}: FileUploadDeps) => {
const requiresAuthz = authorization?.mode.useRbacForRequest(request) ?? false;

if (!authorization || !requiresAuthz) {
Expand Down Expand Up @@ -53,3 +56,31 @@ export const checkFileUploadPrivileges = async ({

return { hasImportPermission: checkPrivilegesResp.hasAllRequested };
};

export const checkFindFileStructurePrivileges = async ({ request, authorization }: BasicDeps) => {
const requiresAuthz = authorization?.mode.useRbacForRequest(request) ?? false;

if (!authorization || !requiresAuthz) {
return { hasFindFileStructurePermission: true };
}

if (!request.auth.isAuthenticated) {
return { hasFindFileStructurePermission: false };
}

const checkPrivilegesPayload: CheckPrivilegesPayload = {
elasticsearch: {
cluster: ['monitor', 'monitor_text_structure'],
index: {},
},
};

const checkPrivileges = authorization.checkPrivilegesDynamicallyWithRequest(request);
const checkPrivilegesResp = await checkPrivileges(checkPrivilegesPayload);

const hasFindFileStructurePermission = checkPrivilegesResp.privileges.elasticsearch.cluster.some(
({ authorized }) => authorized
);

return { hasFindFileStructurePermission };
};
40 changes: 31 additions & 9 deletions x-pack/plugins/file_upload/server/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
runtimeMappingsSchema,
} from './schemas';
import { StartDeps } from './types';
import { checkFileUploadPrivileges } from './check_privileges';
import { checkFileUploadPrivileges, checkFindFileStructurePrivileges } from './check_privileges';

function importData(
client: IScopedClusterClient,
Expand Down Expand Up @@ -81,6 +81,36 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
}
);

/**
* @apiGroup FileDataVisualizer
*
* @api {post} /internal/file_data_visualizer/has_find_file_structure_permission Check permissions for find file structure endpoint
* @apiName HasFindFileStructurePermission
* @apiDescription check permissions for find file structure endpoint
*
*/
router.get(
{
path: '/internal/file_data_visualizer/has_find_file_structure_permission',
validate: false,
},
async (context, request, response) => {
try {
const [, pluginsStart] = await coreSetup.getStartServices();

const { hasFindFileStructurePermission } = await checkFindFileStructurePrivileges({
authorization: pluginsStart.security?.authz,
request,
});

return response.ok({ body: { hasFindFileStructurePermission } });
} catch (e) {
logger.warn(`Unable to check import permission, error: ${e.message}`);
return response.ok({ body: { hasFindFileStructurePermission: false } });
}
}
);

/**
* @apiGroup FileDataVisualizer
*
Expand All @@ -102,7 +132,6 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
accepts: ['text/*', 'application/json'],
maxBytes: MAX_FILE_SIZE_BYTES,
},
tags: ['access:fileUpload:analyzeFile'],
},
},
async (context, request, response) => {
Expand Down Expand Up @@ -141,7 +170,6 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
accepts: ['application/json'],
maxBytes: MAX_FILE_SIZE_BYTES,
},
tags: ['access:fileUpload:import'],
},
},
async (context, request, response) => {
Expand Down Expand Up @@ -185,9 +213,6 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
validate: {
body: schema.object({ index: schema.string() }),
},
options: {
tags: ['access:fileUpload:import'],
},
},
async (context, request, response) => {
try {
Expand Down Expand Up @@ -227,9 +252,6 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
runtimeMappings: schema.maybe(runtimeMappingsSchema),
}),
},
options: {
tags: ['access:fileUpload:analyzeFile'],
},
},
async (context, request, response) => {
try {
Expand Down
8 changes: 2 additions & 6 deletions x-pack/plugins/ml/common/types/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,7 @@ export function getPluginPrivileges() {
return {
admin: {
...privilege,
api: [
'fileUpload:import',
'fileUpload:analyzeFile',
...allMlCapabilitiesKeys.map((k) => `ml:${k}`),
],
api: allMlCapabilitiesKeys.map((k) => `ml:${k}`),
catalogue: [PLUGIN_ID, `${PLUGIN_ID}_file_data_visualizer`],
ui: allMlCapabilitiesKeys,
savedObject: {
Expand All @@ -127,7 +123,7 @@ export function getPluginPrivileges() {
},
user: {
...privilege,
api: ['fileUpload:analyzeFile', ...userMlCapabilitiesKeys.map((k) => `ml:${k}`)],
api: userMlCapabilitiesKeys.map((k) => `ml:${k}`),
catalogue: [PLUGIN_ID],
management: { insightsAndAlerting: [] },
ui: userMlCapabilitiesKeys,
Expand Down