From 33c7a4d939d3e4538871585c8ab188f433f5965b Mon Sep 17 00:00:00 2001 From: Martin Korbel <112644829+korbelm@users.noreply.github.com> Date: Wed, 14 Feb 2024 17:21:23 +0100 Subject: [PATCH 01/56] Remove timestamp from docker build if branch != develop --- .github/workflows/develop_pa-test-internal-testserver-app.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/develop_pa-test-internal-testserver-app.yml b/.github/workflows/develop_pa-test-internal-testserver-app.yml index 43dfa49b..d267f53a 100644 --- a/.github/workflows/develop_pa-test-internal-testserver-app.yml +++ b/.github/workflows/develop_pa-test-internal-testserver-app.yml @@ -29,7 +29,8 @@ jobs: server-username: INTERNAL_USERNAME server-password: INTERNAL_PASSWORD cache: maven - - name: Set Timestamp for docker image tag + - name: Set Timestamp for docker image for development branch + if: github.ref == 'refs/heads/develop' run: echo "TIMESTAMP=-$(date +%Y.%m.%d)" >> $GITHUB_ENV - name: Get Powerauth Test Server version run: | From 89758b0ac58b7bbedb9b5bbb75deede10464a903 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 04:43:22 +0000 Subject: [PATCH 02/56] Bump org.bouncycastle:bcprov-jdk18on from 1.77 to 1.78 Bumps [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.77 to 1.78. - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcprov-jdk18on dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2facdfad..bad0ebd5 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ 1.7.0-SNAPSHOT 1.9.0-SNAPSHOT - 1.77 + 1.78 2.5.0 7.4 0.23.0.RELEASE From bfd5cc82c6e3aa8feb77486b6f9979822c6c39e1 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Wed, 10 Apr 2024 13:17:34 +0200 Subject: [PATCH 03/56] Fix #366: Set develop version to 1.8.0-SNAPSHOT --- pom.xml | 16 ++++++++-------- powerauth-backend-tests/pom.xml | 2 +- powerauth-fido2-tests/pom.xml | 2 +- powerauth-load-tests/pom.xml | 2 +- powerauth-test-server/pom.xml | 2 +- powerauth-webflow-tests/pom.xml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index eeaa197f..e17d9cf9 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT pom Parent pom for backend tests @@ -45,13 +45,13 @@ - 1.7.0 - 1.7.0 - 1.7.0 - 1.7.0 - 1.7.0 - 1.7.0 - 1.9.0 + 1.8.0-SNAPSHOT + 1.8.0-SNAPSHOT + 1.8.0-SNAPSHOT + 1.8.0-SNAPSHOT + 1.8.0-SNAPSHOT + 1.8.0-SNAPSHOT + 1.10.0-SNAPSHOT 1.77 2.5.0 diff --git a/powerauth-backend-tests/pom.xml b/powerauth-backend-tests/pom.xml index cd78b524..6688e176 100644 --- a/powerauth-backend-tests/pom.xml +++ b/powerauth-backend-tests/pom.xml @@ -8,7 +8,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT com.wultra diff --git a/powerauth-fido2-tests/pom.xml b/powerauth-fido2-tests/pom.xml index e25e312c..b8e9912f 100644 --- a/powerauth-fido2-tests/pom.xml +++ b/powerauth-fido2-tests/pom.xml @@ -11,7 +11,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index f61856cf..95cf1697 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -6,7 +6,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT com.wultra diff --git a/powerauth-test-server/pom.xml b/powerauth-test-server/pom.xml index f72896e2..2a0304cf 100644 --- a/powerauth-test-server/pom.xml +++ b/powerauth-test-server/pom.xml @@ -23,7 +23,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT powerauth-test-server diff --git a/powerauth-webflow-tests/pom.xml b/powerauth-webflow-tests/pom.xml index bd85cbdb..efa53101 100644 --- a/powerauth-webflow-tests/pom.xml +++ b/powerauth-webflow-tests/pom.xml @@ -8,7 +8,7 @@ com.wultra powerauth-backend-tests-parent - 1.7.0 + 1.8.0-SNAPSHOT com.wultra From 515aea2ed41f3a59aea8ac93699c15a7092e5a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Ra=C4=8Dansk=C3=BD?= Date: Mon, 15 Apr 2024 11:11:35 +0200 Subject: [PATCH 04/56] Fix #404: Refactor to use module fido2-model (#405) * Fix #404: Refactor to use module fido2-model --- .../PowerAuthWebServiceConfiguration.java | 5 ++-- .../fido2/controller/AssertionController.java | 8 +++---- .../controller/RegistrationController.java | 8 +++---- .../request/RegisterCredentialRequest.java | 2 +- .../request/VerifyAssertionRequest.java | 2 +- .../fido2/service/AssertionService.java | 24 +++++++++---------- .../fido2/service/Fido2SharedService.java | 11 +++++---- .../fido2/service/RegistrationService.java | 22 ++++++++--------- 8 files changed, 42 insertions(+), 40 deletions(-) diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/configuration/PowerAuthWebServiceConfiguration.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/configuration/PowerAuthWebServiceConfiguration.java index 0b92e757..14c37510 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/configuration/PowerAuthWebServiceConfiguration.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/configuration/PowerAuthWebServiceConfiguration.java @@ -19,8 +19,9 @@ package com.wultra.security.powerauth.fido2.configuration; import com.wultra.security.powerauth.client.PowerAuthClient; -import com.wultra.security.powerauth.client.PowerAuthFido2Client; import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; +import com.wultra.security.powerauth.fido2.client.PowerAuthFido2Client; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; import com.wultra.security.powerauth.rest.client.PowerAuthFido2RestClient; import com.wultra.security.powerauth.rest.client.PowerAuthRestClient; import com.wultra.security.powerauth.rest.client.PowerAuthRestClientConfiguration; @@ -49,7 +50,7 @@ public PowerAuthClient powerAuthClient(final PowerAuthConfigProperties propertie } @Bean - public PowerAuthFido2Client powerAuthFido2Client(final PowerAuthConfigProperties properties) throws PowerAuthClientException { + public PowerAuthFido2Client powerAuthFido2Client(final PowerAuthConfigProperties properties) throws PowerAuthFido2Exception { if (StringUtils.hasText(properties.getSecurity().clientToken())) { final PowerAuthRestClientConfiguration config = new PowerAuthRestClientConfiguration(); config.setPowerAuthClientToken(properties.getSecurity().clientToken()); diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java index 6eece2be..2f7367ea 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java @@ -18,11 +18,11 @@ package com.wultra.security.powerauth.fido2.controller; -import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; -import com.wultra.security.powerauth.client.model.response.fido2.AssertionVerificationResponse; import com.wultra.security.powerauth.fido2.controller.request.AssertionOptionsRequest; import com.wultra.security.powerauth.fido2.controller.request.VerifyAssertionRequest; import com.wultra.security.powerauth.fido2.controller.response.AssertionOptionsResponse; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; +import com.wultra.security.powerauth.fido2.model.response.AssertionVerificationResponse; import com.wultra.security.powerauth.fido2.service.AssertionService; import jakarta.servlet.http.HttpSession; import jakarta.validation.Valid; @@ -49,12 +49,12 @@ public class AssertionController { final AssertionService assertionService; @PostMapping("/options") - public AssertionOptionsResponse options(@Valid @RequestBody final AssertionOptionsRequest request) throws PowerAuthClientException { + public AssertionOptionsResponse options(@Valid @RequestBody final AssertionOptionsRequest request) throws PowerAuthFido2Exception { return assertionService.assertionOptions(request); } @PostMapping - public AssertionVerificationResponse verify(@Valid @RequestBody final VerifyAssertionRequest request, final HttpSession session) throws PowerAuthClientException { + public AssertionVerificationResponse verify(@Valid @RequestBody final VerifyAssertionRequest request, final HttpSession session) throws PowerAuthFido2Exception { final AssertionVerificationResponse response = assertionService.authenticate(request); if (response.isAssertionValid()) { session.setAttribute("username", response.getUserId()); diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/RegistrationController.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/RegistrationController.java index ce2e535d..6e7eb5f7 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/RegistrationController.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/RegistrationController.java @@ -18,11 +18,11 @@ package com.wultra.security.powerauth.fido2.controller; -import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; -import com.wultra.security.powerauth.client.model.response.fido2.RegistrationResponse; import com.wultra.security.powerauth.fido2.controller.request.RegisterCredentialRequest; import com.wultra.security.powerauth.fido2.controller.request.RegistrationOptionsRequest; import com.wultra.security.powerauth.fido2.controller.response.RegistrationOptionsResponse; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; +import com.wultra.security.powerauth.fido2.model.response.RegistrationResponse; import com.wultra.security.powerauth.fido2.service.RegistrationService; import jakarta.validation.Valid; import lombok.AllArgsConstructor; @@ -46,12 +46,12 @@ public class RegistrationController { private final RegistrationService registrationService; @PostMapping("/options") - public RegistrationOptionsResponse options(@Valid @RequestBody final RegistrationOptionsRequest request) throws PowerAuthClientException { + public RegistrationOptionsResponse options(@Valid @RequestBody final RegistrationOptionsRequest request) throws PowerAuthFido2Exception { return registrationService.registerOptions(request); } @PostMapping - public RegistrationResponse register(@Valid @RequestBody final RegisterCredentialRequest request) throws PowerAuthClientException { + public RegistrationResponse register(@Valid @RequestBody final RegisterCredentialRequest request) throws PowerAuthFido2Exception { return registrationService.register(request); } diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java index 7a5f195e..530a0937 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java @@ -20,7 +20,7 @@ import com.webauthn4j.data.AuthenticatorAttachment; import com.webauthn4j.data.PublicKeyCredentialType; -import com.wultra.security.powerauth.client.model.entity.fido2.AuthenticatorAttestationResponse; +import com.wultra.security.powerauth.fido2.model.entity.AuthenticatorAttestationResponse; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/VerifyAssertionRequest.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/VerifyAssertionRequest.java index 4e323d6f..5640db9a 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/VerifyAssertionRequest.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/VerifyAssertionRequest.java @@ -20,7 +20,7 @@ import com.webauthn4j.data.AuthenticatorAttachment; import com.webauthn4j.data.PublicKeyCredentialType; -import com.wultra.security.powerauth.client.model.entity.fido2.AuthenticatorAssertionResponse; +import com.wultra.security.powerauth.fido2.model.entity.AuthenticatorAssertionResponse; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java index 984e5f4d..930dc556 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java @@ -20,18 +20,18 @@ import com.webauthn4j.data.AuthenticatorTransport; import com.webauthn4j.data.PublicKeyCredentialType; -import com.wultra.security.powerauth.client.PowerAuthFido2Client; -import com.wultra.security.powerauth.client.model.entity.fido2.AllowCredentials; -import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; -import com.wultra.security.powerauth.client.model.request.fido2.AssertionChallengeRequest; -import com.wultra.security.powerauth.client.model.request.fido2.AssertionVerificationRequest; -import com.wultra.security.powerauth.client.model.response.fido2.AssertionChallengeResponse; -import com.wultra.security.powerauth.client.model.response.fido2.AssertionVerificationResponse; +import com.wultra.security.powerauth.fido2.client.PowerAuthFido2Client; import com.wultra.security.powerauth.fido2.configuration.WebAuthnConfiguration; import com.wultra.security.powerauth.fido2.controller.request.AssertionOptionsRequest; import com.wultra.security.powerauth.fido2.controller.request.VerifyAssertionRequest; import com.wultra.security.powerauth.fido2.controller.response.AssertionOptionsResponse; import com.wultra.security.powerauth.fido2.controller.response.CredentialDescriptor; +import com.wultra.security.powerauth.fido2.model.entity.AllowCredentials; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; +import com.wultra.security.powerauth.fido2.model.request.AssertionChallengeRequest; +import com.wultra.security.powerauth.fido2.model.request.AssertionVerificationRequest; +import com.wultra.security.powerauth.fido2.model.response.AssertionChallengeResponse; +import com.wultra.security.powerauth.fido2.model.response.AssertionVerificationResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -56,9 +56,9 @@ public class AssertionService { * Build public key assertion options. * @param request Request form with user input. * @return Public key assertion options. - * @throws PowerAuthClientException in case of PowerAuth server communication error. + * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ - public AssertionOptionsResponse assertionOptions(final AssertionOptionsRequest request) throws PowerAuthClientException { + public AssertionOptionsResponse assertionOptions(final AssertionOptionsRequest request) throws PowerAuthFido2Exception { final String userId = request.username(); final String applicationId = request.applicationId(); @@ -89,9 +89,9 @@ public AssertionOptionsResponse assertionOptions(final AssertionOptionsRequest r * Verify credential at PowerAuth server. * @param credential Received public key credential. * @return PowerAuth authentication response. - * @throws PowerAuthClientException in case of PowerAuth server communication error. + * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ - public AssertionVerificationResponse authenticate(final VerifyAssertionRequest credential) throws PowerAuthClientException { + public AssertionVerificationResponse authenticate(final VerifyAssertionRequest credential) throws PowerAuthFido2Exception { final byte[] credentialId = Base64.getUrlDecoder().decode(credential.id()); final AssertionVerificationRequest request = new AssertionVerificationRequest(); @@ -114,7 +114,7 @@ public AssertionVerificationResponse authenticate(final VerifyAssertionRequest c return response; } - private AssertionChallengeResponse fetchChallenge(final String userId, final String applicationId, final String templateName, final Map operationParameters) throws PowerAuthClientException { + private AssertionChallengeResponse fetchChallenge(final String userId, final String applicationId, final String templateName, final Map operationParameters) throws PowerAuthFido2Exception { logger.info("Getting registration challenge for userId={}, applicationId={}, template={}, parameters={}", userId, applicationId, templateName, operationParameters); final AssertionChallengeRequest request = new AssertionChallengeRequest(); if (StringUtils.hasText(userId)) { diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/Fido2SharedService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/Fido2SharedService.java index b518408c..b1b4c8c1 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/Fido2SharedService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/Fido2SharedService.java @@ -21,12 +21,13 @@ import com.webauthn4j.data.AuthenticatorTransport; import com.webauthn4j.data.PublicKeyCredentialType; import com.wultra.security.powerauth.client.PowerAuthClient; -import com.wultra.security.powerauth.client.PowerAuthFido2Client; import com.wultra.security.powerauth.client.model.entity.Application; -import com.wultra.security.powerauth.client.model.entity.fido2.AuthenticatorDetail; import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; import com.wultra.security.powerauth.client.model.response.OperationTemplateDetailResponse; +import com.wultra.security.powerauth.fido2.client.PowerAuthFido2Client; import com.wultra.security.powerauth.fido2.controller.response.CredentialDescriptor; +import com.wultra.security.powerauth.fido2.model.entity.AuthenticatorDetail; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -56,9 +57,9 @@ public class Fido2SharedService { * @param userId User to whom the credentials belong. * @param applicationId Of the used application. * @return List of credentials. - * @throws PowerAuthClientException if there is an error in PowerAuth communication. + * @throws PowerAuthFido2Exception if there is an error in PowerAuth communication. */ - public List fetchExistingCredentials(final String userId, final String applicationId) throws PowerAuthClientException { + public List fetchExistingCredentials(final String userId, final String applicationId) throws PowerAuthFido2Exception { if (!StringUtils.hasText(userId) || !StringUtils.hasText(applicationId)) { return Collections.emptyList(); } @@ -92,7 +93,7 @@ public List fetchTemplateNameList() throws PowerAuthClientException { .sorted().toList(); } - private List listAuthenticators(final String userId, final String applicationId) throws PowerAuthClientException { + private List listAuthenticators(final String userId, final String applicationId) throws PowerAuthFido2Exception { return fido2Client.getRegisteredAuthenticatorList(userId, applicationId).getAuthenticators(); } diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java index 0d1b06db..79d0b9e7 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java @@ -23,16 +23,16 @@ import com.webauthn4j.data.PublicKeyCredentialType; import com.webauthn4j.data.PublicKeyCredentialUserEntity; import com.webauthn4j.data.attestation.statement.COSEAlgorithmIdentifier; -import com.wultra.security.powerauth.client.PowerAuthFido2Client; -import com.wultra.security.powerauth.client.model.entity.fido2.AuthenticatorParameters; -import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; -import com.wultra.security.powerauth.client.model.request.fido2.RegistrationRequest; -import com.wultra.security.powerauth.client.model.response.fido2.RegistrationChallengeResponse; -import com.wultra.security.powerauth.client.model.response.fido2.RegistrationResponse; +import com.wultra.security.powerauth.fido2.client.PowerAuthFido2Client; import com.wultra.security.powerauth.fido2.configuration.WebAuthnConfiguration; import com.wultra.security.powerauth.fido2.controller.request.RegisterCredentialRequest; import com.wultra.security.powerauth.fido2.controller.request.RegistrationOptionsRequest; import com.wultra.security.powerauth.fido2.controller.response.RegistrationOptionsResponse; +import com.wultra.security.powerauth.fido2.model.entity.AuthenticatorParameters; +import com.wultra.security.powerauth.fido2.model.error.PowerAuthFido2Exception; +import com.wultra.security.powerauth.fido2.model.request.RegistrationRequest; +import com.wultra.security.powerauth.fido2.model.response.RegistrationChallengeResponse; +import com.wultra.security.powerauth.fido2.model.response.RegistrationResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -58,9 +58,9 @@ public class RegistrationService { * Build public key registration options. * @param request Request form with user input. * @return Public key registration options. - * @throws PowerAuthClientException in case of PowerAuth server communication error. + * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ - public RegistrationOptionsResponse registerOptions(final RegistrationOptionsRequest request) throws PowerAuthClientException { + public RegistrationOptionsResponse registerOptions(final RegistrationOptionsRequest request) throws PowerAuthFido2Exception { final String userId = request.username(); final String applicationId = request.applicationId(); @@ -83,9 +83,9 @@ public RegistrationOptionsResponse registerOptions(final RegistrationOptionsRequ * Register credential at PowerAuth server. * @param credential Newly created public key credential * @return PowerAuth registration response. - * @throws PowerAuthClientException in case of PowerAuth server communication error. + * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ - public RegistrationResponse register(final RegisterCredentialRequest credential) throws PowerAuthClientException { + public RegistrationResponse register(final RegisterCredentialRequest credential) throws PowerAuthFido2Exception { logger.info("Registering created credential of userId={}, applicationId={}", credential.username(), credential.applicationId()); final RegistrationRequest request = new RegistrationRequest(); @@ -99,7 +99,7 @@ public RegistrationResponse register(final RegisterCredentialRequest credential) return response; } - private RegistrationChallengeResponse fetchChallenge(final String userId, final String applicationId) throws PowerAuthClientException { + private RegistrationChallengeResponse fetchChallenge(final String userId, final String applicationId) throws PowerAuthFido2Exception { logger.info("Getting registration challenge for userId={}, applicationId={}", userId, applicationId); final RegistrationChallengeResponse response = fido2Client.requestRegistrationChallenge(userId, applicationId); logger.debug("Registration challenge response for userId={}: {}", userId, response); From 678b0b78244c06aff4568d57a3055223a6c4df5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pe=C5=A1ek?= Date: Mon, 15 Apr 2024 16:44:55 +0200 Subject: [PATCH 05/56] Fix #410: FIDO2 Test application: Fix logging typo (#411) --- .../security/powerauth/fido2/service/AssertionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java index 930dc556..406dc0b3 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java @@ -115,7 +115,7 @@ public AssertionVerificationResponse authenticate(final VerifyAssertionRequest c } private AssertionChallengeResponse fetchChallenge(final String userId, final String applicationId, final String templateName, final Map operationParameters) throws PowerAuthFido2Exception { - logger.info("Getting registration challenge for userId={}, applicationId={}, template={}, parameters={}", userId, applicationId, templateName, operationParameters); + logger.info("Getting assertion challenge for userId={}, applicationId={}, template={}, parameters={}", userId, applicationId, templateName, operationParameters); final AssertionChallengeRequest request = new AssertionChallengeRequest(); if (StringUtils.hasText(userId)) { request.setUserId(userId); From a17ae427e917ff8c43e8135f71970d3cd67cf111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Wed, 17 Apr 2024 09:36:45 +0200 Subject: [PATCH 06/56] Fix #414: Fix swagger generation anchors for test server swagger-ui --- .../app/testserver/controller/ApplicationController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-test-server/src/main/java/com/wultra/security/powerauth/app/testserver/controller/ApplicationController.java b/powerauth-test-server/src/main/java/com/wultra/security/powerauth/app/testserver/controller/ApplicationController.java index 98f1b597..ea1827e6 100644 --- a/powerauth-test-server/src/main/java/com/wultra/security/powerauth/app/testserver/controller/ApplicationController.java +++ b/powerauth-test-server/src/main/java/com/wultra/security/powerauth/app/testserver/controller/ApplicationController.java @@ -56,7 +56,7 @@ public ApplicationController(ApplicationService applicationService) { * @throws AppConfigInvalidException Thrown in case mobile SDK configuration is invalid. */ @PostMapping("config") - public Response createActivation(@Valid @RequestBody ObjectRequest request) throws AppConfigInvalidException { + public Response configActivation(@Valid @RequestBody ObjectRequest request) throws AppConfigInvalidException { return applicationService.configureApplication(request.getRequestObject()); } From e5730422e048c7b03d42c7cb2cb90f4163a7064d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Thu, 18 Apr 2024 10:48:16 +0200 Subject: [PATCH 07/56] Merge pull request #413 from wultra/issues/412-build-fido2-tests * Fix #412: Add build pipeline for fido2-tests war --- .../workflows/maven-deploy-fido2-tests.yml | 22 +++++++++++++++++++ ...eploy.yml => maven-deploy-test-server.yml} | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/maven-deploy-fido2-tests.yml rename .github/workflows/{maven-deploy.yml => maven-deploy-test-server.yml} (79%) diff --git a/.github/workflows/maven-deploy-fido2-tests.yml b/.github/workflows/maven-deploy-fido2-tests.yml new file mode 100644 index 00000000..eb5db212 --- /dev/null +++ b/.github/workflows/maven-deploy-fido2-tests.yml @@ -0,0 +1,22 @@ +name: Deploy FIDO2 Tests with Maven + +on: + workflow_dispatch: + branches: + - 'develop' + - 'master' + - 'releases/*' + +jobs: + maven-deploy-manual: + if: ${{ github.event_name == 'workflow_dispatch' }} + name: Manual deploy fido2-tests + uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop + with: + environment: internal-publish + release_type: snapshot + directory_path: ./powerauth-fido2-tests + java_version: 21 + secrets: + username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy-test-server.yml similarity index 79% rename from .github/workflows/maven-deploy.yml rename to .github/workflows/maven-deploy-test-server.yml index f098c09d..a8788860 100644 --- a/.github/workflows/maven-deploy.yml +++ b/.github/workflows/maven-deploy-test-server.yml @@ -1,4 +1,4 @@ -name: Deploy with Maven +name: Deploy Test Server with Maven on: workflow_dispatch: @@ -10,7 +10,7 @@ on: jobs: maven-deploy-manual: if: ${{ github.event_name == 'workflow_dispatch' }} - name: Manual deploy + name: Manual deploy test-server uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop with: environment: internal-publish @@ -19,4 +19,4 @@ jobs: java_version: 21 secrets: username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} - password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} \ No newline at end of file From cbf3f727d820665a9840573d231a752287a0efe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pe=C5=A1ek?= Date: Thu, 18 Apr 2024 15:25:11 +0200 Subject: [PATCH 08/56] Fix #416: FIDO2 Test application: check if getTransports is a function (#417) --- .../src/main/webapp/resources/js/webauthn.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/powerauth-fido2-tests/src/main/webapp/resources/js/webauthn.js b/powerauth-fido2-tests/src/main/webapp/resources/js/webauthn.js index 34bf0468..e122cc2e 100644 --- a/powerauth-fido2-tests/src/main/webapp/resources/js/webauthn.js +++ b/powerauth-fido2-tests/src/main/webapp/resources/js/webauthn.js @@ -154,6 +154,12 @@ async function fetchAssertionOptions(username, applicationId, templateName, oper async function registerCredentials(username, applicationId, credential) { const userVerification = $("#userVerification").val(); + // Although getTransports() is required by WebAuthn specification, some browsers do not support it + let transports = []; + if (typeof credential.response.getTransports === 'function') { + transports = credential.response.getTransports(); + } + // RP entity and allowedOrigins are added on backend level const requestBody = { applicationId: applicationId, @@ -165,7 +171,7 @@ async function registerCredentials(username, applicationId, credential) { response: { clientDataJSON: toBase64(credential.response.clientDataJSON), attestationObject: toBase64(credential.response.attestationObject), - transports: credential.response.getTransports() + transports: transports } }; From 6ae2d612d71e689f328ee6d38301cbf9d1a96cb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:02:22 +0000 Subject: [PATCH 09/56] Bump org.bouncycastle:bcprov-jdk18on from 1.78 to 1.78.1 Bumps [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.78 to 1.78.1. - [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) --- updated-dependencies: - dependency-name: org.bouncycastle:bcprov-jdk18on dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a5424c4b..07415501 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ 1.8.0-SNAPSHOT 1.10.0-SNAPSHOT - 1.78 + 1.78.1 2.5.0 7.4 0.23.0.RELEASE From 8e2ea8caf88daf558b1d91c496dd017140878666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:02:35 +0000 Subject: [PATCH 10/56] Bump org.springframework.boot:spring-boot-starter-parent Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.2.4 to 3.2.5. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.2.4...v3.2.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a5424c4b..6a6dc85d 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.4 + 3.2.5 From 6a524b70bc7634c5025e2c72c3834ac30feebbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Ra=C4=8Dansk=C3=BD?= Date: Tue, 23 Apr 2024 09:21:16 +0200 Subject: [PATCH 11/56] Fix #418: Refactor BouncyCastle dependency (#419) - Use transient dependency from `powerauth-crypto` --- pom.xml | 7 ------- powerauth-backend-tests/pom.xml | 5 ----- powerauth-load-tests/pom.xml | 4 ---- powerauth-test-server/pom.xml | 4 ---- powerauth-webflow-tests/pom.xml | 5 ----- 5 files changed, 25 deletions(-) diff --git a/pom.xml b/pom.xml index 2fabce51..617d70aa 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,6 @@ 1.8.0-SNAPSHOT 1.10.0-SNAPSHOT - 1.78.1 2.5.0 7.4 0.23.0.RELEASE @@ -71,12 +70,6 @@ - - org.bouncycastle - bcprov-jdk18on - ${bc.version} - - io.getlime.security diff --git a/powerauth-backend-tests/pom.xml b/powerauth-backend-tests/pom.xml index 6688e176..7dd9ff6b 100644 --- a/powerauth-backend-tests/pom.xml +++ b/powerauth-backend-tests/pom.xml @@ -92,11 +92,6 @@ - - org.bouncycastle - bcprov-jdk18on - - io.netty diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 95cf1697..279bf075 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -51,10 +51,6 @@ io.getlime.security powerauth-java-cmd-lib - - org.bouncycastle - bcprov-jdk18on - diff --git a/powerauth-test-server/pom.xml b/powerauth-test-server/pom.xml index 2a0304cf..c85221da 100644 --- a/powerauth-test-server/pom.xml +++ b/powerauth-test-server/pom.xml @@ -127,10 +127,6 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 - - org.bouncycastle - bcprov-jdk18on - diff --git a/powerauth-webflow-tests/pom.xml b/powerauth-webflow-tests/pom.xml index efa53101..2453d5a8 100644 --- a/powerauth-webflow-tests/pom.xml +++ b/powerauth-webflow-tests/pom.xml @@ -97,11 +97,6 @@ - - org.bouncycastle - bcprov-jdk18on - - From b1b9c513606bf7e914e40d6f6d55a378d51054bb Mon Sep 17 00:00:00 2001 From: Jan Dusil <134381434+jandusil@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:59:55 +0200 Subject: [PATCH 12/56] Fix #353: Add Gatling load tests scenarios for performance tests (#354) * Fix #353: Add Gatling load tests scenarios for performance tests - Improve maven deps for gatling java/scala distinction - Create base scenarios for registrations and operations - Create simulation for perf tests - add javadoc - add storing data between simulations --- powerauth-load-tests/lombok.config | 1 + powerauth-load-tests/pom.xml | 44 +++- .../test/config/PowerAuthLoadTestCommon.java | 191 ++++++++++++++++++ .../test/model/UserRegistrationInfo.java | 32 +++ .../test/runner/DataPreparationRunner.java | 36 ++++ .../test/runner/PerformanceTestRunner.java | 36 ++++ .../scenario/CreateApplicationScenario.java | 94 +++++++++ .../CreateApproveOperationScenario.java | 76 +++++++ .../test/scenario/CreateCallbackScenario.java | 72 +++++++ .../scenario/CreateOperationScenario.java | 61 ++++++ .../scenario/CreateRegistrationScenario.java | 137 +++++++++++++ .../ListOperationHistoryScenario.java | 70 +++++++ .../test/shared/SessionDataUtils.java | 97 +++++++++ .../test/shared/SharedSessionData.java | 55 +++++ .../simulation/DataPreparationSimulation.java | 83 ++++++++ .../simulation/PerformanceTestSimulation.java | 84 ++++++++ .../src/test/resources/.perf_test_config | 7 + .../src/test/resources/logback-test.xml | 16 +- .../src/main/resources/application.properties | 1 + 19 files changed, 1184 insertions(+), 9 deletions(-) create mode 100644 powerauth-load-tests/lombok.config create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/config/PowerAuthLoadTestCommon.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/model/UserRegistrationInfo.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApplicationScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApproveOperationScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateCallbackScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateOperationScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateRegistrationScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/ListOperationHistoryScenario.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SessionDataUtils.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SharedSessionData.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/DataPreparationSimulation.java create mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/PerformanceTestSimulation.java create mode 100644 powerauth-load-tests/src/test/resources/.perf_test_config diff --git a/powerauth-load-tests/lombok.config b/powerauth-load-tests/lombok.config new file mode 100644 index 00000000..2bb794fd --- /dev/null +++ b/powerauth-load-tests/lombok.config @@ -0,0 +1 @@ +lombok.log.fieldName=logger diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 279bf075..38075b99 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -9,7 +9,6 @@ 1.8.0-SNAPSHOT - com.wultra powerauth-load-tests 2021 @@ -59,18 +58,47 @@ ${gatling.version} test + + + io.gatling + gatling-test-framework + ${gatling.version} + test + + + + org.postgresql + postgresql + test + + + + org.wiremock + wiremock-standalone + 3.4.2 + test + + + + org.apache.commons + commons-lang3 + test + - src/test/scala + net.alchim31.maven scala-maven-plugin ${maven-plugin-scala.version} + scala-test-compile + test-compile + add-source testCompile @@ -85,13 +113,15 @@ -language:implicitConversions -language:postfixOps + ${scala.version} + + src/test/scala - - ${scala.version} - + + io.gatling gatling-maven-plugin @@ -99,9 +129,11 @@ ${project.basedir}/target/test-results/gatling ${project.basedir}/src/test/scala - Wultra PowerAuth Load Test + Wultra PowerAuth Load Test Scala + + org.apache.maven.plugins maven-surefire-plugin diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/config/PowerAuthLoadTestCommon.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/config/PowerAuthLoadTestCommon.java new file mode 100644 index 00000000..a0cd0196 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/config/PowerAuthLoadTestCommon.java @@ -0,0 +1,191 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.wultra.security.powerauth.test.shared.SharedSessionData; +import io.gatling.javaapi.core.FeederBuilder; +import io.gatling.javaapi.http.HttpProtocolBuilder; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static java.util.UUID.randomUUID; + +/** + * Provides common configurations and utilities for performing load testing on PowerAuth applications. + * This class contains configurations for maximum concurrent users, preparation and execution phase settings, + * and credentials for PowerAuth administration. It also provides methods to fetch environment variable values + * and to create JDBC feeders for Gatling tests. + *

+ * All configuration values can be customized via environment variables. Defaults are provided for ease of use + * and quick setup. + *

+ * + * @author Jan Dusil, jan.dusil@wultra.com + */ +@Slf4j +public class PowerAuthLoadTestCommon { + + @Setter + @Getter + private static boolean isPreparationPhase = false; + + private static FeederBuilder userDataFeedList; + + private static FeederBuilder.FileBased userDataFeedJson; + + private static final String DATA_DUMP_FILE = "registrationDataFeed.json"; + + /* Empirical value from testing */ + public static final int MAX_CONCURRENT_USERS = 20; + + /* Total number of registrations to prepare during preparation phase */ + public static final int PERF_TEST_PREP_N_REG = getIntEnv("PERF_TEST_PREP_N_REG", 100); + + /* Total number of operations per registration to prepare during preparation phase */ + public static final int PERF_TEST_PREP_M_OP = getIntEnv("PERF_TEST_PREP_M_OP", 1000); + + /* Number of registrations to add during execution phase per sec */ + public static final int PERF_TEST_EXE_X_REG = getIntEnv("PERF_TEST_EXE_X_REG", 1); + + /* Number of operations to add during execution phase per sec */ + public static final int PERF_TEST_EXE_Y_OP = getIntEnv("PERF_TEST_EXE_Y_OP", 50); + + /* The length of the execution phase in minutes */ + public static final int PERF_TEST_EXE_MIN = getIntEnv("PERF_TEST_EXE_MIN", 1); + + public static final String PAC_ADMIN_USER = getStringEnv("PAC_ADMIN_USER", "system-admin"); + public static final String PAC_ADMIN_PASS = getStringEnv("PAC_ADMIN_PASS", ""); + public static final String PAC_URL = getStringEnv("PAC_URL", "http://localhost:8089/powerauth-cloud"); + public static final String TEST_SERVER_URL = getStringEnv("TEST_SERVER_URL", "http://localhost:8081"); + public static final String CALLBACK_URL = getStringEnv("PERF_TEST_CALLBACK_URL", "http://localhost:8090/mock-callback"); + + /** + * Common HTTP protocol configuration for Gatling tests. + */ + public final static HttpProtocolBuilder commonProtocol = http + .contentTypeHeader("application/json") + .acceptHeader("application/json") + .userAgentHeader("PowerAuth-LoadTest/gatling").check(); + + /** + * Fetches an integer environment variable by name, or returns the default value if not found or invalid. + * + * @param name The name of the environment variable. + * @param defaultValue The default value to use if the environment variable is not found or invalid. + * @return The environment variable value as an integer, or the default value. + */ + private static int getIntEnv(final String name, final int defaultValue) { + final String value = System.getenv(name); + if (StringUtils.isNotBlank(value)) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + logger.warn("Environment variable {} is not a valid integer: {}. Using default value.", name, defaultValue); + } + } + return defaultValue; + } + + /** + * Fetches a string environment variable by name, or returns the default value if not found. + * + * @param name The name of the environment variable. + * @param defaultValue The default value to use if the environment variable is not found. + * @return The environment variable value as a string, or the default value. + */ + private static String getStringEnv(final String name, final String defaultValue) { + final String value = System.getenv(name); + if (StringUtils.isNotBlank(value)) { + return value; + } else { + logger.warn("Environment variable {} is not set correctly: {}. Using default value.", name, defaultValue); + return defaultValue; + } + } + + /** + * Generates a unique user ID using a UUID for testing purposes. + * + * @return A string representing a unique test user ID. + */ + private static String generateUserId() { + return "TEST_USER_ID" + randomUUID(); + } + + /** + * Prepares user data feed for simulations. If in preparation phase, generates a list of users with unique IDs. + * Otherwise, loads user data from a JSON file. This method ensures that user data is available for testing, + * regardless of the phase of the test. + */ + public static void prepareFeedDataUsers() { + if (isPreparationPhase()) { + final List> userList = Stream.generate(() -> { + final Map stringObjectMap = new HashMap<>(); + stringObjectMap.put("testUserId", generateUserId()); + return stringObjectMap; + }) + .limit(PERF_TEST_PREP_N_REG) + .toList(); + + userDataFeedList = listFeeder(userList); + } else { + userDataFeedJson = jsonFile(DATA_DUMP_FILE); + } + } + + /** + * Returns the appropriate user data feeder for simulations based on the current phase. + * If in preparation phase, returns a feeder with generated user data. Otherwise, returns a feeder + * with user data loaded from a JSON file. + * + * @return A {@link FeederBuilder} object containing user data for the simulation. + */ + public static FeederBuilder getUserDataFeed() { + if (isPreparationPhase()) { + return userDataFeedList; + } else { + return userDataFeedJson; + } + } + + /** + * Saves generated user registration data into a JSON file for later use. This method is called + * after data preparation phase to persist the generated data, making it available for subsequent + * execution phases or future test runs. + */ + public static void saveGeneratedData() { + final ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.writeValue(new File("src/test/resources/" + DATA_DUMP_FILE), SharedSessionData.registrationData); + } catch (IOException e) { + logger.warn("Unable to save generated user data, due to : {}", e.getMessage()); + } + } +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/model/UserRegistrationInfo.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/model/UserRegistrationInfo.java new file mode 100644 index 00000000..a5d3927e --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/model/UserRegistrationInfo.java @@ -0,0 +1,32 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.model; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserRegistrationInfo { + + private String testUserId; + private String registrationId; + private String appId; + private String integrationUser; + private String integrationUserPass; +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java new file mode 100644 index 00000000..c5f8be04 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java @@ -0,0 +1,36 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.runner; + +import com.wultra.security.powerauth.test.simulation.DataPreparationSimulation; +import io.gatling.app.Gatling; +import io.gatling.core.config.GatlingPropertiesBuilder; + +/** + * Executes the DataPreparationSimulation for PowerAuth load testing setup. Useful for initializing test data + * and debugging. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class DataPreparationRunner { + public static void main(String[] args) { + final GatlingPropertiesBuilder props = new GatlingPropertiesBuilder() + .simulationClass(DataPreparationSimulation.class.getName()); + Gatling.fromMap(props.build()); + } +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java new file mode 100644 index 00000000..dbcc3209 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java @@ -0,0 +1,36 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.runner; + +import com.wultra.security.powerauth.test.simulation.PerformanceTestSimulation; +import io.gatling.app.Gatling; +import io.gatling.core.config.GatlingPropertiesBuilder; + +/** + * Executes the PerformanceTestSimulation for conducting performance tests on PowerAuth applications, useful for debugging. + * Utilizes Gatling to run specified simulation, focusing on evaluating the performance under various load conditions. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class PerformanceTestRunner { + public static void main(String[] args) { + GatlingPropertiesBuilder props = new GatlingPropertiesBuilder() + .simulationClass(PerformanceTestSimulation.class.getName()); + Gatling.fromMap(props.build()); + } +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApplicationScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApplicationScenario.java new file mode 100644 index 00000000..b0ac1106 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApplicationScenario.java @@ -0,0 +1,94 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import com.wultra.security.powerauth.test.shared.SessionDataUtils; +import io.gatling.javaapi.core.ScenarioBuilder; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static java.util.UUID.randomUUID; + +/** + * Defines a Gatling scenario for creating a new application in the PowerAuth system. + * The scenario includes making HTTP requests to the PowerAuth Cloud to create an application, + * adding user access to the newly created application, and configuring the application on the Test Server. + * Utilizes dynamic values for application name and roles, and stores important response details for future steps. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class CreateApplicationScenario { + + private static final String APP_NAME = "TEST_APP_" + randomUUID(); + private static final String INTEGRATION_USER_NAME = "integration-user-" + randomUUID(); + private static final String APP_ROLE = "ROLE_ADMIN"; + + public static final ScenarioBuilder createApplicationScenario = scenario(CreateApplicationScenario.class.getName()) + .exec( + http("Create Application PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/admin/applications") + .basicAuth(PowerAuthLoadTestCommon.PAC_ADMIN_USER, PowerAuthLoadTestCommon.PAC_ADMIN_PASS) + .body(StringBody(""" + { + "id": "%s", + "roles": [ + "%s" + ] + } + """.formatted(APP_NAME, APP_ROLE))) + .check(jmesPath("masterServerPublicKey").saveAs("masterServerPublicKey"), + jmesPath("appKey").saveAs("appKey"), + jmesPath("appSecret").saveAs("appSecret"), + jmesPath("mobileSdkConfig").saveAs("mobileSdkConfig"), + jmesPath("id").saveAs("appId")) + ) + .exec( + http("Create new integration user") + .post(PowerAuthLoadTestCommon.PAC_URL + "/admin/users") + .basicAuth(PowerAuthLoadTestCommon.PAC_ADMIN_USER, PowerAuthLoadTestCommon.PAC_ADMIN_PASS) + .body(StringBody(""" + { + "username": "%s" + } + } + """.formatted(INTEGRATION_USER_NAME))) + .check(jmesPath("username").saveAs("pac-int-user")) + .check(jmesPath("password").saveAs("pac-int-user-pass"))) + .exec( + http("Add app access to integration user") + .post(PowerAuthLoadTestCommon.PAC_URL + "/admin/users/#{pac-int-user}/applications/#{appId}") + .basicAuth(PowerAuthLoadTestCommon.PAC_ADMIN_USER, PowerAuthLoadTestCommon.PAC_ADMIN_PASS) + ) + .exec( + http("Create application Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/application/config") + .body(StringBody(""" + { + "requestObject": { + "applicationId": "#{appId}", + "applicationName": "%s", + "applicationKey": "#{appKey}", + "applicationSecret": "#{appSecret}", + "masterPublicKey": "#{masterServerPublicKey}", + "mobileSdkConfig": "#{mobileSdkConfig}" + } + } + """.formatted(APP_NAME)))) + .exec(SessionDataUtils.saveSessionData()); +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApproveOperationScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApproveOperationScenario.java new file mode 100644 index 00000000..efc6c272 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateApproveOperationScenario.java @@ -0,0 +1,76 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import io.gatling.javaapi.core.ScenarioBuilder; +import lombok.extern.slf4j.Slf4j; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static io.gatling.javaapi.http.HttpDsl.status; + +/** + * Defines a scenario for creating and approving operations in PowerAuth. + * Utilizes predefined user and application data to simulate operation creation and approval + * against both PowerAuth Cloud and a Test Server. It randomizes user selection for operation + * initiation. + *

+ * This scenario is part of the suite to evaluate the performance and robustness of the PowerAuth solution. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +@Slf4j +public class CreateApproveOperationScenario{ + + public static final ScenarioBuilder createApproveOperationScenario = scenario(CreateApproveOperationScenario.class.getName()) + .feed(PowerAuthLoadTestCommon.getUserDataFeed().circular()) + .exec( + /* This works assuming template in pa_operation_template is defined */ + http("Create operation PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/operations") + .basicAuth("#{integrationUser}", "#{integrationUserPass}") + .body(StringBody(""" + { + "userId": "#{testUserId}", + "template": "login", + "language": "en" + } + """) + ) + .check(status().is(200)) + .check((jmesPath("operationId").saveAs("operationId"))) + ) + .exec( + http("Approve Operation Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/operations/approve") + .body(StringBody(""" + { + "requestObject": + { + "activationId": "#{registrationId}", + "applicationId": "#{appId}", + "password": "1234", + "operationData": "A2", + "operationId": "#{operationId}" + } + } + """)) + .check(status().is(200)) + ); +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateCallbackScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateCallbackScenario.java new file mode 100644 index 00000000..9f40baa9 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateCallbackScenario.java @@ -0,0 +1,72 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import io.gatling.javaapi.core.ScenarioBuilder; + + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static io.gatling.javaapi.http.HttpDsl.status; +import static java.util.UUID.randomUUID; + +/** + * Defines a Gatling scenario for creating callback configurations in PowerAuth Cloud. + * This scenario focuses on setting up callbacks for both operation status changes and registration status changes. + * Each callback is associated with a randomly generated name and is configured to post + * notifications to a mock callback URL. + *

+ * Successful creation of callbacks is validated by checking the HTTP response status. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ + +public class CreateCallbackScenario { + private static final String CALLBACK_NAME = "TEST_CALLBACK_" + randomUUID(); + public static final ScenarioBuilder createCallbackScenario = scenario(CreateCallbackScenario.class.getName()) + .feed(PowerAuthLoadTestCommon.getUserDataFeed().shuffle()) + .exec( + http("Create callback PowerAuth Cloud - Operations") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/admin/applications/#{appId}/callbacks") + .basicAuth("#{integrationUser}", "#{integrationUserPass}") + .body(StringBody(""" + { + "name": "%s", + "type": "OPERATION_STATUS_CHANGE", + "callbackUrl": "%s" + } + """.formatted(CALLBACK_NAME, PowerAuthLoadTestCommon.CALLBACK_URL)) + ) + .check(status().is(200)) + ).exec( + http("Create callback PowerAuth Cloud - Registrations") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/admin/applications/#{appId}/callbacks") + .basicAuth("#{integrationUser}", "#{integrationUserPass}") + .body(StringBody(""" + { + "name": "%s", + "type": "REGISTRATION_STATUS_CHANGE", + "callbackUrl": "%s" + } + """.formatted(CALLBACK_NAME, PowerAuthLoadTestCommon.CALLBACK_URL)) + ) + .check(status().is(200)) + ); + +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateOperationScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateOperationScenario.java new file mode 100644 index 00000000..e55c462b --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateOperationScenario.java @@ -0,0 +1,61 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; + +import com.wultra.security.powerauth.test.shared.SessionDataUtils; +import io.gatling.javaapi.core.ScenarioBuilder; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static io.gatling.javaapi.http.HttpDsl.status; + +/** + * Defines a Gatling scenario for creating operations within the PowerAuth system. + * This scenario simulates the process of selecting a random user from a pre-defined list and creating an operation + * for that user in PowerAuth Cloud using a specified template. The selection of the user and the operation creation + * are performed dynamically during the test execution. + *

+ * It requires the presence of a valid operation template in the PowerAuth system and utilizes user IDs + * collected in previous test scenarios. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class CreateOperationScenario { + + public static final ScenarioBuilder createOperationScenario = scenario(CreateOperationScenario.class.getName()) + .exec(SessionDataUtils.prepareSessionData()) + .repeat(PowerAuthLoadTestCommon.PERF_TEST_PREP_M_OP / PowerAuthLoadTestCommon.MAX_CONCURRENT_USERS).on( + feed(PowerAuthLoadTestCommon.getUserDataFeed().shuffle().circular()) + .exec( + http("Create operation PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/operations") + .basicAuth("#{pac-int-user}", "#{pac-int-user-pass}") + .body(StringBody(""" + { + "userId": "#{testUserId}", + "template": "login", + "language": "en" + } + """) + ) + .check(status().is(200)) + + )); +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateRegistrationScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateRegistrationScenario.java new file mode 100644 index 00000000..51c23b8c --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/CreateRegistrationScenario.java @@ -0,0 +1,137 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import com.wultra.security.powerauth.test.shared.SessionDataUtils; +import io.gatling.javaapi.core.ScenarioBuilder; + +import static com.wultra.security.powerauth.test.shared.SessionDataUtils.prepareSessionData; +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static io.gatling.javaapi.http.HttpDsl.status; + +/** + * Implements a scenario for testing user registration, activation, and commitment in PowerAuth. + * This scenario simulates the complete lifecycle of a user's registration and activation process + * by dynamically generating a unique user ID, creating a registration in PowerAuth Cloud, initiating + * an activation on the Test Server, and committing the registration. + *

+ * The scenario includes checks for successful HTTP responses at each step and utilizes session management + * to pass necessary data between requests. It also adds the generated test user ID to a list of user IDs + * for potential use in subsequent scenarios. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class CreateRegistrationScenario { + + public static final ScenarioBuilder createRegistrationScenario = scenario(CreateRegistrationScenario.class.getName()) + .exec(prepareSessionData()) + .doIfOrElse(String.valueOf(PowerAuthLoadTestCommon.isPreparationPhase())) + .then(repeat((PowerAuthLoadTestCommon.PERF_TEST_PREP_N_REG / PowerAuthLoadTestCommon.MAX_CONCURRENT_USERS)).on( + feed(PowerAuthLoadTestCommon.getUserDataFeed().shuffle()) + .exec( + http("Create registration PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/registrations") + .basicAuth("#{pac-int-user}", "#{pac-int-user-pass}") + .body(StringBody(""" + { + "userId": "#{testUserId}", + "appId": "#{appId}" + } + """) + ) + .check(status().is(200)) + .check((jmesPath("activationCode").saveAs("activationCode"))) + ) + .exec( + http("Create activation Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/activation/create") + .body(StringBody(""" + { + "requestObject": { + "applicationId": "#{appId}", + "activationName": "TEST ACTIVATION", + "password": "1234", + "activationCode": "#{activationCode}" + } + }""") + ) + .check(status().is(200)) + .check((jmesPath("responseObject.activationId").saveAs("activationId"))) + ) + .exec( + http("Commit registration PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/registrations/#{activationId}/commit") + .basicAuth("#{pac-int-user}", "#{pac-int-user-pass}") + .body(StringBody(""" + { + "externalUserId": null + } + """)) + .check(status().is(200)) + ) + .exec(SessionDataUtils.saveSessionData()) + .exec(SessionDataUtils.saveRegistrationData()))) + + .orElse( + feed(PowerAuthLoadTestCommon.getUserDataFeed().shuffle()) + .exec( + http("Create registration PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/registrations") + .basicAuth("#{integrationUser}", "#{integrationUserPass}") + .body(StringBody(""" + { + "userId": "#{testUserId}", + "appId": "#{appId}" + } + """) + ) + .check(status().is(200)) + .check((jmesPath("activationCode").saveAs("activationCode"))) + ) + .exec( + http("Create activation Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/activation/create") + .body(StringBody(""" + { + "requestObject": { + "applicationId": "#{appId}", + "activationName": "TEST ACTIVATION", + "password": "1234", + "activationCode": "#{activationCode}" + } + }""") + ) + .check(status().is(200)) + .check((jmesPath("responseObject.activationId").saveAs("activationId"))) + ) + .exec( + http("Commit registration PowerAuth Cloud") + .post(PowerAuthLoadTestCommon.PAC_URL + "/v2/registrations/#{activationId}/commit") + .basicAuth("#{integrationUser}", "#{integrationUserPass}") + .body(StringBody(""" + { + "externalUserId": null + } + """)) + .check(status().is(200)) + ) + .exec(SessionDataUtils.saveRegistrationData())); + +} \ No newline at end of file diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/ListOperationHistoryScenario.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/ListOperationHistoryScenario.java new file mode 100644 index 00000000..2f925c1a --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/scenario/ListOperationHistoryScenario.java @@ -0,0 +1,70 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.scenario; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import io.gatling.javaapi.core.ScenarioBuilder; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.http; +import static io.gatling.javaapi.http.HttpDsl.status; + +/** + * Defines the Gatling scenario for listing operation history. + *

+ * This scenario simulates the process of creating a token on the test server and + * then using it to list pending operations. It utilizes a circular feeder from + * {@link PowerAuthLoadTestCommon} to ensure a continuous flow of user data. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class ListOperationHistoryScenario { + + public static final ScenarioBuilder listOperationHistoryScenario = scenario(ListOperationHistoryScenario.class.getName()) + .exec(feed(PowerAuthLoadTestCommon.getUserDataFeed().circular())) + .exec(http("Create Token Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/token/create") + .body(StringBody(""" + { + "requestObject": + { + "activationId": "#{registrationId}", + "applicationId": "#{appId}", + "signatureType": "POSSESSION" + }} + """) + ) + .check(status().is(200)) + .check((jmesPath("responseObject.tokenId").saveAs("tokenId"))) + .check((jmesPath("responseObject.tokenSecret").saveAs("tokenSecret")))) + .exec( + http("List Operation History Test Server") + .post(PowerAuthLoadTestCommon.TEST_SERVER_URL + "/operations/pending") + .body(StringBody(""" + { + "requestObject": + { + "activationId": "#{registrationId}", + "tokenId": "#{tokenId}", + "tokenSecret": "#{tokenSecret}" + }} + """) + ) + .check(status().is(200))); + +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SessionDataUtils.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SessionDataUtils.java new file mode 100644 index 00000000..4f0ca7a5 --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SessionDataUtils.java @@ -0,0 +1,97 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.shared; + +import io.gatling.javaapi.core.ChainBuilder; + +import static io.gatling.javaapi.core.CoreDsl.exec; + +import com.wultra.security.powerauth.test.model.UserRegistrationInfo; +import scala.jdk.javaapi.CollectionConverters; + +import java.util.Map; + +/** + * Provides shared session management functionalities for Gatling simulations in PowerAuth Gatling testing. + * Facilitates the transfer and reuse of session data between different simulation scenarios. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public final class SessionDataUtils { + + /** + * Prepares the Gatling session with pre-stored data from {@link SharedSessionData}. + * This method iterates over a static map and sets each key-value pair into the Gatling session. + * Useful for initializing session variables at the beginning of a simulation scenario. + * + * @return A Gatling {@link ChainBuilder} with session variables set for further execution. + */ + public static ChainBuilder prepareSessionData() { + return exec(session -> { + for (final Map.Entry entry : SharedSessionData.transferVariable.entrySet()) { + session = session.set(entry.getKey(), entry.getValue()); + } + return session; + }); + } + + /** + * Saves session data back to a static map in {@link SharedSessionData} at the end of a simulation scenario. + * This allows for the persistence of certain session variables across different Gatling simulation scenarios. + * Only non-null values and keys not containing "gatling" are saved to avoid overwriting internal Gatling data. + * + * @return A Gatling {@link ChainBuilder} that saves session variables for future use. + */ + public static ChainBuilder saveSessionData() { + return exec(session -> { + CollectionConverters.asJava(session.asScala().attributes()).forEach((key, value) -> { + if (value != null && !key.contains("gatling")) { + SharedSessionData.transferVariable.put(key, value); + } + }); + + return session; + }); + } + + /** + * Captures registration-related data from the current Gatling session and stores it in a shared data structure. + * This method constructs a {@link UserRegistrationInfo} object from session variables, including user ID, + * application ID, and credentials. It then adds this object to a shared collection in {@link SharedSessionData}, + * allowing for the aggregation and subsequent use of registration data across different parts of the testing framework. + *

+ * This functionality is particularly useful for scenarios where registration data needs to be accessed or verified + * in subsequent steps of the simulation, ensuring data consistency and availability throughout the testing process. + * + * @return A Gatling {@link ChainBuilder} that captures and stores user registration information for future use + * in the simulation scenarios. + */ + public static ChainBuilder saveRegistrationData() { + return exec(session -> { + final UserRegistrationInfo registrationData = UserRegistrationInfo.builder() + .registrationId(session.getString("activationId")) + .appId(session.getString("appId")) + .testUserId(session.getString("testUserId")) + .integrationUser(session.getString("pac-int-user")) + .integrationUserPass(session.getString("pac-int-user-pass")) + .build(); + SharedSessionData.registrationData.add(registrationData); + return session; + }); + } +} \ No newline at end of file diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SharedSessionData.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SharedSessionData.java new file mode 100644 index 00000000..6f1d6b7e --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/shared/SharedSessionData.java @@ -0,0 +1,55 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.shared; + +import com.wultra.security.powerauth.test.model.UserRegistrationInfo; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Manages shared session data for Gatling performance testing scenarios within PowerAuth systems. + * Utilizes thread-safe collections to facilitate the consistent transfer and access of critical + * test data across various testing scenarios and simulation steps. + * + *

