Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multitenancy option #33

Merged
merged 3 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/arguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { program, Option } = require('commander');
const { exit } = require('process');
const fs = require('fs');
const ora = require('ora');
const { AUTH, CLI_COMMAND_NAME, DEFAULT_AUTH, DEFAULT_FILENAME, DEFAULT_FORMAT, DEFAULT_MIN_HEIGHT, DEFAULT_TENANT, DEFAULT_WIDTH, ENV_VAR, FORMAT, TRANSPORT_TYPE, DEFAULT_EMAIL_SUBJECT, DEFAULT_EMAIL_NOTE } = require('./constants.js');
const { AUTH, CLI_COMMAND_NAME, DEFAULT_AUTH, DEFAULT_FILENAME, DEFAULT_FORMAT, DEFAULT_MIN_HEIGHT, DEFAULT_TENANT, DEFAULT_WIDTH, ENV_VAR, FORMAT, TRANSPORT_TYPE, DEFAULT_EMAIL_SUBJECT, DEFAULT_EMAIL_NOTE, DEFAULT_MULTI_TENANCY } = require('./constants.js');
const dotenv = require("dotenv");
dotenv.config();
const spinner = ora('');
Expand All @@ -29,6 +29,9 @@ async function getCommandArguments() {
.env(ENV_VAR.USERNAME + ' and ' + ENV_VAR.PASSWORD))
.addOption(new Option('-t, --tenant <tenant>', 'tenants in opensearch dashboards')
.default(DEFAULT_TENANT))
.addOption(new Option('--multitenancy <flag>', 'enable or disable multi-tenancy')
.default(DEFAULT_MULTI_TENANCY)
.choices(['true', 'false']))
.addOption(new Option('-f, --format <type>', 'file format for the report')
.default(DEFAULT_FORMAT)
.choices([FORMAT.PDF, FORMAT.PNG, FORMAT.CSV]))
Expand Down Expand Up @@ -89,6 +92,8 @@ async function getEventArguments(event) {
event['subject'] = DEFAULT_EMAIL_SUBJECT;
if (event.note === undefined)
event['note'] = DEFAULT_EMAIL_NOTE;
if (event.multitenancy === undefined)
event['multitenancy'] = DEFAULT_MULTI_TENANCY;

return getOptions(event);
}
Expand All @@ -100,6 +105,7 @@ function getOptions(options) {
username: null,
password: null,
tenant: null,
multitenancy: null,
format: null,
width: null,
height: null,
Expand Down Expand Up @@ -161,6 +167,9 @@ function getOptions(options) {
// Set tenant
commandOptions.tenant = options.tenant;

// Set multitenancy
commandOptions.multitenancy = options.multitenancy;

// Set report format.
commandOptions.format = options.format;

Expand Down
3 changes: 2 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const DEFAULT_MIN_HEIGHT = '600';
const DEFAULT_FILENAME = 'opensearch-report';
const DEFAULT_EMAIL_SUBJECT = 'This is an email containing your opensearch dashboard report';
const DEFAULT_EMAIL_NOTE = 'Hi,\nHere is the latest report!';
const DEFAULT_MULTI_TENANCY = true;

const REPORT_TYPE = {
DASHBOARD: 'Dashboard',
Expand Down Expand Up @@ -72,5 +73,5 @@ const TRANSPORT_TYPE = {

module.exports = {
CLI_COMMAND_NAME, DEFAULT_AUTH, DEFAULT_TENANT, DEFAULT_FORMAT, DEFAULT_WIDTH, DEFAULT_MIN_HEIGHT, DEFAULT_FILENAME, DEFAULT_EMAIL_SUBJECT,
DEFAULT_EMAIL_NOTE, REPORT_TYPE, SELECTOR, FORMAT, AUTH, URL_SOURCE, ENV_VAR, TRANSPORT_TYPE
DEFAULT_EMAIL_NOTE, REPORT_TYPE, SELECTOR, FORMAT, AUTH, URL_SOURCE, ENV_VAR, TRANSPORT_TYPE, DEFAULT_MULTI_TENANCY
};
104 changes: 65 additions & 39 deletions src/download-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const exit = require('process');
const ora = require('ora');
const spinner = ora('');

module.exports = async function downloadReport(url, format, width, height, filename, authType, username, password, tenant, time, transport, emailbody) {
module.exports = async function downloadReport(url, format, width, height, filename, authType, username, password, tenant, multitenancy, time, transport, emailbody) {
spinner.start('Connecting to url ' + url);
try {
const browser = await puppeteer.launch({
Expand Down Expand Up @@ -43,13 +43,13 @@ module.exports = async function downloadReport(url, format, width, height, filen
// auth
if (authType !== undefined && authType !== AUTH.NONE && username !== undefined && password !== undefined) {
if (authType === AUTH.BASIC) {
await basicAuthentication(page, overridePage, url, username, password, tenant);
await basicAuthentication(page, overridePage, url, username, password, tenant, multitenancy);
}
else if (authType === AUTH.SAML) {
await samlAuthentication(page, url, username, password, tenant);
await samlAuthentication(page, url, username, password, tenant, multitenancy);
}
else if (authType === AUTH.COGNITO) {
await cognitoAuthentication(page, overridePage, url, username, password, tenant);
await cognitoAuthentication(page, overridePage, url, username, password, tenant, multitenancy);
}
spinner.info('Credentials are verified');
}
Expand Down Expand Up @@ -202,42 +202,52 @@ const getUrl = async (url) => {
return urlRef;
};

const basicAuthentication = async (page, overridePage, url, username, password, tenant) => {
const basicAuthentication = async (page, overridePage, url, username, password, tenant, multitenancy) => {
await page.goto(url, { waitUntil: 'networkidle0' });
await new Promise(resolve => setTimeout(resolve, 10000));
await page.type('input[data-test-subj="user-name"]', username);
await page.type('[data-test-subj="password"]', password);
await page.click('button[type=submit]');
await page.waitForTimeout(10000);
try {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
if (multitenancy === true) {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
}
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
if ((await page.$('[name="signInSubmitButton"]')) !== null)
throw new Error('Invalid credentials');
rupal-bq marked this conversation as resolved.
Show resolved Hide resolved
}
}
catch (err) {
spinner.fail('Invalid username or password');
exit(1);
}

await page.waitForTimeout(5000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
if (multitenancy === true) {
await page.waitForTimeout(5000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
}
await overridePage.goto(url, { waitUntil: 'networkidle0' });
await overridePage.waitForTimeout(5000);
// Check if tenant was selected successfully.
if ((await overridePage.$('button[data-test-subj="confirm"]')) !== null) {
spinner.fail('Invalid tenant');
exit(1);

if (multitenancy === true) {
// Check if tenant was selected successfully.
if ((await overridePage.$('button[data-test-subj="confirm"]')) !== null) {
spinner.fail('Invalid tenant');
exit(1);
}
}
await page.goto(url, { waitUntil: 'networkidle0' });
await page.reload({ waitUntil: 'networkidle0' });
};

const samlAuthentication = async (page, url, username, password, tenant) => {
const samlAuthentication = async (page, url, username, password, tenant, multitenancy) => {
await page.goto(url, { waitUntil: 'networkidle0' });
await new Promise(resolve => setTimeout(resolve, 10000));
let refUrl;
Expand All @@ -249,55 +259,71 @@ const samlAuthentication = async (page, url, username, password, tenant) => {
await page.click('[value="Sign in"]')
await page.waitForTimeout(30000);
try {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
if (multitenancy === true) {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
}
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
if ((await page.$('[value="Sign in"]')) !== null)
throw new Error('Invalid credentials');
}
}
catch (err) {
spinner.fail('Invalid username or password');
exit(1);
}
await page.waitForTimeout(2000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
if (multitenancy === true) {
await page.waitForTimeout(2000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
}
await page.click(`a[href='${refUrl}']`);
await page.reload({ waitUntil: 'networkidle0' });
}

const cognitoAuthentication = async (page, overridePage, url, username, password, tenant) => {
const cognitoAuthentication = async (page, overridePage, url, username, password, tenant, multitenancy) => {
await page.goto(url, { waitUntil: 'networkidle0' });
await new Promise(resolve => setTimeout(resolve, 10000));
await page.type('[name="username"]', username);
await page.type('[name="password"]', password);
await page.click('[name="signInSubmitButton"]');
await page.waitForTimeout(30000);
try {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
if (multitenancy === true) {
if (tenant === 'global' || tenant === 'private') {
await page.click('label[for=' + tenant + ']');
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
}
} else {
await page.click('label[for="custom"]');
await page.click('button[data-test-subj="comboBoxToggleListButton"]');
await page.type('input[data-test-subj="comboBoxSearchInput"]', tenant);
if ((await page.$('[name="signInSubmitButton"]')) !== null)
throw new Error('Invalid credentials');
}
}
catch (err) {
spinner.fail('Invalid username or password');
exit(1);
}
await page.waitForTimeout(2000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
if (multitenancy === true) {
await page.waitForTimeout(2000);
await page.click('button[data-test-subj="confirm"]');
await page.waitForTimeout(25000);
}
await overridePage.goto(url, { waitUntil: 'networkidle0' });
await overridePage.waitForTimeout(5000);

// Check if tenant was selected successfully.
if ((await overridePage.$('button[data-test-subj="confirm"]')) !== null) {
spinner.fail('Invalid tenant');
exit(1);
if (multitenancy === true) {
// Check if tenant was selected successfully.
if ((await overridePage.$('button[data-test-subj="confirm"]')) !== null) {
spinner.fail('Invalid tenant');
exit(1);
}
}
await page.goto(url, { waitUntil: 'networkidle0' });
await page.reload({ waitUntil: 'networkidle0' });
Expand Down
1 change: 1 addition & 0 deletions src/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = async function run(args) {
options.username,
options.password,
options.tenant,
options.multitenancy,
options.time,
options.transport,
options.emailbody
Expand Down
1 change: 1 addition & 0 deletions test/help.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Options:
-a, --auth <type> authentication type for the report. (choices: "basic", "cognito", "saml", default: "none")
-c, --credentials <username:password> login credentials (env: OPENSEARCH_USERNAME and OPENSEARCH_PASSWORD)
-t, --tenant <tenant> tenants in opensearch dashboards (default: "private")
--multitenancy <flag> enable or disable multi-tenancy (choices: "true", "false", default: true)
-f, --format <type> file format for the report (choices: "pdf", "png", "csv", default: "pdf")
-w, --width <psize> window width in pixels for the report (default: "1680")
-l, --height <size> minimum window height in pixels for the report (default: "600")
Expand Down