mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Enabling Full FTR, Integration, and Unit tests to the FIPS Test Pipeline (#192632)
## Summary Closes #192233 Just in time for Thanksgiving - a full buffet of FIPS testing fixes Usage of non-compliant algorithms manifest as runtime errors, so it is imperative that we attempt to run all tests possible with Kibana in FIPS mode. However, several overrides are needed to run Kibana in FIPS mode, resulting in setup that make it impossible to run. ## In this PR - Enable Unit tests for FIPS pipeline - Enable Integration Tests for FIPS pipeline - Enable Full FTR suite for FIPS pipeline (smoke test had originally run a subset) - Skip tests that break with overrides - Fix/change tests to work in FIPS mode to maximize coverage - Examine necessity of MD5 when installing from source (TBD based Ops PR feed back, see self review below) - Remove md5 from es_file_client options ## Latest Successful FIPS Test Run https://buildkite.com/elastic/kibana-fips/builds/268 --------- Co-authored-by: Brad White <Ikuni17@users.noreply.github.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Larry Gregory <larry.gregory@elastic.co>
This commit is contained in:
parent
3757e64127
commit
ac0b0b4f05
29 changed files with 518 additions and 398 deletions
|
@ -40,14 +40,15 @@ steps:
|
|||
machineType: n2-standard-2
|
||||
preemptible: true
|
||||
|
||||
- command: .buildkite/scripts/steps/fips/smoke_test.sh
|
||||
label: 'Pick Smoke Test Group Run Order'
|
||||
- command: .buildkite/scripts/steps/test/pick_test_group_run_order.sh
|
||||
label: 'Pick Test Group Run Order'
|
||||
depends_on: build
|
||||
timeout_in_minutes: 10
|
||||
env:
|
||||
FTR_CONFIGS_SCRIPT: '.buildkite/scripts/steps/test/ftr_configs.sh'
|
||||
FTR_EXTRA_ARGS: '$FTR_EXTRA_ARGS'
|
||||
LIMIT_CONFIG_TYPE: 'functional'
|
||||
JEST_UNIT_SCRIPT: '.buildkite/scripts/steps/test/jest.sh'
|
||||
JEST_INTEGRATION_SCRIPT: '.buildkite/scripts/steps/test/jest_integration.sh'
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '*'
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Limit the FTR configs for now to avoid running all the tests. Once we're
|
||||
# ready to utilize the full FTR suite in FIPS mode, we can remove this file and
|
||||
# call pick_test_group_run_order.sh directly in .buildkite/pipelines/fips.yml.
|
||||
configs=(
|
||||
"x-pack/test/reporting_functional/reporting_and_security.config.ts"
|
||||
"x-pack/test/saved_object_api_integration/security_and_spaces/config_trial.ts"
|
||||
"x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts"
|
||||
"x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts"
|
||||
"x-pack/test/alerting_api_integration/security_and_spaces/group3/config.ts"
|
||||
"x-pack/test/alerting_api_integration/security_and_spaces/group4/config.ts"
|
||||
"x-pack/test/functional/apps/saved_objects_management/config.ts"
|
||||
"x-pack/test/functional/apps/user_profiles/config.ts"
|
||||
"x-pack/test/functional/apps/security/config.ts"
|
||||
)
|
||||
|
||||
printf -v FTR_CONFIG_PATTERNS '%s,' "${configs[@]}"
|
||||
FTR_CONFIG_PATTERNS="${FTR_CONFIG_PATTERNS%,}"
|
||||
export FTR_CONFIG_PATTERNS
|
||||
|
||||
.buildkite/scripts/steps/test/pick_test_group_run_order.sh
|
|
@ -60,7 +60,14 @@ while read -r config; do
|
|||
# --trace-warnings to debug
|
||||
# Node.js process-warning detected:
|
||||
# Warning: Closing file descriptor 24 on garbage collection
|
||||
cmd="NODE_OPTIONS=\"--max-old-space-size=12288 --trace-warnings\" node ./scripts/jest --config=\"$config\" $parallelism --coverage=false --passWithNoTests"
|
||||
cmd="NODE_OPTIONS=\"--max-old-space-size=12288 --trace-warnings"
|
||||
|
||||
if [ "${KBN_ENABLE_FIPS:-}" == "true" ]; then
|
||||
cmd=$cmd" --enable-fips --openssl-config=$HOME/nodejs.cnf"
|
||||
fi
|
||||
|
||||
cmd=$cmd"\" node ./scripts/jest --config=\"$config\" $parallelism --coverage=false --passWithNoTests"
|
||||
|
||||
echo "actual full command is:"
|
||||
echo "$cmd"
|
||||
echo ""
|
||||
|
|
|
@ -16,17 +16,32 @@ import { loggerMock, MockedLogger } from '@kbn/logging-mocks';
|
|||
import { mockCoreContext } from '@kbn/core-base-server-mocks';
|
||||
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
|
||||
import { SecurityService } from './security_service';
|
||||
import { configServiceMock } from '@kbn/config-mocks';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
const createStubInternalContract = (): CoreSecurityDelegateContract => {
|
||||
return Symbol('stubContract') as unknown as CoreSecurityDelegateContract;
|
||||
};
|
||||
|
||||
describe('SecurityService', () => {
|
||||
describe('SecurityService', function () {
|
||||
let coreContext: ReturnType<typeof mockCoreContext.create>;
|
||||
let configService: ReturnType<typeof configServiceMock.create>;
|
||||
let service: SecurityService;
|
||||
|
||||
beforeEach(() => {
|
||||
coreContext = mockCoreContext.create();
|
||||
const mockConfig = {
|
||||
xpack: {
|
||||
security: {
|
||||
experimental: {
|
||||
fipsMode: {
|
||||
enabled: !!getFips(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
configService = configServiceMock.create({ getConfig$: mockConfig });
|
||||
coreContext = mockCoreContext.create({ configService });
|
||||
service = new SecurityService(coreContext);
|
||||
|
||||
convertSecurityApiMock.mockReset();
|
||||
|
@ -51,8 +66,11 @@ describe('SecurityService', () => {
|
|||
describe('#isEnabled', () => {
|
||||
it('should return boolean', () => {
|
||||
const { fips } = service.setup();
|
||||
|
||||
expect(fips.isEnabled()).toBe(false);
|
||||
if (getFips() === 0) {
|
||||
expect(fips.isEnabled()).toBe(false);
|
||||
} else {
|
||||
expect(fips.isEnabled()).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,5 +22,6 @@
|
|||
"@kbn/core-base-server-mocks",
|
||||
"@kbn/config",
|
||||
"@kbn/core-logging-server-mocks",
|
||||
"@kbn/config-mocks",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -12,10 +12,12 @@ import loadJsonFile from 'load-json-file';
|
|||
import { defaultsDeep } from 'lodash';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import supertest from 'supertest';
|
||||
import { set } from '@kbn/safer-lodash-set';
|
||||
|
||||
import { getPackages } from '@kbn/repo-packages';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { REPO_ROOT } from '@kbn/repo-info';
|
||||
import { getFips } from 'crypto';
|
||||
import {
|
||||
createTestEsCluster,
|
||||
CreateTestEsClusterOptions,
|
||||
|
@ -75,6 +77,17 @@ export function createRootWithSettings(
|
|||
pkg.version = customKibanaVersion;
|
||||
}
|
||||
|
||||
/*
|
||||
* Most of these integration tests expect OSS to default to true, but FIPS
|
||||
* requires the security plugin to be enabled
|
||||
*/
|
||||
let oss = true;
|
||||
if (getFips() === 1) {
|
||||
set(settings, 'xpack.security.experimental.fipsMode.enabled', true);
|
||||
oss = false;
|
||||
delete cliArgs.oss;
|
||||
}
|
||||
|
||||
const env = Env.createDefault(
|
||||
REPO_ROOT,
|
||||
{
|
||||
|
@ -84,10 +97,10 @@ export function createRootWithSettings(
|
|||
watch: false,
|
||||
basePath: false,
|
||||
runExamples: false,
|
||||
oss: true,
|
||||
disableOptimizer: true,
|
||||
cache: true,
|
||||
dist: false,
|
||||
oss,
|
||||
...cliArgs,
|
||||
},
|
||||
repoPackages: getPackages(REPO_ROOT),
|
||||
|
@ -255,7 +268,13 @@ export function createTestServers({
|
|||
if (!adjustTimeout) {
|
||||
throw new Error('adjustTimeout is required in order to avoid flaky tests');
|
||||
}
|
||||
const license = settings.es?.license ?? 'basic';
|
||||
let license = settings.es?.license ?? 'basic';
|
||||
|
||||
if (getFips() === 1) {
|
||||
// Set license to 'trial' if Node is running in FIPS mode
|
||||
license = 'trial';
|
||||
}
|
||||
|
||||
const usersToBeAdded = settings.users ?? [];
|
||||
if (usersToBeAdded.length > 0) {
|
||||
if (license !== 'trial') {
|
||||
|
@ -292,6 +311,7 @@ export function createTestServers({
|
|||
hosts: es.getHostUrls(),
|
||||
username: kibanaServerTestUser.username,
|
||||
password: kibanaServerTestUser.password,
|
||||
...(getFips() ? kbnSettings.elasticsearch : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"@kbn/repo-packages",
|
||||
"@kbn/es",
|
||||
"@kbn/dev-utils",
|
||||
"@kbn/safer-lodash-set",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -84,7 +84,7 @@ async function sourceInfo(cwd: string, license: string, log: ToolingLog = defaul
|
|||
log.info('on %s at %s', chalk.bold(branch), chalk.bold(sha));
|
||||
log.info('%s locally modified file(s)', chalk.bold(status.modified.length));
|
||||
|
||||
const etag = crypto.createHash('md5').update(branch); // eslint-disable-line @kbn/eslint/no_unsafe_hash
|
||||
const etag = crypto.createHash('sha256').update(branch);
|
||||
etag.update(sha);
|
||||
|
||||
// for changed files, use last modified times in hash calculation
|
||||
|
@ -92,7 +92,7 @@ async function sourceInfo(cwd: string, license: string, log: ToolingLog = defaul
|
|||
etag.update(fs.statSync(path.join(cwd, file.path)).mtime.toString());
|
||||
});
|
||||
|
||||
const cwdHash = crypto.createHash('md5').update(cwd).digest('hex').substr(0, 8); // eslint-disable-line @kbn/eslint/no_unsafe_hash
|
||||
const cwdHash = crypto.createHash('sha256').update(cwd).digest('hex').substr(0, 8);
|
||||
|
||||
const basename = `${branch}-${task}-${cwdHash}`;
|
||||
const filename = `${basename}.${ext}`;
|
||||
|
|
|
@ -21,6 +21,7 @@ import type { ToolingLog } from '@kbn/tooling-log';
|
|||
import { REPO_ROOT } from '@kbn/repo-info';
|
||||
import type { ArtifactLicense } from '@kbn/es';
|
||||
import type { ServerlessOptions } from '@kbn/es/src/utils';
|
||||
import { getFips } from 'crypto';
|
||||
import { CI_PARALLEL_PROCESS_PREFIX } from '../ci_parallel_process_prefix';
|
||||
import { esTestConfig } from './es_test_config';
|
||||
|
||||
|
@ -200,12 +201,15 @@ export function createTestEsCluster<
|
|||
|
||||
const esArgs = assignArgs(defaultEsArgs, customEsArgs);
|
||||
|
||||
// Use 'trial' license if FIPS mode is enabled, otherwise use the provided license or default to 'basic'
|
||||
const testLicense: ArtifactLicense = getFips() === 1 ? 'trial' : license ? license : 'basic';
|
||||
|
||||
const config = {
|
||||
version: esVersion,
|
||||
installPath: Path.resolve(basePath, clusterName),
|
||||
sourcePath: Path.resolve(REPO_ROOT, '../elasticsearch'),
|
||||
license: testLicense,
|
||||
password,
|
||||
license,
|
||||
basePath,
|
||||
esArgs,
|
||||
resources: files,
|
||||
|
|
|
@ -16,128 +16,135 @@ import {
|
|||
request,
|
||||
} from '@kbn/core-test-helpers-kbn-server';
|
||||
import { PLUGIN_SYSTEM_ENABLE_ALL_PLUGINS_CONFIG_PATH } from '@kbn/core-plugins-server-internal/src/constants';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('PUT /internal/core/_settings', () => {
|
||||
let esServer: TestElasticsearchUtils;
|
||||
let root: Root;
|
||||
if (getFips() === 0) {
|
||||
describe('PUT /internal/core/_settings', () => {
|
||||
let esServer: TestElasticsearchUtils;
|
||||
let root: Root;
|
||||
|
||||
const loggerName = 'my-test-logger';
|
||||
const loggerName = 'my-test-logger';
|
||||
|
||||
beforeAll(async () => {
|
||||
const settings = {
|
||||
coreApp: { allowDynamicConfigOverrides: true },
|
||||
logging: {
|
||||
loggers: [{ name: loggerName, level: 'error', appenders: ['console'] }],
|
||||
},
|
||||
server: { restrictInternalApis: false },
|
||||
};
|
||||
const { startES, startKibana } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
kbn: settings,
|
||||
},
|
||||
beforeAll(async () => {
|
||||
const settings = {
|
||||
coreApp: { allowDynamicConfigOverrides: true },
|
||||
logging: {
|
||||
loggers: [{ name: loggerName, level: 'error', appenders: ['console'] }],
|
||||
},
|
||||
server: { restrictInternalApis: false },
|
||||
};
|
||||
const { startES, startKibana } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
kbn: settings,
|
||||
},
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
|
||||
const kbnUtils = await startKibana();
|
||||
root = kbnUtils.root;
|
||||
|
||||
// eslint-disable-next-line dot-notation
|
||||
root['server'].configService.addDynamicConfigPaths('logging', ['loggers']); // just for the sake of being able to change something easy to test
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
|
||||
const kbnUtils = await startKibana();
|
||||
root = kbnUtils.root;
|
||||
|
||||
// eslint-disable-next-line dot-notation
|
||||
root['server'].configService.addDynamicConfigPaths('logging', ['loggers']); // just for the sake of being able to change something easy to test
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await root?.shutdown();
|
||||
await esServer?.stop();
|
||||
});
|
||||
|
||||
test('should update the log level', async () => {
|
||||
const logger = root.logger.get(loggerName);
|
||||
expect(logger.isLevelEnabled('info')).toBe(false);
|
||||
await request
|
||||
.put(root, '/internal/core/_settings')
|
||||
.set('Elastic-Api-Version', '1')
|
||||
.send({ 'logging.loggers': [{ name: loggerName, level: 'debug', appenders: ['console'] }] })
|
||||
.expect(200);
|
||||
expect(logger.isLevelEnabled('info')).toBe(true);
|
||||
});
|
||||
|
||||
test('should remove the setting', async () => {
|
||||
const logger = root.logger.get(loggerName);
|
||||
expect(logger.isLevelEnabled('info')).toBe(true); // still true from the previous test
|
||||
await request
|
||||
.put(root, '/internal/core/_settings')
|
||||
.set('Elastic-Api-Version', '1')
|
||||
.send({ 'logging.loggers': null })
|
||||
.expect(200);
|
||||
expect(logger.isLevelEnabled('info')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checking all opted-in dynamic config settings', () => {
|
||||
let root: Root;
|
||||
|
||||
beforeAll(async () => {
|
||||
const settings = {
|
||||
logging: {
|
||||
loggers: [{ name: 'root', level: 'info', appenders: ['console'] }],
|
||||
},
|
||||
server: {
|
||||
restrictInternalApis: false,
|
||||
},
|
||||
};
|
||||
|
||||
set(settings, PLUGIN_SYSTEM_ENABLE_ALL_PLUGINS_CONFIG_PATH, true);
|
||||
|
||||
root = createRootWithCorePlugins(settings, {
|
||||
basePath: false,
|
||||
cache: false,
|
||||
dev: true,
|
||||
disableOptimizer: true,
|
||||
silent: false,
|
||||
dist: false,
|
||||
oss: false,
|
||||
runExamples: false,
|
||||
watch: false,
|
||||
afterAll(async () => {
|
||||
await root?.shutdown();
|
||||
await esServer?.stop();
|
||||
});
|
||||
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
test('should update the log level', async () => {
|
||||
const logger = root.logger.get(loggerName);
|
||||
expect(logger.isLevelEnabled('info')).toBe(false);
|
||||
await request
|
||||
.put(root, '/internal/core/_settings')
|
||||
.set('Elastic-Api-Version', '1')
|
||||
.send({ 'logging.loggers': [{ name: loggerName, level: 'debug', appenders: ['console'] }] })
|
||||
.expect(200);
|
||||
expect(logger.isLevelEnabled('info')).toBe(true);
|
||||
});
|
||||
|
||||
test('should remove the setting', async () => {
|
||||
const logger = root.logger.get(loggerName);
|
||||
expect(logger.isLevelEnabled('info')).toBe(true); // still true from the previous test
|
||||
await request
|
||||
.put(root, '/internal/core/_settings')
|
||||
.set('Elastic-Api-Version', '1')
|
||||
.send({ 'logging.loggers': null })
|
||||
.expect(200);
|
||||
expect(logger.isLevelEnabled('info')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (root) {
|
||||
await root.shutdown();
|
||||
describe('checking all opted-in dynamic config settings', () => {
|
||||
let root: Root;
|
||||
|
||||
beforeAll(async () => {
|
||||
const settings = {
|
||||
logging: {
|
||||
loggers: [{ name: 'root', level: 'info', appenders: ['console'] }],
|
||||
},
|
||||
server: {
|
||||
restrictInternalApis: false,
|
||||
},
|
||||
};
|
||||
|
||||
set(settings, PLUGIN_SYSTEM_ENABLE_ALL_PLUGINS_CONFIG_PATH, true);
|
||||
|
||||
root = createRootWithCorePlugins(settings, {
|
||||
basePath: false,
|
||||
cache: false,
|
||||
dev: true,
|
||||
disableOptimizer: true,
|
||||
silent: false,
|
||||
dist: false,
|
||||
oss: false,
|
||||
runExamples: false,
|
||||
watch: false,
|
||||
});
|
||||
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (root) {
|
||||
await root.shutdown();
|
||||
}
|
||||
});
|
||||
|
||||
function getListOfDynamicConfigPaths(): string[] {
|
||||
// eslint-disable-next-line dot-notation
|
||||
return [...root['server']['configService']['dynamicPaths'].entries()]
|
||||
.flatMap(([configPath, dynamicConfigKeys]) => {
|
||||
return dynamicConfigKeys.map(
|
||||
(dynamicConfigKey: string) => `${configPath}.${dynamicConfigKey}`
|
||||
);
|
||||
})
|
||||
.sort();
|
||||
}
|
||||
});
|
||||
|
||||
function getListOfDynamicConfigPaths(): string[] {
|
||||
// eslint-disable-next-line dot-notation
|
||||
return [...root['server']['configService']['dynamicPaths'].entries()]
|
||||
.flatMap(([configPath, dynamicConfigKeys]) => {
|
||||
return dynamicConfigKeys.map(
|
||||
(dynamicConfigKey: string) => `${configPath}.${dynamicConfigKey}`
|
||||
);
|
||||
})
|
||||
.sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is meant to fail when any setting is flagged as capable
|
||||
* of dynamic configuration {@link PluginConfigDescriptor.dynamicConfig}.
|
||||
*
|
||||
* Please, add your settings to the list with a comment of why it's required to be dynamic.
|
||||
*
|
||||
* The intent is to trigger a code review from the Core and Security teams to discuss potential issues.
|
||||
*/
|
||||
test('detecting all the settings that have opted-in for dynamic in-memory updates', () => {
|
||||
expect(getListOfDynamicConfigPaths()).toStrictEqual([
|
||||
// Making testing easier by having the ability of overriding the feature flags without the need to restart
|
||||
'feature_flags.overrides',
|
||||
// We need this for enriching our Perf tests with more valuable data regarding the steps of the test
|
||||
// Also helpful in Cloud & Serverless testing because we can't control the labels in those offerings
|
||||
'telemetry.labels',
|
||||
]);
|
||||
/**
|
||||
* This test is meant to fail when any setting is flagged as capable
|
||||
* of dynamic configuration {@link PluginConfigDescriptor.dynamicConfig}.
|
||||
*
|
||||
* Please, add your settings to the list with a comment of why it's required to be dynamic.
|
||||
*
|
||||
* The intent is to trigger a code review from the Core and Security teams to discuss potential issues.
|
||||
*/
|
||||
test('detecting all the settings that have opted-in for dynamic in-memory updates', () => {
|
||||
expect(getListOfDynamicConfigPaths()).toStrictEqual([
|
||||
// Making testing easier by having the ability of overriding the feature flags without the need to restart
|
||||
'feature_flags.overrides',
|
||||
// We need this for enriching our Perf tests with more valuable data regarding the steps of the test
|
||||
// Also helpful in Cloud & Serverless testing because we can't control the labels in those offerings
|
||||
'telemetry.labels',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
it('is running in FIPS mode, skipping tests since they fail due to FIPS overrides', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import { loggingSystemMock } from '@kbn/core-logging-server-mocks';
|
||||
import { mockLoggingSystem } from './config_deprecation.test.mocks';
|
||||
import { createRoot } from '@kbn/core-test-helpers-kbn-server';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('configuration deprecations', () => {
|
||||
let root: ReturnType<typeof createRoot>;
|
||||
|
@ -24,13 +25,19 @@ describe('configuration deprecations', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should not log deprecation warnings for default configuration', async () => {
|
||||
root = createRoot();
|
||||
if (getFips() === 0) {
|
||||
it('should not log deprecation warnings for default configuration', async () => {
|
||||
root = createRoot();
|
||||
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
|
||||
const logs = loggingSystemMock.collect(mockLoggingSystem);
|
||||
expect(logs.warn.flat()).toHaveLength(0);
|
||||
});
|
||||
const logs = loggingSystemMock.collect(mockLoggingSystem);
|
||||
expect(logs.warn.flat()).toHaveLength(0);
|
||||
});
|
||||
} else {
|
||||
it('fips is enabled and the default configuration has been overridden', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -14,74 +14,81 @@ import {
|
|||
request,
|
||||
type TestElasticsearchUtils,
|
||||
} from '@kbn/core-test-helpers-kbn-server';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('default route provider', () => {
|
||||
let esServer: TestElasticsearchUtils;
|
||||
let root: Root;
|
||||
|
||||
beforeAll(async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
});
|
||||
esServer = await startES();
|
||||
root = createRootWithCorePlugins({
|
||||
server: {
|
||||
basePath: '/hello',
|
||||
restrictInternalApis: false,
|
||||
},
|
||||
if (getFips() === 0) {
|
||||
beforeAll(async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
});
|
||||
esServer = await startES();
|
||||
root = createRootWithCorePlugins({
|
||||
server: {
|
||||
basePath: '/hello',
|
||||
restrictInternalApis: false,
|
||||
},
|
||||
});
|
||||
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
});
|
||||
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await esServer.stop();
|
||||
await root.shutdown();
|
||||
});
|
||||
|
||||
it('redirects to the configured default route respecting basePath', async function () {
|
||||
const { status, header } = await request.get(root, '/');
|
||||
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/app/home',
|
||||
afterAll(async () => {
|
||||
await esServer.stop();
|
||||
await root.shutdown();
|
||||
});
|
||||
});
|
||||
|
||||
it('ignores invalid values', async function () {
|
||||
const invalidRoutes = [
|
||||
'http://not-your-kibana.com',
|
||||
'///example.com',
|
||||
'//example.com',
|
||||
' //example.com',
|
||||
];
|
||||
it('redirects to the configured default route respecting basePath', async function () {
|
||||
const { status, header } = await request.get(root, '/');
|
||||
|
||||
for (const url of invalidRoutes) {
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/app/home',
|
||||
});
|
||||
});
|
||||
|
||||
it('ignores invalid values', async function () {
|
||||
const invalidRoutes = [
|
||||
'http://not-your-kibana.com',
|
||||
'///example.com',
|
||||
'//example.com',
|
||||
' //example.com',
|
||||
];
|
||||
|
||||
for (const url of invalidRoutes) {
|
||||
await request
|
||||
.post(root, '/internal/kibana/settings/defaultRoute')
|
||||
.send({ value: url })
|
||||
.expect(400);
|
||||
}
|
||||
|
||||
const { status, header } = await request.get(root, '/');
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/app/home',
|
||||
});
|
||||
});
|
||||
|
||||
it('consumes valid values', async function () {
|
||||
await request
|
||||
.post(root, '/internal/kibana/settings/defaultRoute')
|
||||
.send({ value: url })
|
||||
.expect(400);
|
||||
}
|
||||
.send({ value: '/valid' })
|
||||
.expect(200);
|
||||
|
||||
const { status, header } = await request.get(root, '/');
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/app/home',
|
||||
const { status, header } = await request.get(root, '/');
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/valid',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('consumes valid values', async function () {
|
||||
await request
|
||||
.post(root, '/internal/kibana/settings/defaultRoute')
|
||||
.send({ value: '/valid' })
|
||||
.expect(200);
|
||||
|
||||
const { status, header } = await request.get(root, '/');
|
||||
expect(status).toEqual(302);
|
||||
expect(header).toMatchObject({
|
||||
location: '/hello/valid',
|
||||
} else {
|
||||
it('should have fips enabled, the overrides prevent these tests from working', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import { firstValueFrom, Subject } from 'rxjs';
|
|||
import { CliArgs } from '@kbn/config';
|
||||
import Semver from 'semver';
|
||||
import { unsafeConsole } from '@kbn/security-hardening';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
function nextMinor() {
|
||||
return Semver.inc(esTestConfig.getVersion(), 'minor') || '10.0.0';
|
||||
|
@ -130,9 +131,15 @@ describe('Version Compatibility', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should ignore version mismatch when running on serverless mode and complete startup', async () => {
|
||||
await expect(
|
||||
startServers({ customKibanaVersion: nextMinor(), cliArgs: { serverless: true } })
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
if (getFips() === 0) {
|
||||
it('should ignore version mismatch when running on serverless mode and complete startup', async () => {
|
||||
await expect(
|
||||
startServers({ customKibanaVersion: nextMinor(), cliArgs: { serverless: true } })
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
} else {
|
||||
it('fips is enabled, serverless doesnt like the config overrides', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ import { ToolingLog } from '@kbn/tooling-log';
|
|||
import { createTestEsCluster, kibanaServerTestUser } from '@kbn/test';
|
||||
import { observeLines } from '@kbn/stdio-dev-helpers';
|
||||
import { REPO_ROOT } from '@kbn/repo-info';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('migrator-only node', () => {
|
||||
const log = new ToolingLog({ writeTo: process.stdout, level: 'debug' });
|
||||
|
@ -30,6 +31,7 @@ describe('migrator-only node', () => {
|
|||
let logsSub: undefined | Rx.Subscription;
|
||||
try {
|
||||
await es.start();
|
||||
const isFipsEnabled = getFips();
|
||||
|
||||
proc = ChildProcess.spawn(
|
||||
process.execPath,
|
||||
|
@ -42,7 +44,7 @@ describe('migrator-only node', () => {
|
|||
'--no-optimizer',
|
||||
'--no-base-path',
|
||||
'--no-watch',
|
||||
'--oss',
|
||||
isFipsEnabled ? '--xpack.security.experimental.fipsMode.enabled=true' : '--oss',
|
||||
],
|
||||
{ stdio: ['pipe', 'pipe', 'pipe'] }
|
||||
);
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
} from '@kbn/core-test-helpers-kbn-server';
|
||||
import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
|
||||
import { Root } from '@kbn/core-root-server-internal';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
const LOG_FILE_PREFIX = 'migration_test_multiple_es_nodes';
|
||||
|
||||
|
@ -114,89 +115,95 @@ describe('migration v2', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('migrates saved objects normally with multiple ES nodes', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
clusterName: 'es-test-cluster',
|
||||
nodes: [
|
||||
{
|
||||
name: 'node-01',
|
||||
// original SO (5000 total; 2500 of type `foo` + 2500 of type `bar`):
|
||||
// [
|
||||
// { id: 'foo:1', type: 'foo', foo: { status: 'not_migrated_1' } },
|
||||
// { id: 'bar:1', type: 'bar', bar: { status: 'not_migrated_1' } },
|
||||
// { id: 'foo:2', type: 'foo', foo: { status: 'not_migrated_2' } },
|
||||
// { id: 'bar:2', type: 'bar', bar: { status: 'not_migrated_2' } },
|
||||
// ];
|
||||
dataArchive: Path.join(__dirname, '..', 'archives', '7.13.0_5k_so_node_01.zip'),
|
||||
},
|
||||
{
|
||||
name: 'node-02',
|
||||
dataArchive: Path.join(__dirname, '..', 'archives', '7.13.0_5k_so_node_02.zip'),
|
||||
},
|
||||
],
|
||||
if (getFips() === 0) {
|
||||
it('migrates saved objects normally with multiple ES nodes', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
clusterName: 'es-test-cluster',
|
||||
nodes: [
|
||||
{
|
||||
name: 'node-01',
|
||||
// original SO (5000 total; 2500 of type `foo` + 2500 of type `bar`):
|
||||
// [
|
||||
// { id: 'foo:1', type: 'foo', foo: { status: 'not_migrated_1' } },
|
||||
// { id: 'bar:1', type: 'bar', bar: { status: 'not_migrated_1' } },
|
||||
// { id: 'foo:2', type: 'foo', foo: { status: 'not_migrated_2' } },
|
||||
// { id: 'bar:2', type: 'bar', bar: { status: 'not_migrated_2' } },
|
||||
// ];
|
||||
dataArchive: Path.join(__dirname, '..', 'archives', '7.13.0_5k_so_node_01.zip'),
|
||||
},
|
||||
{
|
||||
name: 'node-02',
|
||||
dataArchive: Path.join(__dirname, '..', 'archives', '7.13.0_5k_so_node_02.zip'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
esServer = await startES();
|
||||
|
||||
root = createRoot({
|
||||
logFileName: Path.join(__dirname, `${LOG_FILE_PREFIX}.log`),
|
||||
hosts: esServer.hosts,
|
||||
});
|
||||
root = createRoot({
|
||||
logFileName: Path.join(__dirname, `${LOG_FILE_PREFIX}.log`),
|
||||
hosts: esServer.hosts,
|
||||
});
|
||||
|
||||
await root.preboot();
|
||||
const setup = await root.setup();
|
||||
setup.savedObjects.registerType({
|
||||
name: 'foo',
|
||||
hidden: false,
|
||||
mappings: { properties: { status: { type: 'text' } } },
|
||||
namespaceType: 'agnostic',
|
||||
migrations: {
|
||||
'7.14.0': (doc) => {
|
||||
if (doc.attributes?.status) {
|
||||
doc.attributes.status = doc.attributes.status.replace('not_migrated', 'migrated');
|
||||
}
|
||||
return doc;
|
||||
await root.preboot();
|
||||
const setup = await root.setup();
|
||||
setup.savedObjects.registerType({
|
||||
name: 'foo',
|
||||
hidden: false,
|
||||
mappings: { properties: { status: { type: 'text' } } },
|
||||
namespaceType: 'agnostic',
|
||||
migrations: {
|
||||
'7.14.0': (doc) => {
|
||||
if (doc.attributes?.status) {
|
||||
doc.attributes.status = doc.attributes.status.replace('not_migrated', 'migrated');
|
||||
}
|
||||
return doc;
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
setup.savedObjects.registerType({
|
||||
name: 'bar',
|
||||
hidden: false,
|
||||
mappings: { properties: { status: { type: 'text' } } },
|
||||
namespaceType: 'agnostic',
|
||||
migrations: {
|
||||
'7.14.0': (doc) => {
|
||||
if (doc.attributes?.status) {
|
||||
doc.attributes.status = doc.attributes.status.replace('not_migrated', 'migrated');
|
||||
}
|
||||
return doc;
|
||||
});
|
||||
setup.savedObjects.registerType({
|
||||
name: 'bar',
|
||||
hidden: false,
|
||||
mappings: { properties: { status: { type: 'text' } } },
|
||||
namespaceType: 'agnostic',
|
||||
migrations: {
|
||||
'7.14.0': (doc) => {
|
||||
if (doc.attributes?.status) {
|
||||
doc.attributes.status = doc.attributes.status.replace('not_migrated', 'migrated');
|
||||
}
|
||||
return doc;
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
await root.start();
|
||||
const esClient = esServer.es.getClient();
|
||||
await root.start();
|
||||
const esClient = esServer.es.getClient();
|
||||
|
||||
const migratedFooDocs = await fetchDocs(esClient, migratedIndexAlias, 'foo');
|
||||
expect(migratedFooDocs.length).toBe(2500);
|
||||
migratedFooDocs.forEach((doc, i) => {
|
||||
expect(doc.id).toBe(`foo:${i}`);
|
||||
expect(doc.foo.status).toBe(`migrated_${i}`);
|
||||
expect(doc.typeMigrationVersion).toBe('7.14.0');
|
||||
});
|
||||
const migratedFooDocs = await fetchDocs(esClient, migratedIndexAlias, 'foo');
|
||||
expect(migratedFooDocs.length).toBe(2500);
|
||||
migratedFooDocs.forEach((doc, i) => {
|
||||
expect(doc.id).toBe(`foo:${i}`);
|
||||
expect(doc.foo.status).toBe(`migrated_${i}`);
|
||||
expect(doc.typeMigrationVersion).toBe('7.14.0');
|
||||
});
|
||||
|
||||
const migratedBarDocs = await fetchDocs(esClient, migratedIndexAlias, 'bar');
|
||||
expect(migratedBarDocs.length).toBe(2500);
|
||||
migratedBarDocs.forEach((doc, i) => {
|
||||
expect(doc.id).toBe(`bar:${i}`);
|
||||
expect(doc.bar.status).toBe(`migrated_${i}`);
|
||||
expect(doc.typeMigrationVersion).toBe('7.14.0');
|
||||
const migratedBarDocs = await fetchDocs(esClient, migratedIndexAlias, 'bar');
|
||||
expect(migratedBarDocs.length).toBe(2500);
|
||||
migratedBarDocs.forEach((doc, i) => {
|
||||
expect(doc.id).toBe(`bar:${i}`);
|
||||
expect(doc.bar.status).toBe(`migrated_${i}`);
|
||||
expect(doc.typeMigrationVersion).toBe('7.14.0');
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
it('skips the test when running in FIPS mode since the data archives cause the es nodes to run with a basic license', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '@kbn/core-test-helpers-kbn-server';
|
||||
import { clearLog, readLog, startElasticsearch } from '../kibana_migrator_test_kit';
|
||||
import { delay } from '../test_utils';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
const logFilePath = join(__dirname, 'read_batch_size.log');
|
||||
|
||||
|
@ -36,33 +37,39 @@ describe('migration v2 - read batch size', () => {
|
|||
await delay(5); // give it a few seconds... cause we always do ¯\_(ツ)_/¯
|
||||
});
|
||||
|
||||
it('reduces the read batchSize in half if a batch exceeds maxReadBatchSizeBytes', async () => {
|
||||
root = createRoot({ maxReadBatchSizeBytes: 15000 });
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
if (getFips() === 0) {
|
||||
it('reduces the read batchSize in half if a batch exceeds maxReadBatchSizeBytes', async () => {
|
||||
root = createRoot({ maxReadBatchSizeBytes: 15000 });
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await readLog(logFilePath);
|
||||
// Check for migration steps present in the logs
|
||||
logs = await readLog(logFilePath);
|
||||
|
||||
expect(logs).toMatch(
|
||||
/Read a batch with a response content length of \d+ bytes which exceeds migrations\.maxReadBatchSizeBytes, retrying by reducing the batch size in half to 15/
|
||||
);
|
||||
expect(logs).toMatch('[.kibana] Migration completed');
|
||||
});
|
||||
expect(logs).toMatch(
|
||||
/Read a batch with a response content length of \d+ bytes which exceeds migrations\.maxReadBatchSizeBytes, retrying by reducing the batch size in half to 15/
|
||||
);
|
||||
expect(logs).toMatch('[.kibana] Migration completed');
|
||||
});
|
||||
|
||||
it('does not reduce the read batchSize in half if no batches exceeded maxReadBatchSizeBytes', async () => {
|
||||
root = createRoot({ maxReadBatchSizeBytes: 50000 });
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
it('does not reduce the read batchSize in half if no batches exceeded maxReadBatchSizeBytes', async () => {
|
||||
root = createRoot({ maxReadBatchSizeBytes: 50000 });
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await readLog(logFilePath);
|
||||
// Check for migration steps present in the logs
|
||||
logs = await readLog(logFilePath);
|
||||
|
||||
expect(logs).not.toMatch('retrying by reducing the batch size in half to');
|
||||
expect(logs).toMatch('[.kibana] Migration completed');
|
||||
});
|
||||
expect(logs).not.toMatch('retrying by reducing the batch size in half to');
|
||||
expect(logs).toMatch('[.kibana] Migration completed');
|
||||
});
|
||||
} else {
|
||||
it('cannot run tests with dataArchives that have a basic licesne in FIPS mode', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function createRoot({ maxReadBatchSizeBytes }: { maxReadBatchSizeBytes?: number }) {
|
||||
|
|
|
@ -13,28 +13,35 @@ import {
|
|||
TestServerlessKibanaUtils,
|
||||
createTestServerlessInstances,
|
||||
} from '@kbn/core-test-helpers-kbn-server';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('Basic smoke test', () => {
|
||||
describe('Basic smoke test', function () {
|
||||
let serverlessES: TestServerlessESUtils;
|
||||
let serverlessKibana: TestServerlessKibanaUtils;
|
||||
let root: TestServerlessKibanaUtils['root'];
|
||||
|
||||
beforeEach(async () => {
|
||||
const { startES, startKibana } = createTestServerlessInstances({
|
||||
adjustTimeout: jest.setTimeout,
|
||||
if (getFips() === 0) {
|
||||
beforeEach(async () => {
|
||||
const { startES, startKibana } = createTestServerlessInstances({
|
||||
adjustTimeout: jest.setTimeout,
|
||||
});
|
||||
serverlessES = await startES();
|
||||
serverlessKibana = await startKibana();
|
||||
root = serverlessKibana.root;
|
||||
});
|
||||
serverlessES = await startES();
|
||||
serverlessKibana = await startKibana();
|
||||
root = serverlessKibana.root;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await serverlessES?.stop();
|
||||
await serverlessKibana?.stop();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await serverlessES?.stop();
|
||||
await serverlessKibana?.stop();
|
||||
});
|
||||
|
||||
test('it can start Kibana running against serverless ES', async () => {
|
||||
const { body } = await request.get(root, '/api/status').expect(200);
|
||||
expect(body).toMatchObject({ status: { overall: { level: 'available' } } });
|
||||
});
|
||||
test('it can start Kibana running against serverless ES', async () => {
|
||||
const { body } = await request.get(root, '/api/status').expect(200);
|
||||
expect(body).toMatchObject({ status: { overall: { level: 'available' } } });
|
||||
});
|
||||
} else {
|
||||
test('FIPS is enabled, serverless doesnt like the config overrides', () => {
|
||||
expect(getFips()).toBe(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import { chmodSync, statSync } from 'fs';
|
|||
import del from 'del';
|
||||
|
||||
import { mkdirp, write, read, getChildPaths, copyAll, getFileHash, untar, gunzip } from '../fs';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
const TMP = resolve(__dirname, '../__tmp__');
|
||||
const FIXTURES = resolve(__dirname, '../__fixtures__');
|
||||
|
@ -266,9 +267,12 @@ describe('getFileHash()', () => {
|
|||
'7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730'
|
||||
);
|
||||
});
|
||||
it('resolves with the md5 hash of a file', async () => {
|
||||
expect(await getFileHash(BAR_TXT_PATH, 'md5')).toBe('c157a79031e1c40f85931829bc5fc552');
|
||||
});
|
||||
|
||||
if (getFips() !== 1) {
|
||||
it('resolves with the md5 hash of a file', async () => {
|
||||
expect(await getFileHash(BAR_TXT_PATH, 'md5')).toBe('c157a79031e1c40f85931829bc5fc552');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('untar()', () => {
|
||||
|
|
|
@ -27,10 +27,13 @@ describe('Elasticsearch blob storage', () => {
|
|||
|
||||
beforeAll(async () => {
|
||||
ElasticsearchBlobStorageClient.configureConcurrentTransfers(Infinity);
|
||||
const { startES, startKibana } = createTestServers({ adjustTimeout: jest.setTimeout });
|
||||
|
||||
const { startES, startKibana } = createTestServers({
|
||||
adjustTimeout: jest.setTimeout,
|
||||
});
|
||||
manageES = await startES();
|
||||
manageKbn = await startKibana();
|
||||
esClient = manageKbn.coreStart.elasticsearch.client.asInternalUser;
|
||||
esClient = manageKbn.coreStart.elasticsearch.createClient('es.test').asInternalUser;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
import type { Logger, ElasticsearchClient } from '@kbn/core/server';
|
||||
import { getFips } from 'crypto';
|
||||
import { ElasticsearchBlobStorageClient } from '../blob_storage_service';
|
||||
import { FileClientImpl } from './file_client';
|
||||
import type { FileClient } from './types';
|
||||
|
@ -66,12 +67,18 @@ export function createEsFileClient(arg: CreateEsFileClientArgs): FileClient {
|
|||
maxSizeBytes,
|
||||
indexIsAlias,
|
||||
} = arg;
|
||||
|
||||
let hashes: Array<'sha1' | 'sha256' | 'sha512' | 'md5'> = ['sha1', 'sha256', 'sha512'];
|
||||
if (getFips() !== 1) {
|
||||
hashes = ['md5', ...hashes];
|
||||
}
|
||||
|
||||
return new FileClientImpl(
|
||||
{
|
||||
id: NO_FILE_KIND,
|
||||
http: {},
|
||||
maxSizeBytes,
|
||||
hashes: ['md5', 'sha1', 'sha256', 'sha512'],
|
||||
hashes,
|
||||
},
|
||||
new EsIndexFilesMetadataClient(metadataIndex, elasticsearchClient, logger, indexIsAlias),
|
||||
new ElasticsearchBlobStorageClient(
|
||||
|
|
|
@ -13,6 +13,7 @@ import { TestEnvironmentUtils, setupIntegrationEnvironment } from '../../test_ut
|
|||
import { createEsFileClient } from '../create_es_file_client';
|
||||
import { FileClient } from '../types';
|
||||
import { FileMetadata } from '../../../common';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('ES-index-backed file client', () => {
|
||||
let esClient: TestEnvironmentUtils['esClient'];
|
||||
|
@ -107,13 +108,21 @@ describe('ES-index-backed file client', () => {
|
|||
});
|
||||
await file.uploadContent(Readable.from([Buffer.from('test')]));
|
||||
|
||||
expect(file.toJSON().hash).toStrictEqual({
|
||||
md5: '098f6bcd4621d373cade4e832627b4f6',
|
||||
let expected: Record<string, string> = {
|
||||
sha1: 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3',
|
||||
sha256: '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
||||
sha512:
|
||||
'ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff',
|
||||
});
|
||||
};
|
||||
|
||||
if (getFips() !== 1) {
|
||||
expected = {
|
||||
md5: '098f6bcd4621d373cade4e832627b4f6',
|
||||
...expected,
|
||||
};
|
||||
}
|
||||
|
||||
expect(file.toJSON().hash).toStrictEqual(expected);
|
||||
|
||||
await deleteFile({ id: file.id, hasContent: true });
|
||||
});
|
||||
|
|
|
@ -24,6 +24,8 @@ import { BlobStorageService } from '../../../blob_storage_service';
|
|||
import { InternalFileShareService } from '../../../file_share_service';
|
||||
import { InternalFileService } from '../../../file_service/internal_file_service';
|
||||
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
describe('When using the FileHashTransform', () => {
|
||||
let file: IFile;
|
||||
let fileContent: Readable;
|
||||
|
@ -75,23 +77,25 @@ describe('When using the FileHashTransform', () => {
|
|||
expect(() => fileHash.getFileHash()).toThrow('File hash generation not yet complete');
|
||||
});
|
||||
|
||||
it.each([
|
||||
['md5', '098f6bcd4621d373cade4e832627b4f6'],
|
||||
['sha1', 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'],
|
||||
['sha256', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'],
|
||||
[
|
||||
'sha512',
|
||||
'ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff',
|
||||
],
|
||||
] as Array<[SupportedFileHashAlgorithm, string]>)(
|
||||
'should generate file hash using algorithm: %s',
|
||||
async (algorithm, expectedHash) => {
|
||||
const fileHash = createFileHashTransform(algorithm);
|
||||
await file.uploadContent(fileContent, undefined, {
|
||||
transforms: [fileHash],
|
||||
});
|
||||
describe('algorithms', function () {
|
||||
it.each([
|
||||
...(getFips() !== 1 ? [['md5', '098f6bcd4621d373cade4e832627b4f6']] : []),
|
||||
['sha1', 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'],
|
||||
['sha256', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'],
|
||||
[
|
||||
'sha512',
|
||||
'ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff',
|
||||
],
|
||||
] as Array<[SupportedFileHashAlgorithm, string]>)(
|
||||
'should generate file hash using algorithm: %s',
|
||||
async (algorithm, expectedHash) => {
|
||||
const fileHash = createFileHashTransform(algorithm);
|
||||
await file.uploadContent(fileContent, undefined, {
|
||||
transforms: [fileHash],
|
||||
});
|
||||
|
||||
expect(fileHash.getFileHash()).toEqual({ algorithm, value: expectedHash });
|
||||
}
|
||||
);
|
||||
expect(fileHash.getFileHash()).toEqual({ algorithm, value: expectedHash });
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
|
||||
describe('dashboard panel listing', () => {
|
||||
describe('dashboard panel listing', function () {
|
||||
this.tags('skipFIPS');
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await kibanaServer.importExport.load(
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
export default function ({ getService }) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('kibana server with ssl', () => {
|
||||
describe('kibana server with ssl', function () {
|
||||
this.tags('skipFIPS');
|
||||
it('handles requests using ssl with a P12 keystore', async () => {
|
||||
await supertest.get('/').expect(302);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
export default function ({ getService }) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('kibana server with ssl', () => {
|
||||
describe('kibana server with ssl', function () {
|
||||
this.tags('skipFIPS');
|
||||
it('handles requests using ssl with a P12 keystore that uses an intermediate CA', async () => {
|
||||
await supertest.get('/').expect(302);
|
||||
});
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
DEFAULT_MICROSOFT_GRAPH_API_SCOPE,
|
||||
DEFAULT_MICROSOFT_GRAPH_API_URL,
|
||||
} from '../../common';
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
const logger = loggingSystemMock.create().get() as jest.Mocked<Logger>;
|
||||
|
||||
|
@ -251,19 +252,6 @@ describe('axios connections', () => {
|
|||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
test('it works with pfx and passphrase in SSL overrides', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
testServer = server;
|
||||
|
||||
const configurationUtilities = getACUfromConfig();
|
||||
const sslOverrides = {
|
||||
pfx: KIBANA_P12,
|
||||
passphrase: 'storepass',
|
||||
};
|
||||
const res = await request({ axios, url, logger, configurationUtilities, sslOverrides });
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
test('it fails with cert and key but no ca in SSL overrides', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
testServer = server;
|
||||
|
@ -278,18 +266,33 @@ describe('axios connections', () => {
|
|||
await expect(fn()).rejects.toThrow('certificate');
|
||||
});
|
||||
|
||||
test('it fails with pfx but no passphrase in SSL overrides', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
testServer = server;
|
||||
if (getFips() !== 1) {
|
||||
test('it works with pfx and passphrase in SSL overrides', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
testServer = server;
|
||||
|
||||
const configurationUtilities = getACUfromConfig();
|
||||
const sslOverrides = {
|
||||
pfx: KIBANA_P12,
|
||||
};
|
||||
const fn = async () =>
|
||||
await request({ axios, url, logger, configurationUtilities, sslOverrides });
|
||||
await expect(fn()).rejects.toThrow('mac verify');
|
||||
});
|
||||
const configurationUtilities = getACUfromConfig();
|
||||
const sslOverrides = {
|
||||
pfx: KIBANA_P12,
|
||||
passphrase: 'storepass',
|
||||
};
|
||||
const res = await request({ axios, url, logger, configurationUtilities, sslOverrides });
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
test('it fails with pfx but no passphrase in SSL overrides', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
testServer = server;
|
||||
|
||||
const configurationUtilities = getACUfromConfig();
|
||||
const sslOverrides = {
|
||||
pfx: KIBANA_P12,
|
||||
};
|
||||
const fn = async () =>
|
||||
await request({ axios, url, logger, configurationUtilities, sslOverrides });
|
||||
await expect(fn()).rejects.toThrow('mac verify');
|
||||
});
|
||||
}
|
||||
|
||||
test('it fails with a client-side certificate issued by an invalid ca', async () => {
|
||||
const { url, server } = await createServer({ useHttps: true, requestCert: true });
|
||||
|
|
|
@ -5,22 +5,30 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getFips } from 'crypto';
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
import { createElement } from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
|
||||
describe('Fleet Storybook Smoke', () => {
|
||||
test('Init', async () => {
|
||||
await initStoryshots({
|
||||
configPath: __dirname,
|
||||
framework: 'react',
|
||||
test: async ({ story }) => {
|
||||
const renderer = mount(createElement(story.render));
|
||||
// wait until the element will perform all renders and resolve all promises (lazy loading, especially)
|
||||
await act(() => new Promise((resolve) => setTimeout(resolve, 0)));
|
||||
expect(renderer.html()).not.toContain('euiErrorBoundary');
|
||||
},
|
||||
describe('Fleet Storybook Smoke', function () {
|
||||
if (getFips() !== 1) {
|
||||
test('Init', async () => {
|
||||
await initStoryshots({
|
||||
configPath: __dirname,
|
||||
framework: 'react',
|
||||
test: async ({ story }) => {
|
||||
const renderer = mount(createElement(story.render));
|
||||
// wait until the element will perform all renders and resolve all promises (lazy loading, especially)
|
||||
await act(() => new Promise((resolve) => setTimeout(resolve, 0)));
|
||||
expect(renderer.html()).not.toContain('euiErrorBoundary');
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
test('fips is enabled', function () {
|
||||
expect(getFips() === 1).toEqual(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -152,7 +152,6 @@ export async function hashSecret(secret: string) {
|
|||
|
||||
return `${salt}:${derivedKey.toString('hex')}`;
|
||||
}
|
||||
|
||||
async function verifySecret(hash: string, secret: string) {
|
||||
const [salt, key] = hash.split(':');
|
||||
const derivedKey = await pbkdf2Async(secret, salt, maxIteration, keyLength, 'sha512');
|
||||
|
|
|
@ -15,6 +15,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const security = getService('security');
|
||||
|
||||
describe('Read only view', function () {
|
||||
this.tags('skipFIPS');
|
||||
before(async () => {
|
||||
await security.testUser.setRoles(['read_ilm']);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue