[Serverless] Disable Login Selector and push Basic authentication providder down the authentication chain. (#165810)

## Summary

Since we're planning to disable login selector in MKI soon, we should
adapt our tests for this new configuration. This PR disables Login
Selector and pushes `Basic` authentication providder down the
authentication chain in Serverless tests.
This commit is contained in:
Aleh Zasypkin 2023-09-13 14:14:45 +02:00 committed by GitHub
parent b35328f2b2
commit 7aa307476c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 300 additions and 231 deletions

View file

@ -5,13 +5,9 @@
* 2.0.
*/
/* eslint-disable import/no-nodejs-modules */
import * as yaml from 'js-yaml';
import type { UrlObject } from 'url';
import Url from 'url';
import type { Role } from '@kbn/security-plugin/common';
import { isLocalhost } from '../../../../scripts/endpoint/common/is_localhost';
import type { LoginState } from '@kbn/security-plugin/common/login_state';
import { getWithResponseActionsRole } from '../../../../scripts/endpoint/common/roles_users/with_response_actions_role';
import { getNoResponseActionsRole } from '../../../../scripts/endpoint/common/roles_users/without_response_actions_role';
import { request } from './common';
@ -90,35 +86,6 @@ const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD';
const KIBANA_USERNAME = 'KIBANA_USERNAME';
const KIBANA_PASSWORD = 'KIBANA_PASSWORD';
/**
* The Kibana server endpoint used for authentication
*/
const LOGIN_API_ENDPOINT = '/internal/security/login';
/**
* cy.visit will default to the baseUrl which uses the default kibana test user
* This function will override that functionality in cy.visit by building the baseUrl
* directly from the environment variables set up in x-pack/test/security_solution_cypress/runner.ts
*
* @param role string role/user to log in with
* @param route string route to visit
*/
export const getUrlWithRoute = (role: string, route: string) => {
const url = Cypress.config().baseUrl;
const kibana = new URL(String(url));
const theUrl = `${Url.format({
auth: `${role}:changeme`,
username: role,
password: Cypress.env(ELASTICSEARCH_PASSWORD),
protocol: kibana.protocol.replace(':', ''),
hostname: kibana.hostname,
port: kibana.port,
} as UrlObject)}${route.startsWith('/') ? '' : '/'}${route}`;
cy.log(`origin: ${theUrl}`);
return theUrl;
};
export const createCustomRoleAndUser = (role: string, rolePrivileges: Omit<Role, 'name'>) => {
// post the role
request({
@ -139,31 +106,44 @@ export const createCustomRoleAndUser = (role: string, rolePrivileges: Omit<Role,
});
};
export const loginWithRole = async (role: ROLE) => {
const loginWithUsernameAndPassword = (username: string, password: string) => {
const baseUrl = Cypress.config().baseUrl;
if (!baseUrl) {
throw Error(`Cypress config baseUrl not set!`);
}
// Programmatically authenticate without interacting with the Kibana login page.
const headers = { 'kbn-xsrf': 'cypress-creds' };
request<LoginState>({ headers, url: `${baseUrl}/internal/security/login_state` }).then(
(loginState) => {
const basicProvider = loginState.body.selector.providers.find(
(provider) => provider.type === 'basic'
);
return request({
url: `${baseUrl}/internal/security/login`,
method: 'POST',
headers,
body: {
providerType: basicProvider.type,
providerName: basicProvider.name,
currentURL: '/',
params: { username, password },
},
});
}
);
};
export const loginWithRole = (role: ROLE) => {
loginWithCustomRole(role, rolesMapping[role]);
};
export const loginWithCustomRole = async (role: string, rolePrivileges: Omit<Role, 'name'>) => {
export const loginWithCustomRole = (role: string, rolePrivileges: Omit<Role, 'name'>) => {
createCustomRoleAndUser(role, rolePrivileges);
const theUrl = new URL(String(Cypress.config().baseUrl));
theUrl.username = role;
theUrl.password = Cypress.env(ELASTICSEARCH_PASSWORD);
cy.log(`origin: ${theUrl}`);
request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username: role,
password: Cypress.env(ELASTICSEARCH_PASSWORD),
},
},
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
method: 'POST',
url: getUrlWithRoute(role, LOGIN_API_ENDPOINT),
});
cy.log(`origin: ${Cypress.config().baseUrl}`);
loginWithUsernameAndPassword(role, Cypress.env(ELASTICSEARCH_PASSWORD));
};
/**
@ -199,14 +179,6 @@ const credentialsProvidedByEnvironment = (): boolean =>
* Kibana's `/internal/security/login` endpoint, bypassing the login page (for speed).
*/
const loginViaEnvironmentCredentials = () => {
const url = Cypress.config().baseUrl;
if (!url) {
throw Error(`Cypress config baseUrl not set!`);
}
const urlObj = new URL(url);
let username: string;
let password: string;
let usernameEnvVar: string;
@ -228,21 +200,7 @@ const loginViaEnvironmentCredentials = () => {
`Authenticating user [${username}] retrieved via environment credentials from the \`CYPRESS_${usernameEnvVar}\` and \`CYPRESS_${passwordEnvVar}\` environment variables`
);
// programmatically authenticate without interacting with the Kibana login page
request({
body: {
providerType: 'basic',
providerName: url && !isLocalhost(urlObj.hostname) ? 'cloud-basic' : 'basic',
currentURL: '/',
params: {
username,
password,
},
},
headers: { 'kbn-xsrf': 'cypress-creds-via-env' },
method: 'POST',
url: `${url}${LOGIN_API_ENDPOINT}`,
});
loginWithUsernameAndPassword(username, password);
};
/**
@ -258,22 +216,10 @@ const loginViaConfig = () => {
// read the login details from `kibana.dev.yaml`
cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => {
const config = yaml.safeLoad(kibanaDevYml);
// programmatically authenticate without interacting with the Kibana login page
request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username: Cypress.env(ELASTICSEARCH_USERNAME),
password: config.elasticsearch.password,
},
},
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
method: 'POST',
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
});
loginWithUsernameAndPassword(
Cypress.env(ELASTICSEARCH_USERNAME),
config.elasticsearch.password
);
});
};

View file

@ -295,18 +295,37 @@ export class SecurityPageObject extends FtrService {
return user as AuthenticatedUser;
}
async forceLogout() {
async forceLogout(
{ waitForLoginPage }: { waitForLoginPage: boolean } = { waitForLoginPage: true }
) {
this.log.debug('SecurityPage.forceLogout');
if (await this.find.existsByDisplayedByCssSelector('.login-form', 100)) {
this.log.debug('Already on the login page, not forcing anything');
return;
}
this.log.debug('Redirecting to /logout to force the logout');
this.log.debug(`Redirecting to ${this.deployment.getHostPort()}/logout to force the logout`);
const url = this.deployment.getHostPort() + '/logout';
await this.browser.get(url);
this.log.debug('Waiting on the login form to appear');
await this.waitForLoginPage();
// After logging out, the user can be redirected to various locations depending on the context. By default, we
// expect the user to be redirected to the login page. However, if the login page is not available for some reason,
// we should simply wait until the user is redirected *elsewhere*.
if (waitForLoginPage) {
this.log.debug('Waiting on the login form to appear');
await this.waitForLoginPage();
} else {
this.log.debug('Waiting for logout to complete');
await this.retry.waitFor('Waiting for logout to complete', async () => {
// There are cases when browser/Kibana would like users to confirm that they want to navigate away from the
// current page and lose the state (e.g. unsaved changes) via native alert dialog.
const alert = await this.browser.getAlert();
if (alert?.accept) {
await alert.accept();
}
return !(await this.browser.getCurrentUrl()).includes('/logout');
});
}
}
async clickRolesSection() {

View file

@ -12,6 +12,7 @@ import Url from 'url';
import type { ROLES } from '@kbn/security-solution-plugin/common/test';
import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '@kbn/security-solution-plugin/common/constants';
import { LoginState } from '@kbn/security-plugin/common/login_state';
import {
hostDetailsUrl,
LOGOUT_URL,
@ -50,11 +51,6 @@ const ELASTICSEARCH_USERNAME = 'ELASTICSEARCH_USERNAME';
*/
const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD';
/**
* The Kibana server endpoint used for authentication
*/
const LOGIN_API_ENDPOINT = '/internal/security/login';
/**
* cy.visit will default to the baseUrl which uses the default kibana test user
* This function will override that functionality in cy.visit by building the baseUrl
@ -141,53 +137,46 @@ export const deleteRoleAndUser = (role: ROLES) => {
});
};
const loginWithUsernameAndPassword = (username: string, password: string) => {
const baseUrl = Cypress.config().baseUrl;
if (!baseUrl) {
throw Error(`Cypress config baseUrl not set!`);
}
const headers = { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' };
// programmatically authenticate without interacting with the Kibana login page
cy.request<LoginState>({ headers, url: `${baseUrl}/internal/security/login_state` }).then(
(loginState) => {
const basicProvider = loginState.body.selector.providers.find(
(provider) => provider.type === 'basic'
);
return cy.request({
url: `${baseUrl}/internal/security/login`,
method: 'POST',
headers,
body: {
providerType: basicProvider.type,
providerName: basicProvider.name,
currentURL: '/',
params: { username, password },
},
});
}
);
};
export const loginWithUser = (user: User) => {
cy.session(user, () => {
cy.request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username: user.username,
password: user.password,
},
},
headers: {
'kbn-xsrf': 'cypress-creds-via-config',
'x-elastic-internal-origin': 'security-solution',
},
method: 'POST',
url: constructUrlWithUser(user, LOGIN_API_ENDPOINT),
});
loginWithUsernameAndPassword(user.username, user.password);
});
};
const loginWithRole = async (role: ROLES) => {
const loginWithRole = (role: ROLES) => {
postRoleAndUser(role);
const theUrl = new URL(String(Cypress.config().baseUrl));
theUrl.username = role;
theUrl.password = Cypress.env(ELASTICSEARCH_PASSWORD);
cy.log(`origin: ${theUrl}`);
cy.log(`origin: ${Cypress.config().baseUrl}`);
cy.session(role, () => {
cy.request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username: role,
password: 'changeme',
},
},
headers: {
'kbn-xsrf': 'cypress-creds-via-config',
'x-elastic-internal-origin': 'security-solution',
},
method: 'POST',
url: getUrlWithRoute(role, LOGIN_API_ENDPOINT),
});
loginWithUsernameAndPassword(role, 'changeme');
});
};
@ -231,24 +220,7 @@ const loginViaEnvironmentCredentials = () => {
const password = Cypress.env(ELASTICSEARCH_PASSWORD);
cy.session([username, password], () => {
// programmatically authenticate without interacting with the Kibana login page
cy.request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username,
password,
},
},
headers: {
'kbn-xsrf': 'cypress-creds-via-env',
'x-elastic-internal-origin': 'security-solution',
},
method: 'POST',
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
});
loginWithUsernameAndPassword(username, password);
});
};
@ -264,26 +236,8 @@ const loginViaConfig = () => {
// read the login details from `kibana.dev.yaml`
cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => {
const config = yaml.safeLoad(kibanaDevYml);
// programmatically authenticate without interacting with the Kibana login page
cy.request({
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username: config.elasticsearch.username,
password: config.elasticsearch.password,
},
},
headers: {
'kbn-xsrf': 'cypress-creds-via-config',
'x-elastic-internal-origin': 'security-solution',
},
method: 'POST',
url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`,
});
const { username, password } = yaml.safeLoad(kibanaDevYml);
loginWithUsernameAndPassword(username, password);
});
};

View file

@ -36,6 +36,7 @@
"@kbn/expandable-flyout",
"@kbn/config-schema",
"@kbn/lists-plugin",
"@kbn/securitysolution-list-constants"
"@kbn/securitysolution-list-constants",
"@kbn/security-plugin"
]
}

View file

@ -68,6 +68,9 @@ export function createTestConfig(options: CreateTestConfigOptions) {
advancedSettings: {
pathname: '/app/management/kibana/settings',
},
login: {
pathname: '/login',
},
},
// choose where screenshots should be saved
screenshots: {

View file

@ -7,10 +7,21 @@
import { FtrProviderContext } from '../ftr_provider_context';
export function SvlCommonPageProvider({ getService }: FtrProviderContext) {
export function SvlCommonPageProvider({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const config = getService('config');
const pageObjects = getPageObjects(['security']);
return {
async login() {
await pageObjects.security.forceLogout({ waitForLoginPage: false });
return await pageObjects.security.login(config.get('servers.kibana.username'));
},
async forceLogout() {
await pageObjects.security.forceLogout({ waitForLoginPage: false });
},
async assertProjectHeaderExists() {
await testSubjects.existOrFail('kibanaProjectHeader');
},

View file

@ -24,15 +24,19 @@ async function clearAllApiKeys(esClient: Client, logger: ToolingLog) {
}
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const pageObjects = getPageObjects(['common', 'apiKeys']);
const pageObjects = getPageObjects(['common', 'svlCommonPage', 'apiKeys']);
const browser = getService('browser');
const es = getService('es');
const log = getService('log');
// FLAKY: https://github.com/elastic/kibana/issues/165553
describe.skip('API keys', () => {
describe('API keys', () => {
before(async () => {
await pageObjects.svlCommonPage.login();
});
after(async () => {
await clearAllApiKeys(es, log);
await pageObjects.svlCommonPage.forceLogout();
});
it('should create and delete API keys correctly', async () => {

View file

@ -12,6 +12,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const dashboard = getPageObject('dashboard');
const lens = getPageObject('lens');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
const svlObltNavigation = getService('svlObltNavigation');
const testSubjects = getService('testSubjects');
const esArchiver = getService('esArchiver');
@ -22,6 +23,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
describe('Cases persistable attachments', () => {
describe('lens visualization', () => {
before(async () => {
await svlCommonPage.login();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.importExport.load(
'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
@ -45,6 +47,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
await kibanaServer.importExport.unload(
'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
);
await svlCommonPage.forceLogout();
});
it('adds lens visualization to a new case', async () => {

View file

@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getPageObject, getService }: FtrProviderContext) => {
const common = getPageObject('common');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
const svlObltNavigation = getService('svlObltNavigation');
const testSubjects = getService('testSubjects');
const cases = getService('cases');
@ -18,6 +19,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
describe('Configure Case', function () {
before(async () => {
await svlCommonPage.login();
await svlObltNavigation.navigateToLandingPage();
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'observability-overview:cases' });
@ -27,6 +30,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
after(async () => {
await cases.api.deleteAllCases();
await svlCommonPage.forceLogout();
});
describe('Closure options', function () {

View file

@ -19,14 +19,20 @@ export default ({ getService, getPageObject }: FtrProviderContext) => {
const find = getService('find');
const cases = getService('cases');
const testSubjects = getService('testSubjects');
const svlCommonPage = getPageObject('svlCommonPage');
const config = getService('config');
before(async () => {
await svlCommonPage.login();
});
beforeEach(async () => {
await navigateToCasesApp(getPageObject, getService, owner);
});
after(async () => {
await cases.api.deleteAllCases();
await svlCommonPage.forceLogout();
});
it('creates a case', async () => {

View file

@ -15,10 +15,12 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
const cases = getService('cases');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
const svlObltNavigation = getService('svlObltNavigation');
describe('Cases list', () => {
before(async () => {
await svlCommonPage.login();
await svlObltNavigation.navigateToLandingPage();
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'observability-overview:cases' });
});
@ -26,6 +28,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
after(async () => {
await cases.api.deleteAllCases();
await cases.casesTable.waitForCasesToBeDeleted();
await svlCommonPage.forceLogout();
});
describe('empty state', () => {

View file

@ -27,8 +27,17 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const retry = getService('retry');
const comboBox = getService('comboBox');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('Case View', () => {
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await svlCommonPage.forceLogout();
});
describe('page', () => {
createOneCaseBeforeDeleteAllAfter(getPageObject, getService, owner);

View file

@ -7,27 +7,36 @@
import 'cypress-axe';
import 'cypress-real-events/support';
import URL from 'url';
import { request } from '@kbn/security-solution-plugin/public/management/cypress/tasks/common';
import { LoginState } from '@kbn/security-plugin/common/login_state';
Cypress.Commands.add('loginAsElasticUser', () => {
const username = Cypress.env('username');
const password = Cypress.env('password');
const kibanaUrlWithoutAuth = Cypress.env('kibanaUrlWithoutAuth');
const headers = { 'kbn-xsrf': 'e2e_test', 'x-elastic-internal-origin': 'kibana' };
cy.log(`Logging in as ${username} on ${kibanaUrlWithoutAuth}`);
cy.visit('/');
cy.request({
log: true,
method: 'POST',
url: `${kibanaUrlWithoutAuth}/internal/security/login`,
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: `${kibanaUrlWithoutAuth}/login`,
params: { username, password },
},
headers: {
'kbn-xsrf': 'e2e_test',
'x-elastic-internal-origin': 'kibana',
},
cy.visit('/login');
cy.request<LoginState>({
headers,
url: `${kibanaUrlWithoutAuth}/internal/security/login_state`,
}).then((loginState) => {
const basicProvider = loginState.body.selector.providers.find(
(provider) => provider.type === 'basic'
);
return request({
headers,
log: true,
method: 'POST',
url: `${kibanaUrlWithoutAuth}/internal/security/login`,
body: {
providerType: basicProvider.type,
providerName: basicProvider.name,
currentURL: `${kibanaUrlWithoutAuth}/login`,
params: { username, password },
},
});
});
cy.visit('/');
});

View file

@ -20,13 +20,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const browser = getService('browser');
const esArchiver = getService('esArchiver');
const retry = getService('retry');
const PageObjects = getPageObjects(['common', 'observabilityLogExplorer']);
const PageObjects = getPageObjects(['common', 'observabilityLogExplorer', 'svlCommonPage']);
describe('Dataset Selector', () => {
before(async () => {
await PageObjects.svlCommonPage.login();
await PageObjects.observabilityLogExplorer.removeInstalledPackages();
});
after(async () => {
await PageObjects.svlCommonPage.forceLogout();
});
describe('without installed integrations or uncategorized data streams', () => {
before(async () => {
await PageObjects.observabilityLogExplorer.navigateTo();

View file

@ -8,16 +8,18 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['observabilityLogExplorer']);
const PageObjects = getPageObjects(['observabilityLogExplorer', 'svlCommonPage']);
const testSubjects = getService('testSubjects');
describe('Filter controls customization', () => {
before('initialize tests', async () => {
await PageObjects.svlCommonPage.login();
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
});
after('clean up archives', async () => {
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
await PageObjects.svlCommonPage.forceLogout();
});
it('renders a filter controls section as part of the unified search bar', async () => {

View file

@ -15,8 +15,17 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const lens = getPageObject('lens');
const svlSearchNavigation = getService('svlSearchNavigation');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('persistable attachment', () => {
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await svlCommonPage.forceLogout();
});
describe('lens visualization', () => {
before(async () => {
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');

View file

@ -16,6 +16,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
'common',
'header',
'lens',
'svlCommonPage',
]);
const pieChart = getService('pieChart');
@ -27,6 +28,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
describe('Building a new dashboard', function () {
before(async () => {
await PageObjects.svlCommonPage.login();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.importExport.load(
'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
@ -42,6 +44,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await kibanaServer.importExport.unload(
'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
);
await PageObjects.svlCommonPage.forceLogout();
});
it('can add a lens panel by value', async () => {

View file

@ -18,10 +18,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const kibanaServer = getService('kibanaServer');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'settings', 'header', 'savedObjects', 'dashboard']);
const PageObjects = getPageObjects([
'common',
'settings',
'header',
'savedObjects',
'dashboard',
'svlCommonPage',
]);
describe('Importing an existing dashboard', () => {
before(async () => {
await PageObjects.svlCommonPage.login();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.uiSettings.replace({});
});
@ -29,6 +37,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.savedObjects.cleanStandardList();
await PageObjects.svlCommonPage.forceLogout();
});
it('should be able to import dashboard created in 8.11', async () => {

View file

@ -11,12 +11,18 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
const svlSearchNavigation = getService('svlSearchNavigation');
const testSubjects = getService('testSubjects');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('empty pages', function () {
before(async () => {
await svlCommonPage.login();
await svlSearchNavigation.navigateToLandingPage();
});
after(async () => {
await svlCommonPage.forceLogout();
});
it('should show search specific empty page in discover', async () => {
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'discover' });
await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted');

View file

@ -7,14 +7,22 @@
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getPageObject, getService }: FtrProviderContext) {
const svlSearchLandingPage = getPageObject('svlSearchLandingPage');
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const pageObjects = getPageObjects(['svlSearchLandingPage', 'svlCommonPage']);
const svlSearchNavigation = getService('svlSearchNavigation');
describe('landing page', function () {
before(async () => {
await pageObjects.svlCommonPage.login();
});
after(async () => {
await pageObjects.svlCommonPage.forceLogout();
});
it('has serverless side nav', async () => {
await svlSearchNavigation.navigateToLandingPage();
await svlSearchLandingPage.assertSvlSearchSideNavExists();
await pageObjects.svlSearchLandingPage.assertSvlSearchSideNavExists();
});
});
}

View file

@ -12,14 +12,20 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
const svlSearchLandingPage = getPageObject('svlSearchLandingPage');
const svlSearchNavigation = getService('svlSearchNavigation');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
describe('navigation', function () {
before(async () => {
await svlCommonPage.login();
await svlSearchNavigation.navigateToLandingPage();
});
after(async () => {
await svlCommonPage.forceLogout();
});
it('navigate search sidenav & breadcrumbs', async () => {
const expectNoPageReload = await svlCommonNavigation.createNoPageReloadCheck();

View file

@ -13,9 +13,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
// const find = getService('find');
// const testSubjects = getService('testSubjects');
const screenshotDirectories = ['response_ops_docs', 'stack_connectors'];
const pageObjects = getPageObjects(['common', 'header']);
const pageObjects = getPageObjects(['common', 'header', 'svlCommonPage']);
describe('connectors', function () {
before(async () => {
await pageObjects.svlCommonPage.login();
});
after(async () => {
await pageObjects.svlCommonPage.forceLogout();
});
it('connectors list screenshot', async () => {
await pageObjects.common.navigateToApp('connectors');
await pageObjects.header.waitUntilLoadingHasFinished();

View file

@ -6,6 +6,7 @@
*/
import { request } from '@kbn/security-solution-plugin/public/management/cypress/tasks/common';
import { LoginState } from '@kbn/security-plugin/common/login_state';
import type { ServerlessRoleName } from '../../../../../shared/lib';
import { STANDARD_HTTP_HEADERS } from '../../../../../shared/lib/security/default_http_headers';
@ -20,30 +21,29 @@ const sendApiLoginRequest = (
username: string,
password: string
): Cypress.Chainable<{ username: string; password: string }> => {
const url = new URL(Cypress.config().baseUrl ?? '');
url.pathname = '/internal/security/login';
const baseUrl = Cypress.config().baseUrl;
cy.log(`Authenticating [${username}] via ${url.toString()}`);
cy.log(`Authenticating [${username}] via ${baseUrl}`);
return request({
headers: { ...STANDARD_HTTP_HEADERS },
method: 'POST',
url: url.toString(),
body: {
providerType: 'basic',
providerName: 'basic',
currentURL: '/',
params: {
username,
password,
},
},
}).then(() => {
return {
username,
password,
};
});
const headers = { ...STANDARD_HTTP_HEADERS };
return request<LoginState>({ headers, url: `${baseUrl}/internal/security/login_state` })
.then((loginState) => {
const basicProvider = loginState.body.selector.providers.find(
(provider) => provider.type === 'basic'
);
return request({
url: `${baseUrl}/internal/security/login`,
method: 'POST',
headers,
body: {
providerType: basicProvider.type,
providerName: basicProvider.name,
currentURL: '/',
params: { username, password },
},
});
})
.then(() => ({ username, password }));
};
interface CyLoginTask {

View file

@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default ({ getPageObject, getService }: FtrProviderContext) => {
const common = getPageObject('common');
const svlCommonPage = getPageObject('svlCommonPage');
const svlSecNavigation = getService('svlSecNavigation');
const testSubjects = getService('testSubjects');
const cases = getService('cases');
@ -17,6 +18,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
describe('Configure Case', function () {
before(async () => {
await svlCommonPage.login();
await svlSecNavigation.navigateToLandingPage();
await testSubjects.click('solutionSideNavItemLink-cases');
@ -26,6 +29,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
after(async () => {
await cases.api.deleteAllCases();
await svlCommonPage.forceLogout();
});
describe('Closure options', function () {

View file

@ -20,13 +20,19 @@ export default ({ getService, getPageObject }: FtrProviderContext) => {
const cases = getService('cases');
const testSubjects = getService('testSubjects');
const config = getService('config');
const svlCommonPage = getPageObject('svlCommonPage');
beforeEach(async () => {
await navigateToCasesApp(getPageObject, getService, owner);
});
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await cases.api.deleteAllCases();
await svlCommonPage.forceLogout();
});
it('creates a case', async () => {

View file

@ -15,9 +15,12 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
const cases = getService('cases');
const svlSecNavigation = getService('svlSecNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('Cases List', () => {
before(async () => {
await svlCommonPage.login();
await svlSecNavigation.navigateToLandingPage();
await testSubjects.click('solutionSideNavItemLink-cases');
@ -26,6 +29,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
after(async () => {
await cases.api.deleteAllCases();
await cases.casesTable.waitForCasesToBeDeleted();
await svlCommonPage.forceLogout();
});
describe('empty state', () => {

View file

@ -27,8 +27,17 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
const retry = getService('retry');
const comboBox = getService('comboBox');
const svlCommonNavigation = getPageObject('svlCommonNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('Case View', () => {
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await svlCommonPage.forceLogout();
});
describe('page', () => {
createOneCaseBeforeDeleteAllAfter(getPageObject, getService, owner);

View file

@ -10,8 +10,17 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getPageObject, getService }: FtrProviderContext) {
const svlSecLandingPage = getPageObject('svlSecLandingPage');
const svlSecNavigation = getService('svlSecNavigation');
const svlCommonPage = getPageObject('svlCommonPage');
describe('landing page', function () {
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await svlCommonPage.forceLogout();
});
it('has serverless side nav', async () => {
await svlSecNavigation.navigateToLandingPage();
await svlSecLandingPage.assertSvlSecSideNavExists();

View file

@ -9,8 +9,17 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getPageObject }: FtrProviderContext) {
const PageObject = getPageObject('common');
const svlCommonPage = getPageObject('svlCommonPage');
describe('Management', function () {
before(async () => {
await svlCommonPage.login();
});
after(async () => {
await svlCommonPage.forceLogout();
});
it('redirects from common management url to security specific page', async () => {
const SUB_URL = '';
await PageObject.navigateToUrl('management', SUB_URL, {

View file

@ -119,13 +119,12 @@ export default async () => {
])}`,
// This ensures that we register the Security SAML API endpoints.
// In the real world the SAML config is injected by control plane.
// basic: { 'basic': { order: 0 } },
`--plugin-path=${samlIdPPlugin}`,
'--xpack.cloud.id=ftr_fake_cloud_id',
'--xpack.security.authc.selector.enabled=false',
`--xpack.security.authc.providers=${JSON.stringify({
basic: { basic: { order: 0 } },
saml: { 'cloud-saml-kibana': { order: 1, realm: 'cloud-saml-kibana' } },
saml: { 'cloud-saml-kibana': { order: 0, realm: 'cloud-saml-kibana' } },
basic: { 'cloud-basic': { order: 1 } },
})}`,
'--xpack.encryptedSavedObjects.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"',
`--server.publicBaseUrl=${servers.kibana.protocol}://${servers.kibana.hostname}:${servers.kibana.port}`,