├── lab1 ├── library-server │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── application-test.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ └── LibraryApplicationIntegrationTest.java │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ ├── book │ │ │ │ ├── data │ │ │ │ │ └── BookRepository.java │ │ │ │ └── web │ │ │ │ │ └── BookModelList.java │ │ │ │ ├── LibraryServerApplication.java │ │ │ │ ├── user │ │ │ │ ├── data │ │ │ │ │ └── UserRepository.java │ │ │ │ ├── web │ │ │ │ │ ├── UserModelList.java │ │ │ │ │ └── UserModelAssembler.java │ │ │ │ └── service │ │ │ │ │ └── UserService.java │ │ │ │ ├── common │ │ │ │ └── web │ │ │ │ │ ├── IndexController.java │ │ │ │ │ └── ErrorHandler.java │ │ │ │ └── config │ │ │ │ └── IdGeneratorConfiguration.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── templates │ │ │ └── index.html │ │ │ └── logback-spring.xml │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── README.md │ ├── .gitignore │ └── build.gradle ├── library-server-complete │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── application-test.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ └── LibraryApplicationIntegrationTest.java │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ ├── book │ │ │ │ ├── data │ │ │ │ │ └── BookRepository.java │ │ │ │ └── web │ │ │ │ │ └── BookModelList.java │ │ │ │ ├── user │ │ │ │ ├── data │ │ │ │ │ └── UserRepository.java │ │ │ │ ├── web │ │ │ │ │ ├── UserModelList.java │ │ │ │ │ └── UserModelAssembler.java │ │ │ │ └── service │ │ │ │ │ └── UserService.java │ │ │ │ ├── Lab1LibraryServerApplication.java │ │ │ │ ├── common │ │ │ │ └── web │ │ │ │ │ ├── IndexController.java │ │ │ │ │ └── ErrorHandler.java │ │ │ │ └── config │ │ │ │ └── IdGeneratorConfiguration.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── templates │ │ │ └── index.html │ │ │ └── logback-spring.xml │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── README.md │ ├── .gitignore │ └── build.gradle └── images │ ├── loginform.png │ ├── logoutform.png │ ├── main_screen.png │ ├── secure_headers.png │ └── owasp_top_10_2017.png ├── bonus-labs ├── csrf-attack-demo │ ├── settings.gradle │ ├── attack │ │ ├── images │ │ │ ├── cat1.jpg │ │ │ └── cat2.jpg │ │ ├── index.html │ │ ├── forum-post.html │ │ └── forum-get.html │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application.properties │ │ │ │ ├── schema.sql │ │ │ │ └── templates │ │ │ │ │ ├── customerform.html │ │ │ │ │ └── index.html │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── csrf │ │ │ │ └── attack │ │ │ │ ├── data │ │ │ │ ├── CustomerRepository.java │ │ │ │ └── Customer.java │ │ │ │ ├── config │ │ │ │ ├── IdGeneratorConfiguration.java │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ ├── CsrfAttackDemoApplication.java │ │ │ │ ├── session │ │ │ │ └── SameSiteCookieConfiguration.java │ │ │ │ ├── api │ │ │ │ ├── CustomerRequest.java │ │ │ │ └── CustomerWebController.java │ │ │ │ ├── service │ │ │ │ └── CustomerService.java │ │ │ │ └── DataInitializer.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── csrf │ │ │ └── attack │ │ │ └── CsrfAttackDemoApplicationTests.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ └── build.gradle ├── README.md └── webauthn │ └── README.md ├── .gitbook.yaml ├── lab2 └── library-server-complete │ ├── settings.gradle │ ├── src │ ├── test │ │ ├── resources │ │ │ └── application-test.yml │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── libraryserver │ │ │ └── LibraryApplicationIntegrationTest.java │ └── main │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── libraryserver │ │ │ ├── book │ │ │ ├── data │ │ │ │ └── BookRepository.java │ │ │ └── web │ │ │ │ └── BookModelList.java │ │ │ ├── user │ │ │ ├── data │ │ │ │ └── UserRepository.java │ │ │ ├── web │ │ │ │ ├── UserModelList.java │ │ │ │ └── UserModelAssembler.java │ │ │ └── service │ │ │ │ ├── InvalidPasswordError.java │ │ │ │ └── UserService.java │ │ │ ├── Lab2LibraryServerApplication.java │ │ │ ├── common │ │ │ └── web │ │ │ │ ├── IndexController.java │ │ │ │ └── ErrorHandler.java │ │ │ ├── config │ │ │ ├── IdGeneratorConfiguration.java │ │ │ └── PasswordValidationConfiguration.java │ │ │ └── security │ │ │ ├── AuthenticatedUser.java │ │ │ └── LibraryUserDetailsService.java │ │ └── resources │ │ ├── application.yml │ │ ├── templates │ │ └── index.html │ │ ├── logback-spring.xml │ │ └── password-list.txt │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── README.md │ └── build.gradle ├── lab3 ├── library-server-complete │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── application-test.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ └── LibraryApplicationIntegrationTest.java │ │ └── main │ │ │ ├── resources │ │ │ ├── pparker-trust.p12 │ │ │ ├── client-keystore.p12 │ │ │ ├── server-keystore.p12 │ │ │ ├── templates │ │ │ │ └── index.html │ │ │ ├── logback-spring.xml │ │ │ ├── application.yml │ │ │ ├── password-list.txt │ │ │ └── pparker.cer │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── libraryserver │ │ │ ├── book │ │ │ ├── data │ │ │ │ └── BookRepository.java │ │ │ └── web │ │ │ │ └── BookModelList.java │ │ │ ├── user │ │ │ ├── data │ │ │ │ └── UserRepository.java │ │ │ ├── web │ │ │ │ ├── UserModelList.java │ │ │ │ └── UserModelAssembler.java │ │ │ └── service │ │ │ │ ├── InvalidPasswordError.java │ │ │ │ └── UserService.java │ │ │ ├── Lab3LibraryServerApplication.java │ │ │ ├── common │ │ │ └── web │ │ │ │ ├── IndexController.java │ │ │ │ └── ErrorHandler.java │ │ │ ├── config │ │ │ ├── IdGeneratorConfiguration.java │ │ │ └── PasswordValidationConfiguration.java │ │ │ └── security │ │ │ ├── AuthenticatedUser.java │ │ │ └── LibraryUserDetailsService.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── README.md │ ├── .gitignore │ └── build.gradle └── images │ ├── cert_export.png │ ├── cert_import_chrome.png │ ├── cert_import_firefox.png │ ├── secured_browser_page.png │ └── cert_identification_request.png ├── lab4 ├── library-server-complete │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── application-test.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ └── LibraryApplicationIntegrationTest.java │ │ └── main │ │ │ ├── resources │ │ │ ├── pparker-trust.p12 │ │ │ ├── client-keystore.p12 │ │ │ ├── server-keystore.p12 │ │ │ ├── templates │ │ │ │ └── index.html │ │ │ ├── logback-spring.xml │ │ │ ├── application.yml │ │ │ ├── password-list.txt │ │ │ └── pparker.cer │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── libraryserver │ │ │ ├── book │ │ │ ├── data │ │ │ │ └── BookRepository.java │ │ │ └── web │ │ │ │ └── BookModelList.java │ │ │ ├── user │ │ │ ├── data │ │ │ │ └── UserRepository.java │ │ │ ├── web │ │ │ │ └── UserModelList.java │ │ │ └── service │ │ │ │ └── InvalidPasswordError.java │ │ │ ├── Lab4LibraryServerApplication.java │ │ │ ├── common │ │ │ └── web │ │ │ │ ├── IndexController.java │ │ │ │ └── ErrorHandler.java │ │ │ ├── config │ │ │ ├── IdGeneratorConfiguration.java │ │ │ └── PasswordValidationConfiguration.java │ │ │ └── security │ │ │ ├── AuthenticatedUser.java │ │ │ └── LibraryUserDetailsService.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── README.md └── images │ └── roles_permissions.png ├── lab5 ├── library-server-complete │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── application-test.yml │ │ └── main │ │ │ ├── resources │ │ │ ├── pparker-trust.p12 │ │ │ ├── client-keystore.p12 │ │ │ ├── server-keystore.p12 │ │ │ ├── templates │ │ │ │ └── index.html │ │ │ ├── logback-spring.xml │ │ │ ├── application.yml │ │ │ ├── password-list.txt │ │ │ └── pparker.cer │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── libraryserver │ │ │ ├── book │ │ │ ├── data │ │ │ │ └── BookRepository.java │ │ │ └── web │ │ │ │ └── BookModelList.java │ │ │ ├── user │ │ │ ├── data │ │ │ │ └── UserRepository.java │ │ │ ├── web │ │ │ │ └── UserModelList.java │ │ │ └── service │ │ │ │ └── InvalidPasswordError.java │ │ │ ├── Lab5LibraryServerApplication.java │ │ │ ├── common │ │ │ └── web │ │ │ │ ├── IndexController.java │ │ │ │ └── ErrorHandler.java │ │ │ ├── config │ │ │ ├── IdGeneratorConfiguration.java │ │ │ └── PasswordValidationConfiguration.java │ │ │ └── security │ │ │ ├── AuthenticatedUser.java │ │ │ └── LibraryUserDetailsService.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── README.md └── images │ ├── burpsuite.png │ ├── owasp_zap.png │ └── testing_pyramid.png ├── lab6 ├── library-server-container-root │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── application-test.yml │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ ├── book │ │ │ │ ├── data │ │ │ │ │ └── BookRepository.java │ │ │ │ └── web │ │ │ │ │ └── BookModelList.java │ │ │ │ ├── user │ │ │ │ ├── data │ │ │ │ │ └── UserRepository.java │ │ │ │ ├── web │ │ │ │ │ └── UserModelList.java │ │ │ │ └── service │ │ │ │ │ └── InvalidPasswordError.java │ │ │ │ ├── common │ │ │ │ └── web │ │ │ │ │ ├── IndexController.java │ │ │ │ │ └── ErrorHandler.java │ │ │ │ ├── LibraryServerApplicationContainerRoot.java │ │ │ │ ├── config │ │ │ │ ├── IdGeneratorConfiguration.java │ │ │ │ └── PasswordValidationConfiguration.java │ │ │ │ └── security │ │ │ │ ├── AuthenticatedUser.java │ │ │ │ └── LibraryUserDetailsService.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── templates │ │ │ └── index.html │ │ │ ├── logback-spring.xml │ │ │ └── password-list.txt │ ├── Dockerfile │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ └── .gitignore ├── library-server-container-rootless │ ├── settings.gradle │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── application-test.yml │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── libraryserver │ │ │ │ ├── book │ │ │ │ ├── data │ │ │ │ │ └── BookRepository.java │ │ │ │ └── web │ │ │ │ │ └── BookModelList.java │ │ │ │ ├── user │ │ │ │ ├── data │ │ │ │ │ └── UserRepository.java │ │ │ │ ├── web │ │ │ │ │ └── UserModelList.java │ │ │ │ └── service │ │ │ │ │ └── InvalidPasswordError.java │ │ │ │ ├── common │ │ │ │ └── web │ │ │ │ │ ├── IndexController.java │ │ │ │ │ └── ErrorHandler.java │ │ │ │ ├── Lab6LibraryServerApplicationContainer.java │ │ │ │ ├── config │ │ │ │ ├── IdGeneratorConfiguration.java │ │ │ │ └── PasswordValidationConfiguration.java │ │ │ │ └── security │ │ │ │ ├── AuthenticatedUser.java │ │ │ │ └── LibraryUserDetailsService.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── templates │ │ │ └── index.html │ │ │ ├── logback-spring.xml │ │ │ └── password-list.txt │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── Dockerfile │ └── .gitignore ├── kubernetes │ ├── third-iteration │ │ ├── no-root-policy-serviceaccount.yaml │ │ ├── service.yaml │ │ ├── no-root-policy-role.yaml │ │ ├── no-root-policy-role-binding.yaml │ │ ├── no-root-policy.yaml │ │ ├── deploy-without-policy.yaml │ │ └── deploy.yaml │ ├── first-iteration │ │ ├── service.yaml │ │ └── deploy.yaml │ └── second-iteration │ │ ├── service.yaml │ │ ├── deploy.yaml │ │ └── deploy_denied.yaml └── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── Cloud Native Microservice Security.pdf ├── .gitignore ├── settings.gradle ├── .github └── workflows │ └── gradle.yml ├── SUMMARY.md └── README.md /lab1/library-server/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab1-library-server' 2 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'csrf-attack-demo' 2 | -------------------------------------------------------------------------------- / .gitbook.yaml: -------------------------------------------------------------------------------- 1 | root: ./ 2 | structure: 3 | readme: ./README.md 4 | summary: ./SUMMARY.md 5 | -------------------------------------------------------------------------------- /lab1/library-server-complete/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab1-library-server-complete' 2 | -------------------------------------------------------------------------------- /lab2/library-server-complete/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab2-library-server-complete' 2 | -------------------------------------------------------------------------------- /lab3/library-server-complete/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab3-library-server-complete' 2 | -------------------------------------------------------------------------------- /lab4/library-server-complete/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab4-library-server-complete' 2 | -------------------------------------------------------------------------------- /lab5/library-server-complete/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lab5-library-server-complete' 2 | -------------------------------------------------------------------------------- /lab1/library-server/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab1/library-server-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab2/library-server-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab3/library-server-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab4/library-server-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab5/library-server-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab6/library-server-container-root/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'library-server-container-root' 2 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'library-server-container-rootless' 2 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: info -------------------------------------------------------------------------------- /lab1/images/loginform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/images/loginform.png -------------------------------------------------------------------------------- /lab1/images/logoutform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/images/logoutform.png -------------------------------------------------------------------------------- /lab5/images/burpsuite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/images/burpsuite.png -------------------------------------------------------------------------------- /lab5/images/owasp_zap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/images/owasp_zap.png -------------------------------------------------------------------------------- /lab1/images/main_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/images/main_screen.png -------------------------------------------------------------------------------- /lab3/images/cert_export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/images/cert_export.png -------------------------------------------------------------------------------- /lab1/images/secure_headers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/images/secure_headers.png -------------------------------------------------------------------------------- /lab5/images/testing_pyramid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/images/testing_pyramid.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab1/images/owasp_top_10_2017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/images/owasp_top_10_2017.png -------------------------------------------------------------------------------- /lab3/images/cert_import_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/images/cert_import_chrome.png -------------------------------------------------------------------------------- /lab4/images/roles_permissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab4/images/roles_permissions.png -------------------------------------------------------------------------------- /lab3/images/cert_import_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/images/cert_import_firefox.png -------------------------------------------------------------------------------- /lab3/images/secured_browser_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/images/secured_browser_page.png -------------------------------------------------------------------------------- /Cloud Native Microservice Security.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/Cloud Native Microservice Security.pdf -------------------------------------------------------------------------------- /lab3/images/cert_identification_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/images/cert_identification_request.png -------------------------------------------------------------------------------- /bonus-labs/README.md: -------------------------------------------------------------------------------- 1 | # Bonus Labs 2 | 3 | * [WebAuthn Demo](webauthn) 4 | * [CSRF Attack Demo](csrf-attack-demo) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/attack/images/cat1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/bonus-labs/csrf-attack-demo/attack/images/cat1.jpg -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/attack/images/cat2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/bonus-labs/csrf-attack-demo/attack/images/cat2.jpg -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.open-in-view=false 2 | spring.security.user.password=secret 3 | spring.thymeleaf.cache=false 4 | 5 | 6 | -------------------------------------------------------------------------------- /lab1/library-server/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/library-server/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/no-root-policy-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: no-root-policy-serviceaccount 5 | namespace: default -------------------------------------------------------------------------------- /lab6/library-server-container-root/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:11.0.6-jre-buster 2 | COPY library-server-container-root-1.0.0-SNAPSHOT.jar app.jar 3 | EXPOSE 9090 4 | ENTRYPOINT java -jar /app.jar 5 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/bonus-labs/csrf-attack-demo/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /bonus-labs/webauthn/README.md: -------------------------------------------------------------------------------- 1 | # Lab 5: WebAuthn 2 | 3 | Let's checkout work in progress for Spring Security: 4 | 5 | [Spring Security WebAuthn (WIP)](https://github.com/rwinch/spring-security-webauthn) 6 | -------------------------------------------------------------------------------- /lab1/library-server-complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab1/library-server-complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab1/library-server/README.md: -------------------------------------------------------------------------------- 1 | # Initial library server application 2 | 3 | This is the provided completely unsecured sample library application. 4 | 5 | Use this as the starting point into the workshop. 6 | -------------------------------------------------------------------------------- /lab2/library-server-complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab2/library-server-complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab3/library-server-complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/library-server-complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab4/library-server-complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab4/library-server-complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab5/library-server-complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/library-server-complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/pparker-trust.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/library-server-complete/src/main/resources/pparker-trust.p12 -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/pparker-trust.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab4/library-server-complete/src/main/resources/pparker-trust.p12 -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/pparker-trust.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/library-server-complete/src/main/resources/pparker-trust.p12 -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/client-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/library-server-complete/src/main/resources/client-keystore.p12 -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/server-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab3/library-server-complete/src/main/resources/server-keystore.p12 -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/client-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab4/library-server-complete/src/main/resources/client-keystore.p12 -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/server-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab4/library-server-complete/src/main/resources/server-keystore.p12 -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/client-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/library-server-complete/src/main/resources/client-keystore.p12 -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/server-keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab5/library-server-complete/src/main/resources/server-keystore.p12 -------------------------------------------------------------------------------- /lab6/library-server-container-root/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab6/library-server-container-root/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andifalk/cloud-native-microservices-security/HEAD/lab6/library-server-container-rootless/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lab3/library-server-complete/README.md: -------------------------------------------------------------------------------- 1 | # Complete reference solution 2 | 3 | This is the reference solution for Lab 3. 4 | 5 | You may also use this project as a starting point for next Lab 4 in case you could 6 | not finish this lab. 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab6/kubernetes/first-iteration/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: library-server-root 5 | spec: 6 | selector: 7 | app: library-server-root 8 | ports: 9 | - port: 9091 10 | targetPort: 9090 11 | type: LoadBalancer -------------------------------------------------------------------------------- /lab1/library-server/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello-rootless-with-policy 5 | spec: 6 | selector: 7 | app: hello-rootless-with-policy 8 | ports: 9 | - port: 8081 10 | targetPort: 8080 11 | type: LoadBalancer -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab1/library-server-complete/README.md: -------------------------------------------------------------------------------- 1 | # Complete library server application 2 | 3 | This is the complete reference solution for the lab 1 of this workshop. 4 | 5 | You may use this one as a starting point for coding the next lab 2 in case 6 | you could not step up with the workshop. 7 | -------------------------------------------------------------------------------- /lab1/library-server-complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab2/library-server-complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab3/library-server-complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab4/library-server-complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab5/library-server-complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lab6/kubernetes/second-iteration/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: library-server-container-security-ctx 5 | spec: 6 | selector: 7 | app: library-server-container-security-ctx 8 | ports: 9 | - port: 9091 10 | targetPort: 9090 11 | type: LoadBalancer -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:11.0.6-jre-buster 2 | COPY library-server-container-rootless-1.0.0-SNAPSHOT.jar app.jar 3 | EXPOSE 9090 4 | RUN addgroup --system --gid 1002 app && adduser --system --uid 1002 --gid 1002 appuser 5 | USER 1002 6 | ENTRYPOINT java -jar /app.jar 7 | -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/no-root-policy-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: no-root-policy-role 5 | namespace: default 6 | rules: 7 | - apiGroups: ['policy'] 8 | resources: ['podsecuritypolicies'] 9 | verbs: ['use'] 10 | resourceNames: 11 | - no-root-policy -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/test/java/com/example/csrf/attack/CsrfAttackDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CsrfAttackDemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /lab1/library-server/src/test/java/com/example/libraryserver/LibraryApplicationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class LibraryApplicationIntegrationTest { 8 | 9 | @Test 10 | void verifyContextLoad() {} 11 | } 12 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/test/java/com/example/libraryserver/LibraryApplicationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class LibraryApplicationIntegrationTest { 8 | 9 | @Test 10 | void verifyContextLoad() {} 11 | } 12 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/test/java/com/example/libraryserver/LibraryApplicationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class LibraryApplicationIntegrationTest { 8 | 9 | @Test 10 | void verifyContextLoad() {} 11 | } 12 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/test/java/com/example/libraryserver/LibraryApplicationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class LibraryApplicationIntegrationTest { 8 | 9 | @Test 10 | void verifyContextLoad() {} 11 | } 12 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/test/java/com/example/libraryserver/LibraryApplicationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class LibraryApplicationIntegrationTest { 8 | 9 | @Test 10 | void verifyContextLoad() {} 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.war 15 | *.nar 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | .idea/ 25 | .gradle/ 26 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/data/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface CustomerRepository extends JpaRepository { 9 | 10 | Optional findByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/no-root-policy-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: no-root-policy-role-binding 5 | namespace: default 6 | roleRef: 7 | kind: Role 8 | name: no-root-policy-role 9 | apiGroup: rbac.authorization.k8s.io 10 | subjects: 11 | - kind: ServiceAccount 12 | name: no-root-policy-serviceaccount 13 | namespace: default -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/book/data/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface BookRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | } 12 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'cloud-native-microservices-security' 2 | 3 | include 'lab1:library-server' 4 | include 'lab1:library-server-complete' 5 | include 'lab2:library-server-complete' 6 | include 'lab3:library-server-complete' 7 | include 'lab4:library-server-complete' 8 | include 'lab5:library-server-complete' 9 | include 'lab6:library-server-container-root' 10 | include 'lab6:library-server-container-rootless' 11 | include 'bonus-labs:csrf-attack-demo' 12 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/Lab1LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab1LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab1LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/Lab2LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab2LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab2LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/Lab3LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab3LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab3LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/Lab4LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab4LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab4LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/Lab5LibraryServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab5LibraryServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab5LibraryServerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/user/data/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import java.util.Optional; 6 | import java.util.UUID; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | Optional findOneByIdentifier(UUID identifier); 11 | 12 | Optional findOneByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab1/library-server/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/common/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @RequestMapping("/") 9 | public class IndexController { 10 | 11 | @GetMapping 12 | public String index() { 13 | return "index"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab1/library-server-complete/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab2/library-server-complete/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab3/library-server-complete/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab4/library-server-complete/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab5/library-server-complete/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/LibraryServerApplicationContainerRoot.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class LibraryServerApplicationContainerRoot { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(LibraryServerApplicationContainerRoot.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/Lab6LibraryServerApplicationContainer.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Lab6LibraryServerApplicationContainer { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Lab6LibraryServerApplicationContainer.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/config/IdGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfiguration { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/book/web/BookModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.book.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class BookModelList extends CollectionModel { 8 | 9 | private final Collection books; 10 | 11 | public BookModelList(Collection books) { 12 | this.books = books; 13 | } 14 | 15 | public Collection getBooks() { 16 | return books; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/user/web/UserModelList.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import org.springframework.hateoas.CollectionModel; 4 | 5 | import java.util.Collection; 6 | 7 | public class UserModelList extends CollectionModel { 8 | 9 | private final Collection users; 10 | 11 | public UserModelList(Collection users) { 12 | this.users = users; 13 | } 14 | 15 | public Collection getUsers() { 16 | return users; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | # test against latest update of each major Java version, as well as specific updates of LTS versions: 12 | java: [ 11, 11.0.3, 11.0.4, 11.0.10, 11.0.11, 16 ] 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Set up JDK 16 | uses: actions/setup-java@v1 17 | with: 18 | java-version: ${{ matrix.java }} 19 | - name: Build with Gradle 20 | run: ./gradlew build 21 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | server: 9 | port: 9090 10 | servlet: 11 | context-path: /library 12 | error: 13 | include-stacktrace: never 14 | 15 | management: 16 | endpoint: 17 | health: 18 | show-details: always 19 | endpoints: 20 | web: 21 | exposure: 22 | include: '*' 23 | 24 | info: 25 | application: 26 | name: library-server 27 | version: 1.0.0 28 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/config/PasswordValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.config; 2 | 3 | import com.example.libraryserver.user.service.PasswordValidationService; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class PasswordValidationConfiguration { 9 | 10 | @Bean 11 | public PasswordValidationService passwordValidationService() { 12 | return new PasswordValidationService(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/CsrfAttackDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession; 6 | 7 | @EnableJdbcHttpSession 8 | @SpringBootApplication 9 | public class CsrfAttackDemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(CsrfAttackDemoApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/user/service/InvalidPasswordError.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import java.util.List; 4 | 5 | public class InvalidPasswordError extends RuntimeException { 6 | 7 | private List validationErrors; 8 | 9 | public InvalidPasswordError(List validationErrors) { 10 | super("Validation failed: " + String.join(",", validationErrors)); 11 | this.validationErrors = validationErrors; 12 | } 13 | 14 | public List getValidationErrors() { 15 | return validationErrors; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | security: 9 | user: 10 | password: secret 11 | server: 12 | port: 9090 13 | servlet: 14 | context-path: /library 15 | error: 16 | include-stacktrace: never 17 | 18 | management: 19 | endpoint: 20 | health: 21 | show-details: always 22 | endpoints: 23 | web: 24 | exposure: 25 | include: '*' 26 | 27 | info: 28 | application: 29 | name: library-server 30 | version: 1.0.0 31 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 9090 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | 16 | management: 17 | endpoint: 18 | health: 19 | show-details: when_authorized 20 | endpoints: 21 | web: 22 | exposure: 23 | include: '*' 24 | 25 | info: 26 | application: 27 | name: library-server 28 | version: 1.0.0 29 | 30 | logging: 31 | level: 32 | org.springframework.security: info 33 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 9090 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | 16 | management: 17 | endpoint: 18 | health: 19 | show-details: when_authorized 20 | endpoints: 21 | web: 22 | exposure: 23 | include: '*' 24 | 25 | info: 26 | application: 27 | name: library-server 28 | version: 1.0.0 29 | 30 | logging: 31 | level: 32 | org.springframework.security: info 33 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 9090 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | 16 | management: 17 | endpoint: 18 | health: 19 | show-details: when_authorized 20 | endpoints: 21 | web: 22 | exposure: 23 | include: '*' 24 | 25 | info: 26 | application: 27 | name: library-server 28 | version: 1.0.0 29 | 30 | logging: 31 | level: 32 | org.springframework.security: info 33 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/attack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | Cat Pictures Forum 8 | 9 | 10 |
11 |

