From e031d808196bab3ea4dd54f39c7e56b42c87551b Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Thu, 15 Aug 2024 09:53:18 -0400 Subject: [PATCH] Auth failure listener page with basic get, delete dummy create Signed-off-by: Derek Ho --- common/index.ts | 1 + public/apps/configuration/app-router.tsx | 12 ++ public/apps/configuration/constants.tsx | 1 + .../panels/auth-failure-listeners.tsx | 125 ++++++++++++++++++ .../__snapshots__/app-router.test.tsx.snap | 4 + ...pensearch_security_configuration_plugin.ts | 10 ++ server/routes/index.ts | 57 ++++++++ 7 files changed, 210 insertions(+) create mode 100644 public/apps/configuration/panels/auth-failure-listeners.tsx diff --git a/common/index.ts b/common/index.ts index b33c099a7..1838c7251 100644 --- a/common/index.ts +++ b/common/index.ts @@ -83,6 +83,7 @@ export enum ResourceType { tenantsConfigureTab = 'tenantsConfigureTab', auth = 'auth', auditLogging = 'auditLogging', + authFailureListeners = 'authFailureListeners', } /** diff --git a/public/apps/configuration/app-router.tsx b/public/apps/configuration/app-router.tsx index f0dc0cae2..abb97d635 100644 --- a/public/apps/configuration/app-router.tsx +++ b/public/apps/configuration/app-router.tsx @@ -41,6 +41,7 @@ import { ResourceType } from '../../../common'; import { buildHashUrl, buildUrl } from './utils/url-builder'; import { CrossPageToast } from './cross-page-toast'; import { getDataSourceFromUrl, LocalCluster } from '../../utils/datasource-utils'; +import { AuthFailureListeners } from './panels/auth-failure-listeners'; const LANDING_PAGE_URL = '/getstarted'; @@ -77,6 +78,10 @@ export const ROUTE_MAP: { [key: string]: RouteItem } = { name: 'Audit logs', href: buildUrl(ResourceType.auditLogging), }, + [ResourceType.authFailureListeners]: { + name: 'Rate limiting', + href: buildUrl(ResourceType.authFailureListeners), + }, }; const getRouteList = (multitenancyEnabled: boolean) => { @@ -262,6 +267,13 @@ export function AppRouter(props: AppDependencies) { return ; }} /> + { + setGlobalBreadcrumbs(); + return ; + }} + /> {multitenancyEnabled && ( { + const data = await createRequestContextWithDataSourceId(dataSource.id).httpGet({ + http: props.coreStart.http, + url: API_ENDPOINT_AUTHFAILURELISTENERS, + }); + setListeners(data.data); + }; + + const handleDelete = async (name: string) => { + await createRequestContextWithDataSourceId(dataSource.id).httpDelete({ + http: props.coreStart.http, + url: getResourceUrl(API_ENDPOINT_AUTHFAILURELISTENERS, name), + }); + }; + + const createDummyAuthFailureListener = async () => { + await createRequestContextWithDataSourceId(dataSource.id).httpPost({ + http: props.coreStart.http, + url: getResourceUrl(API_ENDPOINT_AUTHFAILURELISTENERS, 'test'), + body: { + type: 'ip', + authentication_backend: 'test', + allowed_tries: 10, + time_window_seconds: 3600, + block_expiry_seconds: 600, + max_blocked_clients: 100000, + max_tracked_clients: 100000, + }, + }); + }; + + const columns = [ + { + field: 'name', + name: 'Name', + }, + { + field: 'type', + name: 'Type', + }, + { + field: 'authentication_backend', + name: 'Authentication backend', + }, + { + field: 'allowed_tries', + name: 'Allowed tries', + }, + { + field: 'time_window_seconds', + name: 'Time window (sec)', + }, + { + field: 'block_expiry_seconds', + name: 'Block expiry (sec)', + }, + { + field: 'max_blocked_clients', + name: 'Max blocked clients', + }, + { + field: 'max_tracked_clients', + name: 'Max tracked clients', + }, + { + field: 'name', + name: 'Actions', + render: (name) => handleDelete(name)} />, + }, + ]; + + return ( + <> +
+ +
+ GET + + + CREATE + + ); +} diff --git a/public/apps/configuration/test/__snapshots__/app-router.test.tsx.snap b/public/apps/configuration/test/__snapshots__/app-router.test.tsx.snap index d5ee503be..8ff3a6b42 100644 --- a/public/apps/configuration/test/__snapshots__/app-router.test.tsx.snap +++ b/public/apps/configuration/test/__snapshots__/app-router.test.tsx.snap @@ -484,6 +484,10 @@ exports[`SecurityPluginTopNavMenu renders DataSourceMenu when dataSource is enab path="/getstarted" render={[Function]} /> + > => { + try { + const esResp = await wrapRouteWithDataSource( + dataSourceEnabled, + context, + request, + 'opensearch_security.getAuthFailureListeners' + ); + + return response.ok({ + body: { + total: Object.keys(esResp).length, + data: esResp, + }, + }); + } catch (error) { + return response.custom({ + statusCode: error.statusCode, + body: parseEsErrorResponse(error), + }); + } + } + ); + /** * Update audit log configuration。 *