From aaf87c0c041e0df311371c5f0d6cb5ccc5783265 Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Thu, 1 Feb 2018 17:34:08 -0500 Subject: [PATCH] xss test for per-host recent jobs popup --- awx/ui/test/e2e/fixtures.js | 32 +++++++++++++++++++++++++++---- awx/ui/test/e2e/objects/jobs.js | 11 ----------- awx/ui/test/e2e/tests/test-xss.js | 22 ++++++++++++++++++++- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/awx/ui/test/e2e/fixtures.js b/awx/ui/test/e2e/fixtures.js index a0478ddac5..03f02fea3e 100644 --- a/awx/ui/test/e2e/fixtures.js +++ b/awx/ui/test/e2e/fixtures.js @@ -61,8 +61,21 @@ const getInventory = (namespace = session) => getOrganization(namespace) .then(organization => getOrCreate('/inventories/', { name: `${namespace}-inventory`, description: namespace, - organization: organization.id - })); + organization: organization.id, + }).then(inventory => getOrCreate('/hosts/', { + name: `${namespace}-host`, + description: namespace, + inventory: inventory.id, + variables: JSON.stringify({ ansible_connection: 'local' }), + }).then(() => inventory))); + +const getHost = (namespace = session) => getInventory(namespace) + .then(inventory => getOrCreate('/hosts/', { + name: `${namespace}-host`, + description: namespace, + inventory: inventory.id, + variables: JSON.stringify({ ansible_connection: 'local' }), + }).then((host) => host)); const getInventoryScript = (namespace = session) => getOrganization(namespace) .then(organization => getOrCreate('/inventory_scripts/', { @@ -182,7 +195,7 @@ const waitForJob = endpoint => { const completed = statuses.indexOf(update.data.status) > -1; if (completed) { - return resolve(); + return resolve(update.data); } if (--attempts <= 0) { @@ -206,6 +219,15 @@ const getUpdatedProject = (namespace = session) => getProject(namespace) return project; }); +const getJob = (namespace = session) => getJobTemplate(namespace) + .then(template => { + const launchURL = template.related.launch; + return post(launchURL, {}).then(response => { + const jobURL = response.data.url; + return waitForJob(jobURL).then(() => response.data); + }); + }); + const getJobTemplate = (namespace = session) => { const promises = [ getInventory(namespace), @@ -302,5 +324,7 @@ module.exports = { getSmartInventory, getTeam, getUpdatedProject, - getUser + getUser, + getJob, + getHost, }; diff --git a/awx/ui/test/e2e/objects/jobs.js b/awx/ui/test/e2e/objects/jobs.js index 81bd3d432c..93c43caccd 100644 --- a/awx/ui/test/e2e/objects/jobs.js +++ b/awx/ui/test/e2e/objects/jobs.js @@ -1,16 +1,5 @@ import _ from 'lodash'; -import actions from './sections/actions'; -import breadcrumb from './sections/breadcrumb'; -import createFormSection from './sections/createFormSection'; -import createTableSection from './sections/createTableSection'; -import header from './sections/header'; -import lookupModal from './sections/lookupModal'; -import navigation from './sections/navigation'; -import pagination from './sections/pagination'; -import permissions from './sections/permissions'; -import search from './sections/search'; - module.exports = { url () { return `${this.api.globals.launch_url}/#/jobs`; diff --git a/awx/ui/test/e2e/tests/test-xss.js b/awx/ui/test/e2e/tests/test-xss.js index b5c80afe31..449368f391 100644 --- a/awx/ui/test/e2e/tests/test-xss.js +++ b/awx/ui/test/e2e/tests/test-xss.js @@ -1,5 +1,6 @@ import { getAdminMachineCredential, + getHost, getInventory, getInventoryScript, getInventorySource, @@ -12,7 +13,7 @@ import { getSmartInventory, getTeam, getUpdatedProject, - getJobs, + getJob, } from '../fixtures'; const data = {}; @@ -22,9 +23,11 @@ const pages = {}; module.exports = { before: (client, done) => { const namespace = '
test
'; + const namespaceShort = '
t
'; const resources = [ getOrganization(namespace).then(obj => { data.organization = obj; }), + getHost(namespaceShort).then(obj => { data.host = obj; }), getInventory(namespace).then(obj => { data.inventory = obj; }), getInventoryScript(namespace).then(obj => { data.inventoryScript = obj; }), getSmartInventory(namespace).then(obj => { data.smartInventory = obj; }), @@ -37,6 +40,7 @@ module.exports = { getTeam(namespace).then(obj => { data.team = obj; }), getJobTemplateAdmin(namespace).then(obj => { data.user = obj; }), getNotificationTemplate(namespace).then(obj => { data.notification = obj; }), + getJob(namespaceShort).then(obj => { data.job = obj; }), ]; Promise.all(resources) @@ -44,6 +48,7 @@ module.exports = { pages.organizations = client.page.organizations(); pages.inventories = client.page.inventories(); pages.inventoryScripts = client.page.inventoryScripts(); + pages.hosts = client.page.hosts(); pages.projects = client.page.projects(); pages.credentials = client.page.credentials(); pages.templates = client.page.templates(); @@ -54,6 +59,7 @@ module.exports = { urls.organization = `${pages.organizations.url()}/${data.organization.id}`; urls.inventory = `${pages.inventories.url()}/inventory/${data.inventory.id}`; + urls.hosts = `${pages.hosts.url()}`; urls.inventoryScript = `${pages.inventoryScripts.url()}/${data.inventoryScript.id}`; urls.inventorySource = `${urls.inventory}/inventory_sources/edit/${data.inventorySource.id}`; urls.sourceSchedule = `${urls.inventorySource}/schedules/${data.sourceSchedule.id}`; @@ -681,4 +687,18 @@ module.exports = { }); client.end(); }, + 'check host recent jobs popup for unsanitized content': client => { + const itemRow = `#hosts_table tr[id="${data.host.id}"]`; + const itemName = `${itemRow} td[class*="active_failures-"] a`; + const popOver = `${itemRow} td[class*="active_failures-"] div[class*="popover"]`; + + client.navigateTo(urls.hosts); + + client.click(itemName); + client.expect.element(popOver).present; + + client.expect.element('[class=xss]').not.present; + + client.end(); + }, };