This class contains two main storage structures:

+ * + *
    + *
  • transferVariable: A {@link ConcurrentHashMap} designed to safely store and transfer + * session-related variables, such as user IDs and activation codes, between different parts of + * the simulation. This ensures data consistency and thread safety throughout the test execution.
  • + * + *
  • registrationData: A synchronized {@link List} of {@link UserRegistrationInfo} objects + * which accumulates detailed registration data gathered during the simulations. This list allows + * for the collection and later analysis of user registration flows, including the capture of user, + * application, and authentication details.
  • + *
+ * + *

By providing centralized access to shared data, {@code SharedSessionData} plays a crucial role + * in orchestrating complex simulation scenarios, enabling the reuse of test data and ensuring the + * integrity of performance testing workflows.

+ * + * @author Jan Dusil, jan.dusil@wultra.com + */ +public class SharedSessionData { + public static ConcurrentHashMap transferVariable = new ConcurrentHashMap<>(); + public static List registrationData = Collections.synchronizedList(new ArrayList<>()); +} + diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/DataPreparationSimulation.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/DataPreparationSimulation.java new file mode 100644 index 00000000..cd8bc9cd --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/DataPreparationSimulation.java @@ -0,0 +1,83 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.simulation; + +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import com.wultra.security.powerauth.test.scenario.CreateApplicationScenario; +import com.wultra.security.powerauth.test.scenario.CreateOperationScenario; +import com.wultra.security.powerauth.test.scenario.CreateRegistrationScenario; +import io.gatling.javaapi.core.Simulation; +import lombok.extern.slf4j.Slf4j; + +import static io.gatling.javaapi.core.OpenInjectionStep.atOnceUsers; + +/** + * Prepares the data environment for PowerAuth load testing by simulating application creation, + * user registrations, and operation creation processes. + *

+ * This simulation sequence is critical for setting up a realistic test environment + * that mimics actual user and transactional activity. It executes the following steps: + *

    + *
  1. Creates a single application instance.
  2. + *
  3. Registers multiple users concurrently based on the maximum number of concurrent users defined.
  4. + *
  5. Creates multiple operations concurrently for the registered users.
  6. + *
+ * Each step is crucial for ensuring the subsequent load tests have the necessary data setup for execution. + *

+ * The {@code before()} and {@code after()} methods provide logging information to track the start and end of the preparation phase. + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +@Slf4j +public class DataPreparationSimulation extends Simulation { + + @Override + public void before() { + logger.info("Preparation phase is about to start!"); + } + + @Override + public void after() { + PowerAuthLoadTestCommon.saveGeneratedData(); + logger.info("Preparation phase is finished!"); + } + + public DataPreparationSimulation() { + PowerAuthLoadTestCommon.setPreparationPhase(true); + PowerAuthLoadTestCommon.prepareFeedDataUsers(); + + setUp( + CreateApplicationScenario.createApplicationScenario + .injectOpen(atOnceUsers(1)) + .protocols(PowerAuthLoadTestCommon.commonProtocol) + .andThen( + CreateRegistrationScenario.createRegistrationScenario + .injectOpen(atOnceUsers(PowerAuthLoadTestCommon.MAX_CONCURRENT_USERS)) + .protocols(PowerAuthLoadTestCommon.commonProtocol) + .disablePauses() + .andThen( + CreateOperationScenario.createOperationScenario + .injectOpen(atOnceUsers(PowerAuthLoadTestCommon.MAX_CONCURRENT_USERS)) + .protocols(PowerAuthLoadTestCommon.commonProtocol) + .disablePauses() + ) + ) + + ); + } +} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/PerformanceTestSimulation.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/PerformanceTestSimulation.java new file mode 100644 index 00000000..3b0c6fbd --- /dev/null +++ b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/simulation/PerformanceTestSimulation.java @@ -0,0 +1,84 @@ +/* + * PowerAuth test and related software components + * Copyright (C) 2024 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.test.simulation; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.wultra.security.powerauth.test.config.PowerAuthLoadTestCommon; +import com.wultra.security.powerauth.test.scenario.CreateApproveOperationScenario; +import com.wultra.security.powerauth.test.scenario.CreateCallbackScenario; +import com.wultra.security.powerauth.test.scenario.CreateRegistrationScenario; +import com.wultra.security.powerauth.test.scenario.ListOperationHistoryScenario; +import io.gatling.javaapi.core.Simulation; +import lombok.extern.slf4j.Slf4j; + +import java.time.Duration; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.core.OpenInjectionStep.atOnceUsers; + +/** + * Orchestrates the execution of performance testing scenarios for PowerAuth components. + * This simulation includes steps for creating callbacks, registering users, approving operations, + * and listing operation history to evaluate the performance under various conditions. + *

+ * It utilizes WireMock for mocking external service responses during local testing. The simulation sequence + * is designed to mimic realistic user behavior and system interactions to identify potential bottlenecks and + * performance issues. + *

+ * + * @author Jan Dusil, jan.dusil@wultra.com + */ +@Slf4j +public class PerformanceTestSimulation extends Simulation { + + private final WireMockServer wireMockServer = new WireMockServer(8090); + + @Override + public void before() { + /* Uncomment for local testing + wireMockServer.stubFor(get(urlEqualTo("/mock-callback")).willReturn(aResponse().withBody("Callback ok"))); + wireMockServer.start(); + */ + logger.info("Execution phase is about to start!"); + } + + @Override + public void after() { + logger.info("Execution phase is finished!"); + wireMockServer.stop(); + } + + + public PerformanceTestSimulation() { + PowerAuthLoadTestCommon.prepareFeedDataUsers(); + setUp( + /* Load test */ + CreateCallbackScenario.createCallbackScenario + .injectOpen(atOnceUsers(1)) + .protocols(PowerAuthLoadTestCommon.commonProtocol).andThen( + CreateRegistrationScenario.createRegistrationScenario + .injectOpen(constantUsersPerSec(PowerAuthLoadTestCommon.PERF_TEST_EXE_X_REG).during(Duration.ofMinutes(PowerAuthLoadTestCommon.PERF_TEST_EXE_MIN))) + .protocols(PowerAuthLoadTestCommon.commonProtocol), + CreateApproveOperationScenario.createApproveOperationScenario + .injectOpen(constantUsersPerSec(PowerAuthLoadTestCommon.PERF_TEST_EXE_Y_OP).during(Duration.ofMinutes(PowerAuthLoadTestCommon.PERF_TEST_EXE_MIN))) + .protocols(PowerAuthLoadTestCommon.commonProtocol), + ListOperationHistoryScenario.listOperationHistoryScenario + .injectOpen(constantUsersPerSec(PowerAuthLoadTestCommon.PERF_TEST_EXE_Y_OP * 0.1).during(Duration.ofMinutes(PowerAuthLoadTestCommon.PERF_TEST_EXE_MIN)).randomized()) + .protocols(PowerAuthLoadTestCommon.commonProtocol))); + } +} diff --git a/powerauth-load-tests/src/test/resources/.perf_test_config b/powerauth-load-tests/src/test/resources/.perf_test_config new file mode 100644 index 00000000..d63291f5 --- /dev/null +++ b/powerauth-load-tests/src/test/resources/.perf_test_config @@ -0,0 +1,7 @@ +export PERF_TEST_PREP_N_REG=15000 # Number of registrations to prepare - Preparation phase +export PERF_TEST_PREP_M_OP=30000 # Number of operations to prepare - Preparation phase +export PERF_TEST_EXE_X_REG=1 # Number of registrations to create per sec - Execution phase +export PERF_TEST_EXE_Y_OP=40 # Number of operations to create per sec - Execution phase +export PERF_TEST_EXE_MIN=60 # Length of execution phase in minutes - Execution phase +export PERF_TEST_CALLBACK_URL=CALLBACK_URL # URL for the callback server +export MAVEN_OPTS=-Xmx6000m # OPTIONAL - adding more heap size diff --git a/powerauth-load-tests/src/test/resources/logback-test.xml b/powerauth-load-tests/src/test/resources/logback-test.xml index a3c94782..b92f2d39 100644 --- a/powerauth-load-tests/src/test/resources/logback-test.xml +++ b/powerauth-load-tests/src/test/resources/logback-test.xml @@ -6,10 +6,20 @@ - - + - + + logs/test_${timestamp}.log + true + + %d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%r%ex{full} + + + + + + + diff --git a/powerauth-test-server/src/main/resources/application.properties b/powerauth-test-server/src/main/resources/application.properties index 5c2a0822..3b30b085 100644 --- a/powerauth-test-server/src/main/resources/application.properties +++ b/powerauth-test-server/src/main/resources/application.properties @@ -21,6 +21,7 @@ spring.datasource.password= spring.jpa.properties.hibernate.connection.CharSet=UTF-8 spring.jpa.properties.hibernate.connection.characterEncoding=UTF-8 spring.jpa.properties.hibernate.connection.useUnicode=true +server.port=8081 # Hibernate Configuration - automatically update DB schema spring.jpa.hibernate.ddl-auto=update From a0f435b8b5ae84fb2d23ed254fff148a1cc4cbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pe=C5=A1ek?= Date: Tue, 23 Apr 2024 14:08:17 +0200 Subject: [PATCH 13/56] Fix #420: FIDO2 Test application: Add readme (#421) --- README.md | 1 + powerauth-fido2-tests/README.md | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 powerauth-fido2-tests/README.md diff --git a/README.md b/README.md index 79e9cd43..41cdef49 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ This project contains various tests for PowerAuth backends: - [PowerAuth End-To-End Tests](./powerauth-backend-tests/README.md) - [PowerAuth Load Tests](./powerauth-load-tests/README.md) - [PowerAuth Web Flow UI Tests](./powerauth-webflow-tests/README.md) +- [PowerAuth FIDO2 Tests](./powerauth-fido2-tests/README.md) # License diff --git a/powerauth-fido2-tests/README.md b/powerauth-fido2-tests/README.md new file mode 100644 index 00000000..b10386a5 --- /dev/null +++ b/powerauth-fido2-tests/README.md @@ -0,0 +1,57 @@ +# PowerAuth FIDO2 Tests + +PowerAuth FIDO2 Tests is a web application for exploring and testing the FIDO2 integration with PowerAuth Server. +Using PowerAuth FIDO2 Tests you can simulate registration, login, and payment processing scenarios within the PowerAuth +environment with a variety of software and hardware authenticators using WebAuthN protocol. The web application logs +detailed information of each step of a WebAuthN ceremony, conveniently accessible directly within the browser console. + +## Requirements + +PowerAuth FIDO2 Tests web application communicates with the PowerAuth Server. You can find more details about +the PowerAuth Server on the [Developer Portal](https://developers.wultra.com/components/powerauth-server/develop/documentation/). + +> :information_source: FIDO2 support is integrated into PowerAuth Server since version 1.7.0. + +## Configuration Properties + +### PowerAuth Service Configuration + +| Property | Default | Note | +|-------------------------------------------|-----------------------------------------------|-------------------------------------------| +| `powerauth.service.baseUrl` | `http://localhost:8080/powerauth-java-server` | PowerAuth service REST API base URL. | +| `powerauth.service.security.clientToken` | | PowerAuth REST API authentication token. | +| `powerauth.service.security.clientSecret` | | PowerAuth REST API authentication secret. | + +### WebAuthN Configuration Properties + +| Property | Default | Note | +|-------------------------------------|----------|--------------------------------------------------------------------------------------------| +| `powerauth.webauthn.rpId` | | Relying Party ID. Must be equal to the origin's effective domain. | +| `powerauth.webauthn.rpName` | | Relying Party display name. | +| `powerauth.webauthn.timeout` | `60s` | Specifies a duration that the Relying Party is willing to wait for the client to complete. | +| `powerauth.webauthn.allowedOrigins` | | List of allowed origins. | + + +## Running the Application + +### Running from IntelliJ IDEA + +By default, the development profile is active, so the application should start without any additional configuration. +It is expected an instance of the PowerAuth Server is listening on `http://localhost:8080/powerauth-java-server`. +The application starts on http://localhost:8083/powerauth-fido2-test with following default configuration: + +```properties +# WebAuthn properties configuration +powerauth.webauthn.rpId=localhost +powerauth.webauthn.rpName=Local Development +powerauth.webauthn.allowedOrigins=http://localhost:8083 +``` + +> :information_source: Make sure you visit the application on the `localhost` domain. Ceremonies initiated +> at the address `127.0.0.1` will not be successful. + +### Running from terminal + +Build the project by running `mvn clean package` in the root directory of the project. Once the build is successful, +navigate to the target directory, from which you can run the war file using `java -jar`. Keep in mind you have to +configure necessary properties using external configuration or by using command line argument `-D`. From 591dbb3954a6399f94c9d9de61c50caebaa3cc25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:46:24 +0000 Subject: [PATCH 14/56] Bump gatling.version from 3.10.5 to 3.11.2 Bumps `gatling.version` from 3.10.5 to 3.11.2. Updates `io.gatling.highcharts:gatling-charts-highcharts` from 3.10.5 to 3.11.2 - [Commits](https://github.com/gatling/gatling-highcharts/compare/v3.10.5...v3.11.2) Updates `io.gatling:gatling-test-framework` from 3.10.5 to 3.11.2 - [Commits](https://github.com/gatling/gatling/compare/v3.10.5...v3.11.2) --- updated-dependencies: - dependency-name: io.gatling.highcharts:gatling-charts-highcharts dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: io.gatling:gatling-test-framework dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- powerauth-load-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 38075b99..88f489ff 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -42,7 +42,7 @@ 4.8.2 4.8.1 - 3.10.5 + 3.11.2 From f9b74bd06fc076fcc8792981e48d3e1d32f56e20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:46:55 +0000 Subject: [PATCH 15/56] Bump org.wiremock:wiremock-standalone from 3.4.2 to 3.5.4 Bumps [org.wiremock:wiremock-standalone](https://github.com/wiremock/wiremock) from 3.4.2 to 3.5.4. - [Release notes](https://github.com/wiremock/wiremock/releases) - [Commits](https://github.com/wiremock/wiremock/compare/3.4.2...3.5.4) --- updated-dependencies: - dependency-name: org.wiremock:wiremock-standalone dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- powerauth-load-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 38075b99..7e093d1c 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -75,7 +75,7 @@ org.wiremock wiremock-standalone - 3.4.2 + 3.5.4 test From 78710ee12ad6e65669bac8c86bfea469bc128f1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:46:56 +0000 Subject: [PATCH 16/56] Bump net.alchim31.maven:scala-maven-plugin from 4.8.1 to 4.9.0 Bumps net.alchim31.maven:scala-maven-plugin from 4.8.1 to 4.9.0. --- updated-dependencies: - dependency-name: net.alchim31.maven:scala-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- powerauth-load-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 38075b99..194c1699 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -40,7 +40,7 @@ 2.13.13 4.8.2 - 4.8.1 + 4.9.0 3.10.5 From 06ae06e144d3d60d0e6e8117902890edd0a3298e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 04:30:34 +0000 Subject: [PATCH 17/56] Bump io.gatling:gatling-maven-plugin from 4.8.2 to 4.9.0 Bumps [io.gatling:gatling-maven-plugin](https://github.com/gatling/gatling-maven-plugin) from 4.8.2 to 4.9.0. - [Commits](https://github.com/gatling/gatling-maven-plugin/compare/v4.8.2...v4.9.0) --- updated-dependencies: - dependency-name: io.gatling:gatling-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- powerauth-load-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerauth-load-tests/pom.xml b/powerauth-load-tests/pom.xml index 194c1699..37b4e7b7 100644 --- a/powerauth-load-tests/pom.xml +++ b/powerauth-load-tests/pom.xml @@ -39,7 +39,7 @@ 2.13.13 - 4.8.2 + 4.9.0 4.9.0 3.10.5 From 03147e999f4173377f75857b3847661f3d21195c Mon Sep 17 00:00:00 2001 From: Jan Dusil Date: Tue, 30 Apr 2024 11:31:04 +0200 Subject: [PATCH 18/56] - remove deprecated runner classes --- .../test/runner/DataPreparationRunner.java | 36 ------------------- .../test/runner/PerformanceTestRunner.java | 36 ------------------- 2 files changed, 72 deletions(-) delete mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java delete mode 100644 powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java deleted file mode 100644 index c5f8be04..00000000 --- a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/DataPreparationRunner.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * PowerAuth test and related software components - * Copyright (C) 2024 Wultra s.r.o. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.wultra.security.powerauth.test.runner; - -import com.wultra.security.powerauth.test.simulation.DataPreparationSimulation; -import io.gatling.app.Gatling; -import io.gatling.core.config.GatlingPropertiesBuilder; - -/** - * Executes the DataPreparationSimulation for PowerAuth load testing setup. Useful for initializing test data - * and debugging. - * - * @author Jan Dusil, jan.dusil@wultra.com - */ -public class DataPreparationRunner { - public static void main(String[] args) { - final GatlingPropertiesBuilder props = new GatlingPropertiesBuilder() - .simulationClass(DataPreparationSimulation.class.getName()); - Gatling.fromMap(props.build()); - } -} diff --git a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java b/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java deleted file mode 100644 index dbcc3209..00000000 --- a/powerauth-load-tests/src/test/java/com/wultra/security/powerauth/test/runner/PerformanceTestRunner.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * PowerAuth test and related software components - * Copyright (C) 2024 Wultra s.r.o. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.wultra.security.powerauth.test.runner; - -import com.wultra.security.powerauth.test.simulation.PerformanceTestSimulation; -import io.gatling.app.Gatling; -import io.gatling.core.config.GatlingPropertiesBuilder; - -/** - * Executes the PerformanceTestSimulation for conducting performance tests on PowerAuth applications, useful for debugging. - * Utilizes Gatling to run specified simulation, focusing on evaluating the performance under various load conditions. - * - * @author Jan Dusil, jan.dusil@wultra.com - */ -public class PerformanceTestRunner { - public static void main(String[] args) { - GatlingPropertiesBuilder props = new GatlingPropertiesBuilder() - .simulationClass(PerformanceTestSimulation.class.getName()); - Gatling.fromMap(props.build()); - } -} From abf8a5a7e228fed096847db1d9b5249e82b85085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pe=C5=A1ek?= Date: Fri, 3 May 2024 09:50:25 +0200 Subject: [PATCH 19/56] Fix #430: FIDO2 Test: User details input options (#431) --- .../fido2/controller/AssertionController.java | 2 +- .../fido2/controller/HomeController.java | 12 ++++---- .../request/AssertionOptionsRequest.java | 2 +- .../request/RegisterCredentialRequest.java | 2 +- .../request/RegistrationOptionsRequest.java | 8 +++-- .../fido2/service/AssertionService.java | 4 +-- .../fido2/service/RegistrationService.java | 17 +++++++---- .../src/main/resources/templates/login.html | 10 +++++-- .../src/main/resources/templates/payment.html | 4 +-- .../src/main/webapp/resources/js/login.js | 22 ++++++++++---- .../src/main/webapp/resources/js/payment.js | 4 +-- .../src/main/webapp/resources/js/webauthn.js | 30 ++++++++++--------- 12 files changed, 73 insertions(+), 44 deletions(-) diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java index 2f7367ea..5ca44f06 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/AssertionController.java @@ -57,7 +57,7 @@ public AssertionOptionsResponse options(@Valid @RequestBody final AssertionOptio public AssertionVerificationResponse verify(@Valid @RequestBody final VerifyAssertionRequest request, final HttpSession session) throws PowerAuthFido2Exception { final AssertionVerificationResponse response = assertionService.authenticate(request); if (response.isAssertionValid()) { - session.setAttribute("username", response.getUserId()); + session.setAttribute("userId", response.getUserId()); session.setAttribute("applicationId", response.getApplicationId()); } return response; diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/HomeController.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/HomeController.java index d4274fac..448cdf55 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/HomeController.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/HomeController.java @@ -41,7 +41,7 @@ @Slf4j public class HomeController { - private static final String SESSION_KEY_USERNAME = "username"; + private static final String SESSION_KEY_USER_ID = "userId"; private static final String SESSION_KEY_APPLICATION_ID = "applicationId"; private static final String REDIRECT_LOGIN = "redirect:login"; private static final String REDIRECT_PAYMENT = "redirect:payment"; @@ -58,7 +58,7 @@ public void addAttributes(Map model) { @GetMapping("/") public String homePage(Map model, HttpSession session) { - if (StringUtils.hasText((String) session.getAttribute(SESSION_KEY_USERNAME))) { + if (StringUtils.hasText((String) session.getAttribute(SESSION_KEY_USER_ID))) { return REDIRECT_PAYMENT; } return REDIRECT_LOGIN; @@ -73,13 +73,13 @@ public String loginPage(Map model) throws PowerAuthClientExcepti @GetMapping("/payment") public String profilePage(Map model, HttpSession session) throws PowerAuthClientException { - final String username = (String) session.getAttribute(SESSION_KEY_USERNAME); + final String userId = (String) session.getAttribute(SESSION_KEY_USER_ID); final String applicationId = (String) session.getAttribute(SESSION_KEY_APPLICATION_ID); - if (!StringUtils.hasText(username)) { + if (!StringUtils.hasText(userId)) { return REDIRECT_LOGIN; } - model.put(SESSION_KEY_USERNAME, username); + model.put(SESSION_KEY_USER_ID, userId); model.put(SESSION_KEY_APPLICATION_ID, applicationId); model.put("templates", sharedService.fetchTemplateNameList()); return PAYMENT_PAGE; @@ -87,7 +87,7 @@ public String profilePage(Map model, HttpSession session) throws @GetMapping("/logout") public String logoutPage(Map model, HttpSession session) { - session.removeAttribute(SESSION_KEY_USERNAME); + session.removeAttribute(SESSION_KEY_USER_ID); return REDIRECT_LOGIN; } diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/AssertionOptionsRequest.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/AssertionOptionsRequest.java index ebd79cfc..9dd196e9 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/AssertionOptionsRequest.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/AssertionOptionsRequest.java @@ -28,7 +28,7 @@ * @author Jan Pesek, jan.pesek@wultra.com */ public record AssertionOptionsRequest ( - String username, + String userId, @NotBlank String applicationId, diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java index 530a0937..820b18ef 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegisterCredentialRequest.java @@ -34,7 +34,7 @@ public record RegisterCredentialRequest ( String applicationId, @NotBlank - String username, + String userId, boolean userVerificationRequired, diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegistrationOptionsRequest.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegistrationOptionsRequest.java index dd5726e9..12ef4d0b 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegistrationOptionsRequest.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/controller/request/RegistrationOptionsRequest.java @@ -27,8 +27,12 @@ */ public record RegistrationOptionsRequest( @NotBlank - String username, + String userId, @NotBlank - String applicationId + String applicationId, + + String username, + String userDisplayName + ) {} diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java index 406dc0b3..445db6ff 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/AssertionService.java @@ -59,7 +59,7 @@ public class AssertionService { * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ public AssertionOptionsResponse assertionOptions(final AssertionOptionsRequest request) throws PowerAuthFido2Exception { - final String userId = request.username(); + final String userId = request.userId(); final String applicationId = request.applicationId(); logger.info("Building assertion options for userId={}, applicationId={}", userId, applicationId); @@ -67,7 +67,7 @@ public AssertionOptionsResponse assertionOptions(final AssertionOptionsRequest r final AssertionChallengeResponse challengeResponse = fetchChallenge(userId, applicationId, request.templateName(), request.operationParameters()); final var credentialList = Optional.ofNullable(challengeResponse.getAllowCredentials()); if (credentialList.isEmpty() && StringUtils.hasText(userId)) { - logger.info("User {} is not yet registered.", userId); + logger.info("User ID {} is not yet registered.", userId); throw new IllegalStateException("Not registered yet."); } diff --git a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java index 79d0b9e7..eb0eedbf 100644 --- a/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java +++ b/powerauth-fido2-tests/src/main/java/com/wultra/security/powerauth/fido2/service/RegistrationService.java @@ -36,6 +36,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import java.util.Base64; import java.util.List; @@ -61,15 +62,17 @@ public class RegistrationService { * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ public RegistrationOptionsResponse registerOptions(final RegistrationOptionsRequest request) throws PowerAuthFido2Exception { - final String userId = request.username(); final String applicationId = request.applicationId(); + final String userId = request.userId(); + final String username = StringUtils.hasText(request.username()) ? request.username() : userId; + final String userDisplayName = StringUtils.hasText(request.userDisplayName()) ? request.userDisplayName() : userId; final RegistrationChallengeResponse challengeResponse = fetchChallenge(userId, applicationId); logger.info("Building registration options for userId={}, applicationId={}", userId, applicationId); return RegistrationOptionsResponse.builder() .rp(new PublicKeyCredentialRpEntity(webAuthNConfig.getRpId(), webAuthNConfig.getRpName())) - .user(new PublicKeyCredentialUserEntity(userId.getBytes(), userId, userId)) + .user(new PublicKeyCredentialUserEntity(userId.getBytes(), username, userDisplayName)) .challenge(challengeResponse.getChallenge()) .pubKeyCredParams(List.of( new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256) @@ -86,15 +89,17 @@ public RegistrationOptionsResponse registerOptions(final RegistrationOptionsRequ * @throws PowerAuthFido2Exception in case of PowerAuth server communication error. */ public RegistrationResponse register(final RegisterCredentialRequest credential) throws PowerAuthFido2Exception { - logger.info("Registering created credential of userId={}, applicationId={}", credential.username(), credential.applicationId()); + final String applicationId = credential.applicationId(); + final String userId = credential.userId(); + logger.info("Registering created credential of userId={}, applicationId={}", userId, applicationId); final RegistrationRequest request = new RegistrationRequest(); - request.setActivationName(credential.username()); - request.setApplicationId(credential.applicationId()); + request.setActivationName(userId); + request.setApplicationId(applicationId); request.setAuthenticatorParameters(buildAuthenticatorParameters(credential)); final RegistrationResponse response = fido2Client.register(request); - logger.debug("Credential registration response of userId={}: {}", credential.username(), response); + logger.debug("Credential registration response of userId={}: {}", userId, response); logger.info("Activation ID {} of userId={}: status={}", response.getActivationId(), response.getUserId(), response.getActivationStatus()); return response; } diff --git a/powerauth-fido2-tests/src/main/resources/templates/login.html b/powerauth-fido2-tests/src/main/resources/templates/login.html index 570b33fe..67a6f825 100644 --- a/powerauth-fido2-tests/src/main/resources/templates/login.html +++ b/powerauth-fido2-tests/src/main/resources/templates/login.html @@ -37,9 +37,9 @@ - +
- +
@@ -59,6 +59,12 @@