A forum of Cat pictures

12 | 13 |

Forum (Get)

14 |

Forum (Post)

15 |
16 | 17 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/no-root-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1beta1 2 | kind: PodSecurityPolicy 3 | metadata: 4 | name: no-root-policy 5 | annotations: 6 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' 7 | spec: 8 | readOnlyRootFilesystem: true 9 | privileged: false 10 | allowPrivilegeEscalation: false 11 | requiredDropCapabilities: 12 | - ALL 13 | volumes: 14 | - '*' 15 | hostNetwork: true 16 | hostPorts: 17 | - min: 0 18 | max: 65535 19 | hostIPC: true 20 | hostPID: true 21 | runAsUser: 22 | rule: 'MustRunAsNonRoot' 23 | seLinux: 24 | rule: 'RunAsAny' 25 | supplementalGroups: 26 | rule: 'RunAsAny' 27 | fsGroup: 28 | rule: 'RunAsAny' -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab6/kubernetes/first-iteration/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: library-server-root 6 | name: library-server-root 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: library-server-root 12 | template: 13 | metadata: 14 | labels: 15 | app: library-server-root 16 | spec: 17 | containers: 18 | - image: andifalk/library-server-container-root:1.0 19 | name: library-server-root 20 | readinessProbe: 21 | httpGet: 22 | path: /library/actuator/health 23 | port: 9090 24 | initialDelaySeconds: 5 25 | periodSeconds: 5 26 | restartPolicy: Always 27 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library Server 6 | 7 | 8 |

