From d6271383ebbc33d00287500daf1cb31412f0bf18 Mon Sep 17 00:00:00 2001 From: Yevhen Povietkin <ypovietkin@eservicios.indra.es> Date: Fri, 14 Feb 2025 16:53:03 +0100 Subject: [PATCH] SIMPL-5235: test Unauthorized Access Attempt for CRUD Operations --- .../java/framework/api/enums/ApiEndpoint.java | 61 +++++++++++++------ .../java/framework/api/enums/HttpStatus.java | 3 +- .../features/api/simplOpen/Authority.feature | 17 ++++-- .../api/simplOpen/AuthoritySteps.java | 54 ++++++++++------ 4 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/main/java/framework/api/enums/ApiEndpoint.java b/src/main/java/framework/api/enums/ApiEndpoint.java index 0243ea6c..623659b6 100644 --- a/src/main/java/framework/api/enums/ApiEndpoint.java +++ b/src/main/java/framework/api/enums/ApiEndpoint.java @@ -1,50 +1,73 @@ package framework.api.enums; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public enum ApiEndpoint { - IDENTITY_ATTRIBUTE("/sap-api/identity-attribute", "Identity Attribute"), - USER_ROLE("/user-api/role", "User Role"), - PARTICIPANT_TYPE("/identity-api/participant", "Participant"), - IDENTITY_ATTRIBUTE_LOCAL_AGENT_SEARCH("/user-api/identity-attribute/search", - "Identity Attribute Local Agent Search"); - private final String path; - private final String displayName; + // 🔹 Identity API + IDENTITY_ATTRIBUTE("/sap-api/identity-attribute", true), + IDENTITY_CERTIFICATE("/identity-api/certificate", true), + PARTICIPANT_TYPE("/identity-api/participant", true), + PARTICIPANT_SEARCH("/identity-api/participant/search", true), + + // 🔹 Onboarding API + ONBOARDING_PARTICIPANT("/onboarding-api/participant-type", false), + ONBOARDING_TEMPLATE("/onboarding-api/onboarding-template", true), + ONBOARDING_REQUEST("/onboarding-api/onboarding-request", false), + + // 🔹 User API + USER_ROLE("/user-api/role", true), + USER_SEARCH("/user-api/user/search", true), + USER_CREDENTIAL_MY_ID("/user-api/credential/my-id", true), + USER_SESSION_CREDENTIAL("/user-api/session/credential", true), + USER_CREDENTIAL_CREDENTIAL_ID("/user-api/credential/credential-id", true), + USER_EPHFEMERAL_PROOF("/user-api/mtls/ephemeral-proof", true), - private static final Map<String, ApiEndpoint> DISPLAY_NAME_MAP = new HashMap<>(); + // 🔹 Local Agent API + IDENTITY_ATTRIBUTE_LOCAL_AGENT_SEARCH("/user-api/identity-attribute/search", true); + + private final String path; + private final boolean isCrudTestable; + private static final Map<String, ApiEndpoint> PATH_MAP = new HashMap<>(); static { for (ApiEndpoint endpoint : values()) { - DISPLAY_NAME_MAP.put(endpoint.displayName.toLowerCase(), endpoint); + PATH_MAP.put(endpoint.path.toLowerCase(), endpoint); } } - ApiEndpoint(String path, String displayName) { + ApiEndpoint(String path, boolean isCrudTestable) { this.path = path; - this.displayName = displayName; + this.isCrudTestable = isCrudTestable; } public String getPath() { return path; } - public String getDisplayName() { - return displayName; + public boolean isCrudTestable() { + return isCrudTestable; } - @Override - public String toString() { - return displayName; + public static List<ApiEndpoint> getCrudTestableEndpoints() { + return List.of(values()).stream() + .filter(ApiEndpoint::isCrudTestable) + .collect(Collectors.toList()); } - public static ApiEndpoint fromString(String displayName) { - ApiEndpoint endpoint = DISPLAY_NAME_MAP.get(displayName.toLowerCase()); + public static ApiEndpoint fromPath(String path) { + ApiEndpoint endpoint = PATH_MAP.get(path.toLowerCase()); if (endpoint == null) { - throw new IllegalArgumentException("No endpoint found for display name: " + displayName); + throw new IllegalArgumentException("No endpoint found for path: " + path); } return endpoint; } + @Override + public String toString() { + return path; + } } diff --git a/src/main/java/framework/api/enums/HttpStatus.java b/src/main/java/framework/api/enums/HttpStatus.java index 8c0d92db..65132604 100644 --- a/src/main/java/framework/api/enums/HttpStatus.java +++ b/src/main/java/framework/api/enums/HttpStatus.java @@ -7,7 +7,8 @@ public enum HttpStatus { DELETED(204, "Deleted"), BAD_REQUEST(400, "Bad Request"), FORBIDDEN(403, "Forbidden"), - NOT_FOUND(404, "Not Found"); + NOT_FOUND(404, "Not Found"), + UNAUTHORIZED(401, "Unauthorized"); private final int code; private final String description; diff --git a/src/test/java/features/api/simplOpen/Authority.feature b/src/test/java/features/api/simplOpen/Authority.feature index 20571531..626521e2 100644 --- a/src/test/java/features/api/simplOpen/Authority.feature +++ b/src/test/java/features/api/simplOpen/Authority.feature @@ -4,7 +4,7 @@ Feature: Authority API scenarios @TCA01_API @SIMPL-3336 @SIMPL-3337 @SIMPL-3338 @SIMPL-3344 Scenario: User with IATTR_M Role Creates a New Identity Attribute Given a user with role "IATTR_M" is logged in to governance authority - When the user creates and assigns "Identity attribute" with the following data: + When the user creates and assigns Identity Attribute with the following data: | Code | RANDOM_CODE | | Enabled | true | | Assignable to roles | true | @@ -20,7 +20,7 @@ Feature: Authority API scenarios @TCA02_API @SIMPL-3334 Scenario: Successful retrieval of an Identity Attribute by ID Given a user with role "IATTR_M" is logged in to governance authority - And the user creates and assigns "Identity attribute" with the following data: + And the user creates and assigns Identity Attribute with the following data: | Code | RANDOM_CODE | | Enabled | true | | Assignable to roles | true | @@ -34,7 +34,7 @@ Feature: Authority API scenarios @TCA03_API @SIMPL-3335 @SIMPL-3343 Scenario: User with IATTR_M role updates an Identity Attribute Given a user with role "IATTR_M" is logged in to governance authority - And an "Identity Attribute" is already created and assigned + And an Identity Attribute is already created and assigned When the user updates the Identity Attribute with the new data: | Code | UPDATED_CODE | | Enabled | false | @@ -67,7 +67,7 @@ Feature: Authority API scenarios @TCA06_API @SIMPL-4532 Scenario: Disable an Identity Attribute Given a user with role "IATTR_M" is logged in to governance authority - And an "Identity Attribute" is already created and assigned + And an Identity Attribute is already created and assigned When the user sets the Identity Attribute as assignable to "false" And the operation is completed successfully And the user searches for the identity attribute by ID @@ -77,7 +77,7 @@ Feature: Authority API scenarios @TCA07_API @SIMPL-4502 @SIMPL-4533 @bug:SIMPL-10207 @bug:SIMPL-10297 Scenario: Unsuccessful Identity Attribute enablement and disablement Given a user with role "IATTR_M" is logged in to governance authority - And an "Identity Attribute" is already created and assigned + And an Identity Attribute is already created and assigned When the user attempts to set the Identity Attribute as assignable to "true" with a modified ID And the system indicates bad request And the user attempts to set the Identity Attribute as assignable to "false" with a modified ID @@ -87,8 +87,13 @@ Feature: Authority API scenarios @TCA08_API @SIMPL-5233 Scenario: Creation of New Tier1 Role with T1UAR_M Role - Role Successfully Created Given a user with role "AUTHORITY_T1UAR_M" is logged in to governance authority - When the user creates "User Role" with the following data: + When the user creates User Role with the following data: | name | RANDOM_NAME | | description | RANDOM_DESCRIPTION | Then the system indicates successful creation And the response body contains the expected User Role's details + + @TCA09_API @SIMPL-5265 @SIMPL-5235 + Scenario: Unauthorized Access Attempt for CRUD Operations + When the user tries to perform any CRUD operation + Then the system declines all unauthorized requests diff --git a/src/test/java/stepDefinitions/api/simplOpen/AuthoritySteps.java b/src/test/java/stepDefinitions/api/simplOpen/AuthoritySteps.java index b956fd06..4a189980 100644 --- a/src/test/java/stepDefinitions/api/simplOpen/AuthoritySteps.java +++ b/src/test/java/stepDefinitions/api/simplOpen/AuthoritySteps.java @@ -30,13 +30,12 @@ import static org.junit.Assert.*; public class AuthoritySteps { private RequestHandler requestHandler; - private ApiEndpoint identityAttributeEndpoint; - private ApiEndpoint userRoleEndpoint; private IdentityAttribute identityAttribute = new IdentityAttribute(); private UserRole userRole = new UserRole(); private String savedIdentityAttributeId; private final List<String> createdIdentityAttributesIDs = new ArrayList<>(); private final List<String> createdUserRoleIDs = new ArrayList<>(); + private final List<Integer> unauthorizedStatusCodes = new ArrayList<>(); private String randomIdentityAttributeId; @Before("@AuthorityAPI") @@ -58,32 +57,28 @@ public class AuthoritySteps { requestHandler.addHeader("Authorization", "Bearer " + token); } - @Given("an {string} is already created and assigned") - public void anIdentityAttributeIsAlreadyCreated(String endpointName) { - identityAttributeEndpoint = ApiEndpoint.fromString(endpointName); - + @Given("an Identity Attribute is already created and assigned") + public void anIdentityAttributeIsAlreadyCreated() { JsonObject requestBody = new IdentityAttributeRequestBuilder() .withRandomData() .build(); - requestHandler.sendRequest(HttpMethod.POST, identityAttributeEndpoint.getPath(), requestBody); + requestHandler.sendRequest(HttpMethod.POST, ApiEndpoint.IDENTITY_ATTRIBUTE.getPath(), requestBody); JsonObject createdIdentityAttribute = requestHandler.getLastResponseBody(); Gson gson = new Gson(); identityAttribute = gson.fromJson(createdIdentityAttribute, IdentityAttribute.class); createdIdentityAttributesIDs.add(requestHandler.getLastResponseBody().get("id").getAsString()); } - @When("the user creates and assigns {string} with the following data:") - public void theUserSendsAPostRequestWithAListOfParticipantTypes(String endpointName, DataTable dataTable) { + @When("the user creates and assigns Identity Attribute with the following data:") + public void theUserSendsAPostRequestWithAListOfParticipantTypes(DataTable dataTable) { Gson gson = new Gson(); - identityAttributeEndpoint = ApiEndpoint.fromString(endpointName); - Map<String, String> data = dataTable.asMap(String.class, String.class); JsonObject requestBody = new IdentityAttributeRequestBuilder() .fromMap(data) .build(); - requestHandler.sendRequest(HttpMethod.POST, identityAttributeEndpoint.getPath(), requestBody); + requestHandler.sendRequest(HttpMethod.POST, ApiEndpoint.IDENTITY_ATTRIBUTE.getPath(), requestBody); JsonObject createdIdentityAttribute = requestHandler.getLastResponseBody(); @@ -93,17 +88,15 @@ public class AuthoritySteps { createdIdentityAttributesIDs.add(identityAttribute.getId()); } - @When("the user creates {string} with the following data:") - public void theUserCreatesRoleWithTheFollowingData(String endpointName, DataTable dataTable) { + @When("the user creates User Role with the following data:") + public void theUserCreatesRoleWithTheFollowingData(DataTable dataTable) { Gson gson = new Gson(); - userRoleEndpoint = ApiEndpoint.fromString(endpointName); - Map<String, String> data = dataTable.asMap(String.class, String.class); JsonObject requestBody = new UserRolesRequestBuilder() .fromMap(data) .build(); - requestHandler.sendRequest(HttpMethod.POST, userRoleEndpoint.getPath(), requestBody); + requestHandler.sendRequest(HttpMethod.POST, ApiEndpoint.USER_ROLE.getPath(), requestBody); JsonObject createdUserRole = requestHandler.getLastResponseBody(); @@ -123,7 +116,7 @@ public class AuthoritySteps { .fromMap(data) .build(); - requestHandler.sendRequest(HttpMethod.PUT, identityAttributeEndpoint.getPath() + "/" + identityAttributeId, requestBody); + requestHandler.sendRequest(HttpMethod.PUT, ApiEndpoint.IDENTITY_ATTRIBUTE.getPath() + "/" + identityAttributeId, requestBody); JsonObject updatedIdentityAttribute = requestHandler.getLastRequestBody(); identityAttribute = gson.fromJson(updatedIdentityAttribute, IdentityAttribute.class); } @@ -210,6 +203,19 @@ public class AuthoritySteps { assertEquals("Mismatch in status code", expectedStatusCode, actualStatusCode); } + @When("the user tries to perform any CRUD operation") + public void theUserTriesToPerformAnyCRUDOperation() { + List<ApiEndpoint> endpoints = ApiEndpoint.getCrudTestableEndpoints(); + List<HttpMethod> methods = List.of(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE); + + for (ApiEndpoint endpoint : endpoints) { + for (HttpMethod method : methods) { + requestHandler.sendRequest(method, endpoint.getPath()); + unauthorizedStatusCodes.add(requestHandler.getStatusCode()); + } + } + } + @Then("the system indicates absence of such resource") public void theSystemIndicatesAbsenceOfSuchResource() { int actualStatusCode = requestHandler.getLastStatusCode(); @@ -226,6 +232,16 @@ public class AuthoritySteps { assertEquals("Mismatch in status code", expectedStatusCode, actualStatusCode); } + @Then("the system declines all unauthorized requests") + public void theSystemDeclinesUnauthorizedRequest() { + int expectedStatusCode = HttpStatus.UNAUTHORIZED.getCode(); + + assertFalse("No unauthorized requests were made", unauthorizedStatusCodes.isEmpty()); + for (int statusCode : unauthorizedStatusCodes) { + assertEquals("Mismatch in status code", expectedStatusCode, statusCode); + } + } + @Then("the response body contains updated Identity Attribute data:") public void theResponseBodyContainsUpdatedIdentityAttributeData(DataTable dataTable) { Gson gson = new Gson(); @@ -364,7 +380,7 @@ public class AuthoritySteps { @After(value = "@AuthorityAPI", order = 2) public void deleteIdentityAttribute() { for (String id : createdIdentityAttributesIDs) { - String deleteEndpoint = identityAttributeEndpoint.getPath() + '/' + id; + String deleteEndpoint = ApiEndpoint.IDENTITY_ATTRIBUTE.getPath() + '/' + id; requestHandler.sendRequest(HttpMethod.DELETE, deleteEndpoint); int actualStatusCode = requestHandler.getStatusCode(); int expectedStatusCode = HttpStatus.DELETED.getCode(); -- GitLab