Creating endpoint for the scoreboard

This commit is contained in:
Nanne Baars
2017-05-02 02:29:47 +02:00
parent 39f1597f82
commit eb7a6bd2be
29 changed files with 284 additions and 568 deletions

View File

@ -0,0 +1,109 @@
package org.owasp.webgoat.users;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* ************************************************************************************************
* <p>
* <p>
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @version $Id: $Id
* @since October 29, 2003
*/
public class LessonTracker {
@Getter
private String lessonName;
private final Set<Assignment> solvedAssignments = Sets.newHashSet();
private final List<Assignment> allAssignments = Lists.newArrayList();
@Getter
private int numberOfAttempts = 0;
protected LessonTracker() {
//Mongo
}
public LessonTracker(AbstractLesson lesson) {
lessonName = lesson.getId();
allAssignments.addAll(lesson.getAssignments());
}
public Optional<Assignment> getAssignment(String name) {
return allAssignments.stream().filter(a -> a.getName().equals(name)).findFirst();
}
/**
* Mark an assignment as solved
*
* @param solvedAssignment the assignment which the user solved
*/
public void assignmentSolved(String solvedAssignment) {
getAssignment(solvedAssignment).ifPresent(a -> solvedAssignments.add(a));
}
/**
* @return did they user solved all solvedAssignments for the lesson?
*/
public boolean isLessonSolved() {
return allAssignments.size() == solvedAssignments.size();
}
/**
* Increase the number attempts to solve the lesson
*/
public void incrementAttempts() {
numberOfAttempts++;
}
/**
* Reset the tracker. We do not reset the number of attempts here!
*/
void reset() {
solvedAssignments.clear();
}
/**
* @return list containing all the assignments solved or not
*/
public Map<Assignment, Boolean> getLessonOverview() {
List<Assignment> notSolved = allAssignments.stream()
.filter(i -> !solvedAssignments.contains(i))
.collect(Collectors.toList());
Map<Assignment, Boolean> overview = notSolved.stream().collect(Collectors.toMap(a -> a, b -> false));
overview.putAll(solvedAssignments.stream().collect(Collectors.toMap(a -> a, b -> true)));
return overview;
}
}

View File

@ -2,7 +2,6 @@ package org.owasp.webgoat.users;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.session.WebGoatUser;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;

View File

