From 538b2d73125208389394914ce9a634dd8a3009aa Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Mon, 10 Jul 2023 12:02:35 +0200 Subject: [PATCH 1/4] A1SLDT-1239: Changes for base64 encryption --- .../AssetAdministrationShellApiDelegate.java | 46 +++++++++++-------- .../static/aas-registry-openapi.yaml | 21 +++++---- ...setAdministrationShellApiSecurityTest.java | 35 +++++++------- .../AssetAdministrationShellApiTest.java | 35 +++++++------- .../tractusx/semantics/registry/TestUtil.java | 5 ++ 5 files changed, 80 insertions(+), 62 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index ad02820c..42731f1b 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -72,13 +72,14 @@ public ResponseEntity deleteAssetAdministrationShellDescriptorById( String return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Override - public ResponseEntity deleteAllAssetLinksById(String aasIdentifier) { - shellService.deleteAllIdentifiers(aasIdentifier); + public ResponseEntity deleteAllAssetLinksById(byte[] aasIdentifier) { + + shellService.deleteAllIdentifiers(getDecodedId(aasIdentifier)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Override - public ResponseEntity deleteSubmodelDescriptorByIdThroughSuperpath( String aasIdentifier, String submodelIdentifier ) { - shellService.deleteSubmodel(aasIdentifier, submodelIdentifier); + public ResponseEntity deleteSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, byte[] submodelIdentifier ) { + shellService.deleteSubmodel(getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier )); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @@ -95,8 +96,8 @@ public ResponseEntity getAllAssetA @Override // new todo: correct implementation - public ResponseEntity getAllSubmodelDescriptorsThroughSuperpath( String aasIdentifier, Integer limit, String cursor ) { - Shell savedShell = shellService.findShellByExternalId(aasIdentifier); + public ResponseEntity getAllSubmodelDescriptorsThroughSuperpath( byte[] aasIdentifier, Integer limit, String cursor ) { + Shell savedShell = shellService.findShellByExternalId(getDecodedId( aasIdentifier )); Set submodels = savedShell.getSubmodels(); List descriptorResults = submodelMapper.toApiDto( submodels ); GetSubmodelDescriptorsResult result = new GetSubmodelDescriptorsResult(); @@ -105,14 +106,21 @@ public ResponseEntity getAllSubmodelDescriptorsThr } @Override - public ResponseEntity getAssetAdministrationShellDescriptorById( String aasIdentifier ) { - Shell saved = shellService.findShellByExternalId(aasIdentifier); - return new ResponseEntity<>(shellMapper.toApiDto(saved), HttpStatus.OK); + public ResponseEntity getAssetAdministrationShellDescriptorById( byte[] aasIdentifier ) { + String decodedAasIdentifier = getDecodedId( aasIdentifier ); + Shell saved = shellService.findShellByExternalId(decodedAasIdentifier); + return new ResponseEntity<>(shellMapper.toApiDto(saved), HttpStatus.OK); + } + + private static String getDecodedId( byte[] aasIdentifier ) { + byte[] decodedBytes = Base64.getUrlDecoder().decode( aasIdentifier ); + String decodedAasIdentifier = new String(decodedBytes); + return decodedAasIdentifier; } @Override - public ResponseEntity getSubmodelDescriptorByIdThroughSuperpath( String aasIdentifier, String submodelIdentifier ) { - Submodel submodel = shellService.findSubmodelByExternalId(aasIdentifier, submodelIdentifier); + public ResponseEntity getSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, byte[] submodelIdentifier ) { + Submodel submodel = shellService.findSubmodelByExternalId(getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier )); return new ResponseEntity<>(submodelMapper.toApiDto(submodel), HttpStatus.OK); } @@ -123,9 +131,9 @@ public ResponseEntity postAssetAdministratio } @Override - public ResponseEntity postSubmodelDescriptorThroughSuperpath( String aasIdentifier, SubmodelDescriptor submodelDescriptor ) { + public ResponseEntity postSubmodelDescriptorThroughSuperpath( byte[] aasIdentifier, SubmodelDescriptor submodelDescriptor ) { Submodel toBeSaved = submodelMapper.fromApiDto(submodelDescriptor); - Submodel savedSubModel = shellService.save(aasIdentifier, toBeSaved); + Submodel savedSubModel = shellService.save(getDecodedId( aasIdentifier ), toBeSaved); return new ResponseEntity<>(submodelMapper.toApiDto(savedSubModel), HttpStatus.CREATED); } @@ -137,9 +145,9 @@ public ResponseEntity putAssetAdministrationShellDescriptorById( String aa } @Override - public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( String aasIdentifier, String submodelIdentifier, SubmodelDescriptor submodelDescriptor ) { + public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, byte[] submodelIdentifier, SubmodelDescriptor submodelDescriptor ) { Submodel submodel = submodelMapper.fromApiDto( submodelDescriptor ); - shellService.update( aasIdentifier, submodelIdentifier, submodel.withIdExternal( submodelIdentifier ) ); + shellService.update( getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier ), submodel.withIdExternal( getDecodedId( submodelIdentifier ) ) ); return new ResponseEntity<>( HttpStatus.NO_CONTENT ); } @@ -155,14 +163,14 @@ public ResponseEntity> getAllAssetAdministrationShellIdsByAssetLink } @Override - public ResponseEntity> getAllAssetLinksById(String aasIdentifier) { - Set identifiers = shellService.findShellIdentifiersByExternalShellId(aasIdentifier); + public ResponseEntity> getAllAssetLinksById(byte[] aasIdentifier) { + Set identifiers = shellService.findShellIdentifiersByExternalShellId(getDecodedId( aasIdentifier )); return new ResponseEntity<>(shellMapper.toApiDto(identifiers), HttpStatus.OK); } @Override - public ResponseEntity> postAllAssetLinksById(String aasIdentifier, List specificAssetId) { - Set shellIdentifiers = shellService.save(aasIdentifier, shellMapper.fromApiDto(specificAssetId)); + public ResponseEntity> postAllAssetLinksById(byte[] aasIdentifier, List specificAssetId) { + Set shellIdentifiers = shellService.save(getDecodedId( aasIdentifier ), shellMapper.fromApiDto(specificAssetId)); List list = shellMapper.toApiDto(shellIdentifiers); return new ResponseEntity<>(list, HttpStatus.CREATED); } diff --git a/backend/src/main/resources/static/aas-registry-openapi.yaml b/backend/src/main/resources/static/aas-registry-openapi.yaml index 880797a9..c073fac7 100644 --- a/backend/src/main/resources/static/aas-registry-openapi.yaml +++ b/backend/src/main/resources/static/aas-registry-openapi.yaml @@ -193,7 +193,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte responses: "200": description: Requested Asset Administration Shell Descriptor @@ -349,7 +349,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte - name: limit in: query description: The maximum number of elements in the response array @@ -414,7 +414,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte requestBody: description: Submodel Descriptor object content: @@ -481,7 +481,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte - name: submodelIdentifier in: path description: The Submodel’s unique id (UTF8-BASE64-URL-encoded) @@ -490,7 +490,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte responses: "200": description: Requested Submodel Descriptor @@ -544,7 +544,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte - name: submodelIdentifier in: path description: The Submodel’s unique id (UTF8-BASE64-URL-encoded) @@ -553,7 +553,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte requestBody: description: Submodel Descriptor object content: @@ -609,7 +609,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte - name: submodelIdentifier in: path description: The Submodel’s unique id (UTF8-BASE64-URL-encoded) @@ -618,7 +618,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte responses: "204": description: Submodel Descriptor deleted successfully @@ -745,6 +745,7 @@ paths: explode: false schema: type: string + format: byte responses: "200": description: Requested Asset identifier key-value-pairs @@ -774,6 +775,7 @@ paths: explode: false schema: type: string + format: byte requestBody: description: Asset identifier key-value-pairs content: @@ -816,6 +818,7 @@ paths: explode: false schema: type: string + format: byte responses: "204": description: Asset identifier key-value-pairs deleted successfully diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java index 40c20f8d..81806e15 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java @@ -30,15 +30,14 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.List; import java.util.UUID; +import static org.eclipse.tractusx.semantics.registry.TestUtil.*; import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + /** * This class contains test to verify Authentication and RBAC based Authorization for all API endpoints. * Every API endpoint is tested explicitly. @@ -142,9 +141,10 @@ public void testRbacForGetById() throws Exception { .andDo(MockMvcResultHandlers.print()) .andExpect(status().isForbidden()); + mvc.perform( MockMvcRequestBuilders - .get(SINGLE_SHELL_BASE_PATH, shellId ) + .get(SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId ) ) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.readTwin()) ) @@ -265,7 +265,7 @@ public void testRbacForGetAll() throws Exception { mvc.perform( MockMvcRequestBuilders - .get(SUB_MODEL_BASE_PATH, shellId ) + .get(SUB_MODEL_BASE_PATH, getEncodedValue( shellId ) ) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.readTwin()) ) @@ -294,7 +294,7 @@ public void testRbacForGetById() throws Exception { mvc.perform( MockMvcRequestBuilders - .get(SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelIdAas ) + .get(SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId ), getEncodedValue( submodelIdAas ) ) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.readTwin()) ) @@ -331,7 +331,7 @@ public void testRbacForCreate() throws Exception { mvc.perform( MockMvcRequestBuilders - .post(SUB_MODEL_BASE_PATH, shellId) + .post(SUB_MODEL_BASE_PATH, getEncodedValue( shellId )) .contentType(MediaType.APPLICATION_JSON) .content( submodelPayloadForCreate ) .with(jwtTokenFactory.addTwin()) @@ -370,7 +370,7 @@ public void testRbacForUpdate() throws Exception { mvc.perform( MockMvcRequestBuilders - .put(SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelIdAas) + .put(SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId ), getEncodedValue(submodelIdAas)) .contentType(MediaType.APPLICATION_JSON) .content(submodelPayloadForCreate) .with(jwtTokenFactory.updateTwin()) @@ -398,7 +398,7 @@ public void testRbacForDelete() throws Exception { mvc.perform( MockMvcRequestBuilders - .delete(SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelIdAas) + .delete(SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId ), getEncodedValue( submodelIdAas )) .contentType(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.deleteTwin()) ) @@ -435,7 +435,7 @@ public void testRbacForGet() throws Exception { mvc.perform( MockMvcRequestBuilders - .get(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .get(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.readTwin()) ) @@ -461,7 +461,7 @@ public void testRbacForCreate() throws Exception { mvc.perform( MockMvcRequestBuilders - .post(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .post(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .contentType(MediaType.APPLICATION_JSON) .content(toJson(specificAssetIds)) .with(jwtTokenFactory.addTwin()) @@ -482,7 +482,7 @@ public void testRbacForDelete() throws Exception { mvc.perform( MockMvcRequestBuilders - .delete(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .delete(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .with(jwtTokenFactory.deleteTwin()) ) .andDo(MockMvcResultHandlers.print()) @@ -679,9 +679,10 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio performShellCreateRequest(mapper.writeValueAsString(shellPayload)); String shellId = shellPayload.getId(); + String encodedShellId = getEncodedValue(shellId ); mvc.perform( MockMvcRequestBuilders - .get(SINGLE_SHELL_BASE_PATH, shellId) + .get(SINGLE_SHELL_BASE_PATH, encodedShellId) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -693,7 +694,7 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio // test with tenant two mvc.perform( MockMvcRequestBuilders - .get(SINGLE_SHELL_BASE_PATH, shellId) + .get(SINGLE_SHELL_BASE_PATH, encodedShellId) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -771,7 +772,7 @@ public void testGetSpecificAssetIdsFilteredByTenantId() throws Exception { String shellId = shellPayload.getId(); mvc.perform( MockMvcRequestBuilders - .post(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .post(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(List.of(specificAssetId))) @@ -783,7 +784,7 @@ public void testGetSpecificAssetIdsFilteredByTenantId() throws Exception { mvc.perform( MockMvcRequestBuilders - .get(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .get(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -792,7 +793,7 @@ public void testGetSpecificAssetIdsFilteredByTenantId() throws Exception { mvc.perform( MockMvcRequestBuilders - .get(SINGLE_LOOKUP_SHELL_BASE_PATH, shellId) + .get(SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue( shellId )) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index ca64bf22..24945f7c 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -37,6 +37,7 @@ import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.notIn; +import static org.eclipse.tractusx.semantics.registry.TestUtil.getEncodedValue; import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -89,7 +90,7 @@ public void testGetShellExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SHELL_BASE_PATH, shellId ) + .get( SINGLE_SHELL_BASE_PATH, getEncodedValue( shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -151,7 +152,7 @@ public void testUpdateShellExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SHELL_BASE_PATH, shellId ) + .get( SINGLE_SHELL_BASE_PATH, getEncodedValue( shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -205,7 +206,7 @@ public void testUpdateShellWithDifferentIdInPayloadExpectPathIdIsTaken() throws shellPayload.setId( UUID.randomUUID().toString() ); mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SHELL_BASE_PATH, shellId ) + .get( SINGLE_SHELL_BASE_PATH, getEncodedValue( shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -344,7 +345,7 @@ public void testCreateSpecificAssetIdsReplacesAllExistingSpecificAssetIdsExpectS // ObjectNode expectedShellPayload = shellPayload.set("specificAssetIds", specificAssetIds); mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SHELL_BASE_PATH, shellId ) + .get( SINGLE_SHELL_BASE_PATH, getEncodedValue( shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -418,11 +419,11 @@ public void testCreateSubmodelExpectSuccess() throws Exception { SubmodelDescriptor submodelDescriptor = TestUtil.createSubmodel(); - performSubmodelCreateRequest( mapper.writeValueAsString( submodelDescriptor ), shellId ); + performSubmodelCreateRequest( mapper.writeValueAsString( submodelDescriptor ), getEncodedValue( shellId ) ); mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SHELL_BASE_PATH, shellId ) + .get( SINGLE_SHELL_BASE_PATH, getEncodedValue( shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -444,7 +445,7 @@ public void testCreateSubmodelWithExistingIdExpectBadRequest() throws Exception SubmodelDescriptor existingSubmodel = shellPayload1.getSubmodelDescriptors().get( 0 ); mvc.perform( MockMvcRequestBuilders - .post( SUB_MODEL_BASE_PATH, shellId ) + .post( SUB_MODEL_BASE_PATH, getEncodedValue(shellId) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( mapper.writeValueAsString( existingSubmodel ) ) @@ -462,7 +463,7 @@ public void testUpdateSubModelExpectSuccess() throws Exception { performShellCreateRequest( mapper.writeValueAsString( shellPayload1 ) ); SubmodelDescriptor submodel = TestUtil.createSubmodel(); - performSubmodelCreateRequest( mapper.writeValueAsString( submodel ), shellPayload1.getId() ); + performSubmodelCreateRequest( mapper.writeValueAsString( submodel ),getEncodedValue( shellPayload1.getId() )); String submodelId = submodel.getId(); SubmodelDescriptor updatedSubmodel = TestUtil.createSubmodel(); @@ -475,7 +476,7 @@ public void testUpdateSubModelExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .put( SINGLE_SUB_MODEL_BASE_PATH, shellPayload1.getId(), submodelId ) + .put( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellPayload1.getId() ), getEncodedValue( submodelId ) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( mapper.writeValueAsString( updatedSubmodel ) ) @@ -500,7 +501,7 @@ public void testUpdateSubmodelExpectNotFound() throws Exception { // verify shell is missing mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SUB_MODEL_BASE_PATH, "notexistingshell", "notexistingsubmodel" ) + .get( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( "notexistingshell") , getEncodedValue( "notexistingsubmodel") ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -514,7 +515,7 @@ public void testUpdateSubmodelExpectNotFound() throws Exception { // verify submodel is missing mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SUB_MODEL_BASE_PATH, shellPayload1.getId(), "notexistingsubmodel" ) + .get( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue(shellPayload1.getId()), getEncodedValue("notexistingsubmodel") ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -531,7 +532,7 @@ public void testUpdateSubmodelWithDifferentIdInPayloadExpectPathIdIsTaken() thro String shellId = shellPayload1.getId(); SubmodelDescriptor submodel = TestUtil.createSubmodel(); - performSubmodelCreateRequest( mapper.writeValueAsString( submodel ), shellPayload1.getId() ); + performSubmodelCreateRequest( mapper.writeValueAsString( submodel ), getEncodedValue( shellPayload1.getId() ) ); String submodelId = submodel.getId(); submodel.setIdShort( "newIdShortInUpdateRequest" ); @@ -568,13 +569,13 @@ public void testDeleteSubmodelExpectSuccess() throws Exception { String shellId = shellPayload1.getId(); SubmodelDescriptor submodel = TestUtil.createSubmodel(); - performSubmodelCreateRequest( mapper.writeValueAsString( submodel ), shellPayload1.getId() ); + performSubmodelCreateRequest( mapper.writeValueAsString( submodel ),getEncodedValue( shellPayload1.getId()) ); String submodelId = submodel.getId(); mvc.perform( MockMvcRequestBuilders - .delete( SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelId ) + .delete( SINGLE_SUB_MODEL_BASE_PATH,getEncodedValue( shellId) , getEncodedValue( submodelId) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -583,7 +584,7 @@ public void testDeleteSubmodelExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelId ) + .get( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId) , getEncodedValue( submodelId)) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -596,7 +597,7 @@ public void testDeleteSubmodelExpectNotFound() throws Exception { // verify shell is missing mvc.perform( MockMvcRequestBuilders - .delete( SINGLE_SUB_MODEL_BASE_PATH, "notexistingshell", "notexistingsubmodel" ) + .delete( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( "notexistingshell" ), getEncodedValue( "notexistingsubmodel" )) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -611,7 +612,7 @@ public void testDeleteSubmodelExpectNotFound() throws Exception { // verify submodel is missing mvc.perform( MockMvcRequestBuilders - .delete( SINGLE_SUB_MODEL_BASE_PATH, shellId, "notexistingsubmodel" ) + .delete( SINGLE_SUB_MODEL_BASE_PATH,getEncodedValue( shellId) ,getEncodedValue( "notexistingsubmodel") ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java index f6ed4f25..1e48a380 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java @@ -21,6 +21,7 @@ import org.eclipse.tractusx.semantics.aas.registry.model.*; +import java.util.Base64; import java.util.List; import java.util.UUID; @@ -180,4 +181,8 @@ public static SpecificAssetId createSpecificAssetId(String name, String value, S } return specificAssetId1; } + + public static String getEncodedValue(String shellId){ + return Base64.getUrlEncoder().encodeToString(shellId.getBytes()); + } } \ No newline at end of file From bf14e03ebc69fe9d34208698a485223cd9c8e10f Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Mon, 10 Jul 2023 17:22:42 +0200 Subject: [PATCH 2/4] A1SLDT-1239: Changes for base64 encryption --- .../AssetAdministrationShellApiTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index 24945f7c..3bb2ccd7 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -302,7 +302,7 @@ public void testCreateSpecificAssetIdsExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .post( SINGLE_LOOKUP_SHELL_BASE_PATH, shellId ) + .post( SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue(shellId ) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( toJson( specificAssetIds ) ) @@ -331,7 +331,7 @@ public void testCreateSpecificAssetIdsReplacesAllExistingSpecificAssetIdsExpectS mvc.perform( MockMvcRequestBuilders - .post( SINGLE_LOOKUP_SHELL_BASE_PATH, shellId ) + .post( SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue(shellId ) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( toJson( specificAssetIds ) ) @@ -360,7 +360,7 @@ public void testCreateSpecificIdsExpectNotFound() throws Exception { .add( specificAssetId( "key1", "value1" ) ); mvc.perform( MockMvcRequestBuilders - .post( SINGLE_LOOKUP_SHELL_BASE_PATH, "notexistingshell" ) + .post( SINGLE_LOOKUP_SHELL_BASE_PATH,getEncodedValue("notexistingshell" ) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( toJson( specificAssetIds ) ) @@ -382,7 +382,7 @@ public void testGetSpecificAssetIdsExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_LOOKUP_SHELL_BASE_PATH, shellId ) + .get( SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue(shellId ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -395,7 +395,7 @@ public void testGetSpecificAssetIdsExpectSuccess() throws Exception { public void testGetSpecificIdsExpectNotFound() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_LOOKUP_SHELL_BASE_PATH, "notexistingshell", "notexistingsubmodel" ) + .get( SINGLE_LOOKUP_SHELL_BASE_PATH, getEncodedValue("notexistingshell" ), getEncodedValue("notexistingsubmodel" ) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -487,7 +487,7 @@ public void testUpdateSubModelExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SUB_MODEL_BASE_PATH, shellPayload1.getId(), submodelId ) + .get( SINGLE_SUB_MODEL_BASE_PATH,getEncodedValue( shellPayload1.getId() ), getEncodedValue( submodelId )) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -539,7 +539,7 @@ public void testUpdateSubmodelWithDifferentIdInPayloadExpectPathIdIsTaken() thro mvc.perform( MockMvcRequestBuilders - .put( SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelId ) + .put( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId ), getEncodedValue( submodelId ) ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( mapper.writeValueAsString( submodel ) ) @@ -551,7 +551,7 @@ public void testUpdateSubmodelWithDifferentIdInPayloadExpectPathIdIsTaken() thro // verify that anything expect the identification can be updated mvc.perform( MockMvcRequestBuilders - .get( SINGLE_SUB_MODEL_BASE_PATH, shellId, submodelId ) + .get( SINGLE_SUB_MODEL_BASE_PATH, getEncodedValue( shellId ), getEncodedValue( submodelId )) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) From 0b9ffc109927d7721a2c2c2d2263634a27199d9a Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Mon, 17 Jul 2023 15:34:33 +0200 Subject: [PATCH 3/4] Changes done for Base64 encryption for parameter --- .../AssetAdministrationShellApiDelegate.java | 34 +++++++++++-------- .../static/aas-registry-openapi.yaml | 4 +-- ...setAdministrationShellApiSecurityTest.java | 8 ++--- .../AssetAdministrationShellApiTest.java | 11 +++--- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index c74d40a7..b49b2bdb 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -69,8 +69,8 @@ public ResponseEntity getDescription() { } @Override - public ResponseEntity deleteAssetAdministrationShellDescriptorById( String aasIdentifier ) { - shellService.deleteShell( aasIdentifier ); + public ResponseEntity deleteAssetAdministrationShellDescriptorById( byte[] aasIdentifier ) { + shellService.deleteShell( getDecodedId(aasIdentifier) ); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Override @@ -80,8 +80,8 @@ public ResponseEntity deleteAllAssetLinksById(byte[] aasIdentifier) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Override - public ResponseEntity deleteSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, String submodelIdentifier ) { - shellService.deleteSubmodel(getDecodedId( aasIdentifier ), submodelIdentifier,getExternalSubjectIdOrEmpty( null )); + public ResponseEntity deleteSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, byte[] submodelIdentifier ) { + shellService.deleteSubmodel(getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier ),getExternalSubjectIdOrEmpty( null )); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @@ -110,14 +110,8 @@ public ResponseEntity getAssetAdministration return new ResponseEntity<>(shellMapper.toApiDto(saved), HttpStatus.OK); } - private static String getDecodedId( byte[] aasIdentifier ) { - byte[] decodedBytes = Base64.getUrlDecoder().decode( aasIdentifier ); - String decodedAasIdentifier = new String(decodedBytes); - return decodedAasIdentifier; - } - @Override - public ResponseEntity getSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, String submodelIdentifier ) { + public ResponseEntity getSubmodelDescriptorByIdThroughSuperpath( byte[] aasIdentifier, byte[] submodelIdentifier ) { Submodel submodel = shellService.findSubmodelByExternalId(getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier ),getExternalSubjectIdOrEmpty( null )); return new ResponseEntity<>(submodelMapper.toApiDto(submodel), HttpStatus.OK); } @@ -139,10 +133,10 @@ public ResponseEntity postSubmodelDescriptorThroughSuperpath } @Override - public ResponseEntity putAssetAdministrationShellDescriptorById( String aasIdentifier, AssetAdministrationShellDescriptor assetAdministrationShellDescriptor ) { + public ResponseEntity putAssetAdministrationShellDescriptorById( byte[] aasIdentifier, AssetAdministrationShellDescriptor assetAdministrationShellDescriptor ) { Shell shell = shellMapper.fromApiDto( assetAdministrationShellDescriptor ); - Shell shellFromDb = shellService.findShellByExternalId( aasIdentifier,getExternalSubjectIdOrEmpty(null) ); - shellService.update( shell.withId( shellFromDb.getId() ).withIdExternal(aasIdentifier ),aasIdentifier); + Shell shellFromDb = shellService.findShellByExternalId( getDecodedId( aasIdentifier),getExternalSubjectIdOrEmpty(null) ); + shellService.update( shell.withId( shellFromDb.getId() ).withIdExternal(getDecodedId(aasIdentifier) ),getDecodedId(aasIdentifier)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @@ -151,7 +145,7 @@ public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( byte[] aa Submodel submodel = submodelMapper.fromApiDto( submodelDescriptor ); Submodel fromDB = shellService.findSubmodelByExternalId( getDecodedId( aasIdentifier ),getDecodedId( submodelIdentifier ),getExternalSubjectIdOrEmpty( null ) ); shellService.deleteSubmodel(getDecodedId( aasIdentifier ), getDecodedId( submodelIdentifier ),getExternalSubjectIdOrEmpty( null )); - shellService.update( aasIdentifier, submodel.withIdExternal( submodelIdentifier ).withId( fromDB.getId() ) ,getExternalSubjectIdOrEmpty( "" )); + shellService.update( getDecodedId( aasIdentifier ), submodel.withIdExternal( getDecodedId( submodelIdentifier ) ).withId( fromDB.getId() ) ,getExternalSubjectIdOrEmpty( "" )); return new ResponseEntity<>( HttpStatus.NO_CONTENT ); } @@ -189,5 +183,15 @@ public ResponseEntity> postQueryAllAssetAdministrationShellIds(Shel private String getExternalSubjectIdOrEmpty(String externalSubjectId) { return (null ==externalSubjectId) ? "" : externalSubjectId; } + + private String getDecodedId( byte[] aasIdentifier ) { + try { + byte[] decodedBytes = Base64.getUrlDecoder().decode( aasIdentifier ); + return new String( decodedBytes ); + }catch ( Exception e ){ + throw new IllegalArgumentException("Incorrect Base64 encoded value provided as parameter"); + } + } + } diff --git a/backend/src/main/resources/static/aas-registry-openapi.yaml b/backend/src/main/resources/static/aas-registry-openapi.yaml index b07d622f..3138544d 100644 --- a/backend/src/main/resources/static/aas-registry-openapi.yaml +++ b/backend/src/main/resources/static/aas-registry-openapi.yaml @@ -249,7 +249,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte requestBody: description: Asset Administration Shell Descriptor object content: @@ -306,7 +306,7 @@ paths: explode: false schema: type: string - # format: byte + format: byte responses: "204": description: Asset Administration Shell Descriptor deleted successfully diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java index bbcb2f3d..e82cf353 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java @@ -191,7 +191,7 @@ public void testRbacForUpdate() throws Exception { String shellPayloadForUpdate = mapper.writeValueAsString(testAas); mvc.perform( MockMvcRequestBuilders - .put(SINGLE_SHELL_BASE_PATH, shellId) + .put(SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId)) .contentType(MediaType.APPLICATION_JSON) .content(shellPayloadForUpdate) // test with wrong role @@ -203,7 +203,7 @@ public void testRbacForUpdate() throws Exception { mvc.perform( MockMvcRequestBuilders - .put(SINGLE_SHELL_BASE_PATH, shellId ) + .put(SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) .contentType(MediaType.APPLICATION_JSON) .content(shellPayloadForUpdate) .with(jwtTokenFactory.updateTwin()) @@ -217,7 +217,7 @@ public void testRbacForUpdate() throws Exception { public void testRbacForDelete() throws Exception { mvc.perform( MockMvcRequestBuilders - .delete(SINGLE_SHELL_BASE_PATH, shellId ) + .delete(SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) // test with wrong role .with(jwtTokenFactory.readTwin()) ) @@ -226,7 +226,7 @@ public void testRbacForDelete() throws Exception { mvc.perform( MockMvcRequestBuilders - .delete(SINGLE_SHELL_BASE_PATH, shellId ) + .delete(SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) // test with wrong role .with(jwtTokenFactory.deleteTwin()) ) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index a091fa7a..c85e6242 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -33,7 +33,6 @@ import java.util.UUID; -import static org.assertj.core.api.AssertionsForClassTypes.notIn; import static org.eclipse.tractusx.semantics.registry.TestUtil.getEncodedValue; import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -140,7 +139,7 @@ public void testUpdateShellExpectSuccess() throws Exception { mvc.perform( MockMvcRequestBuilders - .put( SINGLE_SHELL_BASE_PATH, shellId ) + .put( SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) @@ -169,7 +168,7 @@ public void testUpdateShellExpectNotFound() throws Exception { mvc.perform( MockMvcRequestBuilders - .put( SINGLE_SHELL_BASE_PATH, "shellIdthatdoesnotexists" ) + .put( SINGLE_SHELL_BASE_PATH, getEncodedValue("shellIdthatdoesnotexists") ) .accept( MediaType.APPLICATION_JSON ) .contentType( MediaType.APPLICATION_JSON ) .content( mapper.writeValueAsString( shellPayload ) ) @@ -194,7 +193,7 @@ public void testUpdateShellWithDifferentIdInPayloadExpectPathIdIsTaken() throws mvc.perform( MockMvcRequestBuilders - .put( SINGLE_SHELL_BASE_PATH, shellId ) + .put( SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) .accept( MediaType.APPLICATION_JSON ) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) .contentType( MediaType.APPLICATION_JSON ) @@ -228,7 +227,7 @@ public void testDeleteShellExpectSuccess() throws Exception { String shellId = shellPayload.getId(); mvc.perform( MockMvcRequestBuilders - .delete( SINGLE_SHELL_BASE_PATH, shellId ) + .delete( SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -246,7 +245,7 @@ public void testDeleteShellExpectNotFound() throws Exception { String shellId = shellPayload.getId(); mvc.perform( MockMvcRequestBuilders - .delete( SINGLE_SHELL_BASE_PATH, shellId ) + .delete( SINGLE_SHELL_BASE_PATH, getEncodedValue(shellId) ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) From 312bf50e0663d4802d3546ed0f27320d3bd32a29 Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Tue, 18 Jul 2023 10:39:57 +0200 Subject: [PATCH 4/4] Changes done in CHANGELOG.md for new version --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4bbda0d..597c1369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.3.10-M1 +### Added +- In this new version, Base64 decoding is provided for the provided encoded parameters. All the provided path parameters has to be Base64 URL encoded. + +## fixed + + ## 0.3.9-M1 ### Added - In this new version, Cursor pagination is provided for search instead of classical offset pagination in previous version.