Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a098ee0
Update ROR settings configuration in E2E tests
Dzuming Sep 2, 2026
49495bb
Implement custom clipboard capture for Cypress tests
Dzuming Sep 2, 2026
ca4eee8
Add retry logic to E2E HTTP requests
Dzuming Sep 2, 2026
bb78c97
Improve Kibana API client robustness and type safety
Dzuming Sep 2, 2026
b518669
Fix flaky E2E tests by updating wait commands and timeouts
Dzuming Sep 2, 2026
2f72397
Update delete space helper to use waitForResponse
Dzuming Sep 2, 2026
4d47e05
Refactor E2E test configuration files
Dzuming Sep 2, 2026
4b7b218
Refactor Kibana-config E2E tests and improve test stability
Dzuming Sep 2, 2026
9b77dd4
Migrate ReadonlyREST settings E2E tests
Dzuming Sep 2, 2026
b12a52c
Add E2E test for hiding apps in search results
Dzuming Sep 2, 2026
27824fb
Update default settings files and remove search tests
Dzuming Sep 2, 2026
b243fb2
Update e2e tests to use Settings page object and confirm saves
Dzuming Sep 2, 2026
4902f38
Update E2E test configuration and user credentials
Dzuming Sep 2, 2026
f03aa75
Remove unused default settings fixture
Dzuming Sep 2, 2026
c687fb1
Skip flaky test in elk-ror and update chunk load error suppression
Dzuming Sep 2, 2026
75e864e
Fix JSON syntax for whitelistedPaths in E2E test fixture
Dzuming Sep 2, 2026
929b8c8
Remove custom JS injection from ROR Kibana settings
Dzuming Sep 2, 2026
63a10a5
Refactor RorApiClient to handle idempotent settings updates
Dzuming Sep 3, 2026
f7e589c
Add hide_apps to default readonlyrest settings fixture
Dzuming Sep 3, 2026
6378950
Merge branch 'develop' into epic/RORDEV-1524-Keep-ROR-Kibana-and-ES-p…
Dzuming Sep 11, 2026
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
4 changes: 2 additions & 2 deletions e2e-tests/cypress/e2e/Allowed-api-paths.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const apiOnlyInternalUser = 'api_only_internal_user:dev';
const apiOnlyRorUser = 'api_only_ror_user:dev';