Library Server

9 |

Welcome to the library server API

10 |

This server provides the following APIs

11 | 17 | 18 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level ${PID} %logger{36} - %crlf(%mask) %n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/config/WebSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.config; 2 | 3 | import org.springframework.security.config.Customizer; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 | 8 | @EnableWebSecurity 9 | public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 10 | 11 | @Override 12 | protected void configure(HttpSecurity http) throws Exception { 13 | http.authorizeRequests(authReq -> authReq.anyRequest().authenticated()) 14 | .csrf().disable() 15 | .formLogin(Customizer.withDefaults()) 16 | .httpBasic(Customizer.withDefaults()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/session/SameSiteCookieConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.session; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.session.web.http.CookieSerializer; 6 | import org.springframework.session.web.http.DefaultCookieSerializer; 7 | 8 | @Configuration 9 | public class SameSiteCookieConfiguration { 10 | 11 | @Bean 12 | public CookieSerializer cookieSerializer() { 13 | DefaultCookieSerializer serializer = new DefaultCookieSerializer(); 14 | serializer.setCookieName("JSESSIONID"); 15 | serializer.setCookiePath("/"); 16 | serializer.setSameSite("Strict"); 17 | serializer.setUseHttpOnlyCookie(true); 18 | serializer.setUseSecureCookie(false); 19 | serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); 20 | return serializer; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 8443 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | ssl: 16 | enabled: true 17 | key-store: classpath:server-keystore.p12 18 | key-store-type: PKCS12 19 | key-store-password: changeit 20 | key-password: changeit 21 | trust-store: classpath:pparker-trust.p12 22 | trust-store-password: changeit 23 | client-auth: need 24 | 25 | management: 26 | endpoint: 27 | health: 28 | show-details: when_authorized 29 | endpoints: 30 | web: 31 | exposure: 32 | include: '*' 33 | 34 | info: 35 | application: 36 | name: library-server 37 | version: 1.0.0 38 | 39 | logging: 40 | level: 41 | org.springframework.security: info 42 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 8443 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | ssl: 16 | enabled: true 17 | key-store: classpath:server-keystore.p12 18 | key-store-type: PKCS12 19 | key-store-password: changeit 20 | key-password: changeit 21 | trust-store: classpath:pparker-trust.p12 22 | trust-store-password: changeit 23 | client-auth: none 24 | 25 | management: 26 | endpoint: 27 | health: 28 | show-details: when_authorized 29 | endpoints: 30 | web: 31 | exposure: 32 | include: '*' 33 | 34 | info: 35 | application: 36 | name: library-server 37 | version: 1.0.0 38 | 39 | logging: 40 | level: 41 | org.springframework.security: info 42 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: library-server 4 | jpa: 5 | open-in-view: false 6 | jackson: 7 | default-property-inclusion: non_null 8 | 9 | server: 10 | port: 8443 11 | servlet: 12 | context-path: /library 13 | error: 14 | include-stacktrace: never 15 | ssl: 16 | enabled: true 17 | key-store: classpath:server-keystore.p12 18 | key-store-type: PKCS12 19 | key-store-password: changeit 20 | key-password: changeit 21 | trust-store: classpath:pparker-trust.p12 22 | trust-store-password: changeit 23 | client-auth: none 24 | 25 | management: 26 | endpoint: 27 | health: 28 | show-details: when_authorized 29 | endpoints: 30 | web: 31 | exposure: 32 | include: '*' 33 | 34 | info: 35 | application: 36 | name: library-server 37 | version: 1.0.0 38 | 39 | logging: 40 | level: 41 | org.springframework.security: info 42 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE SPRING_SESSION ( 2 | PRIMARY_ID CHAR(36) NOT NULL, 3 | SESSION_ID CHAR(36) NOT NULL, 4 | CREATION_TIME BIGINT NOT NULL, 5 | LAST_ACCESS_TIME BIGINT NOT NULL, 6 | MAX_INACTIVE_INTERVAL INT NOT NULL, 7 | EXPIRY_TIME BIGINT NOT NULL, 8 | PRINCIPAL_NAME VARCHAR(100), 9 | CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) 10 | ); 11 | 12 | CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); 13 | CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); 14 | CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME); 15 | 16 | CREATE TABLE SPRING_SESSION_ATTRIBUTES ( 17 | SESSION_PRIMARY_ID CHAR(36) NOT NULL, 18 | ATTRIBUTE_NAME VARCHAR(200) NOT NULL, 19 | ATTRIBUTE_BYTES LONGVARBINARY NOT NULL, 20 | CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME), 21 | CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE 22 | ); -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/attack/forum-post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | Cat Pictures Forum 8 | 9 | 10 |
11 |

A forum of Cat pictures

12 | 13 |

My nice cat

14 |

A Nice Cat

15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 |

24 | Back 25 |

