Files
b51b4a8937 Fix FIPS-incompatible passwords and config in e2e test suites (#36001)
* Fix FIPS-incompatible passwords and config in e2e test suites

FIPS OpenSSL requires PBKDF2 HMAC keys >= 14 bytes, so the server
now enforces PasswordSettings.MinimumLength >= 14 under FIPS builds.
The e2e suites were failing (Cypress 0/447, Playwright 16/353) because
they used short passwords and set MinimumLength below the FIPS floor.

- Add newTestPassword() to both Cypress and Playwright utilities,
  returning a static FIPS-compliant password (>= 14 chars)
- Replace all short hardcoded Mattermost user passwords ('passwd',
  'Test123456!', 'Testing123', 'Password123!') with newTestPassword()
- Raise PasswordSettings.MinimumLength from 5 to 14 in default configs
- Update password validation tests for the FIPS minimum (error messages,
  default expectations, test password lengths)

* Fix additional FIPS e2e test failures

- Revert server-constant-dependent assertions (MinimumLength defaults
  and validation errors) since those depend on FIPS build tags, not config
- Fix short hardcoded passwords in signup, forgot_password, and
  existing_email_address specs to use newTestPassword()
- Fix password_spec cancel test to use a different password than
  testUser.password (both resolve to newTestPassword())
- Fix Playwright password reset test to use newTestPassword() instead
  of pw.random.id() (7 chars, too short for MinimumLength=14)
- Update password help text assertions to match MinimumLength=14 config
- Use regex for Playwright signup page password error locator
- Fix import order in ABAC support.ts

* Fix FIPS vs non-FIPS build-dependent e2e test assertions

The server's password minimum constants differ between FIPS (14) and
non-FIPS (8/5) builds. Make three test assertions adaptive:

- MM-T1770: Accept default MinimumLength of either 8 or 14
- MM-T1771: Match validation error with either 5 or 14 as the minimum
- MM-T1773: Reload after save and compare against actual server config,
  since saving MinimumLength=5 (webapp default) is rejected on FIPS

* e2e: upgrade demo plugin to v0.11.0 and configure required settings

* update demo plugin download link

---------

Co-authored-by: sabril <[email protected]>
2026-04-13 12:52:13 +08:00

105 lines
3.2 KiB
JavaScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {v4 as uuidv4} from 'uuid';
import messageMenusData from '../fixtures/hooks/message_menus.json';
import messageMenusWithDatasourceData from '../fixtures/hooks/message_menus_with_datasource.json';
export * from './constants';
export * from './email';
export * from './file';
export * from './plugins';
/**
* @param {Number} length - length on random string to return, e.g. 7 (default)
* @return {String} random string
*/
export function getRandomId(length = 7) {
const MAX_SUBSTRING_INDEX = 27;
return uuidv4().replace(/-/g, '').substring(MAX_SUBSTRING_INDEX - length, MAX_SUBSTRING_INDEX);
}
export function getRandomLetter(length) {
return Array.from({length}, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('');
}
export function getMessageMenusPayload({dataSource, options, prefix = Date.now()} = {}) {
let data;
if (dataSource) {
data = messageMenusWithDatasourceData;
data.attachments[0].actions[0].data_source = dataSource;
data.attachments[0].pretext = `${prefix}: This is attachment pretext with ${dataSource} options`;
data.attachments[0].text = `${prefix}: This is attachment text with ${dataSource} options`;
} else {
data = messageMenusData;
data.attachments[0].pretext = `${prefix}: This is attachment pretext with basic options`;
data.attachments[0].text = `${prefix}: This is attachment text with basic options`;
if (options) {
data.attachments[0].actions[0].options = options;
}
}
const callbackUrl = Cypress.env().webhookBaseUrl + '/message_menus';
data.attachments[0].actions[0].integration.url = callbackUrl;
return data;
}
export function hexToRgbArray(hex) {
const rgbArr = hex.replace('#', '').match(/.{1,2}/g);
return [
parseInt(rgbArr[0], 16),
parseInt(rgbArr[1], 16),
parseInt(rgbArr[2], 16),
];
}
export function rgbArrayToString(rgbArr) {
return `rgb(${rgbArr[0]}, ${rgbArr[1]}, ${rgbArr[2]})`;
}
// Returns a FIPS-compliant test password (>= 14 chars with complexity).
// Static for now but could generate unique passwords if requirements change.
export function newTestPassword() {
return 'Passwd4Testing!';
}
export const reUrl = /(https?:\/\/[^ ]*)/;
const userAgent = () => window.navigator.userAgent;
export function isWindows() {
return userAgent().indexOf('Windows') !== -1;
}
export function isMac() {
return userAgent().indexOf('Macintosh') !== -1;
}
// Stubs out the clipboard so that we can intercept copy events. Note that this only stubs out calls to
// navigator.clipboard.writeText and not document.execCommand.
export function stubClipboard() {
const clipboard = {contents: '', wasCalled: false};
cy.window().then((win) => {
if (!win.navigator.clipboard) {
win.navigator.clipboard = {
writeText: () => {},
};
}
cy.stub(win.navigator.clipboard, 'writeText').callsFake((link) => {
clipboard.wasCalled = true;
clipboard.contents = link;
return Promise.resolve(true);
});
});
return cy.wrap(clipboard);
}