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。
*