26 |
27 | 28 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/api/CustomerRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.api; 2 | 3 | import javax.validation.constraints.NotBlank; 4 | import javax.validation.constraints.Size; 5 | 6 | public class CustomerRequest { 7 | 8 | @NotBlank 9 | @Size(max = 100) 10 | private String firstName; 11 | 12 | @NotBlank 13 | @Size(max = 100) 14 | private String lastName; 15 | 16 | public String getFirstName() { 17 | return firstName; 18 | } 19 | 20 | public void setFirstName(String firstName) { 21 | this.firstName = firstName; 22 | } 23 | 24 | public String getLastName() { 25 | return lastName; 26 | } 27 | 28 | public void setLastName(String lastName) { 29 | this.lastName = lastName; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "CustomerRequest{" + 35 | "firstName='" + firstName + '\'' + 36 | ", lastName='" + lastName + '\'' + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native Microservices Workshop 2 | 3 | ## Introduction 4 | 5 | * [Requirements and Setup](setup/README.md) 6 | * [Demo Application Architecture](application-architecture/README.md) 7 | 8 | ## Hands-On Labs 9 | 10 | * [1.Security via Spring Boot Auto-Configuration](lab1/README.md) 11 | * [2.Customized Authentication](lab2/README.md) 12 | * [3.Mutual TLS (MTLS)](lab3/README.md) 13 | * [4.Authorization](lab4/README.md) 14 | * [5.Automated Testing](lab5/README.md) 15 | * [6.Kubernetes Security](lab6/README.md) 16 | * [6.1.Docker as Root](lab6/library-server-container-root/README.md) 17 | * [6.2.Docker as NonRoot](lab6/library-server-container-rootless/README.md) 18 | * [6.3.Kubernetes Deployment](lab6/kubernetes/first-iteration/README.md) 19 | * [6.4.Kubernetes Pod Security Context](lab6/kubernetes/second-iteration/README.md) 20 | * [6.5.Kubernetes Pod Security Policies](lab6/kubernetes/third-iteration/README.md) 21 | 22 | ## Bonus Labs 23 | 24 | * [CSRF Attack Demo](bonus-labs/csrf-attack-demo/README.md) 25 | * [Web Authn](bonus-labs/webauthn/README.md) 26 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/attack/forum-get.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | Cat Pictures Forum 8 | 9 | 10 |
11 |

A forum of Cat pictures

12 | 13 |

My nice cat

14 |

15 | A Nice Cat 16 |

17 |

My other nice cat

18 |

19 | Another Nice Cat 20 |

21 |

22 | 25 |

26 | 27 |
28 | 29 |

30 | Back 31 |

32 |
33 | 34 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.example' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | configurations { 12 | developmentOnly 13 | runtimeClasspath { 14 | extendsFrom developmentOnly 15 | } 16 | } 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-security' 24 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 25 | implementation 'org.springframework.boot:spring-boot-starter-web' 26 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.session:spring-session-jdbc' 29 | runtimeOnly 'com.h2database:h2' 30 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 31 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 32 | testImplementation 'org.springframework.security:spring-security-test' 33 | } 34 | 35 | test { 36 | useJUnitPlatform() 37 | } 38 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/resources/password-list.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | 123456789 3 | 111111 4 | password 5 | qwerty 6 | abc123 7 | 12345678 8 | password1 9 | 1234567 10 | 123123 11 | 1234567890 12 | 000000 13 | 12345 14 | iloveyou 15 | 1q2w3e4r5t 16 | 1234 17 | 123456a 18 | qwertyuiop 19 | monkey 20 | 123321 21 | dragon 22 | 654321 23 | 666666 24 | 123 25 | myspace1 26 | a123456 27 | 121212 28 | 1qaz2wsx 29 | 123qwe 30 | 123abc 31 | tinkle 32 | target123 33 | gwerty 34 | 1g2w3e4r 35 | gwerty123 36 | zag12wsx 37 | 7777777 38 | qwerty1 39 | 1q2w3e4r 40 | 987654321 41 | 222222 42 | qwe123 43 | qwerty123 44 | zxcvbnm 45 | 555555 46 | 112233 47 | fuckyou 48 | asdfghjkl 49 | 12345a 50 | 123123123 51 | 1q2w3e 52 | qazwsx 53 | computer 54 | aaaaaa 55 | 159753 56 | iloveyou1 57 | fuckyou1 58 | princess 59 | 789456123 60 | 11111111 61 | 123654 62 | princess1 63 | 888888 64 | linkedin 65 | michael 66 | sunshine 67 | football 68 | 11111 69 | 777777 70 | 1234qwer 71 | 999999 72 | j38ifUbn 73 | monkey1 74 | football1 75 | daniel 76 | azerty 77 | a12345 78 | 123456789a 79 | 789456 80 | asdfgh 81 | love123 82 | abcd1234 83 | jordan23 84 | 88888888 85 | 5201314 86 | 12qwaszx 87 | FQRG7CS493 88 | ashley 89 | asdf 90 | asd123 91 | superman 92 | jessica 93 | love 94 | samsung 95 | shadow 96 | blink182 97 | 333333 98 | michael1 99 | babygirl1 -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/deploy-without-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: library-server-no-policy 6 | name: library-server-no-policy 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: library-server-no-policy 12 | template: 13 | metadata: 14 | labels: 15 | app: library-server-no-policy 16 | spec: 17 | containers: 18 | - image: andifalk/library-server-container-rootless:1.0 19 | name: library-server-no-policy 20 | resources: 21 | limits: 22 | cpu: "1" 23 | memory: "512Mi" 24 | requests: 25 | cpu: "0.5" 26 | memory: "256Mi" 27 | readinessProbe: 28 | httpGet: 29 | path: /library 30 | port: 9090 31 | initialDelaySeconds: 5 32 | periodSeconds: 5 33 | livenessProbe: 34 | httpGet: 35 | path: /library/actuator/health 36 | port: 9090 37 | initialDelaySeconds: 10 38 | periodSeconds: 5 39 | volumeMounts: 40 | - name: tmp-volume 41 | mountPath: /tmp 42 | restartPolicy: Always 43 | volumes: 44 | - name: tmp-volume 45 | emptyDir: {} 46 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/resources/templates/customerform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CustomerForm 7 | 9 | 10 | 11 | 12 | 13 |
14 |

Customer Form

15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 | 26 |
27 |
28 |

29 | Show List 30 |

31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Customer App 7 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |

Customer App

16 | 17 |
18 | 19 |

List of Customers

20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
First NameLast Name
FirstnameLastname
35 |
36 | 37 | Add customer 38 | 39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.service; 2 | 3 | import com.example.csrf.attack.data.Customer; 4 | import com.example.csrf.attack.data.CustomerRepository; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | import java.util.List; 9 | import java.util.Optional; 10 | import java.util.UUID; 11 | 12 | @Transactional(readOnly = true) 13 | @Service 14 | public class CustomerService { 15 | 16 | private final CustomerRepository customerRepository; 17 | 18 | public CustomerService(CustomerRepository customerRepository) { 19 | this.customerRepository = customerRepository; 20 | } 21 | 22 | public List findAll() { 23 | return customerRepository.findAll(); 24 | } 25 | 26 | @Transactional 27 | public Customer save(Customer entity) { 28 | return customerRepository.save(entity); 29 | } 30 | 31 | public Optional findByIdentifier(UUID identifier) { 32 | return customerRepository.findByIdentifier(identifier); 33 | } 34 | 35 | @Transactional 36 | public boolean deleteByIdentifier(UUID identifier) { 37 | return customerRepository.findByIdentifier(identifier) 38 | .map(customer -> { customerRepository.delete(customer); return true; }) 39 | .orElse(false); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lab6/kubernetes/third-iteration/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: library-server-with-policy 6 | name: library-server-with-policy 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: library-server-with-policy 12 | template: 13 | metadata: 14 | labels: 15 | app: library-server-with-policy 16 | spec: 17 | serviceAccountName: no-root-policy-serviceaccount 18 | automountServiceAccountToken: false 19 | containers: 20 | - image: andifalk/library-server-container-rootless:1.0 21 | name: library-server-with-policy 22 | resources: 23 | limits: 24 | cpu: "1" 25 | memory: "512Mi" 26 | requests: 27 | cpu: "0.5" 28 | memory: "256Mi" 29 | readinessProbe: 30 | httpGet: 31 | path: /library 32 | port: 9090 33 | initialDelaySeconds: 5 34 | periodSeconds: 5 35 | livenessProbe: 36 | httpGet: 37 | path: /library/actuator/health 38 | port: 9090 39 | initialDelaySeconds: 10 40 | periodSeconds: 5 41 | volumeMounts: 42 | - name: tmp-volume 43 | mountPath: /tmp 44 | restartPolicy: Always 45 | volumes: 46 | - name: tmp-volume 47 | emptyDir: {} 48 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | 10 | public class AuthenticatedUser extends User implements UserDetails { 11 | 12 | public AuthenticatedUser(User user) { 13 | super( 14 | user.getIdentifier(), 15 | user.getFirstName(), 16 | user.getLastName(), 17 | user.getEmail(), 18 | user.getPassword(), 19 | user.getRoles()); 20 | } 21 | 22 | @Override 23 | public Collection getAuthorities() { 24 | return AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", getRoles())); 25 | } 26 | 27 | @Override 28 | public String getUsername() { 29 | return getEmail(); 30 | } 31 | 32 | @Override 33 | public boolean isAccountNonExpired() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public boolean isAccountNonLocked() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean isCredentialsNonExpired() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean isEnabled() { 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | 10 | public class AuthenticatedUser extends User implements UserDetails { 11 | 12 | public AuthenticatedUser(User user) { 13 | super( 14 | user.getIdentifier(), 15 | user.getFirstName(), 16 | user.getLastName(), 17 | user.getEmail(), 18 | user.getPassword(), 19 | user.getRoles()); 20 | } 21 | 22 | @Override 23 | public Collection getAuthorities() { 24 | return AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", getRoles())); 25 | } 26 | 27 | @Override 28 | public String getUsername() { 29 | return getEmail(); 30 | } 31 | 32 | @Override 33 | public boolean isAccountNonExpired() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public boolean isAccountNonLocked() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean isCredentialsNonExpired() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean isEnabled() { 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lab6/README.md: -------------------------------------------------------------------------------- 1 | # Lab 6: Container & Kubernetes Security 2 | 3 | ## Setup 4 | 5 | ### Minikube 6 | 7 | If you are using Minikube then you need to follow these steps 8 | to use local docker container images: 9 | 10 | ```shell script 11 | minikube start 12 | eval $(minikube docker-env) 13 | ./gradlew docker 14 | ``` 15 | 16 | To see the exposed url for a service in Minikube just use: 17 | 18 | ```shell script 19 | minikube service list 20 | ``` 21 | 22 | ### Docker for Windows/Mac 23 | 24 | If you are using Docker for Windows or Mac then the integrated single node 25 | Kubernetes automatically can use local container images for deployments. 26 | 27 | ## Deploy Images to Kubernetes 28 | 29 | If you have docker installed you can work with building local docker images yourself and 30 | deploy these to Kubernetes. 31 | 32 | As alternative you may also just use the corresponding container images 33 | already available remotely: 34 | 35 | * [andifalk/library-server-container-root](https://hub.docker.com/repository/docker/andifalk/library-server-container-root) 36 | * [andifalk/library-server-container-rootless](https://hub.docker.com/repository/docker/andifalk/library-server-container-rootless) 37 | 38 | Use tags _latest_ or _1.0_. 39 | 40 | ## Labs 41 | 42 | * [Docker as Root](lab6/library-server-container-root) 43 | * [Docker as NonRoot](lab6/library-server-container-rootless) 44 | * [Kubernetes Deployment](lab6/kubernetes/first-iteration) 45 | * [Secure Kubernetes Deployment](lab6/kubernetes/second-iteration) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.owasp.encoder.Encode; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.MethodArgumentNotValidException; 9 | import org.springframework.web.bind.annotation.ControllerAdvice; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @ControllerAdvice(annotations = RestController.class) 14 | public class ErrorHandler { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 17 | 18 | @ExceptionHandler(MethodArgumentNotValidException.class) 19 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 20 | LOGGER.warn(ex.getMessage()); 21 | StringBuilder builder = new StringBuilder(); 22 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 23 | return ResponseEntity.badRequest() 24 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 25 | } 26 | 27 | @ExceptionHandler(RuntimeException.class) 28 | public ResponseEntity handle(RuntimeException ex) { 29 | LOGGER.error(ex.getMessage(), ex); 30 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![License](https://img.shields.io/badge/License-Apache%20License%202.0-brightgreen.svg) 2 | ![Java Build](https://github.com/andifalk/cloud-native-microservices-security/workflows/Java%20CI/badge.svg) 3 | [![Release](https://img.shields.io/github/release/andifalk/cloud-native-microservices-security.svg?style=flat)](https://github.com/andifalk/cloud-native-microservices-security/releases) 4 | 5 | # Cloud-Native Microservice Security Boot-Camp 6 | 7 | ## Tutorial 8 | 9 | [Tutorial](https://andifalk.gitbook.io/cloud-native-microservices-security) 10 | 11 | ## Slides 12 | 13 | * [Slides for Workshop (PDF)](https://github.com/andifalk/cloud-native-microservices-security/raw/master/Cloud%20Native%20Microservice%20Security.pdf) 14 | 15 | ## Introduction 16 | 17 | * [Requirements and Setup](setup) 18 | * [Demo Application Architecture](application-architecture) 19 | 20 | 21 | ## Hands-On Labs 22 | 23 | * [1.Security via Spring Boot Auto-Configuration](lab1) 24 | * [2.Customized Authentication](lab2) 25 | * [3.Mutual TLS (MTLS)](lab3) 26 | * [4.Authorization](lab4) 27 | * [5.Automated Testing](lab5) 28 | * [6.Kubernetes Security](lab6) 29 | * [6.1.Docker as Root](lab6/library-server-container-root) 30 | * [6.2.Docker as NonRoot](lab6/library-server-container-rootless) 31 | * [6.3.Kubernetes Deployment](lab6/kubernetes/first-iteration) 32 | * [6.4.Secure Kubernetes Deployment](lab6/kubernetes/second-iteration) 33 | 34 | ## Bonus Labs 35 | 36 | * [CSRF Attack Demo](bonus-labs/csrf-attack-demo) 37 | * [Web Authn](bonus-labs/webauthn) -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import org.owasp.encoder.Encode; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.MethodArgumentNotValidException; 9 | import org.springframework.web.bind.annotation.ControllerAdvice; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @ControllerAdvice(annotations = RestController.class) 14 | public class ErrorHandler { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 17 | 18 | @ExceptionHandler(MethodArgumentNotValidException.class) 19 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 20 | LOGGER.warn(ex.getMessage()); 21 | StringBuilder builder = new StringBuilder(); 22 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 23 | return ResponseEntity.badRequest() 24 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 25 | } 26 | 27 | @ExceptionHandler(RuntimeException.class) 28 | public ResponseEntity handle(RuntimeException ex) { 29 | LOGGER.error(ex.getMessage(), ex); 30 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | 11 | public class AuthenticatedUser extends User implements UserDetails { 12 | 13 | public AuthenticatedUser(User user) { 14 | super( 15 | user.getIdentifier(), 16 | user.getFirstName(), 17 | user.getLastName(), 18 | user.getEmail(), 19 | user.getPassword(), 20 | user.getRoles()); 21 | } 22 | 23 | @Override 24 | public Collection getAuthorities() { 25 | 26 | return AuthorityUtils.commaSeparatedStringToAuthorityList( 27 | getRoles().stream().map(rn -> "ROLE_" + rn).collect(Collectors.joining(","))); 28 | } 29 | 30 | @Override 31 | public String getUsername() { 32 | return getEmail(); 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonExpired() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonLocked() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isCredentialsNonExpired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isEnabled() { 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | 11 | public class AuthenticatedUser extends User implements UserDetails { 12 | 13 | public AuthenticatedUser(User user) { 14 | super( 15 | user.getIdentifier(), 16 | user.getFirstName(), 17 | user.getLastName(), 18 | user.getEmail(), 19 | user.getPassword(), 20 | user.getRoles()); 21 | } 22 | 23 | @Override 24 | public Collection getAuthorities() { 25 | 26 | return AuthorityUtils.commaSeparatedStringToAuthorityList( 27 | getRoles().stream().map(rn -> "ROLE_" + rn).collect(Collectors.joining(","))); 28 | } 29 | 30 | @Override 31 | public String getUsername() { 32 | return getEmail(); 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonExpired() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonLocked() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isCredentialsNonExpired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isEnabled() { 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | 11 | public class AuthenticatedUser extends User implements UserDetails { 12 | 13 | public AuthenticatedUser(User user) { 14 | super( 15 | user.getIdentifier(), 16 | user.getFirstName(), 17 | user.getLastName(), 18 | user.getEmail(), 19 | user.getPassword(), 20 | user.getRoles()); 21 | } 22 | 23 | @Override 24 | public Collection getAuthorities() { 25 | 26 | return AuthorityUtils.commaSeparatedStringToAuthorityList( 27 | getRoles().stream().map(rn -> "ROLE_" + rn).collect(Collectors.joining(","))); 28 | } 29 | 30 | @Override 31 | public String getUsername() { 32 | return getEmail(); 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonExpired() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonLocked() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isCredentialsNonExpired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isEnabled() { 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | 11 | public class AuthenticatedUser extends User implements UserDetails { 12 | 13 | public AuthenticatedUser(User user) { 14 | super( 15 | user.getIdentifier(), 16 | user.getFirstName(), 17 | user.getLastName(), 18 | user.getEmail(), 19 | user.getPassword(), 20 | user.getRoles()); 21 | } 22 | 23 | @Override 24 | public Collection getAuthorities() { 25 | 26 | return AuthorityUtils.commaSeparatedStringToAuthorityList( 27 | getRoles().stream().map(rn -> "ROLE_" + rn).collect(Collectors.joining(","))); 28 | } 29 | 30 | @Override 31 | public String getUsername() { 32 | return getEmail(); 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonExpired() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonLocked() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isCredentialsNonExpired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isEnabled() { 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lab6/kubernetes/second-iteration/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: library-server-container-security-ctx 6 | name: library-server-container-security-ctx 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: library-server-container-security-ctx 12 | template: 13 | metadata: 14 | labels: 15 | app: library-server-container-security-ctx 16 | spec: 17 | automountServiceAccountToken: false 18 | securityContext: 19 | runAsNonRoot: true 20 | containers: 21 | - image: andifalk/library-server-container-rootless:1.0 22 | name: library-server-container-security-ctx 23 | resources: 24 | limits: 25 | cpu: "1" 26 | memory: "512Mi" 27 | requests: 28 | cpu: "0.5" 29 | memory: "256Mi" 30 | securityContext: 31 | readOnlyRootFilesystem: true 32 | allowPrivilegeEscalation: false 33 | privileged: false 34 | runAsNonRoot: true 35 | capabilities: 36 | drop: 37 | - ALL 38 | readinessProbe: 39 | httpGet: 40 | path: /library 41 | port: 9090 42 | initialDelaySeconds: 5 43 | periodSeconds: 5 44 | livenessProbe: 45 | httpGet: 46 | path: /library/actuator/health 47 | port: 9090 48 | initialDelaySeconds: 10 49 | periodSeconds: 5 50 | volumeMounts: 51 | - name: tmp-volume 52 | mountPath: /tmp 53 | restartPolicy: Always 54 | volumes: 55 | - name: tmp-volume 56 | emptyDir: {} 57 | -------------------------------------------------------------------------------- /lab6/kubernetes/second-iteration/deploy_denied.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: library-server-container-security-ctx-deny 6 | name: library-server-container-security-ctx-deny 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: library-server-container-security-ctx-deny 12 | template: 13 | metadata: 14 | labels: 15 | app: library-server-container-security-ctx-deny 16 | spec: 17 | automountServiceAccountToken: false 18 | securityContext: 19 | runAsNonRoot: true 20 | containers: 21 | - image: andifalk/library-server-container-root:1.0 22 | name: library-server-container-security-ctx-deny 23 | resources: 24 | limits: 25 | cpu: "1" 26 | memory: "512Mi" 27 | requests: 28 | cpu: "0.5" 29 | memory: "256Mi" 30 | securityContext: 31 | readOnlyRootFilesystem: true 32 | allowPrivilegeEscalation: false 33 | privileged: false 34 | runAsNonRoot: true 35 | capabilities: 36 | drop: 37 | - ALL 38 | readinessProbe: 39 | httpGet: 40 | path: /library 41 | port: 9090 42 | initialDelaySeconds: 5 43 | periodSeconds: 5 44 | livenessProbe: 45 | httpGet: 46 | path: /library/actuator/health 47 | port: 9090 48 | initialDelaySeconds: 10 49 | periodSeconds: 5 50 | volumeMounts: 51 | - name: tmp-volume 52 | mountPath: /tmp 53 | restartPolicy: Always 54 | volumes: 55 | - name: tmp-volume 56 | emptyDir: {} 57 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/resources/pparker.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEgTCCAumgAwIBAgIQPZKP130KwQ5Bl6JPgpdD+zANBgkqhkiG9w0BAQsFADBt 3 | MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGGFmYUB0 4 | NDcwcCAoQW5kcmVhcyBGYWxrKTEoMCYGA1UEAwwfbWtjZXJ0IGFmYUB0NDcwcCAo 5 | QW5kcmVhcyBGYWxrKTAeFw0xOTA2MDEwMDAwMDBaFw0zMDAyMTkwODE0NDdaMG8x 6 | JzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEhMB8GA1UE 7 | CwwYYWZhQHQ0NzBwIChBbmRyZWFzIEZhbGspMSEwHwYDVQQDDBhwZXRlci5wYXJr 8 | ZXJAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj 9 | oGHb1SE1tgqhkB4m+cCZjU9hdJMCdrS8tSSnKc4asgxDVy2x5sebeVCkXryt/IM8 10 | HXPRxt/7HXKXRjJ8hNBWGSSHfRb3MsvnqWYaSRrntzmE0N+LGxodCb+GSzTWPoDD 11 | NOslZMSKHGCIYKeAPsVF786LlybltCB5OriQZfAZ6i2LKnn/E3GJn7beWqnnPQwJ 12 | yJ6jJGFoGdpJ4NPQpUj1ayFMZGHGLnjQ4Z9sM+9hGlk7sm0btsrxHuSTRT5JQnIp 13 | /RD6/WAfpQ12ttwQwDDoXfW0ytKeC575hV8z4rsPtdZ926XwlfDFC+cOoS/6v+Wo 14 | v5+E2o2i0OgvCcdB9iTvAgMBAAGjgZowgZcwDgYDVR0PAQH/BAQDAgWgMDEGA1Ud 15 | JQQqMCgGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEMAwG 16 | A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUFYBfwFCxdOnin/k5HnyZijgoDMgwIwYD 17 | VR0RBBwwGoEYcGV0ZXIucGFya2VyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUA 18 | A4IBgQCaVHI2yaut3lM1dDaoJbjAumYCwmaJy4Ybefz0kLn1iRXF7vqKNm0Hotxl 19 | SwKygSN+Fpv+q5YX57pIzdOwFitpSyhr8IR9P7GX64rfXsTqUvCmSgWuHNmhTNmR 20 | lpCugOAuSHw45kJg0ZWgyvdZ/dKawEOYcNLikIenXR0A6EAowdC5BzPhSWm66DDj 21 | 9pOriWSAG+xpVxIXRsqB0xkJHGp+88nwo6VJsR9niI+PX1cSU/73VkX1O9pBeDrN 22 | pyhv/P7As2O9MySzvJdE24g5dZd/sxp4/u+R1XDGiIFcMs58X9zLmmhHkjNvNBte 23 | CuvQCW+8jiW+ispShdXXXB6A9QnG0uikVTiRK2tcyOBKnybqpcAXq+ndvLuDOJbY 24 | kCxcB34yDNPKz24gF5t3gCcwmzwVCdsUps/TLODi0b+QoHEj1V0EdOxvIVVe86ds 25 | GJgrMrfb1S4PR9euU5hjkcoyLzSeZIWUROmS8+ZqCDAdUxuPmakGS/fwGPNxrGw4 26 | VXtt2xA= 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/resources/pparker.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEgTCCAumgAwIBAgIQPZKP130KwQ5Bl6JPgpdD+zANBgkqhkiG9w0BAQsFADBt 3 | MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGGFmYUB0 4 | NDcwcCAoQW5kcmVhcyBGYWxrKTEoMCYGA1UEAwwfbWtjZXJ0IGFmYUB0NDcwcCAo 5 | QW5kcmVhcyBGYWxrKTAeFw0xOTA2MDEwMDAwMDBaFw0zMDAyMTkwODE0NDdaMG8x 6 | JzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEhMB8GA1UE 7 | CwwYYWZhQHQ0NzBwIChBbmRyZWFzIEZhbGspMSEwHwYDVQQDDBhwZXRlci5wYXJr 8 | ZXJAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj 9 | oGHb1SE1tgqhkB4m+cCZjU9hdJMCdrS8tSSnKc4asgxDVy2x5sebeVCkXryt/IM8 10 | HXPRxt/7HXKXRjJ8hNBWGSSHfRb3MsvnqWYaSRrntzmE0N+LGxodCb+GSzTWPoDD 11 | NOslZMSKHGCIYKeAPsVF786LlybltCB5OriQZfAZ6i2LKnn/E3GJn7beWqnnPQwJ 12 | yJ6jJGFoGdpJ4NPQpUj1ayFMZGHGLnjQ4Z9sM+9hGlk7sm0btsrxHuSTRT5JQnIp 13 | /RD6/WAfpQ12ttwQwDDoXfW0ytKeC575hV8z4rsPtdZ926XwlfDFC+cOoS/6v+Wo 14 | v5+E2o2i0OgvCcdB9iTvAgMBAAGjgZowgZcwDgYDVR0PAQH/BAQDAgWgMDEGA1Ud 15 | JQQqMCgGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEMAwG 16 | A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUFYBfwFCxdOnin/k5HnyZijgoDMgwIwYD 17 | VR0RBBwwGoEYcGV0ZXIucGFya2VyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUA 18 | A4IBgQCaVHI2yaut3lM1dDaoJbjAumYCwmaJy4Ybefz0kLn1iRXF7vqKNm0Hotxl 19 | SwKygSN+Fpv+q5YX57pIzdOwFitpSyhr8IR9P7GX64rfXsTqUvCmSgWuHNmhTNmR 20 | lpCugOAuSHw45kJg0ZWgyvdZ/dKawEOYcNLikIenXR0A6EAowdC5BzPhSWm66DDj 21 | 9pOriWSAG+xpVxIXRsqB0xkJHGp+88nwo6VJsR9niI+PX1cSU/73VkX1O9pBeDrN 22 | pyhv/P7As2O9MySzvJdE24g5dZd/sxp4/u+R1XDGiIFcMs58X9zLmmhHkjNvNBte 23 | CuvQCW+8jiW+ispShdXXXB6A9QnG0uikVTiRK2tcyOBKnybqpcAXq+ndvLuDOJbY 24 | kCxcB34yDNPKz24gF5t3gCcwmzwVCdsUps/TLODi0b+QoHEj1V0EdOxvIVVe86ds 25 | GJgrMrfb1S4PR9euU5hjkcoyLzSeZIWUROmS8+ZqCDAdUxuPmakGS/fwGPNxrGw4 26 | VXtt2xA= 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/resources/pparker.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEgTCCAumgAwIBAgIQPZKP130KwQ5Bl6JPgpdD+zANBgkqhkiG9w0BAQsFADBt 3 | MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGGFmYUB0 4 | NDcwcCAoQW5kcmVhcyBGYWxrKTEoMCYGA1UEAwwfbWtjZXJ0IGFmYUB0NDcwcCAo 5 | QW5kcmVhcyBGYWxrKTAeFw0xOTA2MDEwMDAwMDBaFw0zMDAyMTkwODE0NDdaMG8x 6 | JzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEhMB8GA1UE 7 | CwwYYWZhQHQ0NzBwIChBbmRyZWFzIEZhbGspMSEwHwYDVQQDDBhwZXRlci5wYXJr 8 | ZXJAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj 9 | oGHb1SE1tgqhkB4m+cCZjU9hdJMCdrS8tSSnKc4asgxDVy2x5sebeVCkXryt/IM8 10 | HXPRxt/7HXKXRjJ8hNBWGSSHfRb3MsvnqWYaSRrntzmE0N+LGxodCb+GSzTWPoDD 11 | NOslZMSKHGCIYKeAPsVF786LlybltCB5OriQZfAZ6i2LKnn/E3GJn7beWqnnPQwJ 12 | yJ6jJGFoGdpJ4NPQpUj1ayFMZGHGLnjQ4Z9sM+9hGlk7sm0btsrxHuSTRT5JQnIp 13 | /RD6/WAfpQ12ttwQwDDoXfW0ytKeC575hV8z4rsPtdZ926XwlfDFC+cOoS/6v+Wo 14 | v5+E2o2i0OgvCcdB9iTvAgMBAAGjgZowgZcwDgYDVR0PAQH/BAQDAgWgMDEGA1Ud 15 | JQQqMCgGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEMAwG 16 | A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUFYBfwFCxdOnin/k5HnyZijgoDMgwIwYD 17 | VR0RBBwwGoEYcGV0ZXIucGFya2VyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUA 18 | A4IBgQCaVHI2yaut3lM1dDaoJbjAumYCwmaJy4Ybefz0kLn1iRXF7vqKNm0Hotxl 19 | SwKygSN+Fpv+q5YX57pIzdOwFitpSyhr8IR9P7GX64rfXsTqUvCmSgWuHNmhTNmR 20 | lpCugOAuSHw45kJg0ZWgyvdZ/dKawEOYcNLikIenXR0A6EAowdC5BzPhSWm66DDj 21 | 9pOriWSAG+xpVxIXRsqB0xkJHGp+88nwo6VJsR9niI+PX1cSU/73VkX1O9pBeDrN 22 | pyhv/P7As2O9MySzvJdE24g5dZd/sxp4/u+R1XDGiIFcMs58X9zLmmhHkjNvNBte 23 | CuvQCW+8jiW+ispShdXXXB6A9QnG0uikVTiRK2tcyOBKnybqpcAXq+ndvLuDOJbY 24 | kCxcB34yDNPKz24gF5t3gCcwmzwVCdsUps/TLODi0b+QoHEj1V0EdOxvIVVe86ds 25 | GJgrMrfb1S4PR9euU5hjkcoyLzSeZIWUROmS8+ZqCDAdUxuPmakGS/fwGPNxrGw4 26 | VXtt2xA= 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/DataInitializer.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack; 2 | 3 | import com.example.csrf.attack.data.Customer; 4 | import com.example.csrf.attack.service.CustomerService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | import java.util.UUID; 12 | import java.util.stream.Collectors; 13 | import java.util.stream.Stream; 14 | 15 | @Component 16 | public class DataInitializer implements CommandLineRunner { 17 | 18 | private static final Logger LOGGER = LoggerFactory.getLogger(DataInitializer.class); 19 | 20 | private static final UUID CUSTOMER_1_ID = UUID.fromString("70e8efbf-06ca-4520-9fbd-5762daa01348"); 21 | private static final UUID CUSTOMER_2_ID = UUID.fromString("bf93921b-d2de-432c-87eb-0c017349a427"); 22 | private static final UUID CUSTOMER_3_ID = UUID.fromString("06af7967-310b-4ebb-9ac0-cd2a790dd0b4"); 23 | private static final UUID CUSTOMER_4_ID = UUID.fromString("62bcbf30-3240-4886-9330-5af727b407ce"); 24 | 25 | private final CustomerService customerService; 26 | 27 | public DataInitializer(CustomerService customerService) { 28 | this.customerService = customerService; 29 | } 30 | 31 | @Override 32 | public void run(String... args) { 33 | List customers = Stream.of( 34 | new Customer(CUSTOMER_1_ID, "Hans", "Test1"), 35 | new Customer(CUSTOMER_2_ID, "Hans", "Test2"), 36 | new Customer(CUSTOMER_3_ID, "Hans", "Test3"), 37 | new Customer(CUSTOMER_4_ID, "Hans", "Test4") 38 | ).map(customerService::save).collect(Collectors.toList()); 39 | LOGGER.info("Created {} customers", customers.size()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/common/web/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.common.web; 2 | 3 | import com.example.libraryserver.user.service.InvalidPasswordError; 4 | import org.owasp.encoder.Encode; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @ControllerAdvice(annotations = RestController.class) 15 | public class ErrorHandler { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class); 18 | 19 | @ExceptionHandler(MethodArgumentNotValidException.class) 20 | public ResponseEntity handle(MethodArgumentNotValidException ex) { 21 | LOGGER.warn(ex.getMessage()); 22 | StringBuilder builder = new StringBuilder(); 23 | ex.getBindingResult().getAllErrors().forEach(e -> builder.append(e.toString())); 24 | return ResponseEntity.badRequest() 25 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(builder.toString()))); 26 | } 27 | 28 | @ExceptionHandler(InvalidPasswordError.class) 29 | public ResponseEntity handle(InvalidPasswordError ex) { 30 | LOGGER.warn(ex.getMessage()); 31 | return ResponseEntity.badRequest() 32 | .body(Encode.forJavaScriptSource(Encode.forHtmlContent(ex.getMessage()))); 33 | } 34 | 35 | @ExceptionHandler(RuntimeException.class) 36 | public ResponseEntity handle(RuntimeException ex) { 37 | LOGGER.error(ex.getMessage(), ex); 38 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab1/library-server/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.owasp:security-logging-logback:1.1.6' 30 | implementation 'org.owasp.encoder:encoder:1.2.3' 31 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 32 | runtimeOnly 'com.h2database:h2' 33 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 34 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 35 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 36 | } 37 | 38 | test { 39 | useJUnitPlatform() 40 | outputs.dir snippetsDir 41 | } 42 | 43 | asciidoctor { 44 | inputs.dir snippetsDir 45 | setOptions([ 46 | 'doctype': 'book', 47 | 'backend': 'html5' 48 | ]) 49 | setAttributes([ 50 | 'snippets' : snippetsDir, 51 | 'source-highlighter': 'coderay', 52 | 'toc' : 'left', 53 | 'toclevels' : '3', 54 | 'sectlinks' : 'true' 55 | ]) 56 | dependsOn test 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/data/Customer.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.data; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import org.springframework.data.jpa.domain.AbstractPersistable; 5 | 6 | import javax.persistence.Entity; 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.NotNull; 9 | import javax.validation.constraints.Size; 10 | import java.util.UUID; 11 | 12 | @Entity 13 | public class Customer extends AbstractPersistable { 14 | 15 | @NotBlank 16 | @Size(max = 100) 17 | private String firstName; 18 | 19 | @NotBlank 20 | @Size(max = 100) 21 | private String lastName; 22 | 23 | @NotNull 24 | private UUID identifier; 25 | 26 | public Customer() { 27 | } 28 | 29 | public Customer(UUID identifier, String firstName, String lastName) { 30 | this.identifier = identifier; 31 | this.firstName = firstName; 32 | this.lastName = lastName; 33 | } 34 | 35 | public String getFirstName() { 36 | return firstName; 37 | } 38 | 39 | public void setFirstName(String firstName) { 40 | this.firstName = firstName; 41 | } 42 | 43 | public String getLastName() { 44 | return lastName; 45 | } 46 | 47 | public void setLastName(String lastName) { 48 | this.lastName = lastName; 49 | } 50 | 51 | public UUID getIdentifier() { 52 | return identifier; 53 | } 54 | 55 | public void setIdentifier(UUID identifier) { 56 | this.identifier = identifier; 57 | } 58 | 59 | @JsonIgnore 60 | @Override 61 | public Long getId() { 62 | return super.getId(); 63 | } 64 | 65 | @JsonIgnore 66 | @Override 67 | public boolean isNew() { 68 | return super.isNew(); 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "Customer{" + 74 | "identifier='" + identifier + '\'' + 75 | "firstName='" + firstName + '\'' + 76 | ", lastName='" + lastName + '\'' + 77 | '}'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /bonus-labs/csrf-attack-demo/src/main/java/com/example/csrf/attack/api/CustomerWebController.java: -------------------------------------------------------------------------------- 1 | package com.example.csrf.attack.api; 2 | 3 | import com.example.csrf.attack.data.Customer; 4 | import com.example.csrf.attack.service.CustomerService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.ui.Model; 11 | import org.springframework.util.IdGenerator; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import java.util.List; 15 | 16 | @Controller 17 | @RequestMapping("/") 18 | public class CustomerWebController { 19 | private static final Logger LOGGER = LoggerFactory.getLogger(CustomerWebController.class); 20 | 21 | private final CustomerService customerService; 22 | private final IdGenerator idGenerator; 23 | 24 | public CustomerWebController(CustomerService customerService, IdGenerator idGenerator) { 25 | this.customerService = customerService; 26 | this.idGenerator = idGenerator; 27 | } 28 | 29 | @GetMapping 30 | String index() { 31 | return "index"; 32 | } 33 | 34 | @ModelAttribute("allCustomers") 35 | public List populateCustomers() { 36 | return this.customerService.findAll(); 37 | } 38 | 39 | @PostMapping(path = "/web/create", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE) 40 | @ResponseStatus(HttpStatus.NO_CONTENT) 41 | public void create(CustomerRequest customerRequest) { 42 | 43 | LOGGER.info("Creating new customer via POST request '/web': {}", customerRequest); 44 | 45 | Customer customer = new Customer(idGenerator.generateId(), customerRequest.getFirstName(), customerRequest.getLastName()); 46 | customerService.save(customer); 47 | } 48 | 49 | @GetMapping("/web/form") 50 | public String customerForm(Model model) { 51 | model.addAttribute("customer", new CustomerRequest()); 52 | return "customerform"; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lab1/library-server-complete/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.springframework.boot:spring-boot-starter-security' 30 | implementation 'org.owasp:security-logging-logback:1.1.6' 31 | implementation 'org.owasp.encoder:encoder:1.2.3' 32 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 33 | runtimeOnly 'com.h2database:h2' 34 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 35 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 36 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 37 | testImplementation 'org.springframework.security:spring-security-test' 38 | } 39 | 40 | test { 41 | useJUnitPlatform() 42 | outputs.dir snippetsDir 43 | } 44 | 45 | asciidoctor { 46 | inputs.dir snippetsDir 47 | setOptions([ 48 | 'doctype': 'book', 49 | 'backend': 'html5' 50 | ]) 51 | setAttributes([ 52 | 'snippets' : snippetsDir, 53 | 'source-highlighter': 'coderay', 54 | 'toc' : 'left', 55 | 'toclevels' : '3', 56 | 'sectlinks' : 'true' 57 | ]) 58 | dependsOn test 59 | } 60 | 61 | 62 | -------------------------------------------------------------------------------- /lab6/library-server-container-root/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.context.annotation.Primary; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Primary 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab6/library-server-container-rootless/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.context.annotation.Primary; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Primary 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab3/library-server-complete/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.springframework.boot:spring-boot-starter-security' 30 | implementation 'org.owasp:security-logging-logback:1.1.6' 31 | implementation 'org.owasp.encoder:encoder:1.2.3' 32 | implementation 'org.passay:passay:1.6.0' 33 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 34 | runtimeOnly 'com.h2database:h2' 35 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 36 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 37 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 38 | testImplementation 'org.springframework.security:spring-security-test' 39 | } 40 | 41 | test { 42 | useJUnitPlatform() 43 | outputs.dir snippetsDir 44 | } 45 | 46 | asciidoctor { 47 | inputs.dir snippetsDir 48 | setOptions([ 49 | 'doctype': 'book', 50 | 'backend': 'html5' 51 | ]) 52 | setAttributes([ 53 | 'snippets' : snippetsDir, 54 | 'source-highlighter': 'coderay', 55 | 'toc' : 'left', 56 | 'toclevels' : '3', 57 | 'sectlinks' : 'true' 58 | ]) 59 | dependsOn test 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /lab4/library-server-complete/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.springframework.boot:spring-boot-starter-security' 30 | implementation 'org.owasp:security-logging-logback:1.1.6' 31 | implementation 'org.owasp.encoder:encoder:1.2.3' 32 | implementation 'org.passay:passay:1.6.0' 33 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 34 | runtimeOnly 'com.h2database:h2' 35 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 36 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 37 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 38 | testImplementation 'org.springframework.security:spring-security-test' 39 | } 40 | 41 | test { 42 | useJUnitPlatform() 43 | outputs.dir snippetsDir 44 | } 45 | 46 | asciidoctor { 47 | inputs.dir snippetsDir 48 | setOptions([ 49 | 'doctype': 'book', 50 | 'backend': 'html5' 51 | ]) 52 | setAttributes([ 53 | 'snippets' : snippetsDir, 54 | 'source-highlighter': 'coderay', 55 | 'toc' : 'left', 56 | 'toclevels' : '3', 57 | 'sectlinks' : 'true' 58 | ]) 59 | dependsOn test 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /lab5/library-server-complete/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.springframework.boot:spring-boot-starter-security' 30 | implementation 'org.owasp:security-logging-logback:1.1.6' 31 | implementation 'org.owasp.encoder:encoder:1.2.3' 32 | implementation 'org.passay:passay:1.6.0' 33 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 34 | runtimeOnly 'com.h2database:h2' 35 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 36 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 37 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 38 | testImplementation 'org.springframework.security:spring-security-test' 39 | } 40 | 41 | test { 42 | useJUnitPlatform() 43 | outputs.dir snippetsDir 44 | } 45 | 46 | asciidoctor { 47 | inputs.dir snippetsDir 48 | setOptions([ 49 | 'doctype': 'book', 50 | 'backend': 'html5' 51 | ]) 52 | setAttributes([ 53 | 'snippets' : snippetsDir, 54 | 'source-highlighter': 'coderay', 55 | 'toc' : 'left', 56 | 'toclevels' : '3', 57 | 'sectlinks' : 'true' 58 | ]) 59 | dependsOn test 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Qualifier("library-user-details-service") 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Qualifier("library-user-details-service") 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab4/library-server-complete/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Qualifier("library-user-details-service") 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab5/library-server-complete/src/main/java/com/example/libraryserver/security/LibraryUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.security; 2 | 3 | import com.example.libraryserver.user.service.UserService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsPasswordService; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Qualifier("library-user-details-service") 14 | @Service 15 | public class LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LibraryUserDetailsService.class); 18 | 19 | private final UserService userService; 20 | 21 | public LibraryUserDetailsService(UserService userService) { 22 | this.userService = userService; 23 | } 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | return userService 28 | .findOneByEmail(username) 29 | .map(AuthenticatedUser::new) 30 | .orElseThrow(() -> new UsernameNotFoundException("No user found for " + username)); 31 | } 32 | 33 | @Override 34 | public UserDetails updatePassword(UserDetails user, String newPassword) { 35 | return userService 36 | .findOneByEmail(user.getUsername()) 37 | .map( 38 | u -> { 39 | LOGGER.info( 40 | "Upgrading password {} for user {} to {}", 41 | user.getPassword(), 42 | user.getUsername(), 43 | newPassword); 44 | u.setPassword(newPassword); 45 | return new AuthenticatedUser(userService.save(u)); 46 | }) 47 | .orElseThrow( 48 | () -> new UsernameNotFoundException("No user found for " + user.getUsername())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lab2/library-server-complete/README.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.example.library-server' is invalid and this project uses 'com.example.libraryserver' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Gradle documentation](https://docs.gradle.org) 12 | * [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/gradle-plugin/reference/html/) 13 | * [Spring Web](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications) 14 | * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-jpa-and-spring-data) 15 | * [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#using-boot-devtools) 16 | * [Spring Configuration Processor](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#configuration-metadata-annotation-processor) 17 | * [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#production-ready) 18 | * [Spring HATEOAS](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-spring-hateoas) 19 | 20 | ### Guides 21 | The following guides illustrate how to use some features concretely: 22 | 23 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 24 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 25 | * [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 26 | * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) 27 | * [Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/) 28 | * [Building a Hypermedia-Driven RESTful Web Service](https://spring.io/guides/gs/rest-hateoas/) 29 | 30 | ### Additional Links 31 | These additional references should also help you: 32 | 33 | * [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) 34 | 35 | -------------------------------------------------------------------------------- /lab4/library-server-complete/README.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.example.library-server' is invalid and this project uses 'com.example.libraryserver' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Gradle documentation](https://docs.gradle.org) 12 | * [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/gradle-plugin/reference/html/) 13 | * [Spring Web](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications) 14 | * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-jpa-and-spring-data) 15 | * [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#using-boot-devtools) 16 | * [Spring Configuration Processor](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#configuration-metadata-annotation-processor) 17 | * [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#production-ready) 18 | * [Spring HATEOAS](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-spring-hateoas) 19 | 20 | ### Guides 21 | The following guides illustrate how to use some features concretely: 22 | 23 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 24 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 25 | * [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 26 | * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) 27 | * [Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/) 28 | * [Building a Hypermedia-Driven RESTful Web Service](https://spring.io/guides/gs/rest-hateoas/) 29 | 30 | ### Additional Links 31 | These additional references should also help you: 32 | 33 | * [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) 34 | 35 | -------------------------------------------------------------------------------- /lab5/library-server-complete/README.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.example.library-server' is invalid and this project uses 'com.example.libraryserver' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Gradle documentation](https://docs.gradle.org) 12 | * [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/gradle-plugin/reference/html/) 13 | * [Spring Web](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications) 14 | * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-jpa-and-spring-data) 15 | * [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#using-boot-devtools) 16 | * [Spring Configuration Processor](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#configuration-metadata-annotation-processor) 17 | * [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#production-ready) 18 | * [Spring HATEOAS](https://docs.spring.io/spring-boot/docs/2.2.3.RELEASE/reference/htmlsingle/#boot-features-spring-hateoas) 19 | 20 | ### Guides 21 | The following guides illustrate how to use some features concretely: 22 | 23 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 24 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 25 | * [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 26 | * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) 27 | * [Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/) 28 | * [Building a Hypermedia-Driven RESTful Web Service](https://spring.io/guides/gs/rest-hateoas/) 29 | 30 | ### Additional Links 31 | These additional references should also help you: 32 | 33 | * [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) 34 | 35 | -------------------------------------------------------------------------------- /lab2/library-server-complete/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.5.1' 3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE' 4 | id 'com.adarshr.test-logger' version '3.0.0' 5 | id 'org.asciidoctor.convert' version '1.5.8' 6 | id "org.owasp.dependencycheck" version '6.1.6' 7 | id 'java' 8 | } 9 | 10 | group = 'com.example' 11 | version = '1.0.0-SNAPSHOT' 12 | sourceCompatibility = '11' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | ext { 19 | set('snippetsDir', file("build/generated-snippets")) 20 | } 21 | 22 | dependencies { 23 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 24 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 26 | implementation 'org.springframework.boot:spring-boot-starter-web' 27 | implementation 'org.springframework.boot:spring-boot-starter-validation' 28 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 29 | implementation 'org.springframework.boot:spring-boot-starter-security' 30 | implementation 'org.springdoc:springdoc-openapi-ui:1.5.9' 31 | implementation 'org.owasp:security-logging-logback:1.1.6' 32 | implementation 'org.owasp.encoder:encoder:1.2.3' 33 | implementation 'org.passay:passay:1.6.0' 34 | developmentOnly 'org.springframework.boot:spring-boot-devtools' 35 | runtimeOnly 'com.h2database:h2' 36 | annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 37 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 38 | testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' 39 | testImplementation 'org.springframework.security:spring-security-test' 40 | } 41 | 42 | test { 43 | useJUnitPlatform() 44 | outputs.dir snippetsDir 45 | } 46 | 47 | asciidoctor { 48 | inputs.dir snippetsDir 49 | setOptions([ 50 | 'doctype': 'book', 51 | 'backend': 'html5' 52 | ]) 53 | setAttributes([ 54 | 'snippets' : snippetsDir, 55 | 'source-highlighter': 'coderay', 56 | 'toc' : 'left', 57 | 'toclevels' : '3', 58 | 'sectlinks' : 'true' 59 | ]) 60 | dependsOn test 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import com.example.libraryserver.user.data.UserRepository; 5 | import org.owasp.security.logging.SecurityMarkers; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import org.springframework.util.IdGenerator; 11 | 12 | import java.util.List; 13 | import java.util.Optional; 14 | import java.util.UUID; 15 | 16 | @Service 17 | @Transactional(readOnly = true) 18 | public class UserService { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class); 21 | 22 | private final UserRepository userRepository; 23 | private final IdGenerator idGenerator; 24 | 25 | public UserService(UserRepository userRepository, IdGenerator idGenerator) { 26 | this.userRepository = userRepository; 27 | this.idGenerator = idGenerator; 28 | } 29 | 30 | public Optional findOneByIdentifier(UUID identifier) { 31 | return userRepository.findOneByIdentifier(identifier); 32 | } 33 | 34 | public Optional findOneByEmail(String email) { 35 | return userRepository.findOneByEmail(email); 36 | } 37 | 38 | public List findAll() { 39 | LOGGER.trace("find all users"); 40 | 41 | return userRepository.findAll(); 42 | } 43 | 44 | @Transactional 45 | public User save(User user) { 46 | LOGGER.info(SecurityMarkers.CONFIDENTIAL, "save user with password={}", user.getPassword()); 47 | 48 | LOGGER.trace("save user {}", user); 49 | 50 | if (user.getIdentifier() == null) { 51 | user.setIdentifier(idGenerator.generateId()); 52 | } 53 | return userRepository.save(user); 54 | } 55 | 56 | @Transactional 57 | public boolean deleteOneIdentifier(UUID userIdentifier) { 58 | LOGGER.trace("delete user with identifier {}", userIdentifier); 59 | 60 | return userRepository 61 | .findOneByIdentifier(userIdentifier) 62 | .map( 63 | u -> { 64 | userRepository.delete(u); 65 | return true; 66 | }) 67 | .orElse(false); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import com.example.libraryserver.user.data.UserRepository; 5 | import org.owasp.security.logging.SecurityMarkers; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import org.springframework.util.IdGenerator; 11 | 12 | import java.util.List; 13 | import java.util.Optional; 14 | import java.util.UUID; 15 | 16 | @Service 17 | @Transactional(readOnly = true) 18 | public class UserService { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class); 21 | 22 | private final UserRepository userRepository; 23 | private final IdGenerator idGenerator; 24 | 25 | public UserService(UserRepository userRepository, IdGenerator idGenerator) { 26 | this.userRepository = userRepository; 27 | this.idGenerator = idGenerator; 28 | } 29 | 30 | public Optional findOneByIdentifier(UUID identifier) { 31 | return userRepository.findOneByIdentifier(identifier); 32 | } 33 | 34 | public Optional findOneByEmail(String email) { 35 | return userRepository.findOneByEmail(email); 36 | } 37 | 38 | public List findAll() { 39 | LOGGER.trace("find all users"); 40 | 41 | return userRepository.findAll(); 42 | } 43 | 44 | @Transactional 45 | public User save(User user) { 46 | LOGGER.info(SecurityMarkers.CONFIDENTIAL, "save user with password={}", user.getPassword()); 47 | 48 | LOGGER.trace("save user {}", user); 49 | 50 | if (user.getIdentifier() == null) { 51 | user.setIdentifier(idGenerator.generateId()); 52 | } 53 | return userRepository.save(user); 54 | } 55 | 56 | @Transactional 57 | public boolean deleteOneIdentifier(UUID userIdentifier) { 58 | LOGGER.trace("delete user with identifier {}", userIdentifier); 59 | 60 | return userRepository 61 | .findOneByIdentifier(userIdentifier) 62 | .map( 63 | u -> { 64 | userRepository.delete(u); 65 | return true; 66 | }) 67 | .orElse(false); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import com.example.libraryserver.user.data.UserRepository; 5 | import org.owasp.security.logging.SecurityMarkers; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import org.springframework.util.IdGenerator; 11 | 12 | import java.util.List; 13 | import java.util.Optional; 14 | import java.util.UUID; 15 | 16 | @Service 17 | @Transactional(readOnly = true) 18 | public class UserService { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class); 21 | 22 | private final UserRepository userRepository; 23 | private final IdGenerator idGenerator; 24 | 25 | public UserService(UserRepository userRepository, IdGenerator idGenerator) { 26 | this.userRepository = userRepository; 27 | this.idGenerator = idGenerator; 28 | } 29 | 30 | public Optional findOneByIdentifier(UUID identifier) { 31 | return userRepository.findOneByIdentifier(identifier); 32 | } 33 | 34 | public Optional findOneByEmail(String email) { 35 | return userRepository.findOneByEmail(email); 36 | } 37 | 38 | public List findAll() { 39 | LOGGER.trace("find all users"); 40 | 41 | return userRepository.findAll(); 42 | } 43 | 44 | @Transactional 45 | public User save(User user) { 46 | LOGGER.info(SecurityMarkers.CONFIDENTIAL, "save user with password={}", user.getPassword()); 47 | 48 | LOGGER.trace("save user {}", user); 49 | 50 | if (user.getIdentifier() == null) { 51 | user.setIdentifier(idGenerator.generateId()); 52 | } 53 | return userRepository.save(user); 54 | } 55 | 56 | @Transactional 57 | public boolean deleteOneIdentifier(UUID userIdentifier) { 58 | LOGGER.trace("delete user with identifier {}", userIdentifier); 59 | 60 | return userRepository 61 | .findOneByIdentifier(userIdentifier) 62 | .map( 63 | u -> { 64 | userRepository.delete(u); 65 | return true; 66 | }) 67 | .orElse(false); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/user/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.service; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import com.example.libraryserver.user.data.UserRepository; 5 | import org.owasp.security.logging.SecurityMarkers; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import org.springframework.util.IdGenerator; 11 | 12 | import java.util.List; 13 | import java.util.Optional; 14 | import java.util.UUID; 15 | 16 | @Service 17 | @Transactional(readOnly = true) 18 | public class UserService { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class); 21 | 22 | private final UserRepository userRepository; 23 | private final IdGenerator idGenerator; 24 | 25 | public UserService(UserRepository userRepository, IdGenerator idGenerator) { 26 | this.userRepository = userRepository; 27 | this.idGenerator = idGenerator; 28 | } 29 | 30 | public Optional findOneByIdentifier(UUID identifier) { 31 | return userRepository.findOneByIdentifier(identifier); 32 | } 33 | 34 | public Optional findOneByEmail(String email) { 35 | return userRepository.findOneByEmail(email); 36 | } 37 | 38 | public List findAll() { 39 | LOGGER.trace("find all users"); 40 | 41 | return userRepository.findAll(); 42 | } 43 | 44 | @Transactional 45 | public User save(User user) { 46 | LOGGER.info(SecurityMarkers.CONFIDENTIAL, "save user with password={}", user.getPassword()); 47 | 48 | LOGGER.trace("save user {}", user); 49 | 50 | if (user.getIdentifier() == null) { 51 | user.setIdentifier(idGenerator.generateId()); 52 | } 53 | return userRepository.save(user); 54 | } 55 | 56 | @Transactional 57 | public boolean deleteOneIdentifier(UUID userIdentifier) { 58 | LOGGER.trace("delete user with identifier {}", userIdentifier); 59 | 60 | return userRepository 61 | .findOneByIdentifier(userIdentifier) 62 | .map( 63 | u -> { 64 | userRepository.delete(u); 65 | return true; 66 | }) 67 | .orElse(false); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lab1/library-server/src/main/java/com/example/libraryserver/user/web/UserModelAssembler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.owasp.encoder.Encode; 5 | import org.springframework.hateoas.CollectionModel; 6 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 13 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 14 | 15 | @Component 16 | public class UserModelAssembler extends RepresentationModelAssemblerSupport { 17 | 18 | public UserModelAssembler() { 19 | super(UserRestController.class, UserModel.class); 20 | } 21 | 22 | @Override 23 | public UserModel toModel(User user) { 24 | UserModel userModel = 25 | outputEscaping( 26 | new UserModel( 27 | user.getIdentifier(), 28 | user.getFirstName(), 29 | user.getLastName(), 30 | user.getEmail(), 31 | user.getRoles())); 32 | userModel.add( 33 | linkTo(methodOn(UserRestController.class).getSingleUser(userModel.getIdentifier())) 34 | .withSelfRel()); 35 | 36 | return userModel; 37 | } 38 | 39 | @Override 40 | public CollectionModel toCollectionModel(Iterable entities) { 41 | 42 | List result = new ArrayList<>(); 43 | 44 | for (User entity : entities) { 45 | result.add(toModel(entity)); 46 | } 47 | 48 | return new UserModelList(result); 49 | } 50 | 51 | private UserModel outputEscaping(UserModel input) { 52 | UserModel output = new UserModel(); 53 | output.setEmail(Encode.forJavaScript(Encode.forHtml(input.getEmail()))); 54 | output.setFirstName(Encode.forJavaScript(Encode.forHtml(input.getFirstName()))); 55 | output.setLastName(Encode.forJavaScript(Encode.forHtml(input.getLastName()))); 56 | output.setIdentifier(input.getIdentifier()); 57 | for (String role : input.getRoles()) { 58 | output.getRoles().add(Encode.forJavaScript(Encode.forHtml(role))); 59 | } 60 | 61 | return output; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lab1/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelAssembler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.owasp.encoder.Encode; 5 | import org.springframework.hateoas.CollectionModel; 6 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 13 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 14 | 15 | @Component 16 | public class UserModelAssembler extends RepresentationModelAssemblerSupport { 17 | 18 | public UserModelAssembler() { 19 | super(UserRestController.class, UserModel.class); 20 | } 21 | 22 | @Override 23 | public UserModel toModel(User user) { 24 | UserModel userModel = 25 | outputEscaping( 26 | new UserModel( 27 | user.getIdentifier(), 28 | user.getFirstName(), 29 | user.getLastName(), 30 | user.getEmail(), 31 | user.getRoles())); 32 | userModel.add( 33 | linkTo(methodOn(UserRestController.class).getSingleUser(userModel.getIdentifier())) 34 | .withSelfRel()); 35 | 36 | return userModel; 37 | } 38 | 39 | @Override 40 | public CollectionModel toCollectionModel(Iterable entities) { 41 | 42 | List result = new ArrayList<>(); 43 | 44 | for (User entity : entities) { 45 | result.add(toModel(entity)); 46 | } 47 | 48 | return new UserModelList(result); 49 | } 50 | 51 | private UserModel outputEscaping(UserModel input) { 52 | UserModel output = new UserModel(); 53 | output.setEmail(Encode.forJavaScript(Encode.forHtml(input.getEmail()))); 54 | output.setFirstName(Encode.forJavaScript(Encode.forHtml(input.getFirstName()))); 55 | output.setLastName(Encode.forJavaScript(Encode.forHtml(input.getLastName()))); 56 | output.setIdentifier(input.getIdentifier()); 57 | for (String role : input.getRoles()) { 58 | output.getRoles().add(Encode.forJavaScript(Encode.forHtml(role))); 59 | } 60 | 61 | return output; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lab2/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelAssembler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.owasp.encoder.Encode; 5 | import org.springframework.hateoas.CollectionModel; 6 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 13 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 14 | 15 | @Component 16 | public class UserModelAssembler extends RepresentationModelAssemblerSupport { 17 | 18 | public UserModelAssembler() { 19 | super(UserRestController.class, UserModel.class); 20 | } 21 | 22 | @Override 23 | public UserModel toModel(User user) { 24 | UserModel userModel = 25 | outputEscaping( 26 | new UserModel( 27 | user.getIdentifier(), 28 | user.getFirstName(), 29 | user.getLastName(), 30 | user.getEmail(), 31 | user.getRoles())); 32 | userModel.add( 33 | linkTo(methodOn(UserRestController.class).getSingleUser(userModel.getIdentifier())) 34 | .withSelfRel()); 35 | 36 | return userModel; 37 | } 38 | 39 | @Override 40 | public CollectionModel toCollectionModel(Iterable entities) { 41 | 42 | List result = new ArrayList<>(); 43 | 44 | for (User entity : entities) { 45 | result.add(toModel(entity)); 46 | } 47 | 48 | return new UserModelList(result); 49 | } 50 | 51 | private UserModel outputEscaping(UserModel input) { 52 | UserModel output = new UserModel(); 53 | output.setEmail(Encode.forJavaScript(Encode.forHtml(input.getEmail()))); 54 | output.setFirstName(Encode.forJavaScript(Encode.forHtml(input.getFirstName()))); 55 | output.setLastName(Encode.forJavaScript(Encode.forHtml(input.getLastName()))); 56 | output.setIdentifier(input.getIdentifier()); 57 | for (String role : input.getRoles()) { 58 | output.getRoles().add(Encode.forJavaScript(Encode.forHtml(role))); 59 | } 60 | 61 | return output; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lab3/library-server-complete/src/main/java/com/example/libraryserver/user/web/UserModelAssembler.java: -------------------------------------------------------------------------------- 1 | package com.example.libraryserver.user.web; 2 | 3 | import com.example.libraryserver.user.data.User; 4 | import org.owasp.encoder.Encode; 5 | import org.springframework.hateoas.CollectionModel; 6 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 13 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 14 | 15 | @Component 16 | public class UserModelAssembler extends RepresentationModelAssemblerSupport { 17 | 18 | public UserModelAssembler() { 19 | super(UserRestController.class, UserModel.class); 20 | } 21 | 22 | @Override 23 | public UserModel toModel(User user) { 24 | UserModel userModel = 25 | outputEscaping( 26 | new UserModel( 27 | user.getIdentifier(), 28 | user.getFirstName(), 29 | user.getLastName(), 30 | user.getEmail(), 31 | user.getRoles())); 32 | userModel.add( 33 | linkTo(methodOn(UserRestController.class).getSingleUser(userModel.getIdentifier())) 34 | .withSelfRel()); 35 | 36 | return userModel; 37 | } 38 | 39 | @Override 40 | public CollectionModel toCollectionModel(Iterable entities) { 41 | 42 | List result = new ArrayList<>(); 43 | 44 | for (User entity : entities) { 45 | result.add(toModel(entity)); 46 | } 47 | 48 | return new UserModelList(result); 49 | } 50 | 51 | private UserModel outputEscaping(UserModel input) { 52 | UserModel output = new UserModel(); 53 | output.setEmail(Encode.forJavaScript(Encode.forHtml(input.getEmail()))); 54 | output.setFirstName(Encode.forJavaScript(Encode.forHtml(input.getFirstName()))); 55 | output.setLastName(Encode.forJavaScript(Encode.forHtml(input.getLastName()))); 56 | output.setIdentifier(input.getIdentifier()); 57 | for (String role : input.getRoles()) { 58 | output.getRoles().add(Encode.forJavaScript(Encode.forHtml(role))); 59 | } 60 | 61 | return output; 62 | } 63 | } 64 | --------------------------------------------------------------------------------