diff --git a/.github/scripts/.bash_history b/.github/scripts/.bash_history index 07a1ae38e..5362b71e6 100644 --- a/.github/scripts/.bash_history +++ b/.github/scripts/.bash_history @@ -347,7 +347,7 @@ rm -rf jdk-18_linux-x64_bin.deb git rebase -i main git rebase -i master git stash -export tempPassword="4QMUMCz8BUpSizlIfnb0XPpCDGir1NyfIxkrkN3Emdc=" +export tempPassword="hUdC7XO87aUevikzk5OrNodGrHoihCWHYcORwfxoGXk=" mvn run tempPassword k6 npx k6 diff --git a/.github/scripts/docker-create.sh b/.github/scripts/docker-create.sh index fa0d3f68c..894cf6400 100755 --- a/.github/scripts/docker-create.sh +++ b/.github/scripts/docker-create.sh @@ -300,22 +300,22 @@ create_containers() { echo "Creating containers" if [[ "$script_mode" == "publish" ]]; then docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../. cd ../.. docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:$tag -f Dockerfile_webdesktop --push . - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:latest -f Dockerfile_webdesktop --push . +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:latest -f Dockerfile_webdesktop --push . docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:$tag -f Dockerfile_webdesktopk8s --push . - docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:latest -f Dockerfile_webdesktopk8s --push . +# docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:latest -f Dockerfile_webdesktopk8s --push . cd .github/scripts elif [[ "$script_mode" == "test" ]]; then docker buildx build -t jeroenwillemsen/wrongsecrets:$tag --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --load ./../../. diff --git a/.github/workflows/link_checker.yml b/.github/workflows/link_checker.yml index b3a80d95b..5d15f4033 100644 --- a/.github/workflows/link_checker.yml +++ b/.github/workflows/link_checker.yml @@ -20,7 +20,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v1.8.0 with: - args: --exclude-all-private --exclude-path "src/main/resources/templates/about.html" --exclude-file "config/.lycheeignore" -r 2 './**/*.md' './**/*.html' + args: --exclude-all-private --exclude-path "src/main/resources/templates/about.html" --exclude-path "config/.lycheeignore" -r 2 './**/*.md' './**/*.html' fail: true - name: Create Issue From File diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ee119d52c..fa3c0f9e1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,15 +48,6 @@ jobs: with: java-version: "21" distribution: "corretto" - - name: Test with Cypress - run: | - ./mvnw verify -Dexec.id=xcypress-test -DskipTests -Ddependency-check.skip - - name: Uploading screenshots - uses: actions/upload-artifact@v3 - if: failure() - with: - name: screenshots - path: cypress/screenshots lint: name: lint javacode runs-on: ubuntu-latest diff --git a/.github/workflows/minikube-k8s-test.yml b/.github/workflows/minikube-k8s-test.yml index a846e9c73..ce141db09 100644 --- a/.github/workflows/minikube-k8s-test.yml +++ b/.github/workflows/minikube-k8s-test.yml @@ -44,29 +44,29 @@ jobs: echo "Do minikube delete to stop minikube from running and cleanup to start fresh again" echo "wait 20 seconds so we can check if vault-k8s-container works" sleep 20 - if curl http://localhost:8080/spoil-5 -s | grep -q spoiler-answer + if curl http://localhost:8080/spoil/challenge-5 -s | grep -q spoiler-answer then - echo "spoil-5 works" + echo "spoil-challenge-5 works" else - echo "error in spoil-5" + echo "error in spoil-challenge-5" fi - if curl http://localhost:8080/spoil-6 -s | grep -q spoiler-answer + if curl http://localhost:8080/spoil/challenge-6 -s | grep -q spoiler-answer then - echo "spoil-6 works" + echo "spoil-challenge-6 works" else - echo "error in spoil-6" + echo "error in spoil-challenge-6" fi - if curl http://localhost:8080/spoil-7 -s | grep -q spoiler-answer + if curl http://localhost:8080/spoil/challenge-7 -s | grep -q spoiler-answer then - echo "spoil-7 works" + echo "spoil-challenge-7 works" else - echo "error in spoil-7" + echo "error in spoil-challenge-7" fi - if curl http://localhost:8080/spoil-33 -s | grep -q spoiler-answer + if curl http://localhost:8080/spoil/challenge-33 -s | grep -q spoiler-answer then - echo "spoil-33 works" + echo "spoil-challenge-33 works" else - echo "error in spoil-33" + echo "error in spoil-challenge-33" fi echo "logs from pod to make sure:" cat pod.log diff --git a/.github/workflows/minikube-vault-test.yml b/.github/workflows/minikube-vault-test.yml index b4d0db46d..e0e30ad75 100644 --- a/.github/workflows/minikube-vault-test.yml +++ b/.github/workflows/minikube-vault-test.yml @@ -33,4 +33,4 @@ jobs: id: install - name: test script run: | - ./k8s-vault-minkube-start.sh && sleep 5 && curl http://localhost:8080/spoil-7 && minikube delete + ./k8s-vault-minkube-start.sh && sleep 5 && curl http://localhost:8080/spoil/challenge-7 && minikube delete diff --git a/.gitignore b/.gitignore index 6b7b03674..993514ec9 100644 --- a/.gitignore +++ b/.gitignore @@ -78,8 +78,9 @@ node_modules .npm # Cypress -cypress/videos -cypress/screenshots +src/test/e2e/cypress/videos +src/test/e2e/cypress/screenshots +src/test/e2e/cypress/reports cypress/downloads py_env tmp/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3fe4b6b6..4917a7c7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -268,7 +268,6 @@ First make sure that you have an [Issue](https://github.com/OWASP/wrongsecrets/i Add the **new challenge** in this folder `wrongsecrets/src/main/java/org/owasp/wrongsecrets/challenges/`. These are the things that you have to keep in mind. - First and foremost make sure your challenge is coded in **Java**. -- Don't forget to add your challenge number in `@Order(28)` annotation, **_28_** in my case. - Here is an example of a possible Challenge 28: ```java @@ -287,62 +286,25 @@ These are the things that you have to keep in mind. */ @Slf4j @Component - @Order(28) //make sure this number is the same as your challenge - public class Challenge28 extends Challenge { + public class Challenge28 implements Challenge { private final String secret; - public Challenge28(ScoreCard scoreCard) { - super(scoreCard); - secret = "hello world"; - } - //is this challenge usable in CTF mode? - @Override - public boolean canRunInCTFMode() { - return true; + public Challenge28() { + secret = "hello world"; } + //return the plain text secret here @Override public Spoiler spoiler() { - return new Spoiler(secret); + return new Spoiler(secret); } //here you validate if your answer matches the secret @Override public boolean answerCorrect(String answer) { - return secret.equals(answer); - } - //which runtime can you use to run the challenge on? (You can just use Docker here) - /** - * {@inheritDoc} - */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - //set the difficulty: 1=low, 5=very hard - /** - * {@inheritDoc} - * Difficulty: 1. - */ - @Override - public int difficulty() { - return 1; + return secret.equals(answer); } - //on which tech is this challenge? See ChallengeTechnology.Tech for categories - /** - * {@inheritDoc} - * Secrets based. - */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.SECRETS.id; - } - //if you use this in a shared environment and need to adapt it, then return true here. - @Override - public boolean isLimittedWhenOnlineHosted() { - return false; - - } - } +} ``` + ### Step 3: Adding Test File. Add the **new TestFile** in this folder `wrongsecrets/src/test/java/org/owasp/wrongsecrets/challenges/`. TestFile is required to do **unit testing.** @@ -410,5 +372,28 @@ Use this block as refrence for hints: This challenge is only meant for helping new contributors to add new challenges. Please, have fun with trying more difficult challenges;-). ``` -### Step 5: Submitting your PR. + +### Step 5: Add challenge configuration. + +In this step we configure the challenge to make it known to the application. +Open `src/main/resources/wrong_secrets_configuration.yaml` and add the following configuration: + +```yaml + - name: Challenge 28 + url: "challenge-28" + # For each environment you can add a different implementation and documentation + sources: + # Fully qualified name of the class + - class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge28" + explanation: "explanations/challenge28.adoc" + hint: "explanations/challenge28_hint.adoc" + reason: "explanations/challenge28_reason.adoc" + environments: *docker_envs + difficulty: *easy + category: *secrets + ctf: + enabled: true +``` + +### Step 6: Submitting your PR. After completing all the above steps, final step is to submit the PR and refer [**Contributing.md**](https://github.com/OWASP/wrongsecrets/blob/master/CONTRIBUTING.md#how-to-get-your-pr-accepted) on how to get your PR accepted. diff --git a/Dockerfile b/Dockerfile index fdfb62d09..12d9a8d5d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM amazoncorretto:21.0.1-alpine ARG argBasedPassword="default" -ARG argBasedVersion="0.0.0" +ARG argBasedVersion="1.7.2" ARG spring_profile="" ENV SPRING_PROFILES_ACTIVE=$spring_profile ENV ARG_BASED_PASSWORD=$argBasedPassword diff --git a/README.md b/README.md index 5b0d09661..877dd81ee 100644 --- a/README.md +++ b/README.md @@ -87,40 +87,40 @@ docker run -p 8080:8080 jeroenwillemsen/wrongsecrets:latest-no-vault Now you can try to find the secrets by means of solving the challenge offered at: -- [localhost:8080/challenge/1](http://localhost:8080/challenge/1) -- [localhost:8080/challenge/2](http://localhost:8080/challenge/2) -- [localhost:8080/challenge/3](http://localhost:8080/challenge/3) -- [localhost:8080/challenge/4](http://localhost:8080/challenge/4) -- [localhost:8080/challenge/8](http://localhost:8080/challenge/8) -- [localhost:8080/challenge/12](http://localhost:8080/challenge/12) -- [localhost:8080/challenge/13](http://localhost:8080/challenge/13) -- [localhost:8080/challenge/14](http://localhost:8080/challenge/14) -- [localhost:8080/challenge/15](http://localhost:8080/challenge/15) -- [localhost:8080/challenge/16](http://localhost:8080/challenge/16) -- [localhost:8080/challenge/17](http://localhost:8080/challenge/17) -- [localhost:8080/challenge/18](http://localhost:8080/challenge/18) -- [localhost:8080/challenge/19](http://localhost:8080/challenge/19) -- [localhost:8080/challenge/20](http://localhost:8080/challenge/20) -- [localhost:8080/challenge/21](http://localhost:8080/challenge/21) -- [localhost:8080/challenge/22](http://localhost:8080/challenge/22) -- [localhost:8080/challenge/23](http://localhost:8080/challenge/23) -- [localhost:8080/challenge/24](http://localhost:8080/challenge/24) -- [localhost:8080/challenge/25](http://localhost:8080/challenge/25) -- [localhost:8080/challenge/26](http://localhost:8080/challenge/26) -- [localhost:8080/challenge/27](http://localhost:8080/challenge/27) -- [localhost:8080/challenge/28](http://localhost:8080/challenge/28) -- [localhost:8080/challenge/29](http://localhost:8080/challenge/29) -- [localhost:8080/challenge/30](http://localhost:8080/challenge/30) -- [localhost:8080/challenge/31](http://localhost:8080/challenge/31) -- [localhost:8080/challenge/32](http://localhost:8080/challenge/32) -- [localhost:8080/challenge/34](http://localhost:8080/challenge/34) -- [localhost:8080/challenge/35](http://localhost:8080/challenge/35) -- [localhost:8080/challenge/36](http://localhost:8080/challenge/36) -- [localhost:8080/challenge/37](http://localhost:8080/challenge/37) -- [localhost:8080/challenge/38](http://localhost:8080/challenge/38) -- [localhost:8080/challenge/39](http://localhost:8080/challenge/39) -- [localhost:8080/challenge/40](http://localhost:8080/challenge/40) -- [localhost:8080/challenge/41](http://localhost:8080/challenge/41) +- [localhost:8080/challenge/challenge-1](http://localhost:8080/challenge/challenge-1) +- [localhost:8080/challenge/challenge-2](http://localhost:8080/challenge/challenge-2) +- [localhost:8080/challenge/challenge-3](http://localhost:8080/challenge/challenge-3) +- [localhost:8080/challenge/challenge-4](http://localhost:8080/challenge/challenge-4) +- [localhost:8080/challenge/challenge-8](http://localhost:8080/challenge/challenge-8) +- [localhost:8080/challenge/challenge-12](http://localhost:8080/challenge/challenge-12) +- [localhost:8080/challenge/challenge-13](http://localhost:8080/challenge/challenge-13) +- [localhost:8080/challenge/challenge-14](http://localhost:8080/challenge/challenge-14) +- [localhost:8080/challenge/challenge-15](http://localhost:8080/challenge/challenge-15) +- [localhost:8080/challenge/challenge-16](http://localhost:8080/challenge/challenge-16) +- [localhost:8080/challenge/challenge-17](http://localhost:8080/challenge/challenge-17) +- [localhost:8080/challenge/challenge-18](http://localhost:8080/challenge/challenge-18) +- [localhost:8080/challenge/challenge-19](http://localhost:8080/challenge/challenge-19) +- [localhost:8080/challenge/challenge-20](http://localhost:8080/challenge/challenge-20) +- [localhost:8080/challenge/challenge-21](http://localhost:8080/challenge/challenge-21) +- [localhost:8080/challenge/challenge-22](http://localhost:8080/challenge/challenge-22) +- [localhost:8080/challenge/challenge-23](http://localhost:8080/challenge/challenge-23) +- [localhost:8080/challenge/challenge-24](http://localhost:8080/challenge/challenge-24) +- [localhost:8080/challenge/challenge-25](http://localhost:8080/challenge/challenge-25) +- [localhost:8080/challenge/challenge-26](http://localhost:8080/challenge/challenge-26) +- [localhost:8080/challenge/challenge-27](http://localhost:8080/challenge/challenge-27) +- [localhost:8080/challenge/challenge-28](http://localhost:8080/challenge/challenge-28) +- [localhost:8080/challenge/challenge-29](http://localhost:8080/challenge/challenge-29) +- [localhost:8080/challenge/challenge-30](http://localhost:8080/challenge/challenge-30) +- [localhost:8080/challenge/challenge-31](http://localhost:8080/challenge/challenge-31) +- [localhost:8080/challenge/challenge-32](http://localhost:8080/challenge/challenge-32) +- [localhost:8080/challenge/challenge-34](http://localhost:8080/challenge/challenge-34) +- [localhost:8080/challenge/challenge-35](http://localhost:8080/challenge/challenge-35) +- [localhost:8080/challenge/challenge-36](http://localhost:8080/challenge/challenge-36) +- [localhost:8080/challenge/challenge-37](http://localhost:8080/challenge/challenge-37) +- [localhost:8080/challenge/challenge-38](http://localhost:8080/challenge/challenge-38) +- [localhost:8080/challenge/challenge-39](http://localhost:8080/challenge/challenge-39) +- [localhost:8080/challenge/challenge-40](http://localhost:8080/challenge/challenge-40) +- [localhost:8080/challenge/challenge-41](http://localhost:8080/challenge/challenge-41) Note that these challenges are still very basic, and so are their explanations. Feel free to file a PR to make them look better ;-). @@ -169,9 +169,9 @@ The K8S setup currently is based on using Minikube for local fun: now you can use the provided IP address and port to further play with the K8s variant (instead of localhost). -- [localhost:8080/challenge/5](http://localhost:8080/challenge/5) -- [localhost:8080/challenge/6](http://localhost:8080/challenge/6) -- [localhost:8080/challenge/33](http://localhost:8080/challenge/33) +- [localhost:8080/challenge/challenge-5](http://localhost:8080/challenge/challenge-5) +- [localhost:8080/challenge/challenge-6](http://localhost:8080/challenge/challenge-6) +- [localhost:8080/challenge/challenge-33](http://localhost:8080/challenge/challenge-33) ### k8s based @@ -190,9 +190,9 @@ Want to run vanilla on your own k8s? Use the commands below: now you can use the provided IP address and port to further play with the K8s variant (instead of localhost). -- [localhost:8080/challenge/5](http://localhost:8080/challenge/5) -- [localhost:8080/challenge/6](http://localhost:8080/challenge/6) -- [localhost:8080/challenge/33](http://localhost:8080/challenge/33) +- [localhost:8080/challenge/challenge-5](http://localhost:8080/challenge/challenge-5) +- [localhost:8080/challenge/challenge-6](http://localhost:8080/challenge/challenge-6) +- [localhost:8080/challenge/challenge-33](http://localhost:8080/challenge/challenge-33) ### Okteto based @@ -258,7 +258,7 @@ Therefore, you can manipulate them by overriding the following settings in your - `hints_enabled=false` will turn off the `Show hints` button. - `reason_enabled=false` will turn of the `What's wrong?` explanation button. -- `spoiling_enabled=false` will turn off the `/spoil-x` endpoint (where `x` is the number of the challenge). +- `spoiling_enabled=false` will turn off the `/spoil/challenge-x` endpoint (where `x` is the short-name of the challenge). ## Enabling Swaggerdocs and UI @@ -474,7 +474,7 @@ Follow the steps below on adding a challenge: 1. First make sure that you have an [Issue](https://github.com/OWASP/wrongsecrets/issues) reported for which a challenge is really wanted. 2. Add the new challenge in the `org.owasp.wrongsecrets.challenges` folder. Make sure you add an explanation in `src/main/resources/explanations` and refer to it from your new Challenge class. 3. Add unit, integration and UI tests as appropriate to show that your challenge is working. -4. Don't forget to add `@Order` annotation to your challenge ;-). +4. Do not forget to configure the challenge in `src/main/resources/wrong-secrets-configuration.yaml` 5. Review the [CONTRIBUTING guide](CONTRIBUTING.md) for setting up your contributing environment and writing good commit messages. For more details please refer [_Contributing.md_](https://github.com/OWASP/wrongsecrets/blob/master/CONTRIBUTING.md#how-to-add-a-challenge). diff --git a/k8s-vault-minkube-start.sh b/k8s-vault-minkube-start.sh index 757fc47dd..43bb3de50 100755 --- a/k8s-vault-minkube-start.sh +++ b/k8s-vault-minkube-start.sh @@ -123,6 +123,6 @@ kubectl port-forward \ echo "Do minikube delete to stop minikube from running and cleanup to start fresh again" echo "wait 20 seconds so we can check if vault-k8s-container works" sleep 20 -curl http://localhost:8080/spoil-7 +curl http://localhost:8080/spoil/challenge-7 echo "logs from pod to make sure:" cat pod.log diff --git a/package-lock.json b/package-lock.json index 2ad744937..7b1698772 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ }, "devDependencies": { "@commitlint/config-conventional": "^18.4.3", - "cypress": "^13.3.0", "eslint": "^8.52.0", "eslint-config-standard": "^17.1.0", "eslint-plugin-cypress": "^2.15.1", @@ -28,16 +27,6 @@ "node": ">=0.10.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/@commitlint/config-conventional": { "version": "18.4.3", "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.3.tgz", @@ -50,54 +39,6 @@ "node": ">=v18" } }, - "node_modules/@cypress/request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", - "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.10.4", - "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -114,18 +55,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -146,9 +87,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -223,9 +164,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/json5": { @@ -234,48 +175,20 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/node": { - "version": "18.18.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.1.tgz", - "integrity": "sha512-3G42sxmm0fF2+Vtb9TJQpnjmP+uKlWvFa8KoEGquh4gqRmoUG/N0ufuhikw6HEsdG2G2oIKhog1GCTfz9v5NdQ==", - "dev": true - }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", + "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", "dev": true }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -286,9 +199,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -299,13 +212,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -325,18 +238,33 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -373,13 +301,28 @@ "node": ">=4.0" } }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -408,9 +351,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -428,19 +371,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -457,42 +387,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -517,26 +411,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -664,54 +538,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -723,21 +549,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -763,27 +574,6 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -807,10 +597,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -827,16 +616,19 @@ ], "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, "engines": { - "node": "*" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/builtins": { @@ -848,13 +640,19 @@ "semver": "^7.0.0" } }, - "node_modules/cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "node_modules/builtins/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/call-bind": { @@ -879,12 +677,6 @@ "node": ">=6" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -901,94 +693,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1007,42 +711,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -1071,12 +739,6 @@ "node": ">=16" } }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1091,82 +753,6 @@ "node": ">= 8" } }, - "node_modules/cypress": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.3.0.tgz", - "integrity": "sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@cypress/request": "^3.0.0", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^18.17.5", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.6.0", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dayjs": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", - "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==", - "dev": true - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1204,10 +790,11 @@ } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -1218,15 +805,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1263,43 +841,6 @@ "node": ">=8" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -1353,13 +894,13 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" @@ -1403,15 +944,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1545,13 +1086,13 @@ } }, "node_modules/eslint-plugin-es-x": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz", - "integrity": "sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.3.0.tgz", + "integrity": "sha512-W9zIs+k00I/I13+Bdkl/zG1MEO07G97XjUSQuH117w620SJ6bHtLUmoMvkGA2oYnI/gNdr+G7BONLyYnFaLLEQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.5.0" + "@eslint-community/regexpp": "^4.6.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -1615,15 +1156,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-jest": { "version": "27.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", @@ -1650,9 +1182,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.2.0.tgz", - "integrity": "sha512-AQER2jEyQOt1LG6JkGJCCIFotzmlcCZFur2wdKrp1JX2cNotC7Ae0BcD/4lLv3lUAArM9uNS8z/fsvXTd0L71g==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.1.tgz", + "integrity": "sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -1660,6 +1192,7 @@ "eslint-plugin-es-x": "^7.1.0", "get-tsconfig": "^4.7.0", "ignore": "^5.2.4", + "is-builtin-module": "^3.2.1", "is-core-module": "^2.12.1", "minimatch": "^3.1.2", "resolve": "^1.22.2", @@ -1675,6 +1208,21 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-plugin-promise": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", @@ -1782,12 +1330,6 @@ "node": ">=6" } }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1796,76 +1338,6 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1873,9 +1345,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1904,54 +1376,21 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { @@ -1995,12 +1434,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -2008,9 +1448,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/for-each": { @@ -2021,44 +1461,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2112,21 +1514,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2154,24 +1541,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "dependencies": { - "async": "^3.2.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2204,25 +1573,10 @@ "node": ">=10.13.0" } }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2279,29 +1633,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2320,11 +1657,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2377,29 +1714,6 @@ "node": ">= 0.4" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2420,9 +1734,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -2453,15 +1767,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2478,22 +1783,13 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -2539,6 +1835,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -2550,18 +1861,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -2597,15 +1896,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2618,22 +1908,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -2712,18 +1986,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -2766,24 +2028,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -2806,12 +2050,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2824,16 +2062,10 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, "node_modules/json-schema-traverse": { @@ -2848,12 +2080,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -2866,40 +2092,13 @@ "json5": "lib/cli.js" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true, - "engines": { - "node": "> 0.8" + "json-buffer": "3.0.1" } }, "node_modules/levn": { @@ -2915,33 +2114,6 @@ "node": ">= 0.8.0" } }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2957,89 +2129,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3052,12 +2147,6 @@ "node": ">=10" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3080,36 +2169,6 @@ "node": ">=8.6" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3142,18 +2201,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -3242,21 +2289,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3274,12 +2306,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3310,21 +2336,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3379,18 +2390,6 @@ "node": ">=8" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3403,15 +2402,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3421,18 +2411,6 @@ "node": ">= 0.8.0" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3441,58 +2419,15 @@ "node": ">= 0.6.0" } }, - "node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3514,42 +2449,20 @@ ] }, "node_modules/readable-stream": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.0.tgz", - "integrity": "sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/readable-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -3566,21 +2479,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, - "dependencies": { - "throttleit": "^1.0.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3616,19 +2514,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3639,12 +2524,6 @@ "node": ">=0.10.0" } }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -3683,15 +2562,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -3713,7 +2583,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -3742,25 +2611,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/set-function-length": { @@ -3824,12 +2681,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3839,68 +2690,23 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "safe-buffer": "~5.2.0" } }, "node_modules/string.prototype.replaceall": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.7.tgz", - "integrity": "sha512-xB2WV2GlSCSJT5dMGdhdH1noMPiAB91guiepwTYyWY9/0Vq/TZ7RPmnOSUGAEvry08QIK7EMr28aAii+9jC6kw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.8.tgz", + "integrity": "sha512-MmCXb9980obcnmbEd3guqVl6lXTxpP28zASfgAlAhlBMw5XehQeSKsdIWlAYtLxp/1GtALwex+2HyoIQtaLQwQ==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "is-regex": "^1.1.4" }, @@ -3971,15 +2777,6 @@ "node": ">=4" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3993,18 +2790,15 @@ } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -4041,30 +2835,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4077,30 +2847,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -4114,9 +2860,9 @@ } }, "node_modules/tslib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "node_modules/tsutils": { @@ -4134,30 +2880,6 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4244,9 +2966,9 @@ } }, "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "peer": true, "bin": { @@ -4254,7 +2976,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -4271,24 +2993,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4298,39 +3002,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4379,23 +3050,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4408,16 +3062,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 31826ef30..8d00debbc 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,6 @@ { - "scripts": { - "test:open": "cypress open", - "test:ci": "cypress run --browser chrome" - }, "devDependencies": { "@commitlint/config-conventional": "^18.4.3", - "cypress": "^13.3.0", "eslint": "^8.52.0", "eslint-config-standard": "^17.1.0", "eslint-plugin-cypress": "^2.15.1", diff --git a/pom.xml b/pom.xml index 304e5a0e7..43a9be3e9 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,8 @@ 8.0.3 1.13.5 8.2.1 + 4.6.0 + 3.9.5 4.8.3 2.14.1 21 @@ -103,6 +105,10 @@ spring-boot-starter-thymeleaf + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + nz.net.ultraq.thymeleaf thymeleaf-layout-dialect @@ -117,6 +123,11 @@ org.springframework.boot spring-boot-starter + + org.testcontainers + testcontainers + test + org.springframework.boot spring-boot-starter-actuator @@ -231,6 +242,13 @@ test + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + org.cyclonedx cyclonedx-core-java @@ -243,19 +261,35 @@ ${dependency-check-maven.version} maven-plugin + + com.tngtech.archunit + archunit-junit5 + 1.1.0 + test + com.github.spotbugs spotbugs-annotations 4.8.0 - - - - - + + io.github.wimdeblauwe + testcontainers-cypress + 1.9.0 + test + + + + src/test/resources + + + e2e + src/test/e2e + + @@ -316,31 +350,6 @@ - - - start-app - - start - - pre-integration-test - - local,without-vault - - src/test/resources/ - src/test/resources/ - src/test/resources/alibabacreds.kdbx - src/test/resources/alibabacreds.kdbx - - - - - stop-app - - stop - - post-integration-test - - org.apache.maven.plugins @@ -473,33 +482,6 @@ generate-resources - - npm-install - - exec - - integration-test - - npm - - install - - - - - xcypress-test - - exec - - integration-test - - npm - - run - test:ci - - - @@ -578,6 +560,11 @@ + + io.gatling + gatling-maven-plugin + ${gatling-maven-plugin.version} + diff --git a/src/main/java/org/owasp/wrongsecrets/AllControllerAdvice.java b/src/main/java/org/owasp/wrongsecrets/AllControllerAdvice.java index b3cfc5246..c3f788227 100644 --- a/src/main/java/org/owasp/wrongsecrets/AllControllerAdvice.java +++ b/src/main/java/org/owasp/wrongsecrets/AllControllerAdvice.java @@ -1,11 +1,10 @@ package org.owasp.wrongsecrets; import jakarta.servlet.http.HttpServletRequest; -import java.util.List; -import org.owasp.wrongsecrets.challenges.Challenge; +import java.util.stream.Collectors; import org.owasp.wrongsecrets.challenges.ChallengeUI; +import org.owasp.wrongsecrets.definitions.ChallengeDefinitionsConfiguration; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ModelAttribute; @@ -18,22 +17,40 @@ @ControllerAdvice public class AllControllerAdvice { - private final List challenges; + private final Challenges challenges; private final String version; + private final ScoreCard scoreCard; + private final ChallengeDefinitionsConfiguration challengeDefinitionsConfiguration; private final RuntimeEnvironment runtimeEnvironment; public AllControllerAdvice( - List challenges, + Challenges challenges, @Value("${APP_VERSION}") String version, + ScoreCard scoreCard, + ChallengeDefinitionsConfiguration challengeDefinitionsConfiguration, RuntimeEnvironment runtimeEnvironment) { - this.challenges = ChallengeUI.toUI(challenges, runtimeEnvironment); + this.challenges = challenges; this.version = version; + this.scoreCard = scoreCard; + this.challengeDefinitionsConfiguration = challengeDefinitionsConfiguration; this.runtimeEnvironment = runtimeEnvironment; } @ModelAttribute public void addChallenges(Model model) { - model.addAttribute("challenges", challenges); + model.addAttribute( + "challenges", + challengeDefinitionsConfiguration.challenges().stream() + .map( + def -> + ChallengeUI.toUI( + def, + scoreCard, + runtimeEnvironment, + challenges.difficulties(), + challenges.getDefinitions().environments(), + challenges.navigation(def))) + .collect(Collectors.toList())); } @ModelAttribute @@ -48,12 +65,7 @@ public void addRequest(Model model, HttpServletRequest request) { @ModelAttribute public void addRuntimeEnvironment(Model model) { - model.addAttribute("environment", runtimeEnvironment.getRuntimeEnvironment().name()); + model.addAttribute("environment", runtimeEnvironment.getRuntimeEnvironment().displayName()); model.addAttribute("ctf_enabled", runtimeEnvironment.runtimeInCTFMode()); } - - @Bean - public List uiChallenges() { - return challenges; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/ChallengeConfigurationException.java b/src/main/java/org/owasp/wrongsecrets/ChallengeConfigurationException.java new file mode 100644 index 000000000..54d71bf3a --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/ChallengeConfigurationException.java @@ -0,0 +1,19 @@ +package org.owasp.wrongsecrets; + +import com.google.common.base.Strings; +import java.util.function.Supplier; + +public class ChallengeConfigurationException extends RuntimeException { + public ChallengeConfigurationException(String message) { + super(message); + } + + public ChallengeConfigurationException(Supplier message) { + super(message.get()); + } + + public static Supplier configError( + String errorMessageTemplate, Object... errorMessageArgs) { + return () -> Strings.lenientFormat(errorMessageTemplate, errorMessageArgs); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/ChallengeUiTemplateResolver.java b/src/main/java/org/owasp/wrongsecrets/ChallengeUiTemplateResolver.java new file mode 100644 index 000000000..db8701ebb --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/ChallengeUiTemplateResolver.java @@ -0,0 +1,62 @@ +package org.owasp.wrongsecrets; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.StringUtils; +import org.thymeleaf.IEngineConfiguration; +import org.thymeleaf.templateresolver.FileTemplateResolver; +import org.thymeleaf.templateresource.ITemplateResource; +import org.thymeleaf.templateresource.StringTemplateResource; + +/** + * Dynamically resolve a UI snippet for a specific challenge. + * + *

Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve + * the file in the resource directory. + */ +@Slf4j +public class ChallengeUiTemplateResolver extends FileTemplateResolver { + + private static final String PREFIX = "ui-snippet:"; + private ResourceLoader resourceLoader; + private Map resources = new HashMap<>(); + + public ChallengeUiTemplateResolver(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + setResolvablePatterns(Set.of(PREFIX + "*")); + } + + @Override + protected ITemplateResource computeTemplateResource( + IEngineConfiguration configuration, + String ownerTemplate, + String template, + String resourceName, + String characterEncoding, + Map templateResolutionAttributes) { + var templateName = resourceName.substring(PREFIX.length()); + if (!StringUtils.hasText(templateName) || "null".equals(templateName)) { + return new StringTemplateResource(""); + } + byte[] resource = resources.get(templateName); + if (resource == null) { + try { + resource = + resourceLoader + .getResource("classpath:/" + templateName) + .getInputStream() + .readAllBytes(); + } catch (IOException e) { + log.error("Unable to find resource {}", templateName, e); + return new StringTemplateResource(""); + } + resources.put(templateName, resource); + } + return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8)); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/Challenges.java b/src/main/java/org/owasp/wrongsecrets/Challenges.java new file mode 100644 index 000000000..b7f719f62 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/Challenges.java @@ -0,0 +1,94 @@ +package org.owasp.wrongsecrets; + +import static java.util.stream.Collectors.toMap; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import lombok.Getter; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; +import org.owasp.wrongsecrets.definitions.ChallengeDefinitionsConfiguration; +import org.owasp.wrongsecrets.definitions.Difficulty; +import org.owasp.wrongsecrets.definitions.Navigator; + +/** + * A collection of all challenges. This class glues a challenge definition together with the + * challenge class. + */ +public class Challenges { + + @Getter private final ChallengeDefinitionsConfiguration definitions; + private final Map shortNameToDefinition; + private final Map classNameToChallenge; + private final Map> challengeDefinitionToChallenge; + + public Challenges(ChallengeDefinitionsConfiguration definitions, List challenges) { + this.definitions = definitions; + + shortNameToDefinition = + definitions.challenges().stream() + .collect(toMap(definition -> definition.name().shortName(), Function.identity())); + classNameToChallenge = + challenges.stream() + .collect(toMap(challenge -> challenge.getClass().getName(), Function.identity())); + challengeDefinitionToChallenge = + definitions.challenges().stream() + .collect( + toMap( + definition -> definition, + definition -> + definition.sources().stream() + .map(source -> classNameToChallenge.get(source.className())) + .toList())); + } + + public Navigator navigation(ChallengeDefinition challengeDefinition) { + return new Navigator(definitions.challenges(), challengeDefinition); + } + + public int numberOfChallenges() { + return definitions.challenges().size(); + } + + public Optional findByShortName(String shortName) { + return definitions.challenges().stream() + .filter(challenge -> challenge.name().shortName().equals(shortName)) + .findFirst(); + } + + /** + * Find a challenge based on the name and the runtime environment. + * + * @param shortChallengeName the name of the challenge + * @param runtimeEnvironment the runtime environment + * @return the challenge if found + */ + public Optional findChallenge( + String shortChallengeName, RuntimeEnvironment runtimeEnvironment) { + var challengeDefinition = shortNameToDefinition.get(shortChallengeName); + + if (challengeDefinition == null) { + return Optional.empty(); + } + var source = challengeDefinition.source(runtimeEnvironment); + return source.map(s -> classNameToChallenge.get(s.className())); + } + + public List getChallenge(ChallengeDefinition definition) { + return challengeDefinitionToChallenge.get(definition); + } + + public List difficulties() { + return definitions.difficulties(); + } + + public boolean isFirstChallenge(ChallengeDefinition challengeDefinition) { + return challengeDefinition.equals(definitions.challenges().get(0)); + } + + public List getChallengeDefinitions() { + return definitions.challenges(); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/FailtoStartupException.java b/src/main/java/org/owasp/wrongsecrets/FailtoStartupException.java deleted file mode 100644 index 98079e695..000000000 --- a/src/main/java/org/owasp/wrongsecrets/FailtoStartupException.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.owasp.wrongsecrets; - -import org.springframework.boot.ExitCodeGenerator; - -/** Used to give a clear non-0 exit code when the Application cannot start. */ -public class FailtoStartupException extends RuntimeException implements ExitCodeGenerator { - - public FailtoStartupException(String message) { - super(message); - } - - @Override - public int getExitCode() { - return 1; - } -} diff --git a/src/main/java/org/owasp/wrongsecrets/InMemoryScoreCard.java b/src/main/java/org/owasp/wrongsecrets/InMemoryScoreCard.java index df8d3eb5a..c8fcfd00b 100644 --- a/src/main/java/org/owasp/wrongsecrets/InMemoryScoreCard.java +++ b/src/main/java/org/owasp/wrongsecrets/InMemoryScoreCard.java @@ -1,49 +1,57 @@ package org.owasp.wrongsecrets; +import static java.util.stream.Collectors.toMap; + import java.util.HashSet; -import java.util.List; +import java.util.Map; import java.util.Set; -import org.owasp.wrongsecrets.challenges.Challenge; +import java.util.stream.IntStream; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; +import org.owasp.wrongsecrets.definitions.Difficulty; /** In-memory implementation of the ScoreCard (E.g. no persistence). */ public class InMemoryScoreCard implements ScoreCard { - private final int maxNumberOfChallenges; - private final Set solvedChallenges = new HashSet<>(); - - public InMemoryScoreCard(int numberOfChallenge) { - maxNumberOfChallenges = numberOfChallenge; + private final Set solvedChallenges = new HashSet<>(); + private final Challenges challenges; + private final Map difficultyLevelsToInt; + + public InMemoryScoreCard(Challenges challenges) { + this.challenges = challenges; + var difficulties = challenges.difficulties(); + this.difficultyLevelsToInt = + IntStream.range(1, difficulties.size() + 1) + .boxed() + .collect(toMap(i -> difficulties.get(i - 1), i -> i)); } @Override - public void completeChallenge(Challenge challenge) { - solvedChallenges.add(challenge); + public void completeChallenge(ChallengeDefinition challengeDefinition) { + solvedChallenges.add(challengeDefinition); } @Override - public boolean getChallengeCompleted(Challenge challenge) { + public boolean getChallengeCompleted(ChallengeDefinition challenge) { return solvedChallenges.contains(challenge); } @Override public float getProgress() { - return ((float) 100 / maxNumberOfChallenges) * solvedChallenges.size(); + return ((float) 100 / challenges.numberOfChallenges()) * solvedChallenges.size(); } @Override public int getTotalReceivedPoints() { return solvedChallenges.stream() - .map(challenge -> challenge.difficulty() * (100 + (challenge.difficulty() - 1) * 25)) + .map( + challenge -> + difficultyLevelsToInt.get(challenge.difficulty()) + * (100 + (difficultyLevelsToInt.get(challenge.difficulty()) - 1) * 25)) .reduce(0, Integer::sum); } @Override - public List getCompletedChallenges() { - return solvedChallenges.stream().map(Challenge::getNumber).toList(); - } - - @Override - public void reset(Challenge challenge) { + public void reset(ChallengeDefinition challenge) { solvedChallenges.remove(challenge); } } diff --git a/src/main/java/org/owasp/wrongsecrets/MissingEnvironmentException.java b/src/main/java/org/owasp/wrongsecrets/MissingEnvironmentException.java new file mode 100644 index 000000000..46948cd1e --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/MissingEnvironmentException.java @@ -0,0 +1,13 @@ +package org.owasp.wrongsecrets; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.owasp.wrongsecrets.definitions.Environment; + +@AllArgsConstructor +@Getter +public class MissingEnvironmentException extends RuntimeException { + private final String currentRuntimeEnvironment; + private final List environments; +} diff --git a/src/main/java/org/owasp/wrongsecrets/MvcConfiguration.java b/src/main/java/org/owasp/wrongsecrets/MvcConfiguration.java index 30afd8f0a..e44ffa738 100644 --- a/src/main/java/org/owasp/wrongsecrets/MvcConfiguration.java +++ b/src/main/java/org/owasp/wrongsecrets/MvcConfiguration.java @@ -11,6 +11,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ResourceLoader; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect; import org.thymeleaf.spring6.SpringTemplateEngine; @@ -66,16 +67,27 @@ public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(TemplateGenerator return resolver; } + /** Loads the html for the complete lesson, see lesson_content.html */ + @Bean + public ChallengeUiTemplateResolver uiTemplateResolver(ResourceLoader resourceLoader) { + ChallengeUiTemplateResolver resolver = new ChallengeUiTemplateResolver(resourceLoader); + resolver.setOrder(0); + resolver.setCacheable(false); + resolver.setCharacterEncoding(UTF8); + return resolver; + } + @Bean public SpringTemplateEngine thymeleafTemplateEngine( ITemplateResolver springThymeleafTemplateResolver, + ITemplateResolver uiTemplateResolver, FileTemplateResolver asciiDoctorTemplateResolver) { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setEnableSpringELCompiler(true); engine.addDialect(new LayoutDialect()); engine.addDialect(new SpringSecurityDialect()); engine.setTemplateResolvers( - Set.of(asciiDoctorTemplateResolver, springThymeleafTemplateResolver)); + Set.of(asciiDoctorTemplateResolver, uiTemplateResolver, springThymeleafTemplateResolver)); return engine; } } diff --git a/src/main/java/org/owasp/wrongsecrets/RuntimeEnvironment.java b/src/main/java/org/owasp/wrongsecrets/RuntimeEnvironment.java index 71aa9447d..26558bf79 100644 --- a/src/main/java/org/owasp/wrongsecrets/RuntimeEnvironment.java +++ b/src/main/java/org/owasp/wrongsecrets/RuntimeEnvironment.java @@ -1,113 +1,52 @@ package org.owasp.wrongsecrets; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.*; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; import lombok.Getter; -import org.owasp.wrongsecrets.challenges.Challenge; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; +import org.owasp.wrongsecrets.definitions.ChallengeDefinitionsConfiguration; +import org.owasp.wrongsecrets.definitions.Environment; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; /** * Class establishing whether a challenge can run or not depending on the given RuntimeEnvironment * and whether components are configured and the CTFmode is enabled or not. */ -@Component +@Slf4j +@ToString public class RuntimeEnvironment { @Value("${ctf_enabled}") private boolean ctfModeEnabled; @Value("${SPECIAL_K8S_SECRET}") - private String challenge5Value; // used to determine if k8s/vault challenges are overriden; + private String challenge5Value; // used to determine if k8s/vault challenges are overridden; @Value("${vaultpassword}") private String challenge7Value; @Value("${default_aws_value_challenge_9}") private String - defaultChallenge9Value; // used to determine if the csloud challenge values are overriden - - private static final Map> envToOverlappingEnvs = - Map.of( - FLY_DOCKER, - List.of(DOCKER, FLY_DOCKER), - HEROKU_DOCKER, - List.of(DOCKER, HEROKU_DOCKER), - DOCKER, - List.of(DOCKER, HEROKU_DOCKER, FLY_DOCKER), - GCP, - List.of(DOCKER, K8S, VAULT), - AWS, - List.of(DOCKER, K8S, VAULT), - AZURE, - List.of(DOCKER, K8S, VAULT), - VAULT, - List.of(DOCKER, K8S), - K8S, - List.of(DOCKER), - OKTETO_K8S, - List.of(K8S, DOCKER, OKTETO_K8S)); - - /** Enum with possible environments supported by the app. */ - public enum Environment { - DOCKER("Docker"), - HEROKU_DOCKER("Heroku(Docker)"), - FLY_DOCKER("Fly(Docker)"), - GCP("gcp"), - AWS("aws"), - AZURE("azure"), - VAULT("k8s-with-vault"), - K8S("k8s"), - OKTETO_K8S("Okteto(k8s)"); - - private final String id; - - Environment(String id) { - this.id = id; - } - - static Environment fromId(String id) { - return Arrays.stream(Environment.values()) - .filter(e -> e.id.equalsIgnoreCase(id)) - .findAny() - .get(); - } - } + defaultChallenge9Value; // used to determine if the cloud challenge values are overridden @Getter private final Environment runtimeEnvironment; - @Autowired - public RuntimeEnvironment(@Value("${K8S_ENV}") String currentRuntimeEnvironment) { - this.runtimeEnvironment = Environment.fromId(currentRuntimeEnvironment); - } - public RuntimeEnvironment(Environment runtimeEnvironment) { this.runtimeEnvironment = runtimeEnvironment; } - public boolean canRun(Challenge challenge) { + public boolean canRun(ChallengeDefinition challengeDefinition) { if (isCloudUnlockedInCTFMode()) { return true; } if (isVaultUnlockedInCTFMode() && isK8sUnlockedInCTFMode()) { - return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment) - || challenge.supportedRuntimeEnvironments().contains(DOCKER) - || challenge.supportedRuntimeEnvironments().contains(K8S) - || challenge.supportedRuntimeEnvironments().contains(VAULT); + return challengeDefinition.supportedEnvironments().contains(runtimeEnvironment); } if (isK8sUnlockedInCTFMode()) { - return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment) - || challenge.supportedRuntimeEnvironments().contains(DOCKER) - || challenge.supportedRuntimeEnvironments().contains(K8S); + return challengeDefinition.supportedEnvironments().contains(runtimeEnvironment); } - return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment) - || !Collections.disjoint( - envToOverlappingEnvs.get(runtimeEnvironment), challenge.supportedRuntimeEnvironments()); + return challengeDefinition.supportedEnvironments().contains(this.runtimeEnvironment); } public boolean runtimeInCTFMode() { @@ -131,4 +70,24 @@ private boolean isCloudUnlockedInCTFMode() { String defaultValueAWSValue = "if_you_see_this_please_use_AWS_Setup"; return ctfModeEnabled && !defaultChallenge9Value.equals(defaultValueAWSValue); } + + public static RuntimeEnvironment fromString( + String currentRuntimeEnvironment, ChallengeDefinitionsConfiguration challengeDefinitions) { + var runtimeEnvironment = + challengeDefinitions.environments().stream() + .filter(env -> env.name().equalsIgnoreCase(currentRuntimeEnvironment)) + .findFirst() + .orElseThrow( + () -> { + log.error( + "Unable to determine the runtime environment. Make sure K8S_ENV contains one" + + " of the expected values: {}.", + challengeDefinitions.environments().stream() + .map(Environment::name) + .collect(Collectors.joining())); + throw new MissingEnvironmentException( + currentRuntimeEnvironment, challengeDefinitions.environments()); + }); + return new RuntimeEnvironment(runtimeEnvironment); + } } diff --git a/src/main/java/org/owasp/wrongsecrets/ScoreCard.java b/src/main/java/org/owasp/wrongsecrets/ScoreCard.java index af43b4e3e..f48caa759 100644 --- a/src/main/java/org/owasp/wrongsecrets/ScoreCard.java +++ b/src/main/java/org/owasp/wrongsecrets/ScoreCard.java @@ -1,7 +1,6 @@ package org.owasp.wrongsecrets; -import java.util.List; -import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; /** Interface of a scorecard where a player's progress is stored into. */ public interface ScoreCard { @@ -11,7 +10,7 @@ public interface ScoreCard { * * @param challenge Challenge object which is completed */ - void completeChallenge(Challenge challenge); + void completeChallenge(ChallengeDefinition challenge); /** * Checks if the given challenge is marked as completed in the scorecard. @@ -19,7 +18,7 @@ public interface ScoreCard { * @param challenge Challenge object tested for completion * @return true if challenge solved correctly */ - boolean getChallengeCompleted(Challenge challenge); + boolean getChallengeCompleted(ChallengeDefinition challenge); /** * Gives a 0-100 implementation completeness score. @@ -35,17 +34,10 @@ public interface ScoreCard { */ int getTotalReceivedPoints(); - /** - * Gives all completed challenges - * - * @return Set of ints - */ - List getCompletedChallenges(); - /** * Resets the status of a given challenge its entry in the score-card. * - * @param challenge Challenge of which the status should be reset. + * @param challenge challenge of which the status should be reset. */ - void reset(Challenge challenge); + void reset(ChallengeDefinition challenge); } diff --git a/src/main/java/org/owasp/wrongsecrets/StartupFailureAnalyzer.java b/src/main/java/org/owasp/wrongsecrets/StartupFailureAnalyzer.java new file mode 100644 index 000000000..e3d79c1f3 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/StartupFailureAnalyzer.java @@ -0,0 +1,24 @@ +package org.owasp.wrongsecrets; + +import java.util.stream.Collectors; +import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; +import org.springframework.boot.diagnostics.FailureAnalysis; + +public class StartupFailureAnalyzer extends AbstractFailureAnalyzer { + + @Override + protected FailureAnalysis analyze(Throwable rootFailure, MissingEnvironmentException cause) { + return new FailureAnalysis(getDescription(cause), getAction(cause), cause); + } + + private String getDescription(MissingEnvironmentException ex) { + return String.format( + "K8S_ENV is set to: '%s' which is not correct", ex.getCurrentRuntimeEnvironment()); + } + + private String getAction(MissingEnvironmentException ex) { + return String.format( + "Consider updating the K8S_ENV environment variable to one of the expected values '%s'", + ex.getEnvironments().stream().map(e -> e.name()).collect(Collectors.joining(", "))); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/StartupListener.java b/src/main/java/org/owasp/wrongsecrets/StartupListener.java deleted file mode 100644 index 1fa99448d..000000000 --- a/src/main/java/org/owasp/wrongsecrets/StartupListener.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.owasp.wrongsecrets; - -import java.util.Arrays; -import java.util.stream.Collectors; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; - -/** Helps application startup and breaks nicely if K8S_ENV is wrong. */ -@Slf4j -public class StartupListener implements ApplicationListener { - - @Override - public void onApplicationEvent(final @NotNull ApplicationEvent event) { - if (event instanceof ApplicationEnvironmentPreparedEvent envEvent) { - if (!StartupHelper.passedCorrectEnv(envEvent.getEnvironment().getProperty("K8S_ENV"))) { - log.error( - "K8S_ENV does not contain one of the expected values: {}.", - StartupHelper.envsToReadableString()); - throw new FailtoStartupException("K8S_ENV does not contain one of the expected values"); - } - } - } - - @UtilityClass - private static class StartupHelper { - - private boolean passedCorrectEnv(String k8sEnv) { - try { - RuntimeEnvironment.Environment.fromId(k8sEnv); - return true; - } catch (Exception e) { - return false; - } - } - - private String envsToReadableString() { - return Arrays.stream(RuntimeEnvironment.Environment.values()) - .map(Enum::toString) - .collect(Collectors.joining(", ")); - } - } -} diff --git a/src/main/java/org/owasp/wrongsecrets/WrongSecretsApplication.java b/src/main/java/org/owasp/wrongsecrets/WrongSecretsApplication.java index d910099be..cee0b6fd3 100644 --- a/src/main/java/org/owasp/wrongsecrets/WrongSecretsApplication.java +++ b/src/main/java/org/owasp/wrongsecrets/WrongSecretsApplication.java @@ -1,9 +1,8 @@ package org.owasp.wrongsecrets; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.challenges.Challenge; import org.owasp.wrongsecrets.challenges.kubernetes.Vaultpassword; +import org.owasp.wrongsecrets.definitions.ChallengeDefinitionsConfiguration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -13,7 +12,6 @@ @SpringBootApplication @EnableConfigurationProperties(Vaultpassword.class) -@Slf4j public class WrongSecretsApplication { public static void main(String[] args) { @@ -22,8 +20,14 @@ public static void main(String[] args) { @Bean @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) - public InMemoryScoreCard scoreCard(List challenges) { - log.info("Initializing scorecard with {} challenges", challenges.size()); - return new InMemoryScoreCard(challenges.size()); + public InMemoryScoreCard scoreCard(Challenges challenges) { + return new InMemoryScoreCard(challenges); + } + + @Bean + public RuntimeEnvironment runtimeEnvironment( + @Value("${K8S_ENV}") String currentRuntimeEnvironment, + ChallengeDefinitionsConfiguration challengeDefinitions) { + return RuntimeEnvironment.fromString(currentRuntimeEnvironment, challengeDefinitions); } } diff --git a/src/main/java/org/owasp/wrongsecrets/asciidoc/AsciiDoctorTemplateResolver.java b/src/main/java/org/owasp/wrongsecrets/asciidoc/AsciiDoctorTemplateResolver.java index d1edcca5f..6656ddf4b 100644 --- a/src/main/java/org/owasp/wrongsecrets/asciidoc/AsciiDoctorTemplateResolver.java +++ b/src/main/java/org/owasp/wrongsecrets/asciidoc/AsciiDoctorTemplateResolver.java @@ -42,6 +42,6 @@ protected ITemplateResource computeTemplateResource( } private String computeResourceName(String resourceName) { - return String.format("explanations/%s", resourceName.replace(".adoc", "")); + return String.format("%s", resourceName.replace(".adoc", "")); } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/Challenge.java b/src/main/java/org/owasp/wrongsecrets/challenges/Challenge.java index 55ce2b8ca..a0ba7e885 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/Challenge.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/Challenge.java @@ -1,28 +1,14 @@ package org.owasp.wrongsecrets.challenges; -import java.util.List; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.owasp.wrongsecrets.RuntimeEnvironment.Environment; -import org.owasp.wrongsecrets.ScoreCard; - -/** - * General Abstract Challenge class containing all the necessary members for a challenge. - * - * @see org.owasp.wrongsecrets.ScoreCard for tracking - */ -@RequiredArgsConstructor -@Getter -public abstract class Challenge { - - private final ScoreCard scoreCard; +/** General Abstract Challenge class containing all the necessary members for a challenge. */ +public interface Challenge { /** * Returns a Spoiler object containing the secret for the challenge. * * @return Spoiler with anser */ - public abstract Spoiler spoiler(); + Spoiler spoiler(); /** * method that needs to be overwritten by the Challenge implementation class to do the actual @@ -31,95 +17,5 @@ public abstract class Challenge { * @param answer String provided by the user * @return true if answer is Correct */ - protected abstract boolean answerCorrect(String answer); - - /** - * Gives the supported runtime envs in which the class can run. - * - * @return a list of Environment objects representing supported envs for the class - */ - public abstract List supportedRuntimeEnvironments(); - - /** - * returns the difficulty level. - * - * @return int with difficulty - */ - public abstract int difficulty(); - - /** - * returns the technology used. - * - * @see ChallengeTechnology.Tech - * @return a string from Tech.id - */ - public abstract String getTech(); - - /** - * boolean indicating a challenge needs to be run differently with a different explanation/steps - * when running on a shared platform. - * - * @return boolean with true if a different explanation is required when running on a shared - * platform - */ - public abstract boolean isLimitedWhenOnlineHosted(); - - /** - * boolean indicating if the challenge can be enabled when running in CTF mode. Note: All - * challenges should be able to run in non-CTF mode. - * - * @return true if the challenge can be run in CTF mode. - */ - public abstract boolean canRunInCTFMode(); - - /** - * Solving method which, if the correct answer is provided, will mark the challenge as solved in - * the scorecard. - * - * @param answer String provided by the user to validate. - * @return true if answer was correct. - */ - public boolean solved(String answer) { - var correctAnswer = answerCorrect(answer); - if (correctAnswer) { - scoreCard.completeChallenge(this); - } - return correctAnswer; - } - - /** - * Returns the name of the explanation file for adoc rendering. - * - * @return String with name of file for explanation - */ - public String getExplanation() { - return this.getClass().getSimpleName().toLowerCase(); - } - - /** - * Returns the name of the hints file for adoc rendering. - * - * @return String with name of file for hints - */ - public String getHint() { - return this.getClass().getSimpleName().toLowerCase() + "_hint"; - } - - /** - * Returns the name of the reason file for adoc rendering. - * - * @return String with name of file for reason - */ - public String getReason() { - return this.getClass().getSimpleName().toLowerCase() + "_reason"; - } - - /** - * Returns the number of the challenge extracted from the classname - * - * @return int of the challenge - */ - public String getNumber() { - return this.getClass().getSimpleName().replaceAll("[^0-9]", ""); - } + boolean answerCorrect(String answer); } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeUI.java b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeUI.java index 70c2167cf..ad520dd5d 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeUI.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeUI.java @@ -1,41 +1,58 @@ package org.owasp.wrongsecrets.challenges; -import java.util.Comparator; import java.util.List; -import java.util.regex.Pattern; +import java.util.function.Function; import java.util.stream.Collectors; import lombok.Getter; import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.ScoreCard; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; +import org.owasp.wrongsecrets.definitions.Difficulty; +import org.owasp.wrongsecrets.definitions.Environment; +import org.owasp.wrongsecrets.definitions.Navigator; +import org.owasp.wrongsecrets.definitions.Sources.ChallengeSource; /** Wrapper class to move logic from Thymeleaf to keep logic in code instead of the html file. */ @Getter public class ChallengeUI { + private final DifficultyUI difficultyUI; + private final List environments; + private final Navigator navigation; + /** Wrapper class to express the difficulty level into a UI representation. */ - private record DifficultyUI(int difficulty) { + private record DifficultyUI(int difficulty, int totalOfDifficultyLevels) { public String minimal() { return "☆".repeat(difficulty); } public String scale() { - int numberOfDifficultyLevels = Difficulty.totalOfDifficultyLevels(); - String fullScale = "★".repeat(difficulty) + "☆".repeat(numberOfDifficultyLevels); - return fullScale.substring(0, numberOfDifficultyLevels); + String fullScale = "★".repeat(difficulty) + "☆".repeat(totalOfDifficultyLevels); + return fullScale.substring(0, totalOfDifficultyLevels); } } - private static final Pattern challengePattern = Pattern.compile("(\\D+)(\\d+)"); - - private final Challenge challenge; - private final int challengeNumber; + private final ChallengeDefinition challengeDefinition; + private final ScoreCard scoreCard; private final RuntimeEnvironment runtimeEnvironment; + private final List difficulties; public ChallengeUI( - Challenge challenge, int challengeNumber, RuntimeEnvironment runtimeEnvironment) { - this.challenge = challenge; - this.challengeNumber = challengeNumber; + ChallengeDefinition challengeDefinition, + ScoreCard scoreCard, + RuntimeEnvironment runtimeEnvironment, + List difficulties, + List environments, + Navigator navigation) { + this.challengeDefinition = challengeDefinition; + this.scoreCard = scoreCard; this.runtimeEnvironment = runtimeEnvironment; + this.difficulties = difficulties; + this.environments = environments; + this.navigation = navigation; + this.difficultyUI = + new DifficultyUI(challengeDefinition.difficulty(difficulties), difficulties.size()); } /** @@ -44,20 +61,16 @@ public ChallengeUI( * @return String with name of the challenge. */ public String getName() { - var matchers = challengePattern.matcher(challenge.getClass().getSimpleName()); - if (matchers.matches()) { - return matchers.group(1) + " " + matchers.group(2); - } - return "Unknown"; + return challengeDefinition.name().name(); } /** * gives back the number of the challenge. * - * @return int with challenge number. + * @return the html friendly shortName name for the challenge */ - public Integer getLink() { - return challengeNumber; + public String getLink() { + return challengeDefinition.name().shortName(); } /** @@ -66,7 +79,7 @@ public Integer getLink() { * @return string with tech. */ public String getTech() { - return challenge.getTech(); + return challengeDefinition.category().category(); } /** @@ -74,17 +87,26 @@ public String getTech() { * * @return int with next challenge number. */ - public Integer next() { - return challengeNumber + 1; + public String next() { + return navigation.next().map(c -> c.name().shortName()).orElse(null); } /** - * Returns the number of the previous challenge (e.g current-1). + * Returns the number of the previous challenge. * * @return int with previous challenge number. */ - public Integer previous() { - return challengeNumber - 1; + public String previous() { + return navigation.previous().map(c -> c.name().shortName()).orElse(null); + } + + private String documentation(Function extractor) { + if (runtimeEnvironment.canRun(challengeDefinition)) { + return challengeDefinition.source(runtimeEnvironment).map(extractor).orElse(""); + } else { + // We cannot run the challenge but showing documentation should still be possible + return extractor.apply(challengeDefinition.sources().getFirst()); + } } /** @@ -93,7 +115,7 @@ public Integer previous() { * @return String with filename. */ public String getExplanation() { - return challenge.getExplanation(); + return documentation(s -> s.explanation().fileName()); } /** @@ -102,16 +124,7 @@ public String getExplanation() { * @return String with filename. */ public String getHint() { - List limitedOnlineEnvs = - List.of( - RuntimeEnvironment.Environment.HEROKU_DOCKER, - RuntimeEnvironment.Environment.FLY_DOCKER, - RuntimeEnvironment.Environment.OKTETO_K8S); - if (limitedOnlineEnvs.contains(runtimeEnvironment.getRuntimeEnvironment()) - && challenge.isLimitedWhenOnlineHosted()) { - return challenge.getHint() + "_limited"; - } - return challenge.getHint(); + return documentation(s -> s.hint().fileName()); } /** @@ -120,7 +133,7 @@ public String getHint() { * @return String with filename. */ public String getReason() { - return challenge.getReason(); + return documentation(s -> s.reason().fileName()); } /** @@ -129,10 +142,11 @@ public String getReason() { * @return String with required env. */ public String requiredEnv() { - return challenge.supportedRuntimeEnvironments().stream() - .map(Enum::name) + return challengeDefinition.supportedEnvironments().stream() + .map(e -> e.name()) .limit(1) - .collect(Collectors.joining()); + .collect(Collectors.joining()) + .toUpperCase(); } /** @@ -142,17 +156,17 @@ public String requiredEnv() { * @return stars */ public String getStarsOnScale() { - return new DifficultyUI(challenge.difficulty()).scale(); + return difficultyUI.scale(); } /** * Used to setup the label for the link to the challenge on the homescreen return "challenge - * 1(_disabled)(_solveD)-link" + * 1(_disabled)(_solveD)-link". * * @return label */ public String getDataLabel() { - String label = getName().trim().toLowerCase(); + String label = challengeDefinition.name().shortName().trim().toLowerCase(); if (!this.isChallengeEnabled()) { label = label + "_disabled"; } @@ -164,13 +178,13 @@ public String getDataLabel() { } /** - * Used to return whether the challenge is completed or not + * Used to return whether the challenge is completed or not. * * @return boolean */ public boolean challengeCompleted() { if (!runtimeEnvironment.runtimeInCTFMode()) { - return challenge.getScoreCard().getChallengeCompleted(challenge); + return scoreCard.getChallengeCompleted(challengeDefinition); } return false; } @@ -181,7 +195,7 @@ public boolean challengeCompleted() { * @return stars */ public String getStars() { - return new DifficultyUI(challenge.difficulty()).minimal(); + return difficultyUI.minimal(); } /** @@ -191,26 +205,41 @@ public String getStars() { */ public boolean isChallengeEnabled() { if (runtimeEnvironment.runtimeInCTFMode()) { - return runtimeEnvironment.canRun(challenge) && challenge.canRunInCTFMode(); + return runtimeEnvironment.canRun(challengeDefinition) && challengeDefinition.ctf().enabled(); + } + return runtimeEnvironment.canRun(challengeDefinition); + } + + public String getUiSnippet() { + return challengeDefinition + .source(runtimeEnvironment) + .map(source -> source.uiSnippet()) + .orElse(""); + } + + public String getRuntimeEnvironmentCategory() { + var challengeEnvironmentsOverviewNames = + challengeDefinition.supportedEnvironments().stream().map(env -> env.overview()).toList(); + if (challengeEnvironmentsOverviewNames.size() == 1) { + return challengeEnvironmentsOverviewNames.iterator().next(); + } else { + // Now if we have multiple we select the lowest one for our global environment definition + var allEnvironmentsOverviewNames = environments.stream().map(env -> env.overview()).toList(); + return allEnvironmentsOverviewNames.stream() + .filter(name -> challengeEnvironmentsOverviewNames.contains(name)) + .findFirst() + .orElse("Unknown"); } - return runtimeEnvironment.canRun(challenge); } - /** - * returns the list of challengeUIs based on the status sof the runtime. - * - * @param challenges actual challenges to be used in app. - * @param environment the runtime env we are running on as an app. - * @return list of ChallengeUIs. - */ - public static List toUI(List challenges, RuntimeEnvironment environment) { - return challenges.stream() - .sorted( - Comparator.comparingInt( - challenge -> - Integer.parseInt( - challenge.getClass().getSimpleName().replace("Challenge", "")))) - .map(challenge -> new ChallengeUI(challenge, challenges.indexOf(challenge), environment)) - .toList(); + public static ChallengeUI toUI( + ChallengeDefinition definition, + ScoreCard scoreCard, + RuntimeEnvironment environment, + List difficulties, + List environments, + Navigator navigation) { + return new ChallengeUI( + definition, scoreCard, environment, difficulties, environments, navigation); } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesAPIController.java b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesAPIController.java deleted file mode 100644 index 779bb7610..000000000 --- a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesAPIController.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.owasp.wrongsecrets.challenges; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.swagger.v3.oas.annotations.Operation; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; -import org.asciidoctor.Asciidoctor; -import org.asciidoctor.Options; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.asciidoc.TemplateGenerator; -import org.springframework.http.MediaType; -import org.springframework.util.ResourceUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * Used to request and generate the required json for setting up a CTF through juiceshop CTF CLI. - */ -@Slf4j -@RestController -public class ChallengesAPIController { - - private final ScoreCard scoreCard; - private final List challenges; - - private final List descriptions; - - private final List hints; - - private final TemplateGenerator templateGenerator; - - private final RuntimeEnvironment runtimeEnvironment; - - public ChallengesAPIController( - ScoreCard scoreCard, - List challenges, - RuntimeEnvironment runtimeEnvironment, - TemplateGenerator templateGenerator) { - this.scoreCard = scoreCard; - this.challenges = challenges; - this.descriptions = new ArrayList<>(); - this.hints = new ArrayList<>(); - this.runtimeEnvironment = runtimeEnvironment; - this.templateGenerator = templateGenerator; - } - - @GetMapping( - value = {"/api/Challenges", "/api/challenges"}, - produces = MediaType.APPLICATION_JSON_VALUE) - @Operation( - summary = "Gives all challenges back in a jsonArray, to be used with the Juiceshop CTF cli") - public String getChallenges() { - if (descriptions.size() == 0) { - initializeHintsAndDescriptions(); - } - JSONObject json = new JSONObject(); - JSONArray jsonArray = new JSONArray(); - for (int i = 0; i < challenges.size(); i++) { - JSONObject jsonChallenge = new JSONObject(); - jsonChallenge.put("id", i + 1); - jsonChallenge.put("name", challenges.get(i).getName()); - jsonChallenge.put("key", challenges.get(i).getExplanation()); - jsonChallenge.put( - "category", getCategory(challenges.get(i)) + " - " + challenges.get(i).getTech()); - jsonChallenge.put("description", descriptions.get(i)); - jsonChallenge.put("hint", hints.get(i)); - jsonChallenge.put( - "solved", scoreCard.getChallengeCompleted(challenges.get(i).getChallenge())); - jsonChallenge.put("disabledEnv", getDisabledEnv(challenges.get(i))); - jsonChallenge.put("difficulty", challenges.get(i).getChallenge().difficulty()); - jsonArray.add(jsonChallenge); - } - json.put("status", "success"); - json.put("data", jsonArray); - String result = json.toJSONString(); - log.info("returning {}", result); - return result; - } - - private String getCategory(ChallengeUI challengeUI) { - return switch (challengeUI.getChallenge().supportedRuntimeEnvironments().get(0)) { - case DOCKER, HEROKU_DOCKER, FLY_DOCKER -> "Docker"; - case GCP, AWS, AZURE -> "Cloud"; - case VAULT -> "Vault"; - case K8S, OKTETO_K8S -> "Kubernetes"; - }; - } - - private void initializeHintsAndDescriptions() { - log.info("Initialize hints and descriptions"); - challenges.forEach( - challengeUI -> { // note requires mvn install to generate the html files! - try { - String hint = - templateGenerator.generate( - "explanations/" + challengeUI.getExplanation() + "_hint"); - hints.add(hint); - String description = - templateGenerator.generate("explanations/" + challengeUI.getExplanation()); - descriptions.add(description); - } catch (IOException e) { - String rawHint = - extractResource( - "classpath:explanations/" + challengeUI.getExplanation() + "_hint.adoc"); - try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { - String hint = asciidoctor.convert(rawHint, Options.builder().build()); - hints.add(hint); - } - String rawDescription = - extractResource("classpath:explanations/" + challengeUI.getExplanation() + ".adoc"); - try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { - String description = asciidoctor.convert(rawDescription, Options.builder().build()); - descriptions.add(description); - } - throw new RuntimeException(e); - } - }); - } - - @SuppressFBWarnings( - value = "URLCONNECTION_SSRF_FD", - justification = "Read from specific classpath") - private String extractResource(String resourceName) { - try { - var resource = ResourceUtils.getURL(resourceName); - final StringBuilder resourceStringbuilder = new StringBuilder(); - try (BufferedReader bufferedReader = - new BufferedReader( - new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { - bufferedReader.lines().forEach(resourceStringbuilder::append); - return resourceStringbuilder.toString(); - } - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private String getDisabledEnv(ChallengeUI challenge) { - if (runtimeEnvironment.canRun(challenge.getChallenge())) { - return runtimeEnvironment.getRuntimeEnvironment().name(); - } - return null; - } -} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesController.java b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesController.java index b15d3ca52..7cc62ebf2 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesController.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesController.java @@ -1,21 +1,25 @@ package org.owasp.wrongsecrets.challenges; +import static org.owasp.wrongsecrets.ChallengeConfigurationException.configError; + import com.google.common.base.Strings; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.List; -import java.util.stream.Collectors; +import java.util.Optional; +import java.util.function.Supplier; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import org.owasp.wrongsecrets.ChallengeConfigurationException; +import org.owasp.wrongsecrets.Challenges; import org.owasp.wrongsecrets.RuntimeEnvironment; import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.challenges.docker.Challenge0; -import org.owasp.wrongsecrets.challenges.docker.Challenge30; import org.owasp.wrongsecrets.challenges.docker.Challenge37; import org.owasp.wrongsecrets.challenges.docker.Challenge8; +import org.owasp.wrongsecrets.challenges.docker.challenge30.Challenge30; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.security.crypto.codec.Hex; @@ -32,8 +36,8 @@ public class ChallengesController { private final ScoreCard scoreCard; - private final List challenges; private final RuntimeEnvironment runtimeEnvironment; + private final Challenges challenges; @Value("${hints_enabled}") private boolean hintsEnabled; @@ -63,7 +67,7 @@ public class ChallengesController { public ChallengesController( ScoreCard scoreCard, - List challenges, + Challenges challenges, RuntimeEnvironment runtimeEnvironment, @Value("${spoiling_enabled}") boolean spoilingEnabled) { this.scoreCard = scoreCard; @@ -72,52 +76,85 @@ public ChallengesController( this.spoilingEnabled = spoilingEnabled; } - private void checkValidChallengeNumber(int id) { - // If the id is either negative or larger than the amount of challenges, return false. - if (id < 0 || id >= challenges.size()) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "challenge not found"); - } - } - /** * return a spoil of the secret Please note that there is no way to enable this in ctfMode: spoils * can never be returned during a CTF By default, in normal operations, spoils are enabled, unless * `spoilingEnabled` is set to false. * * @param model exchanged with the FE - * @param id id of the challenge * @return either a notification or a spoil */ - @GetMapping("/spoil-{id}") + @GetMapping("/spoil/{short-name}") @Hidden - public String spoiler(Model model, @PathVariable Integer id) { + public String spoiler(@PathVariable("short-name") String shortName, Model model) { if (ctfModeEnabled) { model.addAttribute("spoiler", new Spoiler("Spoils are disabled in CTF mode")); } else if (!spoilingEnabled) { model.addAttribute("spoiler", new Spoiler("Spoils are disabled in the configuration")); } else { - var challenge = challenges.get(id).getChallenge(); - model.addAttribute("spoiler", challenge.spoiler()); + Optional spoilerFromRuntimeEnvironment = + challenges.findChallenge(shortName, runtimeEnvironment).map(c -> c.spoiler()); + Supplier spoilerFromRandomChallenge = + () -> { + var challengeDefinition = findByShortName(shortName); + return challenges.getChallenge(challengeDefinition).getFirst().spoiler(); + }; + + // We always want to show the spoiler even if we run in a non-supported environment + model.addAttribute( + "spoiler", spoilerFromRuntimeEnvironment.orElseGet(spoilerFromRandomChallenge)); } return "spoil"; } - @GetMapping("/challenge/{id}") - @Operation(description = "Returns the data for a given challenge's form interaction") - public String challenge(Model model, @PathVariable Integer id) { - checkValidChallengeNumber(id); - var challenge = challenges.get(id); + private void addChallengeUI(Model model, ChallengeDefinition challengeDefinition) { + model.addAttribute( + "challenge", + ChallengeUI.toUI( + challengeDefinition, + scoreCard, + runtimeEnvironment, + challenges.difficulties(), + challenges.getDefinitions().environments(), + challenges.navigation(challengeDefinition))); + } + /** + * checks whether challenge is enabled based on used runtimemode and CTF enablement. + * + * @return boolean true if the challenge can run. + */ + private boolean isChallengeEnabled(ChallengeDefinition challengeDefinition) { + if (runtimeEnvironment.runtimeInCTFMode()) { + return runtimeEnvironment.canRun(challengeDefinition) && challengeDefinition.ctf().enabled(); + } + return runtimeEnvironment.canRun(challengeDefinition); + } + + private ChallengeDefinition findByShortName(String shortName) { + return challenges + .findByShortName(shortName) + .orElseThrow( + () -> + new ResponseStatusException( + HttpStatus.NOT_FOUND, + configError("Challenge with short name '%s' not found", shortName).get())); + } + + @GetMapping("/challenge/{short-name}") + @Operation(description = "Returns the data for a given challenge's form interaction") + public String challenge(Model model, @PathVariable("short-name") String shortName) { + var challengeDefinition = findByShortName(shortName); model.addAttribute("challengeForm", new ChallengeForm("")); - model.addAttribute("challenge", challenge); + addChallengeUI(model, challengeDefinition); model.addAttribute("answerCorrect", null); model.addAttribute("answerIncorrect", null); model.addAttribute("solution", null); - if (!challenge.isChallengeEnabled()) { + if (!isChallengeEnabled(challengeDefinition)) { model.addAttribute("answerIncorrect", "This challenge has been disabled."); } - if (ctfModeEnabled && challenge.getChallenge() instanceof Challenge0) { + if (ctfModeEnabled && challenges.isFirstChallenge(challengeDefinition)) { if (!Strings.isNullOrEmpty(ctfServerAddress) && !ctfServerAddress.equals("not_set")) { model.addAttribute( "answerCorrect", @@ -133,41 +170,53 @@ public String challenge(Model model, @PathVariable Integer id) { } } enrichWithHintsAndReasons(model); - includeScoringStatus(model, challenge.getChallenge()); - addWarning(challenge.getChallenge(), model); + includeScoringStatus(model, challengeDefinition); + addWarning(challengeDefinition, model); fireEnding(model); return "challenge"; } - @PostMapping(value = "/challenge/{id}", params = "action=reset") + @PostMapping(value = "/challenge/{name}", params = "action=reset") @Operation(description = "Resets the state of a given challenge") public String reset( - @ModelAttribute ChallengeForm challengeForm, @PathVariable Integer id, Model model) { - checkValidChallengeNumber(id); - var challenge = challenges.get(id); - scoreCard.reset(challenge.getChallenge()); - - model.addAttribute("challenge", challenge); - includeScoringStatus(model, challenge.getChallenge()); - addWarning(challenge.getChallenge(), model); + @ModelAttribute ChallengeForm challengeForm, @PathVariable String name, Model model) { + var challengeDefinition = findByShortName(name); + scoreCard.reset(challengeDefinition); + + addChallengeUI(model, challengeDefinition); + includeScoringStatus(model, challengeDefinition); + addWarning(challengeDefinition, model); enrichWithHintsAndReasons(model); return "challenge"; } - @PostMapping(value = "/challenge/{id}", params = "action=submit") - @Operation(description = "Post your answer to the challenge for a given challenge ID") + @PostMapping(value = "/challenge/{name}", params = "action=submit") + @Operation(description = "Post your answer to the challenge for a given challenge") public String postController( - @ModelAttribute ChallengeForm challengeForm, Model model, @PathVariable Integer id) { - checkValidChallengeNumber(id); - var challenge = challenges.get(id); + @ModelAttribute ChallengeForm challengeForm, Model model, @PathVariable String name) { + var challengeDefinition = findByShortName(name); - if (!challenge.isChallengeEnabled()) { + if (!isChallengeEnabled(challengeDefinition)) { model.addAttribute("answerIncorrect", "This challenge has been disabled."); } else { - if (challenge.getChallenge().solved(challengeForm.solution())) { + var challenge = + challenges + .findChallenge(name, runtimeEnvironment) + .orElseThrow( + () -> + new ChallengeConfigurationException( + configError( + "Challenge '%s' not found for environment: '%s'", + name, runtimeEnvironment.getRuntimeEnvironment().name()))); + + if (challenge.answerCorrect(challengeForm.solution())) { + scoreCard.completeChallenge(challengeDefinition); + // TODO extract this to a separate method probably have separate handler classes in the + // configuration otherwise this is not maintainable, probably give the challenge a CTF + // method hook which you can override and do these kind of things in there. if (ctfModeEnabled) { if (!Strings.isNullOrEmpty(ctfServerAddress) && !ctfServerAddress.equals("not_set")) { - if (challenge.getChallenge() instanceof Challenge8) { + if (challenge instanceof Challenge8) { if (!Strings.isNullOrEmpty(keyToProvideToHost) && !keyToProvideToHost.equals( "not_set")) { // this means that it was overriden with a code that needs to be @@ -180,7 +229,7 @@ public String postController( + "for which you get your code: " + keyToProvideToHost); } - } else if (challenge.getChallenge() instanceof Challenge30) { + } else if (challenge instanceof Challenge30) { if (!Strings.isNullOrEmpty(keyToProvideToHostForChallenge30) && !keyToProvideToHostForChallenge30.equals( "not_set")) { // this means that it was overriden with a code that needs to be @@ -193,7 +242,7 @@ public String postController( + "for which you get your code: " + keyToProvideToHostForChallenge30); } - } else if (challenge.getChallenge() instanceof Challenge37) { + } else if (challenge instanceof Challenge37) { if (!Strings.isNullOrEmpty(getKeyToProvideToHostChallenge37) && !keyToProvideToHostForChallenge30.equals( "not_set")) { // this means that it was overriden with a code that needs to be @@ -214,7 +263,7 @@ public String postController( + ctfServerAddress); } } else { - String code = generateCode(challenge); + String code = generateCode(challengeDefinition); model.addAttribute( "answerCorrect", "Your answer is correct! " + "fill in the following code in CTF scoring: " + code); @@ -226,31 +275,30 @@ public String postController( model.addAttribute("answerIncorrect", "Your answer is incorrect, try harder ;-)"); } } - - model.addAttribute("challenge", challenge); - - includeScoringStatus(model, challenge.getChallenge()); - + addChallengeUI(model, challengeDefinition); + includeScoringStatus(model, challengeDefinition); enrichWithHintsAndReasons(model); fireEnding(model); return "challenge"; } - private String generateCode(ChallengeUI challenge) { + // TODO extract this to the challenge definition @see ChallengeAPIController with nested if + // statement + private String generateCode(ChallengeDefinition challenge) { SecretKeySpec secretKeySpec = new SecretKeySpec(ctfKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1"); try { Mac mac = Mac.getInstance("HmacSHA1"); mac.init(secretKeySpec); - byte[] result = mac.doFinal(challenge.getName().getBytes(StandardCharsets.UTF_8)); + byte[] result = mac.doFinal(challenge.name().name().getBytes(StandardCharsets.UTF_8)); return new String(Hex.encode(result)); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); } } - private void includeScoringStatus(Model model, Challenge challenge) { + private void includeScoringStatus(Model model, ChallengeDefinition challenge) { model.addAttribute("totalPoints", scoreCard.getTotalReceivedPoints()); model.addAttribute("progress", "" + scoreCard.getProgress()); @@ -259,13 +307,14 @@ private void includeScoringStatus(Model model, Challenge challenge) { } } - private void addWarning(Challenge challenge, Model model) { + private void addWarning(ChallengeDefinition challenge, Model model) { if (!runtimeEnvironment.canRun(challenge)) { var warning = - challenge.supportedRuntimeEnvironments().stream() - .map(Enum::name) + challenge.supportedEnvironments().stream() .limit(1) - .collect(Collectors.joining()); + .map(env -> env.missingEnvironment().contents().get()) + .findFirst() + .orElse(null); model.addAttribute("missingEnvWarning", warning); } } @@ -277,9 +326,8 @@ private void enrichWithHintsAndReasons(Model model) { private void fireEnding(Model model) { var notCompleted = - challenges.stream() - .filter(ChallengeUI::isChallengeEnabled) - .map(ChallengeUI::getChallenge) + challenges.getDefinitions().challenges().stream() + .filter(def -> isChallengeEnabled(def)) .filter(this::challengeNotCompleted) .count(); if (notCompleted == 0) { @@ -287,7 +335,7 @@ private void fireEnding(Model model) { } } - private boolean challengeNotCompleted(Challenge challenge) { + private boolean challengeNotCompleted(ChallengeDefinition challenge) { return !scoreCard.getChallengeCompleted(challenge); } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesCtfController.java b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesCtfController.java new file mode 100644 index 000000000..5ac32c9bd --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/ChallengesCtfController.java @@ -0,0 +1,91 @@ +package org.owasp.wrongsecrets.challenges; + +import io.swagger.v3.oas.annotations.Operation; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import org.owasp.wrongsecrets.Challenges; +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.ScoreCard; +import org.owasp.wrongsecrets.definitions.ChallengeDefinition; +import org.owasp.wrongsecrets.definitions.ChallengeDefinitionsConfiguration; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Used to request and generate the required json for setting up a CTF through juiceshop CTF CLI. + */ +@Slf4j +@RestController +public class ChallengesCtfController { + + private final ScoreCard scoreCard; + private final Challenges challenges; + private final ChallengeDefinitionsConfiguration wrongSecretsConfiguration; + private final RuntimeEnvironment runtimeEnvironment; + + public ChallengesCtfController( + ScoreCard scoreCard, + Challenges challenges, + RuntimeEnvironment runtimeEnvironment, + ChallengeDefinitionsConfiguration wrongSecretsConfiguration) { + this.scoreCard = scoreCard; + this.challenges = challenges; + this.wrongSecretsConfiguration = wrongSecretsConfiguration; + this.runtimeEnvironment = runtimeEnvironment; + } + + @GetMapping( + value = {"/api/Challenges", "/api/challenges"}, + produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + summary = "Gives all challenges back in a jsonArray, to be used with the Juiceshop CTF cli") + public String getChallenges() { + List definitions = challenges.getDefinitions().challenges(); + JSONObject json = new JSONObject(); + JSONArray jsonArray = new JSONArray(); + for (int i = 0; i < definitions.size(); i++) { + ChallengeDefinition definition = definitions.get(i); + JSONObject jsonChallenge = new JSONObject(); + jsonChallenge.put("id", i + 1); + jsonChallenge.put("name", definition.name().name()); + jsonChallenge.put("key", definition.name().shortName()); + jsonChallenge.put("category", getCategory() + " - " + definition.category().category()); + jsonChallenge.put( + "description", + definition + .source(runtimeEnvironment) + .map(s -> s.explanation().contents().get()) + .orElse(null)); + jsonChallenge.put( + "hint", + definition.source(runtimeEnvironment).map(s -> s.hint().contents().get()).orElse(null)); + jsonChallenge.put("solved", scoreCard.getChallengeCompleted(definition)); + jsonChallenge.put("disabledEnv", getDisabledEnv(definition)); + jsonChallenge.put("difficulty", definition.difficulty().difficulty()); + jsonArray.add(jsonChallenge); + } + json.put("status", "success"); + json.put("data", jsonArray); + String result = json.toJSONString(); + log.trace("returning {}", result); + return result; + } + + private String getCategory() { + return this.wrongSecretsConfiguration.environments().stream() + .filter(e -> e.equals(runtimeEnvironment.getRuntimeEnvironment())) + .findFirst() + .map(e -> e.ctf()) + .orElse("Unknown"); + } + + private String getDisabledEnv(ChallengeDefinition challengeDefinition) { + if (runtimeEnvironment.canRun(challengeDefinition)) { + return runtimeEnvironment.getRuntimeEnvironment().name(); + } + return null; + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/Difficulty.java b/src/main/java/org/owasp/wrongsecrets/challenges/Difficulty.java deleted file mode 100644 index 10bcce0bc..000000000 --- a/src/main/java/org/owasp/wrongsecrets/challenges/Difficulty.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.owasp.wrongsecrets.challenges; - -/** Representation of the difficulty levels. */ -public class Difficulty { - - public static final int EASY = 1; - public static final int NORMAL = 2; - public static final int HARD = 3; - public static final int EXPERT = 4; - public static final int MASTER = 5; - - private static final int[] allLevels = new int[] {EASY, NORMAL, HARD, EXPERT, MASTER}; - - public static int totalOfDifficultyLevels() { - return allLevels.length; - } -} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge10.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge10.java index 4c8f37d9f..5b59d5ce4 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge10.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge10.java @@ -1,40 +1,27 @@ package org.owasp.wrongsecrets.challenges.cloud; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AWS; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AZURE; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.GCP; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; +import org.owasp.wrongsecrets.challenges.Challenge; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Cloud challenge that leverages the CSI secrets driver of the cloud you are running in. */ @Component @Slf4j -@Order(10) -public class Challenge10 extends CloudChallenge { +public class Challenge10 implements Challenge { private final String awsDefaultValue; private final String challengeAnswer; public Challenge10( - ScoreCard scoreCard, @Value("${secretmountpath}") String filePath, @Value("${default_aws_value_challenge_10}") String awsDefaultValue, - @Value("${FILENAME_CHALLENGE10}") String fileName, - RuntimeEnvironment runtimeEnvironment) { - super(scoreCard, runtimeEnvironment); + @Value("${FILENAME_CHALLENGE10}") String fileName) { this.awsDefaultValue = awsDefaultValue; this.challengeAnswer = getCloudChallenge9and10Value(filePath, fileName); } @@ -65,26 +52,4 @@ private String getCloudChallenge9and10Value(String filePath, String fileName) { return awsDefaultValue; } } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(GCP, AWS, AZURE); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; - } - - /** {@inheritDoc} Uses CSI Driver */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CSI.id; - } - - @Override - public boolean canRunInCTFMode() { - return true; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge9.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge9.java index 6a78238e5..d8636038e 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge9.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge9.java @@ -1,29 +1,19 @@ package org.owasp.wrongsecrets.challenges.cloud; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AWS; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AZURE; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.GCP; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; +import org.owasp.wrongsecrets.challenges.Challenge; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Cloud challenge which focuses on Terraform and secrets. */ @Component @Slf4j -@Order(9) -public class Challenge9 extends CloudChallenge { +public class Challenge9 implements Challenge { private final String awsDefaultValue; private final String challengeAnswer; @@ -31,20 +21,15 @@ public class Challenge9 extends CloudChallenge { /** * Cloud challenge which focuses on Terraform and secrets. * - * @param scoreCard required for score keeping * @param filePath used to mount in the secrets store where teh actual secret lands in from the * cloud * @param awsDefaultValue used to indicate whether a cloud setup is enabled. * @param fileName name of the actual secret file mounted on the filePath - * @param runtimeEnvironment runtime env required to run this in. */ public Challenge9( - ScoreCard scoreCard, @Value("${secretmountpath}") String filePath, @Value("${default_aws_value_challenge_9}") String awsDefaultValue, - @Value("${FILENAME_CHALLENGE9}") String fileName, - RuntimeEnvironment runtimeEnvironment) { - super(scoreCard, runtimeEnvironment); + @Value("${FILENAME_CHALLENGE9}") String fileName) { this.awsDefaultValue = awsDefaultValue; this.challengeAnswer = getCloudChallenge9and10Value(filePath, fileName); } @@ -75,26 +60,4 @@ private String getCloudChallenge9and10Value(String filePath, String fileName) { return awsDefaultValue; } } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(GCP, AWS, AZURE); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} Uses Terraform */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.TERRAFORM.id; - } - - @Override - public boolean canRunInCTFMode() { - return true; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/CloudChallenge.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/CloudChallenge.java deleted file mode 100644 index e635f18f5..000000000 --- a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/CloudChallenge.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.owasp.wrongsecrets.challenges.cloud; - -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.challenges.Challenge; - -/** - * Abstract class used to provide convinient wrapper helpers for cloud type detection for the cloud - * challenges. - */ -public abstract class CloudChallenge extends Challenge { - - private final RuntimeEnvironment runtimeEnvironment; - - protected CloudChallenge(ScoreCard scoreCard, RuntimeEnvironment runtimeEnvironment) { - super(scoreCard); - this.runtimeEnvironment = runtimeEnvironment; - } - - /** - * boolean showing whether we run in AWS. - * - * @return true if we are on AWS - */ - public boolean isAWS() { - return this.runtimeEnvironment.getRuntimeEnvironment() == RuntimeEnvironment.Environment.AWS; - } - - /** - * boolean showing whether we run in GCP. - * - * @return true if we are on GCP - */ - public boolean isGCP() { - return this.runtimeEnvironment.getRuntimeEnvironment() == RuntimeEnvironment.Environment.GCP; - } - - /** - * boolean showing whether we run in Azure. - * - * @return true if we are on Azure - */ - public boolean isAzure() { - return this.runtimeEnvironment.getRuntimeEnvironment() == RuntimeEnvironment.Environment.AZURE; - } - - @Override - public String getExplanation() { - return getData(super.getExplanation()); - } - - @Override - public String getHint() { - return getData(super.getHint()); - } - - @Override - public String getReason() { - return getData(super.getReason()); - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - private String getData(String defaultAWsPath) { - RuntimeEnvironment.Environment env = runtimeEnvironment.getRuntimeEnvironment(); - return switch (env) { - case GCP -> String.format("%s%s", defaultAWsPath, "-gcp"); - case AZURE -> String.format("%s%s", defaultAWsPath, "-azure"); - default -> String.format("%s", defaultAWsPath); // Default is AWS - }; - } -} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge11.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Aws.java similarity index 52% rename from src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge11.java rename to src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Aws.java index 72d636bf6..74a11b6f9 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/Challenge11.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Aws.java @@ -1,28 +1,16 @@ -package org.owasp.wrongsecrets.challenges.cloud; +package org.owasp.wrongsecrets.challenges.cloud.challenge11; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AWS; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.AZURE; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.GCP; - -import com.google.api.gax.rpc.ApiException; -import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse; -import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; -import com.google.cloud.secretmanager.v1.SecretVersionName; import com.google.common.base.Strings; +import com.google.common.base.Supplier; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; +import org.owasp.wrongsecrets.challenges.Challenge; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ssm.SsmClient; @@ -37,101 +25,55 @@ /** Cloud challenge which uses IAM privilelge escalation (differentiating per cloud). */ @Component @Slf4j -@Order(11) -public class Challenge11 extends CloudChallenge { +public class Challenge11Aws implements Challenge { private final String awsRoleArn; private final String awsRegion; private final String tokenFileLocation; private final String awsDefaultValue; - private final String gcpDefaultValue; - private final String azureDefaultValue; - private final String challengeAnswer; - private final String projectId; - private final String azureVaultUri; - private final String azureWrongSecret3; - + private final Supplier challengeAnswer; private final String ctfValue; - private final boolean ctfEnabled; - public Challenge11( - ScoreCard scoreCard, + public Challenge11Aws( @Value("${AWS_ROLE_ARN}") String awsRoleArn, @Value("${AWS_WEB_IDENTITY_TOKEN_FILE}") String tokenFileLocation, @Value("${AWS_REGION}") String awsRegion, - @Value("${default_gcp_value}") String gcpDefaultValue, @Value("${default_aws_value}") String awsDefaultValue, - @Value("${default_azure_value}") String azureDefaultValue, - @Value("${spring.cloud.azure.keyvault.secret.property-sources[0].endpoint}") - String azureVaultUri, - @Value("${wrongsecret-3}") String azureWrongSecret3, // Exclusively auto-wired for Azure - @Value("${GOOGLE_CLOUD_PROJECT}") String projectId, @Value("${default_aws_value_challenge_11}") String ctfValue, - @Value("${ctf_enabled}") boolean ctfEnabled, - RuntimeEnvironment runtimeEnvironment) { - super(scoreCard, runtimeEnvironment); + @Value("${ctf_enabled}") boolean ctfEnabled) { this.awsRoleArn = awsRoleArn; this.tokenFileLocation = tokenFileLocation; this.awsRegion = awsRegion; this.awsDefaultValue = awsDefaultValue; - this.gcpDefaultValue = gcpDefaultValue; - this.azureDefaultValue = azureDefaultValue; - this.projectId = projectId; - this.azureVaultUri = azureVaultUri; - this.azureWrongSecret3 = azureWrongSecret3; this.ctfValue = ctfValue; this.ctfEnabled = ctfEnabled; - this.challengeAnswer = getChallenge11Value(runtimeEnvironment); + this.challengeAnswer = getChallenge11Value(); } /** {@inheritDoc} */ @Override public Spoiler spoiler() { - return new Spoiler(challengeAnswer); + return new Spoiler(challengeAnswer.get()); } /** {@inheritDoc} */ @Override public boolean answerCorrect(String answer) { - return challengeAnswer.equals(answer); - } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(AWS, GCP, AZURE); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; + return challengeAnswer.get().equals(answer); } - /** {@inheritDoc} Uses IAM Privilege escalation */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.IAM.id; - } - - private String getChallenge11Value(RuntimeEnvironment runtimeEnvironment) { + private Supplier getChallenge11Value() { if (!ctfEnabled) { - if (runtimeEnvironment != null && runtimeEnvironment.getRuntimeEnvironment() != null) { - return switch (runtimeEnvironment.getRuntimeEnvironment()) { - case AWS -> getAWSChallenge11Value(); - case GCP -> getGCPChallenge11Value(); - case AZURE -> getAzureChallenge11Value(); - default -> "please_use_supported_cloud_env"; - }; - } + return () -> getAWSChallenge11Value(); } else if (!Strings.isNullOrEmpty(ctfValue) && !Strings.isNullOrEmpty(awsDefaultValue) && !ctfValue.equals(awsDefaultValue)) { - return ctfValue; + return () -> ctfValue; } log.info("CTF enabled, skipping challenge11"); - return "please_use_supported_cloud_env"; + return () -> "please_use_supported_cloud_env"; } @SuppressFBWarnings( @@ -184,41 +126,4 @@ private String getAWSChallenge11Value() { } return awsDefaultValue; } - - private String getGCPChallenge11Value() { - log.info("pre-checking GCP data"); - if (isGCP()) { - log.info("Getting credentials from GCP"); - // Based on https://cloud.google.com/secret-manager/docs/reference/libraries - try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { - log.info("Fetching secret form Google Secret Manager..."); - SecretVersionName secretVersionName = - SecretVersionName.of(projectId, "wrongsecret-3", "latest"); - AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName); - return response.getPayload().getData().toStringUtf8(); - } catch (ApiException e) { - log.error("Exception getting secret: ", e); - } catch (IOException e) { - log.error("Could not get the web identity token, due to ", e); - } - } else { - log.info("Skipping credentials from GCP"); - } - return gcpDefaultValue; - } - - private String getAzureChallenge11Value() { - log.info("pre-checking Azure data"); - if (isAzure()) { - log.info(String.format("Using Azure Key Vault URI: %s", azureVaultUri)); - return azureWrongSecret3; - } - log.error("Fetching secret from Azure did not work, returning default"); - return azureDefaultValue; - } - - @Override - public boolean canRunInCTFMode() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Azure.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Azure.java new file mode 100644 index 000000000..f2f7fa052 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Azure.java @@ -0,0 +1,70 @@ +package org.owasp.wrongsecrets.challenges.cloud.challenge11; + +import com.google.common.base.Strings; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import lombok.extern.slf4j.Slf4j; +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.Spoiler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** Cloud challenge which uses IAM privilelge escalation (differentiating per cloud). */ +@Component +@Slf4j +public class Challenge11Azure implements Challenge { + + private final String azureDefaultValue; + private final Supplier challengeAnswer; + private final String azureVaultUri; + private final String azureWrongSecret3; + private final String ctfValue; + private final boolean ctfEnabled; + + public Challenge11Azure( + @Value("${default_azure_value}") String azureDefaultValue, + @Value("${spring.cloud.azure.keyvault.secret.property-sources[0].endpoint}") + String azureVaultUri, + @Value("${wrongsecret-3}") String azureWrongSecret3, // Exclusively auto-wired for Azure + @Value("${default_aws_value_challenge_11}") String ctfValue, + @Value("${ctf_enabled}") boolean ctfEnabled, + RuntimeEnvironment runtimeEnvironment) { + this.azureDefaultValue = azureDefaultValue; + this.azureVaultUri = azureVaultUri; + this.azureWrongSecret3 = azureWrongSecret3; + this.ctfValue = ctfValue; + this.ctfEnabled = ctfEnabled; + this.challengeAnswer = Suppliers.memoize(getChallenge11Value(runtimeEnvironment)); + } + + /** {@inheritDoc} */ + @Override + public Spoiler spoiler() { + return new Spoiler(challengeAnswer.get()); + } + + /** {@inheritDoc} */ + @Override + public boolean answerCorrect(String answer) { + return challengeAnswer.get().equals(answer); + } + + private Supplier getChallenge11Value(RuntimeEnvironment runtimeEnvironment) { + if (!ctfEnabled) { + return () -> getAzureChallenge11Value(); + } else if (!Strings.isNullOrEmpty(ctfValue) + && !Strings.isNullOrEmpty(azureDefaultValue) + && !ctfValue.equals(azureDefaultValue)) { + return () -> ctfValue; + } + + log.info("CTF enabled, skipping challenge11"); + return () -> "please_use_supported_cloud_env"; + } + + private String getAzureChallenge11Value() { + log.info(String.format("Using Azure Key Vault URI: %s", azureVaultUri)); + return azureWrongSecret3; + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Gcp.java b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Gcp.java new file mode 100644 index 000000000..580116e7a --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/cloud/challenge11/Challenge11Gcp.java @@ -0,0 +1,81 @@ +package org.owasp.wrongsecrets.challenges.cloud.challenge11; + +import com.google.api.gax.rpc.ApiException; +import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretVersionName; +import com.google.common.base.Strings; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import java.io.IOException; +import lombok.extern.slf4j.Slf4j; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.Spoiler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** Cloud challenge which uses IAM privilelge escalation (differentiating per cloud). */ +@Component +@Slf4j +public class Challenge11Gcp implements Challenge { + + private final String gcpDefaultValue; + private final Supplier challengeAnswer; + private final String projectId; + private final String ctfValue; + private final boolean ctfEnabled; + + public Challenge11Gcp( + @Value("${default_gcp_value}") String gcpDefaultValue, + @Value("${GOOGLE_CLOUD_PROJECT}") String projectId, + @Value("${default_aws_value_challenge_11}") String ctfValue, + @Value("${ctf_enabled}") boolean ctfEnabled) { + this.gcpDefaultValue = gcpDefaultValue; + this.projectId = projectId; + this.ctfValue = ctfValue; + this.ctfEnabled = ctfEnabled; + this.challengeAnswer = Suppliers.memoize(getChallenge11Value()); + } + + /** {@inheritDoc} */ + @Override + public Spoiler spoiler() { + return new Spoiler(challengeAnswer.get()); + } + + /** {@inheritDoc} */ + @Override + public boolean answerCorrect(String answer) { + return challengeAnswer.get().equals(answer); + } + + private Supplier getChallenge11Value() { + if (!ctfEnabled) { + return () -> getGCPChallenge11Value(); + } else if (!Strings.isNullOrEmpty(ctfValue) + && !Strings.isNullOrEmpty(gcpDefaultValue) + && !ctfValue.equals(gcpDefaultValue)) { + return () -> ctfValue; + } + + log.info("CTF enabled, skipping challenge11"); + return () -> "please_use_supported_cloud_env"; + } + + private String getGCPChallenge11Value() { + log.info("Getting credentials from GCP"); + // Based on https://cloud.google.com/secret-manager/docs/reference/libraries + try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { + log.info("Fetching secret form Google Secret Manager..."); + SecretVersionName secretVersionName = + SecretVersionName.of(projectId, "wrongsecret-3", "latest"); + AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName); + return response.getPayload().getData().toStringUtf8(); + } catch (ApiException e) { + log.error("Exception getting secret: ", e); + } catch (IOException e) { + log.error("Could not get the web identity token, due to ", e); + } + return gcpDefaultValue; + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge0.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge0.java index 68c8c6c55..e9656ca65 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge0.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge0.java @@ -1,24 +1,12 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Introduction challenge to get a user introduced with the setup. */ @Component -@Order(0) -public class Challenge0 extends Challenge { - - public Challenge0(ScoreCard scoreCard) { - super(scoreCard); - } +public class Challenge0 implements Challenge { /** {@inheritDoc} */ @Override @@ -28,37 +16,10 @@ public Spoiler spoiler() { /** {@inheritDoc} */ @Override - protected boolean answerCorrect(String answer) { + public boolean answerCorrect(String answer) { return getData().equals(answer); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - @Override - public String getTech() { - return "Intro"; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public boolean canRunInCTFMode() { - return true; - } - private String getData() { return "The first answer"; } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge1.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge1.java index abaee43af..88bb8631b 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge1.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge1.java @@ -1,30 +1,12 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Challenge to find the hardcoded password in code. */ @Component -@Order(1) -public class Challenge1 extends Challenge { - - public Challenge1(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge1 implements Challenge { /** {@inheritDoc} */ @Override @@ -37,26 +19,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return WrongSecretsConstants.password.equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Git based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.GIT.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge12.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge12.java index c6c4d7042..afd22baf8 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge12.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge12.java @@ -4,37 +4,23 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Challenge focused on filesystem issues in docker container due to workdir copying. */ @Slf4j @Component -@Order(12) -public class Challenge12 extends Challenge { +public class Challenge12 implements Challenge { private final String dockerMountPath; - public Challenge12( - ScoreCard scoreCard, @Value("${challengedockermtpath}") String dockerMountPath) { - super(scoreCard); + public Challenge12(@Value("${challengedockermtpath}") String dockerMountPath) { this.dockerMountPath = dockerMountPath; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -48,29 +34,6 @@ public boolean answerCorrect(String answer) { return getActualData().equals(answer); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} Docker based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCKER.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - @SuppressFBWarnings( value = "PATH_TRAVERSAL_IN", justification = "The location of the dockerMountPath is based on an Env Var") diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge13.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge13.java index 2be07e65c..4ca47c183 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge13.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge13.java @@ -4,28 +4,21 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Challenge focused on showing CI/CD issues through Github Actions. */ @Slf4j @Component -@Order(13) -public class Challenge13 extends Challenge { +public class Challenge13 implements Challenge { private final String plainText; private final String cipherText; @@ -41,48 +34,17 @@ public Spoiler spoiler() { } public Challenge13( - ScoreCard scoreCard, - @Value("${plainText13}") String plainText, - @Value("${cipherText13}") String cipherText) { - super(scoreCard); + @Value("${plainText13}") String plainText, @Value("${cipherText13}") String cipherText) { this.plainText = plainText; this.cipherText = cipherText; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override - protected boolean answerCorrect(String answer) { + public boolean answerCorrect(String answer) { return isKeyCorrect(answer); } - /** {@inheritDoc} */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} CI/CD based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CICD.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private boolean isKeyCorrect(String base64EncodedKey) { if (Strings.isNullOrEmpty(base64EncodedKey) || !isBase64(base64EncodedKey) diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge14.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge14.java index f622a6a87..4044643e1 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge14.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge14.java @@ -6,7 +6,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.linguafranca.pwdb.Database; import org.linguafranca.pwdb.kdbx.KdbxCreds; @@ -14,42 +13,29 @@ import org.linguafranca.pwdb.kdbx.simple.SimpleEntry; import org.linguafranca.pwdb.kdbx.simple.SimpleGroup; import org.linguafranca.pwdb.kdbx.simple.SimpleIcon; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a weak password for your password manager. */ @Slf4j @Component -@Order(14) -public class Challenge14 extends Challenge { +public class Challenge14 implements Challenge { private final String keepassxPassword; private final String defaultKeepassValue; private final String filePath; public Challenge14( - ScoreCard scoreCard, @Value("${keepasxpassword}") String keepassxPassword, @Value("${KEEPASS_BROKEN}") String defaultKeepassValue, @Value("${keepasspath}") String filePath) { - super(scoreCard); this.keepassxPassword = keepassxPassword; this.defaultKeepassValue = defaultKeepassValue; this.filePath = filePath; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -58,33 +44,10 @@ public Spoiler spoiler() { /** {@inheritDoc} */ @Override - protected boolean answerCorrect(String answer) { + public boolean answerCorrect(String answer) { return isanswerCorrectInKeeyPassx(answer); } - /** {@inheritDoc} */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; - } - - /** {@inheritDoc} Password manager based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.PASSWORD_MANAGER.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - @SuppressFBWarnings("PATH_TRAVERSAL_IN") private String findAnswer() { if (Strings.isNullOrEmpty(keepassxPassword)) { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge15.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge15.java index a830f6465..e50ac67ea 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge15.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge15.java @@ -4,42 +4,29 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about AWS keys in git history, with actual canarytokens. */ @Slf4j @Component -@Order(15) -public class Challenge15 extends Challenge { +public class Challenge15 implements Challenge { private final String ciphterText; private final String encryptionKey; - public Challenge15(ScoreCard scoreCard, @Value("${challenge15ciphertext}") String ciphterText) { - super(scoreCard); + public Challenge15(@Value("${challenge15ciphertext}") String ciphterText) { this.ciphterText = ciphterText; encryptionKey = Base64.getEncoder().encodeToString("this is it for now".getBytes(StandardCharsets.UTF_8)); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -48,34 +35,11 @@ public Spoiler spoiler() { /** {@inheritDoc} */ @Override - protected boolean answerCorrect(String answer) { + public boolean answerCorrect(String answer) { String correctString = quickDecrypt(ciphterText); return answer.equals(correctString) || minimummatch_found(answer); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Git based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.GIT.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private boolean minimummatch_found(String answer) { if (!Strings.isNullOrEmpty(answer)) { if (answer.length() < 19) { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge16.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge16.java index bcf4380f2..9097d2d02 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge16.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge16.java @@ -4,37 +4,23 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a secret obfuscated in the front-end code. */ @Slf4j @Component -@Order(16) -public class Challenge16 extends Challenge { +public class Challenge16 implements Challenge { private final String dockerMountPath; - public Challenge16( - ScoreCard scoreCard, @Value("${challengedockermtpath}") String dockerMountPath) { - super(scoreCard); + public Challenge16(@Value("${challengedockermtpath}") String dockerMountPath) { this.dockerMountPath = dockerMountPath; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -48,29 +34,6 @@ public boolean answerCorrect(String answer) { return getActualData().equals(answer); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} Frontend based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.FRONTEND.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - @SuppressFBWarnings( value = "PATH_TRAVERSAL_IN", justification = "The location of the dockerMountPath is based on an Env Var") diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge17.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge17.java index ac6511159..dd563a4eb 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge17.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge17.java @@ -4,37 +4,23 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having secrets in copied in bash history as part of a container. */ @Slf4j @Component -@Order(17) -public class Challenge17 extends Challenge { +public class Challenge17 implements Challenge { private final String dockerMountPath; - public Challenge17( - ScoreCard scoreCard, @Value("${challengedockermtpath}") String dockerMountPath) { - super(scoreCard); + public Challenge17(@Value("${challengedockermtpath}") String dockerMountPath) { this.dockerMountPath = dockerMountPath; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -47,29 +33,6 @@ public boolean answerCorrect(String answer) { return getActualData().equals(answer); } - /** {@inheritDoc} */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} Docker based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCKER.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - @SuppressFBWarnings( value = "PATH_TRAVERSAL_IN", justification = "The location of the dockerMountPath is based on an Env Var") diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge18.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge18.java index 81047b5d5..9fffc50ea 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge18.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge18.java @@ -1,44 +1,29 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.security.crypto.codec.Hex; import org.springframework.stereotype.Component; /** This challenge is about finding the value of a secret through weak hash mechanisms. */ -@Component -@Order(18) @Slf4j -public class Challenge18 extends Challenge { +@Component +public class Challenge18 implements Challenge { private final String hashPassword; private static final String md5Hash = "MD5"; private static final String sha1Hash = "SHA1"; - public Challenge18(ScoreCard scoreCard, @Value("aHVudGVyMg==") String hashPassword) { - super(scoreCard); + public Challenge18(@Value("aHVudGVyMg==") String hashPassword) { this.hashPassword = hashPassword; } - @Override - public boolean canRunInCTFMode() { - return true; - } - private String base64Decode(String base64) { byte[] decodedBytes = Base64.getDecoder().decode(base64); return new String(decodedBytes, StandardCharsets.UTF_8); @@ -69,26 +54,4 @@ public boolean answerCorrect(String answer) { || calculateHash(sha1Hash, base64Decode(hashPassword)) .equals(calculateHash(sha1Hash, answer)); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.MASTER; - } - - /** {@inheritDoc} Cryptography based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge19.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge19.java index 3714d5a42..53285d78a 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge19.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge19.java @@ -1,38 +1,23 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a C binary. */ -@Component -@Order(19) @Slf4j -public class Challenge19 extends Challenge { +@Component +public class Challenge19 implements Challenge { private final BinaryExecutionHelper binaryExecutionHelper; - public Challenge19(ScoreCard scoreCard) { - super(scoreCard); + public Challenge19() { this.binaryExecutionHelper = new BinaryExecutionHelper(19, new MuslDetectorImpl()); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -46,26 +31,4 @@ public boolean answerCorrect(String answer) { .executeCommand(answer, "wrongsecrets-c") .equals("This is correct! Congrats!"); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; - } - - /** {@inheritDoc} Binary based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.BINARY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge2.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge2.java index b4b6d4e0e..01bab1057 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge2.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge2.java @@ -1,16 +1,8 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** @@ -19,28 +11,19 @@ * The javadoc is generated using ChatGPT. */ @Component -@Order(2) -public class Challenge2 extends Challenge { +public class Challenge2 implements Challenge { private final String hardcodedPassword; /** * Constructor for creating a new Challenge2 object. * - * @param scoreCard The scorecard object used for tracking points. * @param hardcodedPassword The hardcoded password for the challenge. */ - public Challenge2(ScoreCard scoreCard, @Value("${password}") String hardcodedPassword) { - super(scoreCard); + public Challenge2(@Value("${password}") String hardcodedPassword) { this.hardcodedPassword = hardcodedPassword; } - /** {@inheritDoc} This challenge can always run in CTF mode. */ - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -58,27 +41,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return hardcodedPassword.equals(answer); } - - /** {@inheritDoc} This challenge supports the Docker runtime environment. */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Git based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.GIT.id; - } - - /** {@inheritDoc} This challenge is not limited when hosted online. */ - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge20.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge20.java index f33294304..0b2d983a1 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge20.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge20.java @@ -1,38 +1,23 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a C++ binary. */ -@Component -@Order(20) @Slf4j -public class Challenge20 extends Challenge { +@Component +public class Challenge20 implements Challenge { private final BinaryExecutionHelper binaryExecutionHelper; - public Challenge20(ScoreCard scoreCard) { - super(scoreCard); + public Challenge20() { this.binaryExecutionHelper = new BinaryExecutionHelper(20, new MuslDetectorImpl()); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -46,26 +31,4 @@ public boolean answerCorrect(String answer) { .executeCommand(answer, "wrongsecrets-cplus") .equals("This is correct! Congrats!"); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; - } - - /** {@inheritDoc} Binary based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.BINARY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge21.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge21.java index 46267e296..8c25ed482 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge21.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge21.java @@ -1,38 +1,23 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a Golang binary. */ -@Component -@Order(21) @Slf4j -public class Challenge21 extends Challenge { +@Component +public class Challenge21 implements Challenge { private final BinaryExecutionHelper binaryExecutionHelper; - public Challenge21(ScoreCard scoreCard) { - super(scoreCard); + public Challenge21() { this.binaryExecutionHelper = new BinaryExecutionHelper(21, new MuslDetectorImpl()); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -44,26 +29,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return binaryExecutionHelper.executeGoCommand(answer).equals("This is correct! Congrats!"); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.MASTER; - } - - /** {@inheritDoc} Binary based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.BINARY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge22.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge22.java index edafcdf7c..2cfef6442 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge22.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge22.java @@ -1,38 +1,23 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a Rust binary. */ -@Component -@Order(22) @Slf4j -public class Challenge22 extends Challenge { +@Component +public class Challenge22 implements Challenge { private final BinaryExecutionHelper binaryExecutionHelper; - public Challenge22(ScoreCard scoreCard) { - super(scoreCard); + public Challenge22() { this.binaryExecutionHelper = new BinaryExecutionHelper(22, new MuslDetectorImpl()); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -46,26 +31,4 @@ public boolean answerCorrect(String answer) { .executeCommand(answer, "wrongsecrets-rust") .equals("This is correct! Congrats!"); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.MASTER; - } - - /** {@inheritDoc} Binary based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.BINARY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge23.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge23.java index 393c885c1..d2a506f20 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge23.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge23.java @@ -1,28 +1,17 @@ package org.owasp.wrongsecrets.challenges.docker; import java.nio.charset.StandardCharsets; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in comments in a front-end. */ @Slf4j @Component -@Order(23) -public class Challenge23 extends Challenge { - - public Challenge23(ScoreCard scoreCard) { - super(scoreCard); - } +public class Challenge23 implements Challenge { /** {@inheritDoc} */ @Override @@ -37,34 +26,6 @@ public boolean answerCorrect(String answer) { return getActualData().equals(answer); } - @Override - public boolean canRunInCTFMode() { - return true; - } - - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Frontend based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.FRONTEND.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - public String getActualData() { return new String( Base64.decode( diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge24.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge24.java index 9b542c56b..d43a383c9 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge24.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge24.java @@ -1,32 +1,16 @@ package org.owasp.wrongsecrets.challenges.docker; import java.nio.charset.StandardCharsets; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about using a publicly specified key to safeguard data. */ @Slf4j @Component -@Order(24) -public class Challenge24 extends Challenge { - - public Challenge24(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge24 implements Challenge { /** {@inheritDoc} */ @Override @@ -40,29 +24,6 @@ public boolean answerCorrect(String answer) { return getActualData().equals(answer); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Cryptography based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - public String getActualData() { return new String( Hex.decode( diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge25.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge25.java index f2d7378c9..289699bb0 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge25.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge25.java @@ -2,40 +2,27 @@ import java.nio.charset.StandardCharsets; import java.security.spec.AlgorithmParameterSpec; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a web3 contract. */ @Slf4j @Component -@Order(25) -public class Challenge25 extends Challenge { +public class Challenge25 implements Challenge { private final String cipherText; - public Challenge25(ScoreCard scoreCard, @Value("${challenge25ciphertext}") String cipherText) { - super(scoreCard); + public Challenge25(@Value("${challenge25ciphertext}") String cipherText) { this.cipherText = cipherText; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -49,29 +36,6 @@ public boolean answerCorrect(String answer) { return answer.equals(correctString); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Web3 based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.WEB3.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private String quickDecrypt(String cipherText) { try { final Cipher decryptor = Cipher.getInstance("AES/GCM/NoPadding"); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java index 360ede4fa..1bbfa60e4 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java @@ -2,40 +2,27 @@ import java.nio.charset.StandardCharsets; import java.security.spec.AlgorithmParameterSpec; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a web3 contract. */ @Slf4j @Component -@Order(26) -public class Challenge26 extends Challenge { +public class Challenge26 implements Challenge { private final String cipherText; - public Challenge26(ScoreCard scoreCard, @Value("${challenge26ciphertext}") String cipherText) { - super(scoreCard); + public Challenge26(@Value("${challenge26ciphertext}") String cipherText) { this.cipherText = cipherText; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -49,29 +36,6 @@ public boolean answerCorrect(String answer) { return answer.equals(correctString); } - /** {@inheritDoc} */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Web3 based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.WEB3.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private String quickDecrypt(String cipherText) { try { final Cipher decryptor = Cipher.getInstance("AES/GCM/NoPadding"); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java index 515e5346d..998164525 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java @@ -2,40 +2,27 @@ import java.nio.charset.StandardCharsets; import java.security.spec.AlgorithmParameterSpec; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret hardcoded in a web3 contract based on hashing. */ @Slf4j @Component -@Order(26) -public class Challenge27 extends Challenge { +public class Challenge27 implements Challenge { private final String cipherText; - public Challenge27(ScoreCard scoreCard, @Value("${challenge27ciphertext}") String cipherText) { - super(scoreCard); + public Challenge27(@Value("${challenge27ciphertext}") String cipherText) { this.cipherText = cipherText; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -49,29 +36,6 @@ public boolean answerCorrect(String answer) { return answer.equals(correctString); } - @Override - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} This is a normal level challenge */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Web3 based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.WEB3.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private String quickDecrypt(String cipherText) { try { final Cipher decryptor = Cipher.getInstance("AES/GCM/NoPadding"); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge28.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge28.java index 7ad7f97cf..f78cf1a69 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge28.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge28.java @@ -1,32 +1,15 @@ package org.owasp.wrongsecrets.challenges.docker; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; -import java.util.List; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret in a Github issue. */ @Component -@Order(28) -public class Challenge28 extends Challenge { - - public Challenge28(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge28 implements Challenge { /** {@inheritDoc} */ @Override @@ -40,28 +23,6 @@ public boolean answerCorrect(String answer) { return getSecretKey().equals(answer); } - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} This is an easy challenge */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Documentation based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCUMENTATION.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private String getSecretKey() { return new String( Base64.decode( diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge29.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge29.java index b31a06e2e..a97e548f5 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge29.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge29.java @@ -1,7 +1,5 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -10,32 +8,16 @@ import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; -import java.util.List; import javax.crypto.Cipher; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about finding a secret in a Github issue (screenshot). */ -@Component @Slf4j -@Order(29) -public class Challenge29 extends Challenge { - - public Challenge29(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +@Component +public class Challenge29 implements Challenge { @Override public Spoiler spoiler() { @@ -47,27 +29,6 @@ public boolean answerCorrect(String answer) { return decryptActualAnswer().equals(answer); } - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Documentation based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCUMENTATION.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - private byte[] decode(byte[] encoded, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge3.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge3.java index b5891fc92..8c6f3ed9e 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge3.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge3.java @@ -1,39 +1,22 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** * This challenge can be run in CTF mode and is limited to using Docker as a runtime environment. */ @Component -@Order(3) -public class Challenge3 extends Challenge { +public class Challenge3 implements Challenge { private final String hardcodedEnvPassword; - public Challenge3( - ScoreCard scoreCard, @Value("${DOCKER_ENV_PASSWORD}") String hardcodedEnvPassword) { - super(scoreCard); + public Challenge3(@Value("${DOCKER_ENV_PASSWORD}") String hardcodedEnvPassword) { this.hardcodedEnvPassword = hardcodedEnvPassword; } - /** {@inheritDoc} */ - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -45,26 +28,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return hardcodedEnvPassword.equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Docker based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCKER.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge31.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge31.java index 31f333b85..82a4b364a 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge31.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge31.java @@ -1,27 +1,15 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.List; import java.util.UUID; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -/** This challenge is about finding a secret in website */ +/** This challenge is about finding a secret in website. */ @Component -@Order(31) -public class Challenge31 extends Challenge { - - public Challenge31(ScoreCard scoreCard) { - super(scoreCard); - } +public class Challenge31 implements Challenge { private String getanswer() { String str = "vozvtbeY6++kjJz3tPn84LeM77I="; @@ -49,11 +37,6 @@ private String getanswer() { return new String(xoredBytes, StandardCharsets.UTF_8); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -65,26 +48,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return getanswer().equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return 1; - } - - /** {@inheritDoc} Documentation based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCUMENTATION.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge32.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge32.java index d1df02a1a..c9b9b3611 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge32.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge32.java @@ -2,20 +2,14 @@ import java.nio.charset.StandardCharsets; import java.security.spec.AlgorithmParameterSpec; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** @@ -24,17 +18,7 @@ */ @Slf4j @Component -@Order(32) -public class Challenge32 extends Challenge { - - public Challenge32(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge32 implements Challenge { @Override public Spoiler spoiler() { @@ -46,28 +30,6 @@ public boolean answerCorrect(String answer) { return getSolution().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} This is an AI type of challenge */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.AI.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - private String getSolution() { return decrypt( decrypt( diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge34.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge34.java index bd4f30b17..d7f8eef3e 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge34.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge34.java @@ -1,15 +1,9 @@ package org.owasp.wrongsecrets.challenges.docker; import com.google.common.base.Strings; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.springframework.stereotype.Component; @@ -19,20 +13,10 @@ */ @Slf4j @Component -@Order(34) -public class Challenge34 extends Challenge { +public class Challenge34 implements Challenge { private String key; - public Challenge34(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(getKey()); @@ -43,28 +27,6 @@ public boolean answerCorrect(String answer) { return getKey().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} This is a crypto (hashing) type of challenge */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - private String getKey() { if (Strings.isNullOrEmpty(key)) { key = generateKey(); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge35.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge35.java index df99341be..2a9e92acb 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge35.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge35.java @@ -4,7 +4,6 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.List; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; @@ -13,29 +12,14 @@ import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This is a challenge based on the idea of leaking a secret trough a vulnerability report. */ @Slf4j @Component -@Order(35) -public class Challenge35 extends Challenge { - - public Challenge35(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge35 implements Challenge { @Override public Spoiler spoiler() { @@ -47,28 +31,6 @@ public boolean answerCorrect(String answer) { return getKey().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} This is a Documentation type of challenge */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCUMENTATION.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - private String getKey() { String ciphertext = "zRR77ETjg5GsXv3az1TZU73xiFWYHbVceJBvBbjChxLyMjHkF6kFdwIXIduVBHAT"; try { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge36.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge36.java index 0aaf264d7..645763c53 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge36.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge36.java @@ -1,39 +1,26 @@ package org.owasp.wrongsecrets.challenges.docker; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper; import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** - * This is a binary based challenge with encryption involved to make it harder to find the answer + * This is a binary based challenge with encryption involved to make it harder to find the answer. */ @Slf4j @Component -@Order(36) // make sure this number is the same as your challenge -public class Challenge36 extends Challenge { +public class Challenge36 implements Challenge { private final BinaryExecutionHelper binaryExecutionHelper; private String executable; - public Challenge36(ScoreCard scoreCard) { - super(scoreCard); + public Challenge36() { this.executable = "wrongsecrets-advanced-c"; this.binaryExecutionHelper = new BinaryExecutionHelper(36, new MuslDetectorImpl()); } - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(binaryExecutionHelper.executeCommand("spoil", executable)); @@ -45,27 +32,4 @@ public boolean answerCorrect(String answer) { .executeCommand(answer, executable) .equals("This is correct! Congrats!"); } - - /** {@inheritDoc} This is a Docker based challenge */ - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - - /** {@inheritDoc} This is a 5 star challenge */ - @Override - public int difficulty() { - return Difficulty.MASTER; - } - - /** {@inheritDoc} This is a binary based challenge. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.BINARY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge37.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge37.java index 04363cc8f..f9ff2f775 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge37.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge37.java @@ -2,19 +2,13 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.List; import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; import org.owasp.wrongsecrets.BasicAuthentication; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.context.annotation.Bean; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** @@ -23,14 +17,12 @@ */ @Slf4j @Component -@Order(37) -public class Challenge37 extends Challenge { +public class Challenge37 implements Challenge { private String secret; private static final String password = "YjNCbGJpQnpaWE5oYldVPQo="; - public Challenge37(ScoreCard scoreCard) { - super(scoreCard); + public Challenge37() { secret = UUID.randomUUID().toString(); } @@ -45,11 +37,6 @@ public BasicAuthentication challenge37BasicAuth() { "authenticated/**"); } - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(secret); @@ -60,27 +47,6 @@ public boolean answerCorrect(String answer) { return secret.equals(answer); } - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} This is a CICD type of challenge */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CICD.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - public String getPassword() { return new String(Base64.decode(Base64.decode(Base64.decode(password))), StandardCharsets.UTF_8) diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge38.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge38.java index 6125eb97d..67a3d2d16 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge38.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge38.java @@ -1,28 +1,12 @@ package org.owasp.wrongsecrets.challenges.docker; -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -/** This is a challenge based on leaking secrets with the misuse of Git notes */ +/** This is a challenge based on leaking secrets with the misuse of Git notes. */ @Component -@Order(38) -public class Challenge38 extends Challenge { - - public Challenge38(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } +public class Challenge38 implements Challenge { @Override public Spoiler spoiler() { @@ -34,28 +18,6 @@ public boolean answerCorrect(String answer) { return getSolution().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Git based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.GIT.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - private String getSolution() { return unobfuscate("UOZFGZTLOLLXHTKEGGS"); } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge39.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge39.java index b7a50108c..baa94374d 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge39.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge39.java @@ -4,41 +4,29 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.annotation.Order; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; -/** This is a challenge based on leaking secrets due to choice of filename as encryption key */ +/** This is a challenge based on leaking secrets due to choice of filename as encryption key. */ @Slf4j @Component @Order(39) -public class Challenge39 extends Challenge { +public class Challenge39 implements Challenge { private final Resource resource; - public Challenge39( - ScoreCard scoreCard, @Value("classpath:executables/secrchallenge.md") Resource resource) { - super(scoreCard); + public Challenge39(@Value("classpath:executables/secrchallenge.md") Resource resource) { this.resource = resource; } - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(getSolution()); @@ -49,28 +37,6 @@ public boolean answerCorrect(String answer) { return getSolution().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Cryptography based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - @SuppressFBWarnings( value = {"CIPHER_INTEGRITY", "ECB_MODE"}, justification = "This is to allow for easy ECB online decryptors") diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge4.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge4.java index 37f1f8cb9..a751a3607 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge4.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge4.java @@ -1,36 +1,20 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a secrets stored as a Docker ARG var. */ @Component -@Order(4) -public class Challenge4 extends Challenge { +public class Challenge4 implements Challenge { private final String argBasedPassword; - public Challenge4(ScoreCard scoreCard, @Value("${ARG_BASED_PASSWORD}") String argBasedPassword) { - super(scoreCard); + public Challenge4(@Value("${ARG_BASED_PASSWORD}") String argBasedPassword) { this.argBasedPassword = argBasedPassword; } - @Override - public boolean canRunInCTFMode() { - return true; - } - - /** {@inheritDoc} */ @Override public Spoiler spoiler() { return new Spoiler(argBasedPassword); @@ -41,26 +25,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return argBasedPassword.equals(answer) || argBasedPassword.equals("'" + answer + "'"); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Docker based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.DOCKER.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge40.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge40.java index 7e809d8c9..6701e1fdc 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge40.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge40.java @@ -6,44 +6,30 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; /** * This is a challenge based on leaking secrets due to keeping the encryption key and secret - * together + * together. */ @Slf4j @Component -@Order(40) -public class Challenge40 extends Challenge { +public class Challenge40 implements Challenge { private final Resource resource; - public Challenge40( - ScoreCard scoreCard, @Value("classpath:executables/secrchallenge.json") Resource resource) { - super(scoreCard); + public Challenge40(@Value("classpath:executables/secrchallenge.json") Resource resource) { this.resource = resource; } - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(getSolution()); @@ -54,28 +40,6 @@ public boolean answerCorrect(String answer) { return getSolution().equals(answer); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EASY; - } - - /** {@inheritDoc} Cryptography based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - @SuppressFBWarnings( value = {"CIPHER_INTEGRITY", "ECB_MODE"}, justification = "This is to allow for easy ECB online decryptors") diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge41.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge41.java index 7abdfc7a1..4b562fe97 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge41.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge41.java @@ -5,64 +5,31 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.annotation.Order; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Component; -/** This is a challenge based on finding secret using password shucking */ +/** This is a challenge based on finding secret using password shucking. */ @Slf4j @Component @Order(41) -public class Challenge41 extends Challenge { +public class Challenge41 implements Challenge { private final String password; - public Challenge41(ScoreCard scoreCard, @Value("${challenge41password}") String password) { - super(scoreCard); + public Challenge41(@Value("${challenge41password}") String password) { this.password = password; } - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { return new Spoiler(base64Decode(password)); } - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.HARD; - } - - /** {@inheritDoc} Cryptography based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CRYPTOGRAPHY.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } - @Override public boolean answerCorrect(String answer) { try { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge8.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge8.java index e1fd5c3c3..797dcf6fd 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge8.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge8.java @@ -1,27 +1,18 @@ package org.owasp.wrongsecrets.challenges.docker; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.DOCKER; - import com.google.api.client.util.Strings; import java.security.SecureRandom; -import java.util.List; import java.util.Random; import lombok.extern.slf4j.Slf4j; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** Challenge which leaks the data in the logs instead of anywhere else. */ @Slf4j @Component -@Order(8) -public class Challenge8 extends Challenge { +public class Challenge8 implements Challenge { private static final String alphabet = "0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"; @@ -29,9 +20,7 @@ public class Challenge8 extends Challenge { private final Random secureRandom = new SecureRandom(); private final String randomValue; - public Challenge8( - ScoreCard scoreCard, @Value("${challenge_acht_ctf_host_value}") String serverCode) { - super(scoreCard); + public Challenge8(@Value("${challenge_acht_ctf_host_value}") String serverCode) { if (!Strings.isNullOrEmpty(serverCode) && !serverCode.equals("not_set")) { randomValue = serverCode; } else { @@ -40,11 +29,6 @@ public Challenge8( log.info("Initializing challenge 8 with random value {}", randomValue); } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -57,28 +41,6 @@ public boolean answerCorrect(String answer) { return randomValue.equals(answer); } - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(DOCKER); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Challenge is wrapped around logging */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.LOGGING.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return true; - } - private String generateRandomString() { final int length = 10; StringBuilder builder = new StringBuilder(length); diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/authchallenge/AuthenticatedRestControllerChallenge37.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/authchallenge/AuthenticatedRestControllerChallenge37.java index 204920b9d..0ef054fa3 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/authchallenge/AuthenticatedRestControllerChallenge37.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/authchallenge/AuthenticatedRestControllerChallenge37.java @@ -1,21 +1,19 @@ package org.owasp.wrongsecrets.challenges.docker.authchallenge; import io.swagger.v3.oas.annotations.Operation; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.owasp.wrongsecrets.challenges.docker.Challenge37; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @Slf4j +@AllArgsConstructor @RestController public class AuthenticatedRestControllerChallenge37 { private final Challenge37 challenge37; - public AuthenticatedRestControllerChallenge37(Challenge37 challenge37) { - this.challenge37 = challenge37; - } - @Operation(summary = "Endpoint for interaction at challenge 37") @GetMapping("/authenticated/challenge37") public String getAuthSecret() { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge30.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/Challenge30.java similarity index 54% rename from src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge30.java rename to src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/Challenge30.java index 0322a011e..da63c0f86 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge30.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/Challenge30.java @@ -1,24 +1,17 @@ -package org.owasp.wrongsecrets.challenges.docker; +package org.owasp.wrongsecrets.challenges.docker.challenge30; import com.google.common.base.Strings; import java.security.SecureRandom; -import java.util.List; import java.util.Random; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** * This is a localstorage based challenge to educate people on the use of localstorage and secrets. */ @Component -@Order(30) -public class Challenge30 extends Challenge { +public class Challenge30 implements Challenge { private final Random secureRandom = new SecureRandom(); private static final String alphabet = "0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"; @@ -32,15 +25,6 @@ private String generateRandomString(int length) { return new String(builder); } - public Challenge30(ScoreCard scoreCard) { - super(scoreCard); - } - - @Override - public boolean canRunInCTFMode() { - return true; - } - @Override public Spoiler spoiler() { if (Strings.isNullOrEmpty(solution)) { @@ -56,26 +40,4 @@ public boolean answerCorrect(String answer) { } return solution.equals(answer); } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} This is a front-end / web type of challenge */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.FRONTEND.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.DOCKER); - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeRestController.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/ChallengeRestController.java similarity index 85% rename from src/main/java/org/owasp/wrongsecrets/challenges/ChallengeRestController.java rename to src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/ChallengeRestController.java index 615462fbb..a8935f0f8 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/ChallengeRestController.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/challenge30/ChallengeRestController.java @@ -1,7 +1,6 @@ -package org.owasp.wrongsecrets.challenges; +package org.owasp.wrongsecrets.challenges.docker.challenge30; import io.swagger.v3.oas.annotations.Hidden; -import org.owasp.wrongsecrets.challenges.docker.Challenge30; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge33.java b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge33.java index 6996fff6b..cf713eaea 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge33.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge33.java @@ -1,39 +1,29 @@ package org.owasp.wrongsecrets.challenges.kubernetes; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.K8S; - import com.google.common.base.Strings; import java.nio.charset.StandardCharsets; import java.security.spec.AlgorithmParameterSpec; -import java.util.List; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** - * Challenge that teaches something about converting/migrating a secret while opening the metadata + * Challenge that teaches something about converting/migrating a secret while opening the metadata. */ @Slf4j @Component -@Order(33) -public class Challenge33 extends Challenge { +public class Challenge33 implements Challenge { private final String secretSecret; - public Challenge33(ScoreCard scoreCard, @Value("${CHALLENGE33}") String secretSecret) { - super(scoreCard); + public Challenge33(@Value("${CHALLENGE33}") String secretSecret) { this.secretSecret = secretSecret; } @@ -43,35 +33,10 @@ public Spoiler spoiler() { } @Override - protected boolean answerCorrect(String answer) { + public boolean answerCorrect(String answer) { return getSolution().equals(answer); } - @Override - public List supportedRuntimeEnvironments() { - return List.of(K8S); - } - - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - @Override - public String getTech() { - return ChallengeTechnology.Tech.SECRETS.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } - - @Override - public boolean canRunInCTFMode() { - return true; - } - private String getSolution() { if ("if_you_see_this_please_use_k8s".equals(secretSecret) || Strings.isNullOrEmpty(secretSecret)) { diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge5.java b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge5.java index 7fde520f4..57f385fd4 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge5.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge5.java @@ -1,36 +1,20 @@ package org.owasp.wrongsecrets.challenges.kubernetes; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.K8S; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a secrets stored as a K8s Configmap. */ @Component -@Order(5) -public class Challenge5 extends Challenge { +public class Challenge5 implements Challenge { private final String configmapK8sSecret; - public Challenge5( - ScoreCard scoreCard, @Value("${SPECIAL_K8S_SECRET}") String configmapK8sSecret) { - super(scoreCard); + public Challenge5(@Value("${SPECIAL_K8S_SECRET}") String configmapK8sSecret) { this.configmapK8sSecret = configmapK8sSecret; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -42,26 +26,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return configmapK8sSecret.equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(K8S); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} Configmaps based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.CONFIGMAPS.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return true; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge6.java b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge6.java index 756cd9a5f..ed316d3d1 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge6.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge6.java @@ -1,36 +1,20 @@ package org.owasp.wrongsecrets.challenges.kubernetes; -import static org.owasp.wrongsecrets.RuntimeEnvironment.Environment.K8S; - -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a secrets stored as a K8s Secret. */ @Component -@Order(6) -public class Challenge6 extends Challenge { +public class Challenge6 implements Challenge { private final String secretK8sSecret; - public Challenge6( - ScoreCard scoreCard, @Value("${SPECIAL_SPECIAL_K8S_SECRET}") String secretK8sSecret) { - super(scoreCard); + public Challenge6(@Value("${SPECIAL_SPECIAL_K8S_SECRET}") String secretK8sSecret) { this.secretK8sSecret = secretK8sSecret; } - @Override - public boolean canRunInCTFMode() { - return true; - } - /** {@inheritDoc} */ @Override public Spoiler spoiler() { @@ -42,26 +26,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return secretK8sSecret.equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(K8S); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.NORMAL; - } - - /** {@inheritDoc} K8s secrets based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.SECRETS.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return true; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge7.java b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge7.java index b4085fd03..31dede81a 100644 --- a/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge7.java +++ b/src/main/java/org/owasp/wrongsecrets/challenges/kubernetes/Challenge7.java @@ -1,39 +1,24 @@ package org.owasp.wrongsecrets.challenges.kubernetes; import com.google.common.base.Strings; -import java.util.List; -import org.owasp.wrongsecrets.RuntimeEnvironment; -import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; -import org.owasp.wrongsecrets.challenges.ChallengeTechnology; -import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** This challenge is about having a secrets stored in a misconfigured Hashicorp Vault. */ @Component -@Order(7) -public class Challenge7 extends Challenge { +public class Challenge7 implements Challenge { private final Vaultpassword vaultPassword; private final String vaultPasswordString; public Challenge7( - ScoreCard scoreCard, - Vaultpassword vaultPassword, - @Value("${vaultpassword}") String vaultPasswordString) { - super(scoreCard); + Vaultpassword vaultPassword, @Value("${vaultpassword}") String vaultPasswordString) { this.vaultPassword = vaultPassword; this.vaultPasswordString = vaultPasswordString; } - @Override - public boolean canRunInCTFMode() { - return true; - } - private String getAnswer() { return vaultPassword != null && !Strings.isNullOrEmpty(vaultPassword.getPasssword()) ? vaultPassword.getPasssword() @@ -51,26 +36,4 @@ public Spoiler spoiler() { public boolean answerCorrect(String answer) { return getAnswer().equals(answer); } - - /** {@inheritDoc} */ - public List supportedRuntimeEnvironments() { - return List.of(RuntimeEnvironment.Environment.VAULT); - } - - /** {@inheritDoc} */ - @Override - public int difficulty() { - return Difficulty.EXPERT; - } - - /** {@inheritDoc} Vault based. */ - @Override - public String getTech() { - return ChallengeTechnology.Tech.VAULT.id; - } - - @Override - public boolean isLimitedWhenOnlineHosted() { - return false; - } } diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeCategory.java b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeCategory.java new file mode 100644 index 000000000..8fe0a1e93 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeCategory.java @@ -0,0 +1,8 @@ +package org.owasp.wrongsecrets.definitions; + +/** + * Defines the category of a challenge. + * + * @param category the category of the challenge as defined in the yaml configuration + */ +public record ChallengeCategory(String category) {} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeConfig.java b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeConfig.java new file mode 100644 index 000000000..b07b9c614 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeConfig.java @@ -0,0 +1,79 @@ +package org.owasp.wrongsecrets.definitions; + +import java.io.IOException; +import java.util.List; +import java.util.function.Supplier; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FilenameUtils; +import org.owasp.wrongsecrets.Challenges; +import org.owasp.wrongsecrets.asciidoc.TemplateGenerator; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.definitions.Sources.TextWithFileLocation; +import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +@Configuration +@Slf4j +@EnableConfigurationProperties(ChallengeDefinitionsConfiguration.class) +public class ChallengeConfig { + + /** + * Define a converter for {@link TextWithFileLocation} which reads the source location from the + * configuration and reads the file contents. This way we only have to read the files once. + * + * @param templateGenerator the template generator + * @return {@link StringToChallengeNameConverter} + */ + @ConfigurationPropertiesBinding + @Bean + public TextWithFileLocationConverter textConverter(TemplateGenerator templateGenerator) { + return new TextWithFileLocationConverter(templateGenerator); + } + + @ConfigurationPropertiesBinding + @Bean + public StringToChallengeNameConverter nameConverter() { + return new StringToChallengeNameConverter(); + } + + private record TextWithFileLocationConverter(TemplateGenerator templateGenerator) + implements Converter { + + @Override + public TextWithFileLocation convert(String source) { + return new TextWithFileLocation(source, read(source)); + } + + private Supplier read(String name) { + return () -> { + try { + return templateGenerator.generate(FilenameUtils.removeExtension(name)); + } catch (IOException e) { + return ""; + } + }; + } + } + + private record StringToChallengeNameConverter() implements Converter { + + @Override + public ChallengeName convert(String name) { + return new ChallengeName(name, name.strip().replace(" ", "-").toLowerCase()); + } + } + + @Bean + public Challenges challenges( + ChallengeDefinitionsConfiguration challengeDefinitions, List challenges) { + log.info( + "Loaded {} definitions and {} challenges", + challengeDefinitions.challenges().size(), + challenges.size()); + + return new Challenges(challengeDefinitions, challenges); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinition.java b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinition.java new file mode 100644 index 000000000..29020c4c2 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinition.java @@ -0,0 +1,71 @@ +package org.owasp.wrongsecrets.definitions; + +import static java.util.stream.Collectors.toMap; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.definitions.Sources.ChallengeSource; + +/** + * We can define a challenge as follows: + * + *

+ *       challenges:
+ *     - name: Challenge 0
+ *       sources:
+ *         - class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge0"
+ *           hint: "explanation/challenge0_hint.adoc"
+ *           explanation: "explanation/challenge0.adoc"
+ *           reason: "explanation/challenge0_reason.adoc"
+ *           environments: *all_envs
+ *       difficulty: *easy
+ *       category: *intro
+ *       ctf:
+ *         enabled: true
+ * 
+ * + *

During runtime a {@link ChallengeDefinition} is linked to a {@link Challenge} instance. Be + * aware a challenge can have multiple sources. This is useful for having different implementations + * for different environments. For example, we can have a challenge which is implemented for AWS and + * Azure. This way you can define multiple challenge classes and the correct one is chosen during + * runtime. + */ +public record ChallengeDefinition( + ChallengeName name, + List sources, + Difficulty difficulty, + ChallengeCategory category, + Ctf ctf, + Sources environmentToSource) { + + @SuppressFBWarnings(value = "IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN") + public ChallengeDefinition { + environmentToSource = + new Sources( + sources.stream().collect(toMap(s -> s.environments(), s -> s)).entrySet().stream() + .flatMap( + entry -> entry.getKey().stream().map(env -> Map.entry(env, entry.getValue()))) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue))); + } + + public Sources challengeSources() { + return environmentToSource; + } + + public int difficulty(List difficulties) { + return difficulties.indexOf(difficulty) + 1; + } + + public Optional source(RuntimeEnvironment runtimeEnvironment) { + return environmentToSource.source(runtimeEnvironment); + } + + public Set supportedEnvironments() { + return environmentToSource().sources().keySet(); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinitionsConfiguration.java b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinitionsConfiguration.java new file mode 100644 index 000000000..4d19fe62d --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeDefinitionsConfiguration.java @@ -0,0 +1,18 @@ +package org.owasp.wrongsecrets.definitions; + +import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Represents the configuration part of the application. It consists of the global configuration and + * the challenges, which we call {@link ChallengeDefinition}. + * + *

The complete configuration is read from a yaml file and it uses {@link + * ConfigurationProperties}. This way we get full support for YAML anchors and references. + */ +@ConfigurationProperties(prefix = "configurations") +public record ChallengeDefinitionsConfiguration( + List difficulties, + List technologies, + List environments, + List challenges) {} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeName.java b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeName.java new file mode 100644 index 000000000..12a81f23d --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/ChallengeName.java @@ -0,0 +1,10 @@ +package org.owasp.wrongsecrets.definitions; + +/** + * Name of a challenge, @see {@link ChallengeConfig#nameConverter()} for more information. + * + * @param name the name of the challenge from the configuration, the full class name + * @param shortName the short name under which the challenge is available. Used in the URL for + * example. + */ +public record ChallengeName(String name, String shortName) {} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Ctf.java b/src/main/java/org/owasp/wrongsecrets/definitions/Ctf.java new file mode 100644 index 000000000..664c1e679 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Ctf.java @@ -0,0 +1,9 @@ +package org.owasp.wrongsecrets.definitions; + +/** + * Defines if a challenge is a CTF challenge or not. Later on we might add more types of challenges + * which needs to have more configuration, that's why we have this as a record. + * + * @param enabled true if the challenge is a CTF challenge + */ +public record Ctf(boolean enabled) {} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Difficulty.java b/src/main/java/org/owasp/wrongsecrets/definitions/Difficulty.java new file mode 100644 index 000000000..6b7a625fc --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Difficulty.java @@ -0,0 +1,9 @@ +package org.owasp.wrongsecrets.definitions; + +/** + * Defines the difficulty of a challenge, as defined in the yaml configuration. + * + * @param difficulty description of the difficulty level, see + * `src/main/resources/wrong-secrets-configuration.yml` + */ +public record Difficulty(String difficulty) {} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Environment.java b/src/main/java/org/owasp/wrongsecrets/definitions/Environment.java new file mode 100644 index 000000000..9f82d9bcc --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Environment.java @@ -0,0 +1,32 @@ +package org.owasp.wrongsecrets.definitions; + +import java.util.Objects; + +/** + * Defines an environment for a challenge. + * + * @param name the name of the environment used in the code + * @param ctf the name of the environment when used in the CTF context + * @param overview the name of the environment when used in the overview + * @param displayName the name of the environment when used in the UI + * @param missingEnvironment the location of the missing environment message + */ +public record Environment( + String name, + String ctf, + String overview, + String displayName, + Sources.TextWithFileLocation missingEnvironment) { + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Environment that = (Environment) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Navigator.java b/src/main/java/org/owasp/wrongsecrets/definitions/Navigator.java new file mode 100644 index 000000000..85d585a93 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Navigator.java @@ -0,0 +1,26 @@ +package org.owasp.wrongsecrets.definitions; + +import java.util.List; +import java.util.Optional; + +/** Encapsulate the navigation, we can optimise this later. */ +public record Navigator(List challenges, ChallengeDefinition current) { + + public Optional next() { + return navigate(1); + } + + public Optional previous() { + return navigate(-1); + } + + private Optional navigate(int direction) { + int index = challenges.indexOf(current); + int navigationIndex = index + direction; + + if (navigationIndex < 0 || navigationIndex >= challenges.size()) { + return Optional.empty(); + } + return Optional.of(challenges.get(navigationIndex)); + } +} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Sources.java b/src/main/java/org/owasp/wrongsecrets/definitions/Sources.java new file mode 100644 index 000000000..b1e30dcbe --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Sources.java @@ -0,0 +1,44 @@ +package org.owasp.wrongsecrets.definitions; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; +import org.owasp.wrongsecrets.ChallengeUiTemplateResolver; +import org.owasp.wrongsecrets.RuntimeEnvironment; + +/** + * We allow to define multiple sources for a challenge. This is useful for having different + * implementations for different environments. For example, we can have a challenge which is + * implemented for AWS and Azure. This way you can define multiple challenge classes and the correct + * one is chosen based on the runtime environment. The runtime environment is defined as environment + * variable or system property or in application.properties. + */ +public record Sources(Map sources) { + public Optional source(RuntimeEnvironment runtimeEnvironment) { + return Optional.ofNullable(sources.get(runtimeEnvironment.getRuntimeEnvironment())); + } + + /** + * Represent a single source for a challenge. + * + * @param className the name of the class which implements the challenge + * @param environments the environments for which this challenge should run on + * @param explanation the filename of the explanation + * @param reason the filename of the reason + * @param hint the filename of the hint + * @param hintLimited the filename of the hint when the user has limited access + * @param uiSnippet the filename of the UI snippet, this can be used to include JavaScript and is + * used by {@link ChallengeUiTemplateResolver} + */ + public record ChallengeSource( + String className, + List environments, + TextWithFileLocation explanation, + TextWithFileLocation reason, + TextWithFileLocation hint, + TextWithFileLocation hintLimited, + String uiSnippet) {} + + public record TextWithFileLocation(String fileName, Supplier contents) {} +} diff --git a/src/main/java/org/owasp/wrongsecrets/definitions/Technology.java b/src/main/java/org/owasp/wrongsecrets/definitions/Technology.java new file mode 100644 index 000000000..7c2c22532 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/definitions/Technology.java @@ -0,0 +1,4 @@ +package org.owasp.wrongsecrets.definitions; + +/** Defines a technology for a challenge. */ +public record Technology(String technology) {} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index 67b228fef..ed2b7a1bf 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1 +1,2 @@ -org.springframework.context.ApplicationListener=org.owasp.wrongsecrets.StartupListener +org.springframework.boot.diagnostics.FailureAnalyzer=\ + org.owasp.wrongsecrets.StartupFailureAnalyzer diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8191dac0c..90e2a7f58 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,6 +3,7 @@ #spring.devtools.restart.enabled=true spring.web.resources.cache.period=PT2H server.compression.enabled=true +spring.config.import=classpath:/wrong-secrets-configuration.yaml password=ThisEnvironmentIsAnotherPlaceToHide SPECIAL_K8S_SECRET=if_you_see_this_please_use_k8s diff --git a/src/main/resources/challenges/challenge-16/challenge-16.snippet b/src/main/resources/challenges/challenge-16/challenge-16.snippet new file mode 100644 index 000000000..b79e30cd7 --- /dev/null +++ b/src/main/resources/challenges/challenge-16/challenge-16.snippet @@ -0,0 +1,11 @@ + + + diff --git a/src/main/resources/challenges/challenge-30/challenge-30.snippet b/src/main/resources/challenges/challenge-30/challenge-30.snippet new file mode 100644 index 000000000..c56390602 --- /dev/null +++ b/src/main/resources/challenges/challenge-30/challenge-30.snippet @@ -0,0 +1,5 @@ + diff --git a/src/main/resources/challenges/missing_cloud.adoc b/src/main/resources/challenges/missing_cloud.adoc new file mode 100644 index 000000000..b1dd9ea29 --- /dev/null +++ b/src/main/resources/challenges/missing_cloud.adoc @@ -0,0 +1,2 @@ +We are running outside a properly configured Cloud environment. Please run this in an AWS/Azure/GCP environment as +explained in the https://github.com/OWASP/wrongsecrets#cloud-challenges[README.md] diff --git a/src/main/resources/challenges/missing_docker.adoc b/src/main/resources/challenges/missing_docker.adoc new file mode 100644 index 000000000..49059876c --- /dev/null +++ b/src/main/resources/challenges/missing_docker.adoc @@ -0,0 +1,2 @@ +We are running outside a docker container. +Please run this in a container as explained in the https://github.com/OWASP/wrongsecrets#basic-docker-exercises[README] diff --git a/src/main/resources/challenges/missing_k8s.adoc b/src/main/resources/challenges/missing_k8s.adoc new file mode 100644 index 000000000..4e7315753 --- /dev/null +++ b/src/main/resources/challenges/missing_k8s.adoc @@ -0,0 +1,3 @@ +We are running outside a K8s cluster. +Please run this in the K8s cluster as explained in the +https://github.com/OWASP/wrongsecrets#basic-k8s-exercise[README.md] diff --git a/src/main/resources/challenges/missing_vault.adoc b/src/main/resources/challenges/missing_vault.adoc new file mode 100644 index 000000000..006e40ad1 --- /dev/null +++ b/src/main/resources/challenges/missing_vault.adoc @@ -0,0 +1,2 @@ +We are running outside a K8s cluster with Vault. Please run this in the K8s cluster as explained in the +https://github.com/OWASP/wrongsecrets#vault-exercises-with-minikube[README.md] diff --git a/src/main/resources/templates/about.html b/src/main/resources/templates/about.html index e7f8af40b..de2af1703 100644 --- a/src/main/resources/templates/about.html +++ b/src/main/resources/templates/about.html @@ -38,33 +38,33 @@

  • Lists of 348 third-party dependencies.
  • (Eclipse Public License - v 1.0) (GNU Lesser General Public License) Logback Classic Module (ch.qos.logback:logback-classic:1.4.11 - http://logback.qos.ch/logback-classic)
  • (Eclipse Public License - v 1.0) (GNU Lesser General Public License) Logback Core Module (ch.qos.logback:logback-core:1.4.11 - http://logback.qos.ch/logback-core)
  • -
  • (The MIT License (MIT)) Microsoft Azure Java Core Library (com.azure:azure-core:1.42.0 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Microsoft Azure Java Core AMQP Library (com.azure:azure-core-amqp:2.8.8 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Microsoft Azure Netty HTTP Client Library (com.azure:azure-core-http-netty:1.13.6 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Microsoft Azure Management Java Core Library (com.azure:azure-core-management:1.11.4 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Microsoft Azure client library for Identity (com.azure:azure-identity:1.10.0 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Microsoft Azure Java Core Library (com.azure:azure-core:1.43.0 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Microsoft Azure Java Core AMQP Library (com.azure:azure-core-amqp:2.8.9 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Microsoft Azure Netty HTTP Client Library (com.azure:azure-core-http-netty:1.13.7 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Microsoft Azure Management Java Core Library (com.azure:azure-core-management:1.11.5 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Microsoft Azure client library for Identity (com.azure:azure-identity:1.10.1 - https://github.com/Azure/azure-sdk-for-java)
  • (The MIT License (MIT)) Microsoft Azure Java JSON Library (com.azure:azure-json:1.1.0 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Microsoft Azure client library for KeyVault Secrets (com.azure:azure-security-keyvault-secrets:4.6.5 - https://github.com/Azure/azure-sdk-for-java)
  • -
  • (The MIT License (MIT)) Spring Cloud Azure AutoConfigure (com.azure.spring:spring-cloud-azure-autoconfigure:5.5.0 - https://microsoft.github.io/spring-cloud-azure)
  • -
  • (The MIT License (MIT)) Spring Cloud Azure Core (com.azure.spring:spring-cloud-azure-core:5.5.0 - https://microsoft.github.io/spring-cloud-azure)
  • -
  • (The MIT License (MIT)) Spring Cloud Azure Service (com.azure.spring:spring-cloud-azure-service:5.5.0 - https://microsoft.github.io/spring-cloud-azure)
  • -
  • (The MIT License (MIT)) Spring Cloud Azure Starter (com.azure.spring:spring-cloud-azure-starter:5.5.0 - https://microsoft.github.io/spring-cloud-azure)
  • -
  • (The MIT License (MIT)) Spring Cloud Azure Starter Key Vault Secrets (com.azure.spring:spring-cloud-azure-starter-keyvault-secrets:5.5.0 - https://microsoft.github.io/spring-cloud-azure)
  • +
  • (The MIT License (MIT)) Microsoft Azure client library for KeyVault Secrets (com.azure:azure-security-keyvault-secrets:4.7.0 - https://github.com/Azure/azure-sdk-for-java)
  • +
  • (The MIT License (MIT)) Spring Cloud Azure AutoConfigure (com.azure.spring:spring-cloud-azure-autoconfigure:5.6.0 - https://microsoft.github.io/spring-cloud-azure)
  • +
  • (The MIT License (MIT)) Spring Cloud Azure Core (com.azure.spring:spring-cloud-azure-core:5.6.0 - https://microsoft.github.io/spring-cloud-azure)
  • +
  • (The MIT License (MIT)) Spring Cloud Azure Service (com.azure.spring:spring-cloud-azure-service:5.6.0 - https://microsoft.github.io/spring-cloud-azure)
  • +
  • (The MIT License (MIT)) Spring Cloud Azure Starter (com.azure.spring:spring-cloud-azure-starter:5.6.0 - https://microsoft.github.io/spring-cloud-azure)
  • +
  • (The MIT License (MIT)) Spring Cloud Azure Starter Key Vault Secrets (com.azure.spring:spring-cloud-azure-starter-keyvault-secrets:5.6.0 - https://microsoft.github.io/spring-cloud-azure)
  • (Apache License, Version 2.0) jcommander (com.beust:jcommander:1.82 - https://jcommander.org)
  • (The Apache Software License, Version 2.0) Simple XML (safe) (com.carrotsearch.thirdparty:simple-xml-safe:2.7.1 - https://github.com/dweiss/simplexml)
  • (3-Clause BSD License) MinLog (com.esotericsoftware:minlog:1.3.1 - https://github.com/EsotericSoftware/minlog)
  • (Apache License, Version 2.0) Internet Time Utility (com.ethlo.time:itu:1.7.0 - https://github.com/ethlo/itu)
  • (The Apache Software License, Version 2.0) aalto-xml (com.fasterxml:aalto-xml:1.3.2 - https://github.com/FasterXML/aalto-xml)
  • -
  • (The Apache Software License, Version 2.0) Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.15.2 - https://github.com/FasterXML/jackson)
  • -
  • (The Apache Software License, Version 2.0) Jackson-core (com.fasterxml.jackson.core:jackson-core:2.15.2 - https://github.com/FasterXML/jackson-core)
  • -
  • (The Apache Software License, Version 2.0) jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.15.2 - https://github.com/FasterXML/jackson)
  • -
  • (The Apache Software License, Version 2.0) Jackson-dataformat-XML (com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2 - https://github.com/FasterXML/jackson-dataformat-xml)
  • -
  • (The Apache Software License, Version 2.0) Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2 - https://github.com/FasterXML/jackson-dataformats-text)
  • -
  • (The Apache Software License, Version 2.0) Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
  • -
  • (The Apache Software License, Version 2.0) Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
  • -
  • (The Apache Software License, Version 2.0) Jackson module: Afterburner (com.fasterxml.jackson.module:jackson-module-afterburner:2.15.2 - https://github.com/FasterXML/jackson-modules-base)
  • -
  • (The Apache Software License, Version 2.0) Jackson module: Blackbird (com.fasterxml.jackson.module:jackson-module-blackbird:2.15.2 - https://github.com/FasterXML/jackson-modules-base)
  • -
  • (The Apache Software License, Version 2.0) Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.2 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
  • +
  • (The Apache Software License, Version 2.0) Jackson-annotations (com.fasterxml.jackson.core:jackson-annotations:2.15.3 - https://github.com/FasterXML/jackson)
  • +
  • (The Apache Software License, Version 2.0) Jackson-core (com.fasterxml.jackson.core:jackson-core:2.15.3 - https://github.com/FasterXML/jackson-core)
  • +
  • (The Apache Software License, Version 2.0) jackson-databind (com.fasterxml.jackson.core:jackson-databind:2.15.3 - https://github.com/FasterXML/jackson)
  • +
  • (The Apache Software License, Version 2.0) Jackson-dataformat-XML (com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.3 - https://github.com/FasterXML/jackson-dataformat-xml)
  • +
  • (The Apache Software License, Version 2.0) Jackson-dataformat-YAML (com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.3 - https://github.com/FasterXML/jackson-dataformats-text)
  • +
  • (The Apache Software License, Version 2.0) Jackson datatype: jdk8 (com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8)
  • +
  • (The Apache Software License, Version 2.0) Jackson datatype: JSR310 (com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310)
  • +
  • (The Apache Software License, Version 2.0) Jackson module: Afterburner (com.fasterxml.jackson.module:jackson-module-afterburner:2.15.3 - https://github.com/FasterXML/jackson-modules-base)
  • +
  • (The Apache Software License, Version 2.0) Jackson module: Blackbird (com.fasterxml.jackson.module:jackson-module-blackbird:2.15.3 - https://github.com/FasterXML/jackson-modules-base)
  • +
  • (The Apache Software License, Version 2.0) Jackson-module-parameter-names (com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.3 - https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names)
  • (The Apache License, Version 2.0) Woodstox (com.fasterxml.woodstox:woodstox-core:6.5.1 - https://github.com/FasterXML/woodstox)
  • (The Apache Software License, Version 2.0) jffi (com.github.jnr:jffi:1.3.10 - http://github.com/jnr/jffi)
  • (The Apache Software License, Version 2.0) jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm)
  • @@ -80,29 +80,29 @@
  • (Apache License 2.0) compiler (com.github.spullara.mustache.java:compiler:0.9.6 - http://github.com/spullara/mustache.java)
  • (Apache License, Version 2.0) JCIP Annotations under Apache License (com.github.stephenc.jcip:jcip-annotations:1.0-1 - http://stephenc.github.com/jcip-annotations)
  • (Apache 2.0) Google Android Annotations Library (com.google.android:annotations:4.1.1.4 - http://source.android.com/)
  • -
  • (BSD-3-Clause) API Common (com.google.api:api-common:2.18.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (Core) (com.google.api:gax:2.35.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (gRPC) (com.google.api:gax-grpc:2.35.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (HTTP JSON) (com.google.api:gax-httpjson:2.35.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (Apache-2.0) proto-google-cloud-secretmanager-v1 (com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.28.0 - https://github.com/googleapis/google-cloud-java)
  • -
  • (Apache-2.0) proto-google-cloud-secretmanager-v1beta1 (com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.28.0 - https://github.com/googleapis/google-cloud-java)
  • -
  • (Apache-2.0) proto-google-common-protos (com.google.api.grpc:proto-google-common-protos:2.26.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (Apache-2.0) proto-google-iam-v1 (com.google.api.grpc:proto-google-iam-v1:1.21.0 - https://github.com/googleapis/sdk-platform-java)
  • -
  • (BSD New license) Google Auth Library for Java - Credentials (com.google.auth:google-auth-library-credentials:1.19.0 - https://github.com/googleapis/google-auth-library-java/google-auth-library-credentials)
  • -
  • (BSD New license) Google Auth Library for Java - OAuth2 HTTP (com.google.auth:google-auth-library-oauth2-http:1.19.0 - https://github.com/googleapis/google-auth-library-java/google-auth-library-oauth2-http)
  • +
  • (BSD-3-Clause) API Common (com.google.api:api-common:2.19.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (Core) (com.google.api:gax:2.36.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (gRPC) (com.google.api:gax-grpc:2.36.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (BSD-3-Clause) GAX (Google Api eXtensions) for Java (HTTP JSON) (com.google.api:gax-httpjson:2.36.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (Apache-2.0) proto-google-cloud-secretmanager-v1 (com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.29.0 - https://github.com/googleapis/google-cloud-java)
  • +
  • (Apache-2.0) proto-google-cloud-secretmanager-v1beta1 (com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.29.0 - https://github.com/googleapis/google-cloud-java)
  • +
  • (Apache-2.0) proto-google-common-protos (com.google.api.grpc:proto-google-common-protos:2.27.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (Apache-2.0) proto-google-iam-v1 (com.google.api.grpc:proto-google-iam-v1:1.22.0 - https://github.com/googleapis/sdk-platform-java)
  • +
  • (BSD New license) Google Auth Library for Java - Credentials (com.google.auth:google-auth-library-credentials:1.20.0 - https://github.com/googleapis/google-auth-library-java/google-auth-library-credentials)
  • +
  • (BSD New license) Google Auth Library for Java - OAuth2 HTTP (com.google.auth:google-auth-library-oauth2-http:1.20.0 - https://github.com/googleapis/google-auth-library-java/google-auth-library-oauth2-http)
  • (Apache 2.0) AutoValue Annotations (com.google.auto.value:auto-value-annotations:1.10.4 - https://github.com/google/auto/tree/main/value)
  • -
  • (Apache-2.0) Google Cloud Secret Manager (com.google.cloud:google-cloud-secretmanager:2.28.0 - https://github.com/googleapis/google-cloud-java)
  • +
  • (Apache-2.0) Google Cloud Secret Manager (com.google.cloud:google-cloud-secretmanager:2.29.0 - https://github.com/googleapis/google-cloud-java)
  • (The Apache Software License, Version 2.0) FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - http://findbugs.sourceforge.net/)
  • (Apache-2.0) Gson (com.google.code.gson:gson:2.10.1 - https://github.com/google/gson/gson)
  • -
  • (Apache 2.0) error-prone annotations (com.google.errorprone:error_prone_annotations:2.20.0 - https://errorprone.info/error_prone_annotations)
  • +
  • (Apache 2.0) error-prone annotations (com.google.errorprone:error_prone_annotations:2.22.0 - https://errorprone.info/error_prone_annotations)
  • (The Apache Software License, Version 2.0) Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess)
  • (Apache License, Version 2.0) Guava: Google Core Libraries for Java (com.google.guava:guava:32.1.2-jre - https://github.com/google/guava)
  • (The Apache Software License, Version 2.0) Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture)
  • (The Apache Software License, Version 2.0) Google HTTP Client Library for Java (com.google.http-client:google-http-client:1.43.3 - https://github.com/googleapis/google-http-java-client/google-http-client)
  • (The Apache Software License, Version 2.0) GSON extensions to the Google HTTP Client Library for Java. (com.google.http-client:google-http-client-gson:1.43.3 - https://github.com/googleapis/google-http-java-client/google-http-client-gson)
  • (Apache License, Version 2.0) J2ObjC Annotations (com.google.j2objc:j2objc-annotations:2.8 - https://github.com/google/j2objc/)
  • -
  • (BSD-3-Clause) Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.24.3 - https://developers.google.com/protocol-buffers/protobuf-java/)
  • -
  • (BSD-3-Clause) Protocol Buffers [Util] (com.google.protobuf:protobuf-java-util:3.24.3 - https://developers.google.com/protocol-buffers/protobuf-java-util/)
  • +
  • (BSD-3-Clause) Protocol Buffers [Core] (com.google.protobuf:protobuf-java:3.24.4 - https://developers.google.com/protocol-buffers/protobuf-java/)
  • +
  • (BSD-3-Clause) Protocol Buffers [Util] (com.google.protobuf:protobuf-java-util:3.24.4 - https://developers.google.com/protocol-buffers/protobuf-java-util/)
  • (Go License) RE2/J (com.google.re2j:re2j:1.7 - http://github.com/google/re2j)
  • (EPL 1.0) (MPL 2.0) H2 Database Engine (com.h2database:h2:2.1.214 - https://h2database.com)
  • (The Apache Software License, Version 2.0) retirejs-core (com.h3xstream.retirejs:retirejs-core:3.0.4 - https://github.com/h3xstream/burp-retire-js/retirejs-core)
  • @@ -145,37 +145,37 @@
  • (Apache 2.0) io.grpc:grpc-stub (io.grpc:grpc-stub:1.58.0 - https://github.com/grpc/grpc-java)
  • (Apache 2.0) io.grpc:grpc-util (io.grpc:grpc-util:1.58.0 - https://github.com/grpc/grpc-java)
  • (Apache 2.0) io.grpc:grpc-xds (io.grpc:grpc-xds:1.58.0 - https://github.com/grpc/grpc-java)
  • -
  • (The Apache Software License, Version 2.0) micrometer-commons (io.micrometer:micrometer-commons:1.11.4 - https://github.com/micrometer-metrics/micrometer)
  • -
  • (The Apache Software License, Version 2.0) micrometer-core (io.micrometer:micrometer-core:1.11.4 - https://github.com/micrometer-metrics/micrometer)
  • -
  • (The Apache Software License, Version 2.0) micrometer-observation (io.micrometer:micrometer-observation:1.11.4 - https://github.com/micrometer-metrics/micrometer)
  • -
  • (Apache License, Version 2.0) Netty/Buffer (io.netty:netty-buffer:4.1.97.Final - https://netty.io/netty-buffer/)
  • -
  • (Apache License, Version 2.0) Netty/Codec (io.netty:netty-codec:4.1.97.Final - https://netty.io/netty-codec/)
  • -
  • (Apache License, Version 2.0) Netty/Codec/DNS (io.netty:netty-codec-dns:4.1.97.Final - https://netty.io/netty-codec-dns/)
  • -
  • (Apache License, Version 2.0) Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.97.Final - https://netty.io/netty-codec-http/)
  • -
  • (Apache License, Version 2.0) Netty/Codec/HTTP2 (io.netty:netty-codec-http2:4.1.97.Final - https://netty.io/netty-codec-http2/)
  • -
  • (Apache License, Version 2.0) Netty/Codec/Socks (io.netty:netty-codec-socks:4.1.97.Final - https://netty.io/netty-codec-socks/)
  • -
  • (Apache License, Version 2.0) Netty/Common (io.netty:netty-common:4.1.97.Final - https://netty.io/netty-common/)
  • -
  • (Apache License, Version 2.0) Netty/Handler (io.netty:netty-handler:4.1.97.Final - https://netty.io/netty-handler/)
  • -
  • (Apache License, Version 2.0) Netty/Handler/Proxy (io.netty:netty-handler-proxy:4.1.97.Final - https://netty.io/netty-handler-proxy/)
  • -
  • (Apache License, Version 2.0) Netty/Resolver (io.netty:netty-resolver:4.1.97.Final - https://netty.io/netty-resolver/)
  • -
  • (Apache License, Version 2.0) Netty/Resolver/DNS (io.netty:netty-resolver-dns:4.1.97.Final - https://netty.io/netty-resolver-dns/)
  • -
  • (Apache License, Version 2.0) Netty/Resolver/DNS/Classes/MacOS (io.netty:netty-resolver-dns-classes-macos:4.1.97.Final - https://netty.io/netty-resolver-dns-classes-macos/)
  • -
  • (Apache License, Version 2.0) Netty/Resolver/DNS/Native/MacOS (io.netty:netty-resolver-dns-native-macos:4.1.97.Final - https://netty.io/netty-resolver-dns-native-macos/)
  • +
  • (The Apache Software License, Version 2.0) micrometer-commons (io.micrometer:micrometer-commons:1.11.5 - https://github.com/micrometer-metrics/micrometer)
  • +
  • (The Apache Software License, Version 2.0) micrometer-core (io.micrometer:micrometer-core:1.11.5 - https://github.com/micrometer-metrics/micrometer)
  • +
  • (The Apache Software License, Version 2.0) micrometer-observation (io.micrometer:micrometer-observation:1.11.5 - https://github.com/micrometer-metrics/micrometer)
  • +
  • (Apache License, Version 2.0) Netty/Buffer (io.netty:netty-buffer:4.1.100.Final - https://netty.io/netty-buffer/)
  • +
  • (Apache License, Version 2.0) Netty/Codec (io.netty:netty-codec:4.1.100.Final - https://netty.io/netty-codec/)
  • +
  • (Apache License, Version 2.0) Netty/Codec/DNS (io.netty:netty-codec-dns:4.1.100.Final - https://netty.io/netty-codec-dns/)
  • +
  • (Apache License, Version 2.0) Netty/Codec/HTTP (io.netty:netty-codec-http:4.1.100.Final - https://netty.io/netty-codec-http/)
  • +
  • (Apache License, Version 2.0) Netty/Codec/HTTP2 (io.netty:netty-codec-http2:4.1.100.Final - https://netty.io/netty-codec-http2/)
  • +
  • (Apache License, Version 2.0) Netty/Codec/Socks (io.netty:netty-codec-socks:4.1.100.Final - https://netty.io/netty-codec-socks/)
  • +
  • (Apache License, Version 2.0) Netty/Common (io.netty:netty-common:4.1.100.Final - https://netty.io/netty-common/)
  • +
  • (Apache License, Version 2.0) Netty/Handler (io.netty:netty-handler:4.1.100.Final - https://netty.io/netty-handler/)
  • +
  • (Apache License, Version 2.0) Netty/Handler/Proxy (io.netty:netty-handler-proxy:4.1.100.Final - https://netty.io/netty-handler-proxy/)
  • +
  • (Apache License, Version 2.0) Netty/Resolver (io.netty:netty-resolver:4.1.100.Final - https://netty.io/netty-resolver/)
  • +
  • (Apache License, Version 2.0) Netty/Resolver/DNS (io.netty:netty-resolver-dns:4.1.100.Final - https://netty.io/netty-resolver-dns/)
  • +
  • (Apache License, Version 2.0) Netty/Resolver/DNS/Classes/MacOS (io.netty:netty-resolver-dns-classes-macos:4.1.100.Final - https://netty.io/netty-resolver-dns-classes-macos/)
  • +
  • (Apache License, Version 2.0) Netty/Resolver/DNS/Native/MacOS (io.netty:netty-resolver-dns-native-macos:4.1.100.Final - https://netty.io/netty-resolver-dns-native-macos/)
  • (The Apache Software License, Version 2.0) Netty/TomcatNative [BoringSSL - Static] (io.netty:netty-tcnative-boringssl-static:2.0.61.Final - https://github.com/netty/netty-tcnative/netty-tcnative-boringssl-static/)
  • (The Apache Software License, Version 2.0) Netty/TomcatNative [OpenSSL - Classes] (io.netty:netty-tcnative-classes:2.0.61.Final - https://github.com/netty/netty-tcnative/netty-tcnative-classes/)
  • -
  • (Apache License, Version 2.0) Netty/Transport (io.netty:netty-transport:4.1.97.Final - https://netty.io/netty-transport/)
  • -
  • (Apache License, Version 2.0) Netty/Transport/Classes/Epoll (io.netty:netty-transport-classes-epoll:4.1.97.Final - https://netty.io/netty-transport-classes-epoll/)
  • -
  • (Apache License, Version 2.0) Netty/Transport/Classes/KQueue (io.netty:netty-transport-classes-kqueue:4.1.97.Final - https://netty.io/netty-transport-classes-kqueue/)
  • -
  • (Apache License, Version 2.0) Netty/Transport/Native/Epoll (io.netty:netty-transport-native-epoll:4.1.97.Final - https://netty.io/netty-transport-native-epoll/)
  • -
  • (Apache License, Version 2.0) Netty/Transport/Native/KQueue (io.netty:netty-transport-native-kqueue:4.1.97.Final - https://netty.io/netty-transport-native-kqueue/)
  • -
  • (Apache License, Version 2.0) Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.97.Final - https://netty.io/netty-transport-native-unix-common/)
  • +
  • (Apache License, Version 2.0) Netty/Transport (io.netty:netty-transport:4.1.100.Final - https://netty.io/netty-transport/)
  • +
  • (Apache License, Version 2.0) Netty/Transport/Classes/Epoll (io.netty:netty-transport-classes-epoll:4.1.100.Final - https://netty.io/netty-transport-classes-epoll/)
  • +
  • (Apache License, Version 2.0) Netty/Transport/Classes/KQueue (io.netty:netty-transport-classes-kqueue:4.1.100.Final - https://netty.io/netty-transport-classes-kqueue/)
  • +
  • (Apache License, Version 2.0) Netty/Transport/Native/Epoll (io.netty:netty-transport-native-epoll:4.1.100.Final - https://netty.io/netty-transport-native-epoll/)
  • +
  • (Apache License, Version 2.0) Netty/Transport/Native/KQueue (io.netty:netty-transport-native-kqueue:4.1.100.Final - https://netty.io/netty-transport-native-kqueue/)
  • +
  • (Apache License, Version 2.0) Netty/Transport/Native/Unix/Common (io.netty:netty-transport-native-unix-common:4.1.100.Final - https://netty.io/netty-transport-native-unix-common/)
  • (The Apache License, Version 2.0) OpenCensus (io.opencensus:opencensus-api:0.31.1 - https://github.com/census-instrumentation/opencensus-java)
  • (The Apache License, Version 2.0) OpenCensus (io.opencensus:opencensus-contrib-http-util:0.31.1 - https://github.com/census-instrumentation/opencensus-java)
  • (The Apache License, Version 2.0) OpenCensus (io.opencensus:opencensus-proto:0.2.0 - https://github.com/census-instrumentation/opencensus-proto)
  • (Apache 2.0) perfmark:perfmark-api (io.perfmark:perfmark-api:0.26.0 - https://github.com/perfmark/perfmark)
  • -
  • (Apache License, Version 2.0) Non-Blocking Reactive Foundation for the JVM (io.projectreactor:reactor-core:3.5.10 - https://github.com/reactor/reactor-core)
  • -
  • (The Apache Software License, Version 2.0) Core functionality for the Reactor Netty library (io.projectreactor.netty:reactor-netty-core:1.1.11 - https://github.com/reactor/reactor-netty)
  • -
  • (The Apache Software License, Version 2.0) HTTP functionality for the Reactor Netty library (io.projectreactor.netty:reactor-netty-http:1.1.11 - https://github.com/reactor/reactor-netty)
  • +
  • (Apache License, Version 2.0) Non-Blocking Reactive Foundation for the JVM (io.projectreactor:reactor-core:3.5.11 - https://github.com/reactor/reactor-core)
  • +
  • (The Apache Software License, Version 2.0) Core functionality for the Reactor Netty library (io.projectreactor.netty:reactor-netty-core:1.1.12 - https://github.com/reactor/reactor-netty)
  • +
  • (The Apache Software License, Version 2.0) HTTP functionality for the Reactor Netty library (io.projectreactor.netty:reactor-netty-http:1.1.12 - https://github.com/reactor/reactor-netty)
  • (Apache License 2.0) swagger-annotations-jakarta (io.swagger.core.v3:swagger-annotations-jakarta:2.2.15 - https://github.com/swagger-api/swagger-core/modules/swagger-annotations-jakarta)
  • (Apache License 2.0) swagger-core-jakarta (io.swagger.core.v3:swagger-core-jakarta:2.2.15 - https://github.com/swagger-api/swagger-core/modules/swagger-core-jakarta)
  • (Apache License 2.0) swagger-models-jakarta (io.swagger.core.v3:swagger-models-jakarta:2.2.15 - https://github.com/swagger-api/swagger-core/modules/swagger-models-jakarta)
  • @@ -191,7 +191,7 @@
  • (Apache License, Version 2.0) Joda-Time (joda-time:joda-time:2.10.10 - https://www.joda.org/joda-time/)
  • (Eclipse Public License 1.0) JUnit (junit:junit:4.13.2 - http://junit.org)
  • (The Apache Software License, Version 2.0) jitescript (me.qmx.jitescript:jitescript:0.4.1 - https://github.com/qmx/jitescript)
  • -
  • (Apache-2.0) (LGPL-2.1-or-later) Java Native Access (net.java.dev.jna:jna:5.13.0 - https://github.com/java-native-access/jna)
  • +
  • (Apache-2.0) (LGPL-2.1-or-later) Java Native Access (net.java.dev.jna:jna:5.12.1 - https://github.com/java-native-access/jna)
  • (Apache License v2.0) (LGPL, version 2.1) Java Native Access Platform (net.java.dev.jna:jna-platform:5.6.0 - https://github.com/java-native-access/jna)
  • (The Apache Software License, Version 2.0) ASM based accessors helper used by json-smart (net.minidev:accessors-smart:2.4.11 - https://urielch.github.io/)
  • (The Apache Software License, Version 2.0) JSON Small and Fast Parser (net.minidev:json-smart:2.4.11 - https://urielch.github.io/)
  • @@ -211,8 +211,8 @@
  • (Apache License, Version 2.0) Apache HttpClient (org.apache.httpcomponents:httpclient:4.5.14 - http://hc.apache.org/httpcomponents-client-ga)
  • (Apache License, Version 2.0) Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.16 - http://hc.apache.org/httpcomponents-core-ga)
  • (Apache License, Version 2.0) Apache HttpClient (org.apache.httpcomponents.client5:httpclient5:5.2.1 - https://hc.apache.org/httpcomponents-client-5.0.x/5.2.1/httpclient5/)
  • -
  • (Apache License, Version 2.0) Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.2.2 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.2/httpcore5/)
  • -
  • (Apache License, Version 2.0) Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.2.2 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.2/httpcore5-h2/)
  • +
  • (Apache License, Version 2.0) Apache HttpComponents Core HTTP/1.1 (org.apache.httpcomponents.core5:httpcore5:5.2.3 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.3/httpcore5/)
  • +
  • (Apache License, Version 2.0) Apache HttpComponents Core HTTP/2 (org.apache.httpcomponents.core5:httpcore5-h2:5.2.3 - https://hc.apache.org/httpcomponents-core-5.2.x/5.2.3/httpcore5-h2/)
  • (Apache License, Version 2.0) Apache Log4j API (org.apache.logging.log4j:log4j-api:2.20.0 - https://logging.apache.org/log4j/2.x/log4j-api/)
  • (Apache License, Version 2.0) Apache Log4j to SLF4J Adapter (org.apache.logging.log4j:log4j-to-slf4j:2.20.0 - https://logging.apache.org/log4j/2.x/log4j-to-slf4j/)
  • (Apache License, Version 2.0) Lucene Common Analyzers (org.apache.lucene:lucene-analyzers-common:8.11.2 - https://lucene.apache.org/lucene-parent/lucene-analyzers-common)
  • @@ -238,9 +238,9 @@
  • (Apache License, Version 2.0) Apache Maven Dependency Tree (org.apache.maven.shared:maven-dependency-tree:3.2.1 - https://maven.apache.org/shared/maven-dependency-tree/)
  • (Apache License, Version 2.0) Apache Maven Shared Utils (org.apache.maven.shared:maven-shared-utils:3.1.0 - https://maven.apache.org/shared/maven-shared-utils/)
  • (Apache License, Version 2.0) Proton-J (org.apache.qpid:proton-j:0.33.8 - https://qpid.apache.org/proton/proton-j)
  • -
  • (Apache License, Version 2.0) tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.13 - https://tomcat.apache.org/)
  • -
  • (Apache License, Version 2.0) tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.13 - https://tomcat.apache.org/)
  • -
  • (Apache License, Version 2.0) tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.13 - https://tomcat.apache.org/)
  • +
  • (Apache License, Version 2.0) tomcat-embed-core (org.apache.tomcat.embed:tomcat-embed-core:10.1.15 - https://tomcat.apache.org/)
  • +
  • (Apache License, Version 2.0) tomcat-embed-el (org.apache.tomcat.embed:tomcat-embed-el:10.1.15 - https://tomcat.apache.org/)
  • +
  • (Apache License, Version 2.0) tomcat-embed-websocket (org.apache.tomcat.embed:tomcat-embed-websocket:10.1.15 - https://tomcat.apache.org/)
  • (Apache License, Version 2.0) Apache Velocity - Engine (org.apache.velocity:velocity-engine-core:2.3 - http://velocity.apache.org/engine/devel/velocity-engine-core/)
  • (The Apache Software License, Version 2.0) asciidoctorj (org.asciidoctor:asciidoctorj:2.5.10 - https://github.com/asciidoctor/asciidoctorj)
  • (The Apache Software License, Version 2.0) asciidoctorj-api (org.asciidoctor:asciidoctorj-api:2.5.10 - https://github.com/asciidoctor/asciidoctorj)
  • @@ -249,7 +249,7 @@
  • (Bouncy Castle Licence) Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (org.bouncycastle:bcpkix-jdk18on:1.73 - https://www.bouncycastle.org/java.html)
  • (Bouncy Castle Licence) Bouncy Castle Provider (org.bouncycastle:bcprov-jdk18on:1.73 - https://www.bouncycastle.org/java.html)
  • (Bouncy Castle Licence) Bouncy Castle ASN.1 Extension and Utility APIs (org.bouncycastle:bcutil-jdk18on:1.73 - https://www.bouncycastle.org/java.html)
  • -
  • (The MIT License) Checker Qual (org.checkerframework:checker-qual:3.33.0 - https://checkerframework.org/)
  • +
  • (The MIT License) Checker Qual (org.checkerframework:checker-qual:3.39.0 - https://checkerframework.org/)
  • (MIT license) Animal Sniffer Annotations (org.codehaus.mojo:animal-sniffer-annotations:1.23 - https://www.mojohaus.org/animal-sniffer/animal-sniffer-annotations)
  • (The Apache Software License, Version 2.0) Plexus Classworlds (org.codehaus.plexus:plexus-classworlds:2.2.3 - http://plexus.codehaus.org/plexus-classworlds/)
  • (Apache License, Version 2.0) Plexus :: Component Annotations (org.codehaus.plexus:plexus-component-annotations:2.0.0 - http://codehaus-plexus.github.io/plexus-containers/plexus-component-annotations/)
  • @@ -257,7 +257,7 @@
  • (Apache License, Version 2.0) Plexus Common Utilities (org.codehaus.plexus:plexus-utils:3.5.1 - https://codehaus-plexus.github.io/plexus-utils/)
  • (The BSD License) Stax2 API (org.codehaus.woodstox:stax2-api:4.2.1 - http://github.com/FasterXML/stax2-api)
  • (Apache 2) org.conscrypt:conscrypt-openjdk-uber (org.conscrypt:conscrypt-openjdk-uber:2.5.2 - https://conscrypt.org/)
  • -
  • (Apache-2.0) CycloneDX Core (Java) (org.cyclonedx:cyclonedx-core-java:8.0.1 - https://github.com/CycloneDX/cyclonedx-core-java)
  • +
  • (Apache-2.0) CycloneDX Core (Java) (org.cyclonedx:cyclonedx-core-java:8.0.3 - https://github.com/CycloneDX/cyclonedx-core-java)
  • (Eclipse Public License, Version 1.0) Aether API (org.eclipse.aether:aether-api:1.0.0.v20140518 - http://www.eclipse.org/aether/aether-api/)
  • (Eclipse Public License, Version 1.0) Aether Utilities (org.eclipse.aether:aether-util:1.0.0.v20140518 - http://www.eclipse.org/aether/aether-util/)
  • (EDL 1.0) Angus Activation Registries (org.eclipse.angus:angus-activation:2.0.1 - https://github.com/eclipse-ee4j/angus-activation/angus-activation)
  • @@ -268,11 +268,11 @@
  • (BSD License 3) Hamcrest Core (org.hamcrest:hamcrest-core:2.2 - http://hamcrest.org/JavaHamcrest/)
  • (BSD-2-Clause) (Public Domain, per Creative Commons CC0) HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.12 - http://hdrhistogram.github.io/HdrHistogram/)
  • (Apache License 2.0) (LGPL 2.1) (MPL 1.1) Javassist (org.javassist:javassist:3.29.0-GA - http://www.javassist.org/)
  • -
  • (The Apache Software License, Version 2.0) JetBrains Java Annotations (org.jetbrains:annotations:24.0.1 - https://github.com/JetBrains/java-annotations)
  • +
  • (The Apache Software License, Version 2.0) JetBrains Java Annotations (org.jetbrains:annotations:17.0.0 - https://github.com/JetBrains/java-annotations)
  • (EPL) Dirgra (org.jruby:dirgra:0.3 - https://github.com/jruby/dirgra)
  • (EPL-2.0) (GPL-2.0) (LGPL-2.1) JRuby Main Maven Artifact (org.jruby:jruby:9.4.2.0 - https://github.com/jruby/jruby/jruby-artifacts/jruby)
  • (EPL-2.0) (GPL-2.0) (LGPL-2.1) JRuby Base (org.jruby:jruby-base:9.4.2.0 - https://github.com/jruby/jruby/jruby-base)
  • -
  • (EPL-2.0) (GPL-2.0) (LGPL-2.1) JRuby Complete (org.jruby:jruby-complete:9.4.3.0 - https://github.com/jruby/jruby/jruby-artifacts/jruby-complete)
  • +
  • (EPL-2.0) (GPL-2.0) (LGPL-2.1) JRuby Complete (org.jruby:jruby-complete:9.4.4.0 - https://github.com/jruby/jruby/jruby-artifacts/jruby-complete)
  • (EPL-2.0) (GPL-2.0) (LGPL-2.1) JRuby Lib Setup (org.jruby:jruby-stdlib:9.4.2.0 - https://github.com/jruby/jruby/jruby-stdlib)
  • (MIT License) JCodings (org.jruby.jcodings:jcodings:1.0.58 - http://nexus.sonatype.org/oss-repository-hosting.html/jcodings)
  • (MIT License) Joni (org.jruby.joni:joni:2.1.48 - http://nexus.sonatype.org/oss-repository-hosting.html/joni)
  • @@ -314,35 +314,35 @@
  • (The Apache License, Version 2.0) springdoc-openapi-starter-common (org.springdoc:springdoc-openapi-starter-common:2.2.0 - https://springdoc.org/springdoc-openapi-starter-common/)
  • (The Apache License, Version 2.0) springdoc-openapi-starter-webmvc-api (org.springdoc:springdoc-openapi-starter-webmvc-api:2.2.0 - https://springdoc.org/springdoc-openapi-starter-webmvc-api/)
  • (The Apache License, Version 2.0) springdoc-openapi-starter-webmvc-ui (org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0 - https://springdoc.org/springdoc-openapi-starter-webmvc-ui/)
  • -
  • (Apache License, Version 2.0) Spring AOP (org.springframework:spring-aop:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Beans (org.springframework:spring-beans:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Context (org.springframework:spring-context:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Core (org.springframework:spring-core:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Expression Language (SpEL) (org.springframework:spring-expression:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Commons Logging Bridge (org.springframework:spring-jcl:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Web (org.springframework:spring-web:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) Spring Web MVC (org.springframework:spring-webmvc:6.0.12 - https://github.com/spring-projects/spring-framework)
  • -
  • (Apache License, Version 2.0) spring-boot (org.springframework.boot:spring-boot:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter (org.springframework.boot:spring-boot-starter:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-logging (org.springframework.boot:spring-boot-starter-logging:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-thymeleaf (org.springframework.boot:spring-boot-starter-thymeleaf:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.1.4 - https://spring.io/projects/spring-boot)
  • -
  • (Apache License, Version 2.0) spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.1.4 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) Spring AOP (org.springframework:spring-aop:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Beans (org.springframework:spring-beans:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Context (org.springframework:spring-context:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Core (org.springframework:spring-core:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Expression Language (SpEL) (org.springframework:spring-expression:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Commons Logging Bridge (org.springframework:spring-jcl:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Web (org.springframework:spring-web:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) Spring Web MVC (org.springframework:spring-webmvc:6.0.13 - https://github.com/spring-projects/spring-framework)
  • +
  • (Apache License, Version 2.0) spring-boot (org.springframework.boot:spring-boot:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-actuator (org.springframework.boot:spring-boot-actuator:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-actuator-autoconfigure (org.springframework.boot:spring-boot-actuator-autoconfigure:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-autoconfigure (org.springframework.boot:spring-boot-autoconfigure:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter (org.springframework.boot:spring-boot-starter:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-actuator (org.springframework.boot:spring-boot-starter-actuator:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-json (org.springframework.boot:spring-boot-starter-json:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-logging (org.springframework.boot:spring-boot-starter-logging:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-thymeleaf (org.springframework.boot:spring-boot-starter-thymeleaf:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-tomcat (org.springframework.boot:spring-boot-starter-tomcat:3.1.5 - https://spring.io/projects/spring-boot)
  • +
  • (Apache License, Version 2.0) spring-boot-starter-web (org.springframework.boot:spring-boot-starter-web:3.1.5 - https://spring.io/projects/spring-boot)
  • (Apache License, Version 2.0) Spring Cloud Commons (org.springframework.cloud:spring-cloud-commons:4.0.4 - https://projects.spring.io/spring-cloud/spring-cloud-commons/)
  • (Apache License, Version 2.0) Spring Cloud Context (org.springframework.cloud:spring-cloud-context:4.0.4 - https://projects.spring.io/spring-cloud/spring-cloud-context/)
  • (Apache License, Version 2.0) spring-cloud-starter (org.springframework.cloud:spring-cloud-starter:4.0.4 - https://projects.spring.io/spring-cloud)
  • (Apache License, Version 2.0) Spring Cloud Starter Vault Config (org.springframework.cloud:spring-cloud-starter-vault-config:4.0.1 - https://cloud.spring.io/spring-cloud-vault/)
  • (Apache License, Version 2.0) Spring Cloud Vault Configuration Integration (org.springframework.cloud:spring-cloud-vault-config:4.0.1 - https://spring.io/spring-cloud/spring-cloud-vault-parent/spring-cloud-vault-config)
  • -
  • (Apache License, Version 2.0) spring-security-config (org.springframework.security:spring-security-config:6.1.4 - https://spring.io/projects/spring-security)
  • -
  • (Apache License, Version 2.0) spring-security-core (org.springframework.security:spring-security-core:6.1.4 - https://spring.io/projects/spring-security)
  • -
  • (Apache License, Version 2.0) spring-security-crypto (org.springframework.security:spring-security-crypto:6.1.4 - https://spring.io/projects/spring-security)
  • +
  • (Apache License, Version 2.0) spring-security-config (org.springframework.security:spring-security-config:6.1.5 - https://spring.io/projects/spring-security)
  • +
  • (Apache License, Version 2.0) spring-security-core (org.springframework.security:spring-security-core:6.1.5 - https://spring.io/projects/spring-security)
  • +
  • (Apache License, Version 2.0) spring-security-crypto (org.springframework.security:spring-security-crypto:6.1.5 - https://spring.io/projects/spring-security)
  • (Apache 2.0) spring-security-rsa (org.springframework.security:spring-security-rsa:1.0.12.RELEASE - http://github.com/spring-projects/spring-security-oauth)
  • -
  • (Apache License, Version 2.0) spring-security-web (org.springframework.security:spring-security-web:6.1.4 - https://spring.io/projects/spring-security)
  • +
  • (Apache License, Version 2.0) spring-security-web (org.springframework.security:spring-security-web:6.1.5 - https://spring.io/projects/spring-security)
  • (Apache License, Version 2.0) Spring Vault Core (org.springframework.vault:spring-vault-core:3.0.2 - https://projects.spring.io/spring-vault/spring-vault-core/)
  • (BSD-3-Clause) ThreeTen backport (org.threeten:threetenbp:1.6.8 - https://www.threeten.org/threetenbp)
  • (The Apache Software License, Version 2.0) thymeleaf (org.thymeleaf:thymeleaf:3.1.2.RELEASE - http://www.thymeleaf.org/thymeleaf-lib/thymeleaf)
  • @@ -357,31 +357,31 @@
  • (BSD 2-Clause) github-buttons (org.webjars.npm:github-buttons:2.14.1 - https://www.webjars.org)
  • (Common Public 1.0) pecoff4j (org.whitesource:pecoff4j:0.0.2.1 - https://github.com/whitesource/pecoff4j-maven)
  • (Apache License, Version 2.0) SnakeYAML (org.yaml:snakeyaml:1.33 - https://bitbucket.org/snakeyaml/snakeyaml)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Annotations (software.amazon.awssdk:annotations:2.21.2 - https://aws.amazon.com/sdkforjava/core/annotations)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Clients :: Apache (software.amazon.awssdk:apache-client:2.21.2 - https://aws.amazon.com/sdkforjava/http-clients/apache-client)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Auth (software.amazon.awssdk:auth:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: AWS Core (software.amazon.awssdk:aws-core:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: AWS Json Protocol (software.amazon.awssdk:aws-json-protocol:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: AWS Query Protocol (software.amazon.awssdk:aws-query-protocol:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Checksums (software.amazon.awssdk:checksums:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Checksums SPI (software.amazon.awssdk:checksums-spi:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Endpoints SPI (software.amazon.awssdk:endpoints-spi:2.21.2 - https://aws.amazon.com/sdkforjava/core/endpoints-spi)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth (software.amazon.awssdk:http-auth:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth AWS (software.amazon.awssdk:http-auth-aws:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth SPI (software.amazon.awssdk:http-auth-spi:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Client Interface (software.amazon.awssdk:http-client-spi:2.21.2 - https://aws.amazon.com/sdkforjava/http-client-spi)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Identity SPI (software.amazon.awssdk:identity-spi:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: Json Utils (software.amazon.awssdk:json-utils:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Metrics SPI (software.amazon.awssdk:metrics-spi:2.21.2 - https://aws.amazon.com/sdkforjava/core/metrics-spi)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Clients :: Netty Non-Blocking I/O (software.amazon.awssdk:netty-nio-client:2.21.2 - https://aws.amazon.com/sdkforjava/http-clients/netty-nio-client)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Profiles (software.amazon.awssdk:profiles:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: Protocol Core (software.amazon.awssdk:protocol-core:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Regions (software.amazon.awssdk:regions:2.21.2 - https://aws.amazon.com/sdkforjava/core/regions)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: SDK Core (software.amazon.awssdk:sdk-core:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Services :: AWS Simple Systems Management (SSM) (software.amazon.awssdk:ssm:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Services :: AWS STS (software.amazon.awssdk:sts:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Third Party :: Jackson-core (software.amazon.awssdk:third-party-jackson-core:2.21.2 - https://aws.amazon.com/sdkforjava)
  • -
  • (Apache License, Version 2.0) AWS Java SDK :: Utilities (software.amazon.awssdk:utils:2.21.2 - https://aws.amazon.com/sdkforjava/utils)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Annotations (software.amazon.awssdk:annotations:2.21.13 - https://aws.amazon.com/sdkforjava/core/annotations)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Clients :: Apache (software.amazon.awssdk:apache-client:2.21.13 - https://aws.amazon.com/sdkforjava/http-clients/apache-client)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Auth (software.amazon.awssdk:auth:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: AWS Core (software.amazon.awssdk:aws-core:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: AWS Json Protocol (software.amazon.awssdk:aws-json-protocol:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: AWS Query Protocol (software.amazon.awssdk:aws-query-protocol:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Checksums (software.amazon.awssdk:checksums:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Checksums SPI (software.amazon.awssdk:checksums-spi:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Endpoints SPI (software.amazon.awssdk:endpoints-spi:2.21.13 - https://aws.amazon.com/sdkforjava/core/endpoints-spi)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth (software.amazon.awssdk:http-auth:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth AWS (software.amazon.awssdk:http-auth-aws:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Auth SPI (software.amazon.awssdk:http-auth-spi:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Client Interface (software.amazon.awssdk:http-client-spi:2.21.13 - https://aws.amazon.com/sdkforjava/http-client-spi)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Identity SPI (software.amazon.awssdk:identity-spi:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: Json Utils (software.amazon.awssdk:json-utils:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Metrics SPI (software.amazon.awssdk:metrics-spi:2.21.13 - https://aws.amazon.com/sdkforjava/core/metrics-spi)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: HTTP Clients :: Netty Non-Blocking I/O (software.amazon.awssdk:netty-nio-client:2.21.13 - https://aws.amazon.com/sdkforjava/http-clients/netty-nio-client)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Profiles (software.amazon.awssdk:profiles:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Core :: Protocols :: Protocol Core (software.amazon.awssdk:protocol-core:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Regions (software.amazon.awssdk:regions:2.21.13 - https://aws.amazon.com/sdkforjava/core/regions)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: SDK Core (software.amazon.awssdk:sdk-core:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Services :: AWS Simple Systems Management (SSM) (software.amazon.awssdk:ssm:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Services :: AWS STS (software.amazon.awssdk:sts:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Third Party :: Jackson-core (software.amazon.awssdk:third-party-jackson-core:2.21.13 - https://aws.amazon.com/sdkforjava)
  • +
  • (Apache License, Version 2.0) AWS Java SDK :: Utilities (software.amazon.awssdk:utils:2.21.13 - https://aws.amazon.com/sdkforjava/utils)
  • (Apache License, Version 2.0) AWS Event Stream (software.amazon.eventstream:eventstream:1.0.1 - https://github.com/awslabs/aws-eventstream-java)
  • (Apache-2.0) CPE Parser (us.springett:cpe-parser:2.0.2 - https://github.com/stevespringett/CPE-Parser)
  • diff --git a/src/main/resources/templates/challenge.html b/src/main/resources/templates/challenge.html index 1c0012f99..af35e21d7 100644 --- a/src/main/resources/templates/challenge.html +++ b/src/main/resources/templates/challenge.html @@ -3,14 +3,16 @@
    -

    +

    +

    -

    You need to guess the secret +

    You need to guess the secret that is hidden in Java, Docker, Kubernetes, Vault, AWS or GCP.

    -
    +
    @@ -21,12 +23,16 @@ th:text="${answerIncorrect}" th:attr="data-cy='incorrect-alert'">
    - Answer to solution : + Answer to solution :
    - +
    @@ -36,28 +42,34 @@
    -
    -
    +
    -
    -
    +
    @@ -72,22 +84,8 @@ th:text="${totalPoints}">
    - - - - diff --git a/src/main/resources/templates/fragments/navigation.html b/src/main/resources/templates/fragments/navigation.html index f90f96001..239bb1605 100644 --- a/src/main/resources/templates/fragments/navigation.html +++ b/src/main/resources/templates/fragments/navigation.html @@ -3,13 +3,13 @@ diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 598875a20..edb745fc9 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -29,22 +29,9 @@ }); - - - - + + +