describe('allowed_api_paths enforcement for api_only users', () => {
before(() => rorApiClient.configureRorIndexMainSettings('allowedApiPathsSettings.yaml'));
after(() => rorApiClient.configureRorIndexMainSettings('defaultSettings.yaml'));
before(() => rorApiClient.configureRorIndexMainSettingsFromFixture('allowedApiPathsSettings.yaml'));
after(() => rorApiClient.configureRorIndexMainSettingsFromFixture('defaultReadonlyRestEsAndKbnSettings.yaml'));

describe('exact /api/ path', () => {
it('allows direct API calls to paths listed in allowed_api_paths', () => {
Expand Down
8 changes: 4 additions & 4 deletions e2e-tests/cypress/e2e/Direct-kibana-request.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ import * as semver from 'semver';
import { getKibanaVersion, userCredentials } from '../support/helpers';
import { kbnApiAdvancedClient } from '../support/helpers/KbnApiAdvancedClient';
import { kbnApiClient } from '../support/helpers/KbnApiClient';
import { rorApiClient } from '../support/helpers/RorApiClient';
import { Settings } from '../support/page-objects/Settings';

describe('Direct kibana request', () => {
const user1 = 'user1:dev';
const admin = 'admin:dev';

beforeEach(() => {
clearDirectKibanaRequestState();
rorApiClient.configureRorIndexMainSettings('defaultSettings.yaml');
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');
});

afterEach(() => {
clearDirectKibanaRequestState();
rorApiClient.configureRorIndexMainSettings('defaultSettings.yaml');
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');
});

it('should check direct kibana request', () => {
Expand Down Expand Up @@ -84,7 +84,7 @@ describe('Direct kibana request', () => {
});

it('should create short URL with x-ror-tenancy-id header', () => {
rorApiClient.configureRorIndexMainSettings('defaultSettings.yaml');
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');

const createShortUrl = semver.gte(getKibanaVersion(), '8.0.0')
? kbnApiClient.createShortUrl(
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/cypress/e2e/Discover.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getKibanaVersion } from '../support/helpers';
import { esApiAdvancedClient } from '../support/helpers/EsApiAdvancedClient';
import { SearchSessions } from '../support/page-objects/SearchSessions';

const userCredentials = 'user4:dev';
const userCredentials = 'user2:dev';
const tenantIndex = '.kibana_admins_group';
const indexWithSearchSessions = semver.lt(getKibanaVersion(), '8.0.0')
? `${tenantIndex}_${getKibanaVersion()}_001`
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/cypress/e2e/Forbidden-login.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Settings } from '../support/page-objects/Settings';

describe('Forbidden login test', () => {
before(() => {
Settings.setSettingsData('defaultSettings.yaml');
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');
});

beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/cypress/e2e/Hide_apps.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Home } from '../support/page-objects/Home';

describe('hidden apps', () => {
afterEach(() => {
Settings.setSettingsData('defaultSettings.yaml');
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');
});

context('Stack Management navigation', () => {
Expand Down
97 changes: 74 additions & 23 deletions e2e-tests/cypress/e2e/Kibana-config.cy.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import * as semver from 'semver';
import { rorApiInternalKbnClient } from '../support/helpers/RorApiInternalKbnClient';
import { Login } from '../support/page-objects/Login';
import { kbnApiAdvancedClient } from '../support/helpers/KbnApiAdvancedClient';
import { RorMenu } from '../support/page-objects/RorMenu';
import { getKibanaVersion, requiredBaseUrl } from '../support/helpers';
import { Discover } from '../support/page-objects/Discover';
import { esApiAdvancedClient } from '../support/helpers/EsApiAdvancedClient';
import { esApiClient } from '../support/helpers/EsApiClient';
import { kbnApiAdvancedClient } from '../support/helpers/KbnApiAdvancedClient';
import { rorApiInternalKbnClient } from '../support/helpers/RorApiInternalKbnClient';
import { SampleData } from '../support/helpers/SampleData';
import { Dashboard } from '../support/page-objects/Dashboard';
import { Discover } from '../support/page-objects/Discover';
import { Login } from '../support/page-objects/Login';
import { Reporting } from '../support/page-objects/Reporting';
import { SampleData } from '../support/helpers/SampleData';
import { esApiClient } from '../support/helpers/EsApiClient';
import { esApiAdvancedClient } from '../support/helpers/EsApiAdvancedClient';
import { RorMenu } from '../support/page-objects/RorMenu';
import { Settings } from '../support/page-objects/Settings';
import { Tenancy } from '../support/page-objects/Tenancy';

const customKibanaIndexName = '.kibana_custom';
Expand All @@ -29,6 +30,7 @@ describe.skip('Kibana-config', () => {
after(() => {
rorApiInternalKbnClient.changeKibanaConfig('defaultKibanaConfig.yml');
kbnApiAdvancedClient.waitForKibanaHealth(requiredBaseUrl());
Settings.setSettingsData('defaultReadonlyRestEsAndKbnSettings.yaml');
esApiAdvancedClient.deleteIndicesByPattern(customKibanaIndexName);
esApiAdvancedClient.deleteDataStreamsByPattern(customKibanaIndexName);
});
Expand All @@ -38,15 +40,19 @@ describe.skip('Kibana-config', () => {
const customSessionIndex = `test_index`;

before(() => {
// Without an explicit value this stack runs with no session clearing, and a previous
// spec's tenancy survives login. Clearing on login and tenancy hop keeps the specs
// independent of each other.
Settings.setReadonlyRestKbnSettings(customReadonlyRestKbnSettings);
rorApiInternalKbnClient.changeKibanaConfig('customKibanaConfig.yml');
kbnApiAdvancedClient.waitForKibanaHealth(requiredBaseUrl());
});

afterEach(() => {
kbnApiAdvancedClient.deleteSavedObjects(adminCredentials, 'template_group');

// deleteSavedObjects will return 404 error because, thanks to resetKibanaIndexToTemplate: true, ROR KBN plugin will reset all data to template_group deleted above, first
kbnApiAdvancedClient.getSavedObjects(adminCredentials);
// This GET returns 404/403 because, thanks to resetKibanaIndexToTemplate: true, ROR KBN plugin will reset all data to template_group deleted above, first
kbnApiAdvancedClient.getSavedObjects(adminCredentials, undefined, { failOnStatusCode: false });

esApiClient.deleteIndex(customSessionIndex);
});
Expand All @@ -61,7 +67,7 @@ describe.skip('Kibana-config', () => {

Login.initialization();
Discover.openDataViewPage();
Discover.verifyIndexPatternSwitchLink('readonlyrest_audit-*');
Discover.verifyIndexPatternSwitchLink('AUDIT_INDEX_PATTERN');
Dashboard.openDashboard();
Dashboard.verifyDashboardExists('ReadonlyREST Audit Dashboard');

Expand All @@ -85,7 +91,16 @@ describe.skip('Kibana-config', () => {
Dashboard.verifyDashboardNotExist('Look at my dashboard');
});

it('should verify index based session', () => {
// FIXME: the session cleanup task never runs against this fixture. server/SessionCleanupTaskManager.ts
// (setup()/start(), registerTaskDefinitions()/ensureScheduled()) only registers and schedules the
// 'ror_session_cleanup' task when `KibanaConfigManager.getKibanaConfig().readonlyrest_kbn` is truthy —
// i.e. only when readonlyrest_kbn is declared inline in kibana.yml (the deprecated path). This describe
// block now pushes readonlyrest_kbn through Settings.setReadonlyRestKbnSettings (the ES settings index)
// instead, so that file-based field is empty and both guards bail out before the task is ever created.
// The mechanism needs to read storeInIndex/indexName/cleanupInterval from RorSettingsStore (the same
// resolved index-or-file source RorSettingsManager already exposes) instead of the raw file config,
// otherwise anyone configuring readonlyrest_kbn purely through the index silently loses session cleanup.
it.skip('should verify index based session', () => {
Login.initialization();
esApiAdvancedClient.waitForDocsCount(customSessionIndex, 1).then(() => {
// Backdate the session instead of waiting out the 1-minute timeout: the cleanup task
Expand Down Expand Up @@ -137,6 +152,9 @@ describe.skip('Kibana-config', () => {

describe('Default tenant middleware', () => {
before(() => {
// Reset index-stored readonlyrest_kbn settings left over from the previous describe block,
// matching the sibling reset at the 'xpack.reporting.index' block below.
Settings.setReadonlyRestKbnSettings();
rorApiInternalKbnClient.changeKibanaConfig('customMiddlewareDefaultTenantKibanaConfig.yml');
kbnApiAdvancedClient.waitForKibanaHealth(requiredBaseUrl());
});
Expand All @@ -155,6 +173,9 @@ describe.skip('Kibana-config', () => {

describe('Custom kibana config multitenancy disabled', () => {
before(() => {
Settings.setReadonlyRestKbnSettings(`
multiTenancyEnabled: false
`);
rorApiInternalKbnClient.changeKibanaConfig('customKibanaConfigMultitenancyDisabled.yml');
kbnApiAdvancedClient.waitForKibanaHealth(requiredBaseUrl());
});
Expand All @@ -169,21 +190,20 @@ describe.skip('Kibana-config', () => {

it('should verify custom Kibana index', () => {
const customIndex = `${customKibanaIndexName}_${getKibanaVersion()}_001`;
esApiClient.findIndicesByPattern(customIndex).then(result => {
const foundIndex = result.find(({ index }) => index === customIndex);
if (!foundIndex) throw new Error(`Expected to find an index matching ${customIndex}`);
expect(foundIndex.index).to.equal(customIndex);
expect(foundIndex.health).to.equal('green');
expect(Number.parseInt(foundIndex['docs.count'], 10)).to.be.greaterThan(0);
});
esApiAdvancedClient.waitForIndexReady(customIndex);
});
});
// xpack.reporting.index was removed in Kibana 8.0, so this only applies to the 7.x leg.
if (semver.lt(getKibanaVersion(), '8.0.0')) {
describe('Custom kibana config custom xpack.reporting.index', () => {
before(() => {
// changeKibanaConfig must run first: the preceding describe block leaves kibana.yml with
// a custom kibana.index, and RorKbnSettingsPolicy rejects a custom kibana.index together
// with multiTenancyEnabled: true (the default here) — posting settings before switching
// configs makes that POST fail, silently leaving multi-tenancy disabled from the prior test.
rorApiInternalKbnClient.changeKibanaConfig('customKibanaConfigXpackReportingIndex.yml');
kbnApiAdvancedClient.waitForKibanaHealth(requiredBaseUrl());
Settings.setReadonlyRestKbnSettings(``);
});

it('should verify custom reporting index', () => {
Expand Down Expand Up @@ -213,9 +233,40 @@ describe.skip('Kibana-config', () => {
kbnApiAdvancedClient.deleteSavedObjects('admin:dev');
});
});
} else {
describe.skip('Custom kibana config custom xpack.reporting.index', () => {
// Tests are skipped
});
}
});

const customReadonlyRestKbnSettings = `
clearSessionOnEvents: [login, tenancyHop]
kibanaIndexTemplate: ".kibana_template_group"
resetKibanaIndexToTemplate: true
store_sessions_in_index: true
sessions_index_name: 'test_index'
session_timeout_minutes: 1
sessions_cleanup_interval: '1s'
sessions_probe_interval_seconds: 180
whitelistedPaths: [".*/api/status$", ".*/api/index_management/indices$"]
kibana_custom_css_inject: 'h1 { color: rgb(0,128,0) !important;}'
kibana_custom_js_inject: "if (window.ROR_METADATA.customMetadata && window.ROR_METADATA.customMetadata.alert_message) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'metadata-alert-message');
div.textContent = window.ROR_METADATA.customMetadata.alert_message;
document.body.appendChild(div);
};
if (window.ROR_METADATA.enrichedData) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'metadata-enriched-data');
div.textContent = window.ROR_METADATA.enrichedData;
document.body.appendChild(div);
};"
custom_middleware_inject: "async function customMiddleware(req, res, next) {
const metadata =
req.rorRequest && req.rorRequest.getIdentitySession() && req.rorRequest.getIdentitySession().metadata;
if (metadata && metadata.username === 'admin') {
req.rorRequest.enrichIdentitySessionMetadata({
enrichedData: 'custom enriched data',
});
}
return next();
}"
`;
Loading
Loading