Skip to content

Commit 02916a8

Browse files
authored
Merge pull request #2950 from RedisInsight/e2e/feature/RI-5072-docker-encryption
E2e/feature/ri 5072 docker encryption
2 parents c385cef + ea4f296 commit 02916a8

File tree

11 files changed

+161
-80
lines changed

11 files changed

+161
-80
lines changed

tests/e2e/docker.web.docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ services:
4242
env_file:
4343
- ./.env
4444
environment:
45+
RI_ENCRYPTION_KEY: $E2E_RI_ENCRYPTION_KEY
4546
RI_SERVER_TLS_CERT: $RI_SERVER_TLS_CERT
4647
RI_SERVER_TLS_KEY: $RI_SERVER_TLS_KEY
4748
volumes:

tests/e2e/helpers/database-scripts.ts

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,70 +3,84 @@ import { workingDirectory } from '../helpers/conf';
33

44
const dbPath = `${workingDirectory}/redisinsight.db`;
55

6-
/**
7-
* Update table column value into local DB
8-
* @param tableName The name of table in DB
9-
* @param columnName The name of column in table
10-
* @param value Value to update in table
11-
*/
12-
export async function updateColumnValueInDBTable(tableName: string, columnName: string, value: number | string): Promise<void> {
13-
const db = new sqlite3.Database(dbPath);
14-
const query = `UPDATE ${tableName} SET ${columnName} = ${value}`;
6+
export class DatabaseScripts {
7+
/**
8+
* Update table column value into local DB for a specific row
9+
* @param dbTableParameters The sqlite database table parameters
10+
*/
11+
static async updateColumnValueInDBTable(dbTableParameters: DbTableParameters): Promise<void> {
12+
const db = new sqlite3.Database(dbPath);
13+
const query = `UPDATE ${dbTableParameters.tableName} SET ${dbTableParameters.columnName} = ? WHERE ${dbTableParameters.conditionWhereColumnName} = ?`;
1514

16-
return new Promise<void>((resolve, reject) => {
17-
db.run(query, (err: { message: string }) => {
18-
if (err) {
19-
reject(new Error(`Error during changing ${columnName} column value: ${err.message}`));
20-
}
21-
else {
22-
db.close();
23-
resolve();
24-
}
15+
return new Promise<void>((resolve, reject) => {
16+
db.run(query, [dbTableParameters.rowValue, dbTableParameters.conditionWhereColumnValue], (err: { message: string }) => {
17+
if (err) {
18+
reject(new Error(`Error during changing ${dbTableParameters.columnName} column value: ${err.message}`));
19+
}
20+
else {
21+
db.close();
22+
resolve();
23+
}
24+
});
2525
});
26-
});
27-
}
26+
}
2827

29-
/**
30-
* Get Column value from table in local Database
31-
* @param tableName The name of table in DB
32-
* @param columnName The name of column in table
33-
*/
34-
export async function getColumnValueFromTableInDB(tableName: string, columnName: string): Promise<any> {
35-
const db = new sqlite3.Database(dbPath);
36-
const query = `SELECT ${columnName} FROM ${tableName}`;
28+
/**
29+
* Get Column value from table in local Database
30+
* @param dbTableParameters The sqlite database table parameters
31+
*/
32+
static async getColumnValueFromTableInDB(dbTableParameters: DbTableParameters): Promise<any> {
33+
const db = new sqlite3.Database(dbPath);
34+
const query = `SELECT ${dbTableParameters.columnName} FROM ${dbTableParameters.tableName} WHERE ${dbTableParameters.conditionWhereColumnName} = ?`;
3735

38-
return new Promise<void>((resolve, reject) => {
39-
db.get(query, (err: { message: string }, row: any) => {
40-
if (err) {
41-
reject(new Error(`Error during getting ${columnName} column value: ${err.message}`));
42-
}
43-
else {
44-
const columnValue = row[columnName];
45-
db.close();
46-
resolve(columnValue);
47-
}
36+
return new Promise<void>((resolve, reject) => {
37+
db.get(query, [dbTableParameters.conditionWhereColumnValue], (err: { message: string }, row: any) => {
38+
if (err) {
39+
reject(new Error(`Error during getting ${dbTableParameters.columnName} column value: ${err.message}`));
40+
}
41+
else {
42+
const columnValue = row[dbTableParameters.columnName!];
43+
db.close();
44+
resolve(columnValue);
45+
}
46+
});
4847
});
49-
});
50-
}
48+
}
5149

52-
/**
53-
* Delete all rows from table in local DB
54-
* @param tableName The name of table in DB
55-
*/
56-
export async function deleteRowsFromTableInDB(tableName: string): Promise<void> {
57-
const db = new sqlite3.Database(dbPath);
58-
const query = `DELETE FROM ${tableName}`;
50+
/**
51+
* Delete all rows from table in local DB
52+
* @param dbTableParameters The sqlite database table parameters
53+
*/
54+
static async deleteRowsFromTableInDB(dbTableParameters: DbTableParameters): Promise<void> {
55+
const db = new sqlite3.Database(dbPath);
56+
const query = `DELETE FROM ${dbTableParameters.tableName}`;
5957

60-
return new Promise<void>((resolve, reject) => {
58+
return new Promise<void>((resolve, reject) => {
6159

62-
db.run(query, (err: { message: string }) => {
63-
if (err) {
64-
reject(new Error(`Error during ${tableName} table rows deletion: ${err.message}`));
65-
}
66-
else {
67-
db.close();
68-
resolve();
69-
}
60+
db.run(query, (err: { message: string }) => {
61+
if (err) {
62+
reject(new Error(`Error during ${dbTableParameters.tableName} table rows deletion: ${err.message}`));
63+
}
64+
else {
65+
db.close();
66+
resolve();
67+
}
68+
});
7069
});
71-
});
70+
}
7271
}
72+
/**
73+
* Add new database parameters
74+
* @param tableName The name of table in DB
75+
* @param columnName The name of column in table
76+
* @param rowValue Value to update in table
77+
* @param conditionWhereColumnName The name of the column to search
78+
* @param conditionWhereColumnValue The value to match in the column
79+
*/
80+
export type DbTableParameters = {
81+
tableName: string,
82+
columnName?: string,
83+
rowValue?: string | number,
84+
conditionWhereColumnName?: string,
85+
conditionWhereColumnValue?: string
86+
};

tests/e2e/helpers/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { DatabaseScripts, DbTableParameters } from './database-scripts';
2+
import { Common } from './common';
3+
import { DatabaseHelper } from './database';
4+
import { Telemetry } from './telemetry';
5+
6+
export {
7+
DatabaseScripts,
8+
DbTableParameters,
9+
Common,
10+
DatabaseHelper,
11+
Telemetry
12+
};

tests/e2e/helpers/insights.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import * as path from 'path';
22
import * as fs from 'fs-extra';
33
import { BasePage } from '../pageObjects';
4-
import { deleteRowsFromTableInDB, updateColumnValueInDBTable } from './database-scripts';
54
import { syncFeaturesApi } from './api/api-info';
5+
import { DatabaseScripts, DbTableParameters } from './database-scripts';
66

77
const basePage = new BasePage();
8+
const dbTableParams: DbTableParameters = {
9+
tableName: 'features_config',
10+
columnName: 'controlNumber',
11+
conditionWhereColumnName: 'id',
12+
conditionWhereColumnValue: '1'
13+
};
814

915
/**
1016
* Update features-config file for static server
@@ -21,7 +27,7 @@ export async function modifyFeaturesConfigJson(filePath: string): Promise<void>
2127
fs.writeFileSync(targetFilePath, fs.readFileSync(filePath));
2228
resolve();
2329
}
24-
catch (err) {
30+
catch (err: any) {
2531
reject(new Error(`Error updating remote config file: ${err.message}`));
2632
}
2733
});
@@ -32,10 +38,8 @@ export async function modifyFeaturesConfigJson(filePath: string): Promise<void>
3238
* @param controlNumber Control number to update
3339
*/
3440
export async function updateControlNumber(controlNumber: number): Promise<void> {
35-
const featuresConfigTable = 'features_config';
36-
3741
await syncFeaturesApi();
38-
await updateColumnValueInDBTable(featuresConfigTable, 'controlNumber', controlNumber);
42+
await DatabaseScripts.updateColumnValueInDBTable({ ...dbTableParams, rowValue: controlNumber });
3943
await syncFeaturesApi();
4044
await basePage.reloadPage();
4145
}
@@ -44,10 +48,9 @@ export async function updateControlNumber(controlNumber: number): Promise<void>
4448
* Refresh test data for features sync
4549
*/
4650
export async function refreshFeaturesTestData(): Promise<void> {
47-
const featuresConfigTable = 'features_config';
4851
const defaultConfigPath = path.join('.', 'test-data', 'features-configs', 'insights-default-remote.json');
4952

5053
await modifyFeaturesConfigJson(defaultConfigPath);
51-
await deleteRowsFromTableInDB(featuresConfigTable);
54+
await DatabaseScripts.deleteRowsFromTableInDB(dbTableParams);
5255
await syncFeaturesApi();
5356
}

tests/e2e/local.web.docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ services:
4646
context: ./../../
4747
dockerfile: Dockerfile
4848
environment:
49+
RI_ENCRYPTION_KEY: $E2E_RI_ENCRYPTION_KEY
4950
RI_SERVER_TLS_CERT: $RI_SERVER_TLS_CERT
5051
RI_SERVER_TLS_KEY: $RI_SERVER_TLS_KEY
5152
volumes:

tests/e2e/tests/electron/critical-path/a-first-start-form/user-agreements-form.e2e.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ test('Verify that user should accept User Agreements to continue working with th
1717
await t.expect(userAgreementDialog.submitButton.hasAttribute('disabled')).ok('Submit button not disabled by default');
1818
await t.expect(myRedisDatabasePage.AddRedisDatabase.addDatabaseManually.exists).notOk('User can\'t add a database');
1919
});
20-
// Skipped due to docker currently doesn't support encryption https://redislabs.atlassian.net/browse/RI-5036
21-
test.skip('Verify that the encryption enabled by default and specific message', async t => {
20+
test('Verify that the encryption enabled by default and specific message', async t => {
2221
const expectedPluginText = 'To avoid automatic execution of malicious code, when adding new Workbench plugins, use files from trusted authors only.';
2322
// Verify that section with plugin warning is displayed
2423
await t.expect(userAgreementDialog.pluginSectionWithText.exists).ok('Plugin text is not displayed');

tests/e2e/tests/electron/regression/database/cloud-sso.e2e.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import { rte } from '../../../../helpers/constants';
44
import { DatabaseHelper } from '../../../../helpers/database';
55
import { commonUrl } from '../../../../helpers/conf';
66
import { DatabaseAPIRequests } from '../../../../helpers/api/api-database';
7-
import { deleteRowsFromTableInDB } from '../../../../helpers/database-scripts';
7+
import { DatabaseScripts } from '../../../../helpers/database-scripts';
88
import { modifyFeaturesConfigJson, updateControlNumber } from '../../../../helpers/insights';
99

1010
const myRedisDatabasePage = new MyRedisDatabasePage();
1111
const databaseHelper = new DatabaseHelper();
1212
const databaseAPIRequests = new DatabaseAPIRequests();
1313
const welcomePage = new WelcomePage();
1414

15-
const featuresConfigTable = 'features_config';
1615
const pathes = {
1716
defaultRemote: path.join('.', 'test-data', 'features-configs', 'insights-default-remote.json'),
1817
dockerConfig: path.join('.', 'test-data', 'features-configs', 'sso-docker-build.json'),
@@ -32,7 +31,7 @@ fixture `Cloud SSO`
3231
// Update remote config .json to default
3332
await modifyFeaturesConfigJson(pathes.defaultRemote);
3433
// Clear features config table
35-
await deleteRowsFromTableInDB(featuresConfigTable);
34+
await DatabaseScripts.deleteRowsFromTableInDB({ tableName: 'features_config' });
3635
});
3736
test('Verify that user can see SSO feature if it is enabled in feature config', async t => {
3837
// Update remote config .json to config with buildType filter excluding current app build

tests/e2e/tests/electron/regression/insights/feature-flag.e2e.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import { rte } from '../../../../helpers/constants';
44
import { DatabaseHelper } from '../../../../helpers/database';
55
import { commonUrl, ossStandaloneV5Config } from '../../../../helpers/conf';
66
import { DatabaseAPIRequests } from '../../../../helpers/api/api-database';
7-
import { deleteRowsFromTableInDB } from '../../../../helpers/database-scripts';
7+
import { DatabaseScripts } from '../../../../helpers/database-scripts';
88
import { modifyFeaturesConfigJson, updateControlNumber } from '../../../../helpers/insights';
99

1010
const browserPage = new BrowserPage();
1111
const databaseHelper = new DatabaseHelper();
1212
const databaseAPIRequests = new DatabaseAPIRequests();
1313

14-
const featuresConfigTable = 'features_config';
1514
const pathes = {
1615
defaultRemote: path.join('.', 'test-data', 'features-configs', 'insights-default-remote.json'),
1716
dockerConfig: path.join('.', 'test-data', 'features-configs', 'insights-docker-build.json'),
@@ -29,7 +28,7 @@ fixture `Feature flag`
2928
// Update remote config .json to default
3029
await modifyFeaturesConfigJson(pathes.defaultRemote);
3130
// Clear features config table
32-
await deleteRowsFromTableInDB(featuresConfigTable);
31+
await DatabaseScripts.deleteRowsFromTableInDB({ tableName: 'features_config' });
3332
});
3433
test('Verify that Insights panel can be displayed for Electron app according to filters', async t => {
3534
// Update remote config .json to config with buildType filter excluding current app build

tests/e2e/tests/web/critical-path/a-first-start-form/user-agreements-form.e2e.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ test('Verify that user should accept User Agreements to continue working with th
2222
await t.expect(userAgreementDialog.submitButton.hasAttribute('disabled')).ok('Submit button not disabled by default');
2323
await t.expect(myRedisDatabasePage.AddRedisDatabase.addDatabaseManually.exists).notOk('User can\'t add a database');
2424
});
25-
// Skipped due to docker currently doesn't support encryption https://redislabs.atlassian.net/browse/RI-5036
26-
test.skip('Verify that the encryption enabled by default and specific message', async t => {
25+
test('Verify that the encryption enabled by default and specific message', async t => {
2726
const expectedPluginText = 'To avoid automatic execution of malicious code, when adding new Workbench plugins, use files from trusted authors only.';
2827
// Verify that section with plugin warning is displayed
2928
await t.expect(userAgreementDialog.pluginSectionWithText.exists).ok('Plugin text is not displayed');
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { rte } from '../../../../helpers/constants';
2+
import { MyRedisDatabasePage } from '../../../../pageObjects';
3+
import {
4+
commonUrl,
5+
ossSentinelConfig
6+
} from '../../../../helpers/conf';
7+
import { DatabaseHelper } from '../../../../helpers/database';
8+
import { DatabaseAPIRequests } from '../../../../helpers/api/api-database';
9+
import { DatabaseScripts, DbTableParameters } from '../../../../helpers/database-scripts';
10+
11+
const myRedisDatabasePage = new MyRedisDatabasePage();
12+
const databaseHelper = new DatabaseHelper();
13+
const databaseAPIRequests = new DatabaseAPIRequests();
14+
15+
const dbTableParams: DbTableParameters = {
16+
tableName: 'database_instance',
17+
columnName: 'password',
18+
rowValue: 'invalid',
19+
conditionWhereColumnName: 'name',
20+
conditionWhereColumnValue: ossSentinelConfig.masters[1].alias
21+
};
22+
23+
fixture `Encryption`
24+
.meta({ type: 'critical_path', rte: rte.none })
25+
.page(commonUrl)
26+
.beforeEach(async() => {
27+
await databaseHelper.acceptLicenseTerms();
28+
await databaseAPIRequests.discoverSentinelDatabaseApi(ossSentinelConfig);
29+
await myRedisDatabasePage.reloadPage();
30+
})
31+
.afterEach(async() => {
32+
await databaseHelper.deleteDatabase(ossSentinelConfig.masters[1].alias);
33+
});
34+
test('Verify that data encrypted using KEY', async t => {
35+
const decryptionError = 'Unable to decrypt data';
36+
// Connect to DB
37+
await myRedisDatabasePage.clickOnDBByName(ossSentinelConfig.masters[1].alias);
38+
// Return back to db list page
39+
await t.click(myRedisDatabasePage.NavigationPanel.myRedisDBButton);
40+
41+
await DatabaseScripts.updateColumnValueInDBTable(dbTableParams);
42+
// Verify that Encription by KEY applied for connection if RI_ENCRYPTION_KEY variable exists
43+
await t
44+
.expect(await DatabaseScripts.getColumnValueFromTableInDB({ ...dbTableParams, columnName: 'encryption' }))
45+
.eql('KEY', 'Encryption is not applied by RI_ENCRYPTION_KEY');
46+
await databaseHelper.clickOnEditDatabaseByName(ossSentinelConfig.masters[1].alias);
47+
await t.expect(myRedisDatabasePage.Toast.toastError.textContent).contains(decryptionError, 'Invalid encrypted field is decrypted');
48+
});

0 commit comments

Comments
 (0)