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
This commit is contained in:
		
							
								
								
									
										66
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -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' | ||||
							
								
								
									
										10
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								pom.xml
									
									
									
									
									
								
							| @ -514,21 +514,11 @@ | ||||
|             <artifactId>wiremock</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.seleniumhq.selenium</groupId> | ||||
|             <artifactId>selenium-java</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>io.rest-assured</groupId> | ||||
|             <artifactId>rest-assured</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>io.github.bonigarcia</groupId> | ||||
|             <artifactId>webdrivermanager</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|  | ||||
							
								
								
									
										18
									
								
								robot/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								robot/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
							
								
								
									
										101
									
								
								robot/goat.robot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								robot/goat.robot
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
|  | ||||
| @ -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(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user