@ -1,22 +1,13 @@
package org.owasp.webgoat.users;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.session.LessonTracker;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Temp endpoint just for the CTF.
@ -25,13 +16,11 @@ import java.util.Map;
* @since 3/23/17.
*/
@RestController
@AllArgsConstructor
public class Scoreboard {
@AllArgsConstructor
@Getter
private class Challenge {
private List<Ranking> rankings;
}
private final UserTrackerRepository userTrackerRepository;
private final UserRepository userRepository;
@AllArgsConstructor
@Getter
@ -40,40 +29,23 @@ public class Scoreboard {
private int flagsCaptured;
}
private final String webgoatDirectory;
public Scoreboard(@Value("${webgoat.server.directory}") final String webgoatDirectory) {
this.webgoatDirectory = webgoatDirectory;
}
@GetMapping("/scoreboard")
public Challenge getRankings() {
File homeDir = new File(webgoatDirectory);
File[] files = homeDir.listFiles(f -> f.getName().endsWith(".progress"));
for (File progressFile : files) {
String username = progressFile.getName().replace(".progress", "");
Map<String, LessonTracker> storage = load(progressFile);
LessonTracker lessonTracker = storage.get("WebGoat Challenge");
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview();
for (int i = 0; i <= 5; i++) {
//lessonOverview.e
}
public List<Ranking> getRankings() {
List<WebGoatUser> allUsers = userRepository.findAll();
List<Ranking> rankings = Lists.newArrayList();
for (WebGoatUser user : allUsers) {
UserTracker userTracker = userTrackerRepository.findOne(user.getUsername());
int challengesSolved = challengesSolved(userTracker);
rankings.add(new Ranking(user.getUsername(), challengesSolved));
}
return null;
return rankings;
}
@SneakyThrows
private Map<String, LessonTracker> load(File progressFile) {
Map<String, LessonTracker> storage = Maps.newHashMap();
if (progressFile.exists() && progressFile.isFile()) {
DefaultDeserializer deserializer = new DefaultDeserializer(Thread.currentThread().getContextClassLoader());
try (FileInputStream fis = new FileInputStream(progressFile)) {
byte[] b = ByteStreams.toByteArray(fis);
storage = (Map<String, LessonTracker>) deserializer.deserialize(new ByteArrayInputStream(b));
}
}
return storage;
private int challengesSolved(UserTracker userTracker) {
List<String> challenges = Lists.newArrayList("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5");
List<LessonTracker> challengeTrackers = challenges.stream()
.map(c -> userTracker.getLessonTracker(c))
.filter(l -> l.isPresent()).map(l -> l.get()).collect(Collectors.toList());
return challengeTrackers.size();
}
}

View File

@ -1,13 +1,12 @@
package org.owasp.webgoat.users;
import org.owasp.webgoat.session.WebGoatUser;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @author nbaars
* @since 3/19/17.
*/
public interface UserRepository extends CrudRepository<WebGoatUser, Long> {
public interface UserRepository extends MongoRepository<WebGoatUser, String> {
WebGoatUser findByUsername(String username);
}

View File

@ -1,7 +1,6 @@
package org.owasp.webgoat.users;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.session.WebGoatUser;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@ -15,6 +14,7 @@ import org.springframework.stereotype.Service;
public class UserService implements UserDetailsService {
private final UserRepository userRepository;
private final UserTrackerRepository userTrackerRepository;
@Override
public WebGoatUser loadUserByUsername(String username) throws UsernameNotFoundException {
@ -29,5 +29,6 @@ public class UserService implements UserDetailsService {
public void addUser(String username, String password) {
userRepository.save(new WebGoatUser(username, password));
userTrackerRepository.save(new UserTracker(username));
}
}

View File

@ -0,0 +1,119 @@
package org.owasp.webgoat.users;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment;
import org.springframework.data.annotation.Id;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* ************************************************************************************************
* <p>
* <p>
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @version $Id: $Id
* @since October 29, 2003
*/
@Slf4j
public class UserTracker {
@Id
private final String user;
private List<LessonTracker> lessonTrackers = Lists.newArrayList();
public UserTracker(final String user) {
this.user = user;
}
/**
* Returns an existing lesson tracker or create a new one based on the lesson
*
* @param lesson the lesson
* @return a lesson tracker created if not already present
*/
public LessonTracker getLessonTracker(AbstractLesson lesson) {
Optional<LessonTracker> lessonTracker = lessonTrackers
.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst();
if (!lessonTracker.isPresent()) {
LessonTracker newLessonTracker = new LessonTracker(lesson);
lessonTrackers.add(newLessonTracker);
return newLessonTracker;
} else {
return lessonTracker.get();
}
}
/**
* Query method for finding a specific lesson tracker based on id
*
* @param id the id of the lesson
* @return optional due to the fact we can only create a lesson tracker based on a lesson
*/
public Optional<LessonTracker> getLessonTracker(String id) {
return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst();
}
public void assignmentSolved(AbstractLesson lesson, String assignmentName) {
LessonTracker lessonTracker = getLessonTracker(lesson);
lessonTracker.incrementAttempts();
lessonTracker.assignmentSolved(assignmentName);
}
public void assignmentFailed(AbstractLesson lesson) {
LessonTracker lessonTracker = getLessonTracker(lesson);
lessonTracker.incrementAttempts();
}
public void reset(AbstractLesson al) {
LessonTracker lessonTracker = getLessonTracker(al);
lessonTracker.reset();
}
public int numberOfLessonsSolved() {
int numberOfLessonsSolved = 0;
for (LessonTracker lessonTracker : lessonTrackers) {
if (lessonTracker.isLessonSolved()) {
numberOfLessonsSolved = numberOfLessonsSolved + 1;
}
}
return numberOfLessonsSolved;
}
public int numberOfAssignmentsSolved() {
int numberOfAssignmentsSolved = 0;
for (LessonTracker lessonTracker : lessonTrackers) {
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview();
numberOfAssignmentsSolved = lessonOverview.values().stream().filter(b -> b).collect(Collectors.counting()).intValue();
}
return numberOfAssignmentsSolved;
}
}

View File

@ -0,0 +1,12 @@
package org.owasp.webgoat.users;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @author nbaars
* @since 4/30/17.
*/
public interface UserTrackerRepository extends MongoRepository<UserTracker, String> {
}

View File

@ -0,0 +1,69 @@
package org.owasp.webgoat.users;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Collections;
/**
* @author nbaars
* @since 3/19/17.
*/
@Getter
public class WebGoatUser implements UserDetails {
public static final String ROLE_USER = "WEBGOAT_USER";
public static final String ROLE_ADMIN = "WEBGOAT_ADMIN";
@Id
private String username;
private String password;
private String role = ROLE_USER;
@Transient
private User user;
protected WebGoatUser() {
}
public WebGoatUser(String username, String password) {
this.username = username;
this.password = password;
createUser();
}
public void createUser() {
this.user = new User(username, password, getAuthorities());
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority(getRole()));
}
@Override
public boolean isAccountNonExpired() {
return this.user.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return this.user.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return this.user.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return this.user.isEnabled();
}
}