From 6b63aaf8b13a7277bd1fd05106fdd59e60968458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Sun, 24 Jul 2022 12:28:01 +0200 Subject: [PATCH] Robot framework (#1304) * added Robot framework UI tests * added Robot framework UI tests workflow * Update test.yml wait in workflow * remove obsolete selenium java libs and test * Update test.yml push result to commit as comment * Update test.yml push comment does not seem to work on WebGoat PR * clean up unrequired robot options * update readme --- .github/workflows/test.yml | 66 +++++++++++ pom.xml | 10 -- robot/README.md | 18 +++ robot/goat.robot | 101 ++++++++++++++++ .../webgoat/SeleniumIntegrationTest.java | 111 ------------------ 5 files changed, 185 insertions(+), 121 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 robot/README.md create mode 100644 robot/goat.robot delete mode 100644 src/it/java/org/owasp/webgoat/SeleniumIntegrationTest.java diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..c9430479c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,66 @@ +name: "UI-Test" +on: + pull_request: + paths-ignore: + - '.txt' + - '*.MD' + - '*.md' + - 'LICENSE' + - 'docs/**' + push: + tags-ignore: + - '*' + paths-ignore: + - '.txt' + - '*.MD' + - '*.md' + - 'LICENSE' + - 'docs/**' + +jobs: + build: + runs-on: ubuntu-latest + # display name of the job + name: "Robot framework test" + steps: + # Uses an default action to checkout the code + - uses: actions/checkout@v3 + # Uses an action to add Python to the VM + - name: Setup Pyton + uses: actions/setup-python@v4 + with: + python-version: '3.7' + architecture: x64 + # Uses an action to add JDK 17 to the VM (and mvn?) + - name: set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: 17 + architecture: x64 + #Uses an action to set up a cache using a certain key based on the hash of the dependencies + - name: Cache Maven packages + uses: actions/cache@v3.0.5 + with: + path: ~/.m2 + key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ubuntu-latest-m2- + - uses: BSFishy/pip-action@v1 + with: + packages: | + robotframework + robotframework-SeleniumLibrary + webdriver-manager + - name: Run with Maven + run: mvn --no-transfer-progress spring-boot:run & + - name: Wait to start + uses: ifaxity/wait-on-action@v1 + with: + resource: http://127.0.0.1:8080/WebGoat + - name: Test with Robotframework + run: python3 -m robot --variable HEADLESS:"1" --outputdir robotreport robot/goat.robot + #- name: Send report to commit + # uses: joonvena/robotframework-reporter-action@v2.1 + # with: + # gh_access_token: ${{ secrets.GITHUB_TOKEN }} + # report_path: 'robotreport' diff --git a/pom.xml b/pom.xml index 66ff1c85b..3c07b76dd 100644 --- a/pom.xml +++ b/pom.xml @@ -514,21 +514,11 @@ wiremock test - - org.seleniumhq.selenium - selenium-java - test - io.rest-assured rest-assured test - - io.github.bonigarcia - webdrivermanager - test - diff --git a/robot/README.md b/robot/README.md new file mode 100644 index 000000000..7acf94023 --- /dev/null +++ b/robot/README.md @@ -0,0 +1,18 @@ +# Install and use Robotframework + +## Install Chromedriver on Mac OS + + brew install cask chromedriver + chromedriver --version + +Then see security settings and allow the file to run + +## Install + + pip3 install virtualenv --user + python3 -m virtualenv .venv + source .venv/bin/activate + pip install robotframework + pip install robotframework-SeleniumLibrary + pip install webdriver-manager + robot --variable HEADLESS:"0" --variable ENDPOINT:"http://127.0.0.1:8080/WebGoat" goat.robot diff --git a/robot/goat.robot b/robot/goat.robot new file mode 100644 index 000000000..972fdf421 --- /dev/null +++ b/robot/goat.robot @@ -0,0 +1,101 @@ +*** Settings *** +Documentation Setup WebGoat Robotframework tests +Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot +Library String + +Suite Setup Initial_Page ${ENDPOINT} ${BROWSER} +Suite Teardown Close_Page + +*** Variables *** +${BROWSER} chrome +${SLEEP} 100 +${DELAY} 0.25 +${ENDPOINT} http://127.0.0.1:8080/WebGoat +${ENDPOINT_WOLF} http://127.0.0.1:9090 +${USERNAME} robotuser +${PASSWORD} password +${HEADLESS} ${FALSE} + +*** Keywords *** +Initial_Page + [Documentation] Check the inital page + [Arguments] ${ENDPOINT} ${BROWSER} + Log To Console Start WebGoat UI Testing + IF ${HEADLESS} + Open Browser ${ENDPOINT} ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat + ELSE + Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat + END + IF ${HEADLESS} + Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf + ELSE + Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf + END + Switch Browser webgoat + Maximize Browser Window + Set Window Size ${1400} ${1000} + Switch Browser webwolf + Maximize Browser Window + Set Window Size ${1400} ${1000} + Set Window Position ${400} ${200} + Set Selenium Speed ${DELAY} + +Close_Page + [Documentation] Closing the browser + Log To Console ==> Stop WebGoat UI Testing + IF ${HEADLESS} + Switch Browser webgoat + Close Browser + Switch Browser webwolf + Close Browser + END + +*** Test Cases *** + +Check_Initial_Page + Switch Browser webgoat + Page Should Contain Username + Click Button Sign in + Page Should Contain Invalid username + Click Link /WebGoat/registration + +Check_Registration_Page + Page Should Contain Username + Input Text username ${USERNAME} + Input Text password ${PASSWORD} + Input Text matchingPassword ${PASSWORD} + Click Element agree + Click Button Sign up + +Check_Welcome_Page + Page Should Contain WebGoat + Go To ${ENDPOINT}/login + Page Should Contain Username + Input Text username ${USERNAME} + Input Text password ${PASSWORD} + Click Button Sign in + Page Should Contain WebGoat + +Check_Menu_Page + Click Element css=a[category='Introduction'] + Click Element Introduction-WebGoat + CLick Element Introduction-WebWolf + Click Element css=a[category='General'] + CLick Element General-HTTPBasics + Click Element xpath=//*[.='2'] + Input Text person ${USERNAME} + Click Button Go! + ${OUT_VALUE} Get Text xpath=//div[contains(@class, 'attack-feedback')] + ${OUT_RESULT} Evaluate "resutobor" in """${OUT_VALUE}""" + IF not ${OUT_RESULT} + Fail "not ok" + END + +Check_WebWolf + Switch Browser webwolf + location should be ${ENDPOINT_WOLF}/WebWolf + Go To ${ENDPOINT_WOLF}/mail + Input Text username ${USERNAME} + Input Text password ${PASSWORD} + Click Button Sign In + diff --git a/src/it/java/org/owasp/webgoat/SeleniumIntegrationTest.java b/src/it/java/org/owasp/webgoat/SeleniumIntegrationTest.java deleted file mode 100644 index beb3b71aa..000000000 --- a/src/it/java/org/owasp/webgoat/SeleniumIntegrationTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.owasp.webgoat; - -import java.util.concurrent.TimeUnit; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.firefox.FirefoxBinary; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.firefox.FirefoxOptions; - -import io.github.bonigarcia.wdm.WebDriverManager; -import io.github.bonigarcia.wdm.config.DriverManagerType; - -public class SeleniumIntegrationTest extends IntegrationTest { - - static { - try { - WebDriverManager.getInstance(DriverManagerType.FIREFOX).setup(); - } catch (Exception e) { - //sometimes a 403 cause an ExceptionInInitializerError - } - } - private WebDriver driver; - - @BeforeEach - public void setUpAndLogin() { - try { - FirefoxBinary firefoxBinary = new FirefoxBinary(); - firefoxBinary.addCommandLineOptions("--headless"); - - FirefoxOptions firefoxOptions = new FirefoxOptions(); - firefoxOptions.setBinary(firefoxBinary); - driver = new FirefoxDriver(firefoxOptions); - driver.get(url("/login")); - driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); - // Login - driver.findElement(By.name("username")).sendKeys(this.getUser()); - driver.findElement(By.name("password")).sendKeys("password"); - driver.findElement(By.className("btn")).click(); - - // Check if user exists. If not, create user. - if (driver.getCurrentUrl().equals(url("/login?error"))) { - driver.get(url("/registration")); - driver.findElement(By.id("username")).sendKeys(this.getUser()); - driver.findElement(By.id("password")).sendKeys("password"); - driver.findElement(By.id("matchingPassword")).sendKeys("password"); - driver.findElement(By.name("agree")).click(); - driver.findElement(By.className("btn-primary")).click(); - } - } catch (Exception e) { - System.err.println("Selenium test failed "+System.getProperty("webdriver.gecko.driver")+", message: "+e.getMessage()); - } - - } - - @AfterEach - public void tearDown() { - if (null != driver) { - driver.close(); - } - } - - @Test - public void sqlInjection() { - - if (null==driver) return; - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson")); - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/1")); - driver.findElement(By.id("restart-lesson-button")).click(); - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/0")); - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/1")); - driver.findElement(By.name("query")).sendKeys(SqlInjectionLessonIntegrationTest.sql_2); - driver.findElement(By.name("query")).submit(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/2")); - driver.findElements(By.name("query")).get(1).sendKeys(SqlInjectionLessonIntegrationTest.sql_3); - driver.findElements(By.name("query")).get(1).submit(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/3")); - driver.findElements(By.name("query")).get(2).sendKeys(SqlInjectionLessonIntegrationTest.sql_4_drop); - driver.findElements(By.name("query")).get(2).submit(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/3")); - driver.findElements(By.name("query")).get(2).clear(); - driver.findElements(By.name("query")).get(2).sendKeys(SqlInjectionLessonIntegrationTest.sql_4_add); - driver.findElements(By.name("query")).get(2).submit(); - driver.findElements(By.name("query")).get(2).clear(); - driver.findElements(By.name("query")).get(2).sendKeys(SqlInjectionLessonIntegrationTest.sql_4_drop); - driver.findElements(By.name("query")).get(2).submit(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/4")); - driver.findElements(By.name("query")).get(3).sendKeys(SqlInjectionLessonIntegrationTest.sql_5); - driver.findElements(By.name("query")).get(3).submit(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/8")); - driver.findElement(By.name("account")).sendKeys("Smith'"); - driver.findElement(By.name("operator")).sendKeys("OR"); - driver.findElement(By.name("injection")).sendKeys("'1'='1"); - driver.findElement(By.name("Get Account Info")).click(); - - driver.get(url("/start.mvc#lesson/SqlInjection.lesson/9")); - driver.findElement(By.name("userid")).sendKeys(SqlInjectionLessonIntegrationTest.sql_10_userid); - driver.findElement(By.name("login_count")).sendKeys(SqlInjectionLessonIntegrationTest.sql_10_login_count); - driver.findElements(By.name("Get Account Info")).get(1).click(); - } - -}