From 077da863cb404f0402f66fc3326cd82aee6a11e1 Mon Sep 17 00:00:00 2001 From: Tunahan Cicek Date: Tue, 26 Mar 2024 16:53:45 +0100 Subject: [PATCH] - Fixed behaviour of access rule management in case of multiple specificAssetIds with same keys and different values. --- CHANGELOG.md | 3 +- DEPENDENCIES | 163 +++++++--------- .../api/model/ShellVisibilityCriteria.java | 4 +- .../model/ShellVisibilityCriteriaTest.java | 25 ++- .../SqlBackedAccessControlRuleService.java | 47 ++++- ...SqlBackedAccessControlRuleServiceTest.java | 33 +++- .../service/GranularShellAccessHandler.java | 13 +- ...setAdministrationShellApiSecurityTest.java | 34 ++-- ...setAdministrationShellApiSecurityTest.java | 183 +++++++++++++++++- docs/README.md | 15 +- pom.xml | 4 +- 11 files changed, 379 insertions(+), 145 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a35a70ab..65676c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added lookup api test in aas-registry-e2e-test action ## fixed - KICS findings fixed - +- Fixed behaviour of access rule management in case of multiple specificAssetIds with same keys and different values. +- Update Springboot to version 3.2.4 ## 0.4.1 ### Added diff --git a/DEPENDENCIES b/DEPENDENCIES index 92ded5c5..3e14cde6 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -10,11 +10,9 @@ maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.15.4, maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.4, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-parameter-names/2.15.4, Apache-2.0, approved, #8803 maven/mavencentral/com.fasterxml/classmate/1.6.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.github.ben-manes.caffeine/caffeine/3.1.8, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.errorprone/error_prone_annotations/2.18.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.google.errorprone/error_prone_annotations/2.21.1, Apache-2.0, approved, #9834 maven/mavencentral/com.google.guava/failureaccess/1.0.1, Apache-2.0, approved, CQ22654 maven/mavencentral/com.google.guava/guava/32.1.1-jre, Apache-2.0 AND CC0-1.0 AND LicenseRef-Public-Domain, approved, #9229 maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 @@ -22,22 +20,17 @@ maven/mavencentral/com.google.j2objc/j2objc-annotations/2.8, Apache-2.0, approve maven/mavencentral/com.h2database/h2/2.2.220, (EPL-1.0 OR MPL-2.0) AND (LGPL-3.0-or-later OR EPL-1.0 OR MPL-2.0), approved, #9322 maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.24.4, Apache-2.0, approved, clearlydefined maven/mavencentral/com.opencsv/opencsv/5.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.squareup.okhttp3/okhttp/4.12.0, Apache-2.0, approved, #11156 -maven/mavencentral/com.squareup.okio/okio-jvm/3.6.0, Apache-2.0, approved, #11158 -maven/mavencentral/com.squareup.okio/okio/3.6.0, Apache-2.0, approved, #11155 maven/mavencentral/com.zaxxer/HikariCP/5.0.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/dev.failsafe/failsafe-okhttp/3.3.2, Apache-2.0, approved, #9178 -maven/mavencentral/dev.failsafe/failsafe/3.3.2, Apache-2.0, approved, #9268 maven/mavencentral/io.github.classgraph/classgraph/4.8.149, MIT, approved, CQ22530 -maven/mavencentral/io.micrometer/micrometer-commons/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 -maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 -maven/mavencentral/io.micrometer/micrometer-jakarta9/1.12.3, Apache-2.0, approved, #12923 -maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 +maven/mavencentral/io.micrometer/micrometer-commons/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 +maven/mavencentral/io.micrometer/micrometer-core/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 +maven/mavencentral/io.micrometer/micrometer-jakarta9/1.12.4, Apache-2.0, approved, #12923 +maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, approved, #11680 maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.7, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.7, Apache-2.0, approved, #5929 maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.7, Apache-2.0, approved, #5919 -maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.2, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.3, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.persistence/jakarta.persistence-api/3.1.0, EPL-2.0 OR BSD-3-Clause, approved, ee4j.jpa maven/mavencentral/jakarta.servlet/jakarta.servlet-api/6.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.servlet @@ -45,7 +38,7 @@ maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.1, EPL-2.0 OR maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, ee4j.validation maven/mavencentral/jakarta.websocket/jakarta.websocket-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.websocket maven/mavencentral/jakarta.websocket/jakarta.websocket-client-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.websocket -maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.1, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.2, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/javax.activation/javax.activation-api/1.2.0, (CDDL-1.1 OR GPL-2.0 WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ18740 maven/mavencentral/javax.xml.bind/jaxb-api/2.3.1, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ16911 maven/mavencentral/org.antlr/antlr4-runtime/4.13.0, BSD-3-Clause, approved, #10767 @@ -55,57 +48,37 @@ maven/mavencentral/org.apache.commons/commons-text/1.10.0, Apache-2.0, approved, maven/mavencentral/org.apache.logging.log4j/log4j-api/2.21.1, Apache-2.0 AND (Apache-2.0 AND LGPL-2.0-or-later), approved, #11079 maven/mavencentral/org.apache.logging.log4j/log4j-to-slf4j/2.21.1, Apache-2.0, approved, #11919 maven/mavencentral/org.aspectj/aspectjweaver/1.9.21, Apache-2.0 AND BSD-3-Clause AND EPL-1.0 AND BSD-3-Clause AND Apache-1.1, approved, #7695 -maven/mavencentral/org.checkerframework/checker-qual/3.37.0, MIT, approved, clearlydefined maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined -maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-20240327-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jetty-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-servlet/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-annotations/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-plus/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlet/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlets/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-webapp/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-api/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-http/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-io/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-jndi/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-plus/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-security/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-session/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-util/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-xml/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jetty-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-servlet/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-annotations/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-plus/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlet/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlets/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-webapp/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-api/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-http/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-io/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-jndi/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-plus/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-security/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-session/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-util/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-xml/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.glassfish/jakarta.json/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/org.hibernate.orm/hibernate-core/6.4.4.Final, LGPL-2.1-or-later AND (EPL-2.0 OR BSD-3-Clause) AND MIT, approved, #12490 maven/mavencentral/org.hibernate.validator/hibernate-validator/8.0.1.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jboss.logging/jboss-logging/3.5.3.Final, Apache-2.0, approved, #9471 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.22, Apache-2.0, approved, #14186 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.22, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.22, None, restricted, #14185 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.22, Apache-2.0, approved, #11827 -maven/mavencentral/org.jetbrains/annotations/24.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.liquibase/liquibase-core/4.19.1, Apache-2.0, approved, clearlydefined maven/mavencentral/org.mapstruct/mapstruct/1.5.3.Final, Apache-2.0, approved, #6277 maven/mavencentral/org.openapitools/jackson-databind-nullable/0.1.0, Apache-2.0, approved, clearlydefined @@ -120,42 +93,42 @@ maven/mavencentral/org.slf4j/slf4j-simple/2.0.7, MIT, approved, #10372 maven/mavencentral/org.springdoc/springdoc-openapi-starter-common/2.0.2, Apache-2.0, approved, #5920 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-api/2.0.2, Apache-2.0, approved, #5950 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-ui/2.0.2, Apache-2.0, approved, #5923 -maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.2.3, Apache-2.0, approved, #11921 -maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.2.3, Apache-2.0, approved, #11918 -maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.2.3, Apache-2.0, approved, #11751 -maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.2.3, Apache-2.0, approved, #12918 -maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.2.3, Apache-2.0, approved, #11928 -maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.2.3, Apache-2.0, approved, #11926 -maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.2.3, Apache-2.0, approved, #11878 -maven/mavencentral/org.springframework.boot/spring-boot-starter-jetty/3.2.3, Apache-2.0, approved, #13220 -maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.2.3, Apache-2.0, approved, #11894 -maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.2.3, Apache-2.0, approved, #11890 -maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.2.3, Apache-2.0, approved, #11931 -maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.2.3, Apache-2.0, approved, #12921 -maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.2.3, Apache-2.0, approved, #11916 -maven/mavencentral/org.springframework.boot/spring-boot-starter/3.2.3, Apache-2.0, approved, #11935 -maven/mavencentral/org.springframework.boot/spring-boot/3.2.3, Apache-2.0, approved, #11752 -maven/mavencentral/org.springframework.data/spring-data-commons/3.2.3, Apache-2.0, approved, #11917 -maven/mavencentral/org.springframework.data/spring-data-jpa/3.2.3, Apache-2.0, approved, #11882 -maven/mavencentral/org.springframework.security/spring-security-config/6.2.2, Apache-2.0, approved, #11896 -maven/mavencentral/org.springframework.security/spring-security-core/6.2.2, Apache-2.0, approved, #11904 -maven/mavencentral/org.springframework.security/spring-security-crypto/6.2.2, Apache-2.0 AND ISC, approved, #11908 -maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.2.2, Apache-2.0, approved, #11925 -maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.2.2, Apache-2.0, approved, #11893 -maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.2.2, Apache-2.0, approved, #11920 -maven/mavencentral/org.springframework.security/spring-security-web/6.2.2, Apache-2.0, approved, #11911 -maven/mavencentral/org.springframework/spring-aop/6.1.4, Apache-2.0, approved, #11755 -maven/mavencentral/org.springframework/spring-aspects/6.1.4, Apache-2.0, approved, #11905 -maven/mavencentral/org.springframework/spring-beans/6.1.4, Apache-2.0, approved, #11754 -maven/mavencentral/org.springframework/spring-context/6.1.4, Apache-2.0, approved, #11753 -maven/mavencentral/org.springframework/spring-core/6.1.4, Apache-2.0 AND BSD-3-Clause, approved, #11750 -maven/mavencentral/org.springframework/spring-expression/6.1.4, Apache-2.0, approved, #11747 -maven/mavencentral/org.springframework/spring-jcl/6.1.4, Apache-2.0, approved, #11749 -maven/mavencentral/org.springframework/spring-jdbc/6.1.4, Apache-2.0, approved, #11897 -maven/mavencentral/org.springframework/spring-orm/6.1.4, Apache-2.0, approved, #11924 -maven/mavencentral/org.springframework/spring-tx/6.1.4, Apache-2.0, approved, #11901 -maven/mavencentral/org.springframework/spring-web/6.1.4, Apache-2.0, approved, #11748 -maven/mavencentral/org.springframework/spring-webmvc/6.1.4, Apache-2.0, approved, #11879 +maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.2.4, Apache-2.0, approved, #11921 +maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.2.4, Apache-2.0, approved, #11918 +maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.2.4, Apache-2.0, approved, #11751 +maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.2.4, Apache-2.0, approved, #12918 +maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.2.4, Apache-2.0, approved, #11928 +maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.2.4, Apache-2.0, approved, #11926 +maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.2.4, Apache-2.0, approved, #11878 +maven/mavencentral/org.springframework.boot/spring-boot-starter-jetty/3.2.4, Apache-2.0, approved, #13220 +maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.2.4, Apache-2.0, approved, #11894 +maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.2.4, Apache-2.0, approved, #11890 +maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.2.4, Apache-2.0, approved, #11931 +maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.2.4, Apache-2.0, approved, #12921 +maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.2.4, Apache-2.0, approved, #11916 +maven/mavencentral/org.springframework.boot/spring-boot-starter/3.2.4, Apache-2.0, approved, #11935 +maven/mavencentral/org.springframework.boot/spring-boot/3.2.4, Apache-2.0, approved, #11752 +maven/mavencentral/org.springframework.data/spring-data-commons/3.2.4, Apache-2.0, approved, #11917 +maven/mavencentral/org.springframework.data/spring-data-jpa/3.2.4, Apache-2.0, approved, #11882 +maven/mavencentral/org.springframework.security/spring-security-config/6.2.3, Apache-2.0, approved, #11896 +maven/mavencentral/org.springframework.security/spring-security-core/6.2.3, Apache-2.0, approved, #11904 +maven/mavencentral/org.springframework.security/spring-security-crypto/6.2.3, Apache-2.0 AND ISC, approved, #11908 +maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.2.3, Apache-2.0, approved, #11925 +maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.2.3, Apache-2.0, approved, #11893 +maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.2.3, Apache-2.0, approved, #11920 +maven/mavencentral/org.springframework.security/spring-security-web/6.2.3, Apache-2.0, approved, #11911 +maven/mavencentral/org.springframework/spring-aop/6.1.5, Apache-2.0, approved, #11755 +maven/mavencentral/org.springframework/spring-aspects/6.1.5, Apache-2.0, approved, #11905 +maven/mavencentral/org.springframework/spring-beans/6.1.5, Apache-2.0, approved, #11754 +maven/mavencentral/org.springframework/spring-context/6.1.5, Apache-2.0, approved, #11753 +maven/mavencentral/org.springframework/spring-core/6.1.5, Apache-2.0 AND BSD-3-Clause, approved, #11750 +maven/mavencentral/org.springframework/spring-expression/6.1.5, Apache-2.0, approved, #11747 +maven/mavencentral/org.springframework/spring-jcl/6.1.5, Apache-2.0, approved, #11749 +maven/mavencentral/org.springframework/spring-jdbc/6.1.5, Apache-2.0, approved, #11897 +maven/mavencentral/org.springframework/spring-orm/6.1.5, Apache-2.0, approved, #11924 +maven/mavencentral/org.springframework/spring-tx/6.1.5, Apache-2.0, approved, #11901 +maven/mavencentral/org.springframework/spring-web/6.1.5, Apache-2.0, approved, #11748 +maven/mavencentral/org.springframework/spring-webmvc/6.1.5, Apache-2.0, approved, #11879 maven/mavencentral/org.webjars/swagger-ui/4.15.5, Apache-2.0 AND MIT, approved, #5921 maven/mavencentral/org.webjars/webjars-locator-core/0.55, MIT, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 diff --git a/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java b/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java index 9b640040..1db2bc96 100644 --- a/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java +++ b/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java @@ -20,10 +20,12 @@ package org.eclipse.tractusx.semantics.accesscontrol.api.model; +import java.util.Map; import java.util.Set; import lombok.NonNull; public record ShellVisibilityCriteria( - @NonNull String aasId, @NonNull Set visibleSpecificAssetIdNames, @NonNull Set visibleSemanticIds, boolean publicOnly) { + @NonNull String aasId, @NonNull Set visibleSpecificAssetIdNamesRegardlessOfValues, + @NonNull Map> visibleSpecificAssetIdWhenMatchingValues, @NonNull Set visibleSemanticIds, boolean publicOnly) { } diff --git a/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java b/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java index c36c7139..0900639d 100644 --- a/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java +++ b/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java @@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.*; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Stream; @@ -35,32 +36,38 @@ class ShellVisibilityCriteriaTest { public static Stream nullProvider() { return Stream. builder() - .add( Arguments.of( null, null, null, true ) ) - .add( Arguments.of( UUID.randomUUID().toString(), null, null, true ) ) - .add( Arguments.of( null, Set.of(), null, false ) ) - .add( Arguments.of( null, null, Set.of(), false ) ) + .add( Arguments.of( null, null, null, null, true ) ) + .add( Arguments.of( UUID.randomUUID().toString(), null, null, null, true ) ) + .add( Arguments.of( null, Set.of(), null, null, false ) ) + .add( Arguments.of( null, null, Map.of(), null, false ) ) + .add( Arguments.of( null, null, null, Set.of(), false ) ) .build(); } @ParameterizedTest @MethodSource( "nullProvider" ) void testConstructorCalledWithNullExpectException( - String aasId, Set visibleSpecificAssetIdNames, Set visibleSemanticIds, boolean publicOnly ) { - assertThatThrownBy( () -> new ShellVisibilityCriteria( aasId, visibleSpecificAssetIdNames, visibleSemanticIds, publicOnly ) ) + String aasId, Set visibleSpecificAssetIdNamesRegardlessOfValues, Map> visibleSpecificAssetIdWhenMatchingValues, + Set visibleSemanticIds, boolean publicOnly ) { + assertThatThrownBy( () -> new ShellVisibilityCriteria( aasId, visibleSpecificAssetIdNamesRegardlessOfValues, visibleSpecificAssetIdWhenMatchingValues, + visibleSemanticIds, publicOnly ) ) .isExactlyInstanceOf( NullPointerException.class ); } @Test void testConstructorCalledWithValidDataExpectSuccess() { final String aasId = UUID.randomUUID().toString(); - final Set visibleSpecificAssetIdNames = Set.of( "name1" ); + + final Set visibleSpecificAssetIdNamesRegardlessOfValues = Set.of(); + final Map> visibleSpecificAssetIdWhenMatchingValues = Map.of( "name1", Set.of( "" ) ); final Set visibleSemanticIds = Set.of( "name2" ); final boolean publicOnly = true; - ShellVisibilityCriteria actual = new ShellVisibilityCriteria( aasId, visibleSpecificAssetIdNames, visibleSemanticIds, publicOnly ); + ShellVisibilityCriteria actual = new ShellVisibilityCriteria( aasId, visibleSpecificAssetIdNamesRegardlessOfValues, + visibleSpecificAssetIdWhenMatchingValues, visibleSemanticIds, publicOnly ); assertThat( actual.aasId() ).isEqualTo( aasId ); - assertThat( actual.visibleSpecificAssetIdNames() ).isEqualTo( visibleSpecificAssetIdNames ); + assertThat( actual.visibleSpecificAssetIdWhenMatchingValues() ).isEqualTo( visibleSpecificAssetIdWhenMatchingValues ); assertThat( actual.visibleSemanticIds() ).isEqualTo( visibleSemanticIds ); assertThat( actual.publicOnly() ).isEqualTo( publicOnly ); } diff --git a/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java b/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java index 51c857f2..c3c24cf4 100644 --- a/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java +++ b/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java @@ -61,13 +61,22 @@ public List filterValidSpecificAssetIdsForLookup( Set allAccessControlRulesForBpn = findPotentiallyMatchingAccessControlRules( bpn ).collect( Collectors.toSet() ); return shellContext.stream() .filter( aShellContext -> { - Set visibleSpecificAssetIdNames = allAccessControlRulesForBpn.stream() - .filter( accessControlRule -> aShellContext.specificAssetIds().containsAll( accessControlRule.getMandatorySpecificAssetIds() ) ) - .flatMap( accessControlRule -> accessControlRule.getVisibleSpecificAssetIdNames().stream() ) + Set visibleSpecificAssetIdNamesRegardlessOfValues = allAccessControlRulesForBpn.stream() + .filter( accessControlRule -> aShellContext.specificAssetIds().containsAll( + accessControlRule.getMandatorySpecificAssetIds() ) ) + .flatMap( this::keepVisibleSpecificAssetIdNamesWithoutValueRestrictions ) .collect( Collectors.toSet() ); + + Map> visibleSpecificAssetIdWhenMatchingValues = allAccessControlRulesForBpn.stream() + .filter( accessControlRule -> aShellContext.specificAssetIds().containsAll( + accessControlRule.getMandatorySpecificAssetIds() ) ) + .flatMap( this::keepVisibleSpecificAssetIdNamesWithValueRestrictions ) + .collect( Collectors.groupingBy( SpecificAssetId::name, Collectors.mapping( SpecificAssetId::value, Collectors.toSet() ) ) ); + return aShellContext.specificAssetIds().stream() - .filter( id -> visibleSpecificAssetIdNames.contains( id.name() ) ) - .collect( Collectors.toSet() ).containsAll( userQuery ); + .filter( id -> isSpecificAssetIdVisible( id, visibleSpecificAssetIdNamesRegardlessOfValues, visibleSpecificAssetIdWhenMatchingValues ) ) + .collect( Collectors.toSet() ) + .containsAll( userQuery ); } ) .map( ShellVisibilityContext::aasId ) .toList(); @@ -76,15 +85,21 @@ public List filterValidSpecificAssetIdsForLookup( @Override public ShellVisibilityCriteria fetchVisibilityCriteriaForShell( ShellVisibilityContext shellContext, String bpn ) throws DenyAccessException { Set matchingAccessControlRules = findMatchingAccessControlRules( shellContext, bpn ); - Set visibleSpecificAssetIdNames = matchingAccessControlRules.stream() - .flatMap( accessControlRule -> accessControlRule.getVisibleSpecificAssetIdNames().stream() ) + Set visibleSpecificAssetIdNamesRegardlessOfValues = matchingAccessControlRules.stream() + .flatMap( this::keepVisibleSpecificAssetIdNamesWithoutValueRestrictions ) .collect( Collectors.toSet() ); + + Map> visibleSpecificAssetIdWhenMatchingValues = matchingAccessControlRules.stream() + .flatMap( this::keepVisibleSpecificAssetIdNamesWithValueRestrictions ) + .collect( Collectors.groupingBy( SpecificAssetId::name, Collectors.mapping( SpecificAssetId::value, Collectors.toSet() ) ) ); + Set visibleSemanticIds = matchingAccessControlRules.stream() .map( AccessRulePolicy::getVisibleSemanticIds ) .flatMap( Collection::stream ) .collect( Collectors.toSet() ); boolean publicOnly = matchingAccessControlRules.stream().noneMatch( rule -> rule.getBpn().equals( bpn ) ); - return new ShellVisibilityCriteria( shellContext.aasId(), visibleSpecificAssetIdNames, visibleSemanticIds, publicOnly ); + return new ShellVisibilityCriteria( shellContext.aasId(), visibleSpecificAssetIdNamesRegardlessOfValues, visibleSpecificAssetIdWhenMatchingValues, + visibleSemanticIds, publicOnly ); } @Override @@ -123,4 +138,20 @@ private Set findMatchingAccessControlRules( ShellVisibilityCon } return matching; } + + private boolean isSpecificAssetIdVisible( SpecificAssetId specificAssetId, Set visibleSpecificAssetIdNamesRegardlessOfValues, + Map> visibleSpecificAssetIdWhenMatchingValues ) { + return visibleSpecificAssetIdNamesRegardlessOfValues.contains( specificAssetId.name() ) + || visibleSpecificAssetIdWhenMatchingValues.getOrDefault( specificAssetId.name(), Set.of() ).contains( specificAssetId.value() ); + } + + private Stream keepVisibleSpecificAssetIdNamesWithoutValueRestrictions( AccessRulePolicy accessRulePolicy ) { + return accessRulePolicy.getVisibleSpecificAssetIdNames().stream() + .filter( name -> accessRulePolicy.getMandatorySpecificAssetIds().stream().map( SpecificAssetId::name ).noneMatch( name::equals ) ); + } + + private Stream keepVisibleSpecificAssetIdNamesWithValueRestrictions( AccessRulePolicy accessRulePolicy ) { + return accessRulePolicy.getMandatorySpecificAssetIds().stream() + .filter( mandatory -> accessRulePolicy.getVisibleSpecificAssetIdNames().contains( mandatory.name() ) ); + } } diff --git a/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java b/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java index 1c44c853..0aaad488 100644 --- a/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java +++ b/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -89,19 +90,36 @@ public static Stream matchingSpecificAssetIdFilterProvider() { public static Stream matchingSpecificAssetIdVisibilityProvider() { return Stream. builder() .add( Arguments.of( - Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, VERSION_NUMBER_01 ), + Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, PART_INSTANCE_ID_00002, VERSION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, VERSION_NUMBER ), + Set.of( VERSION_NUMBER ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), Set.of( MANUFACTURER_PART_ID_99991.value() ), + CUSTOMER_PART_ID_ACME001.name(), Set.of( CUSTOMER_PART_ID_ACME001.value() ), + PART_INSTANCE_ID_00001.name(), Set.of( PART_INSTANCE_ID_00001.value() ) + ), Set.of( TRACEABILITYV_1_1_0 ) ) ) .add( Arguments.of( Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00002, REVISION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, REVISION_NUMBER ), + Set.of( PART_INSTANCE_ID ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), Set.of( MANUFACTURER_PART_ID_99991.value() ), + CUSTOMER_PART_ID_ACME001.name(), Set.of( CUSTOMER_PART_ID_ACME001.value() ), + REVISION_NUMBER_01.name(), Set.of( REVISION_NUMBER_01.value() ) + ), Set.of( PRODUCT_CARBON_FOOTPRINTV_1_1_0 ) ) ) .add( Arguments.of( Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, VERSION_NUMBER_01, REVISION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, REVISION_NUMBER, VERSION_NUMBER ), + Set.of( PART_INSTANCE_ID, VERSION_NUMBER ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), + Set.of( MANUFACTURER_PART_ID_99991.value() ), + CUSTOMER_PART_ID_ACME001.name(), Set.of( CUSTOMER_PART_ID_ACME001.value() ), + PART_INSTANCE_ID_00001.name(), Set.of( PART_INSTANCE_ID_00001.value() ), + REVISION_NUMBER_01.name(), Set.of( REVISION_NUMBER_01.value() ) + ), Set.of( PRODUCT_CARBON_FOOTPRINTV_1_1_0, TRACEABILITYV_1_1_0 ) ) ) .build(); } @@ -164,13 +182,14 @@ void testFetchVisibilityCriteriaForShellWhenNoMatchingBpnExpectException() { @ParameterizedTest @MethodSource( "matchingSpecificAssetIdVisibilityProvider" ) void testFetchVisibilityCriteriaForShellWhenMatchingSpecificAssetIdsProvidedExpectFilteringList( - Set specificAssetIds, String bpn, - Set expectedSpecificAssetIdNames, Set expectedSemanticIds ) throws DenyAccessException { + Set specificAssetIds, String bpn, Set expectedSpecificAssetIdNamesRegardlessOfValues, + Map> expectedSpecificAssetIdWhenMatchingValues, Set expectedSemanticIds ) throws DenyAccessException { ShellVisibilityContext shellContext = new ShellVisibilityContext( UUID.randomUUID().toString(), specificAssetIds ); final var actual = underTest.fetchVisibilityCriteriaForShell( shellContext, bpn ); assertThat( actual.visibleSemanticIds() ).isEqualTo( expectedSemanticIds ); - assertThat( actual.visibleSpecificAssetIdNames() ).isEqualTo( expectedSpecificAssetIdNames ); + assertThat( actual.visibleSpecificAssetIdNamesRegardlessOfValues() ).isEqualTo( expectedSpecificAssetIdNamesRegardlessOfValues ); + assertThat( actual.visibleSpecificAssetIdWhenMatchingValues() ).isEqualTo( expectedSpecificAssetIdWhenMatchingValues ); } } diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java index 3e64a88b..7ae8f577 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java @@ -23,6 +23,7 @@ import java.time.Instant; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -151,7 +152,7 @@ private Shell filterShellContents( Shell shell, ShellVisibilityCriteria visibili Set filteredSubmodels = shell.getSubmodels().stream() .filter( submodel -> submodel.getSemanticId().getKeys().stream() .anyMatch( key -> key.getType() == ReferenceKeyType.SUBMODEL - && visibilityCriteria.visibleSemanticIds().contains( key.getValue() ) ) ) + && visibilityCriteria.visibleSemanticIds().contains( key.getValue() ) ) ) .collect( Collectors.toSet() ); final Shell filtered; if ( visibilityCriteria.publicOnly() ) { @@ -182,8 +183,7 @@ private ShellVisibilityContext toShellVisibilityContext( Shell shell ) { private Set filterSpecificAssetIdsByTenantId( Set shellIdentifiers, ShellVisibilityCriteria visibilityCriteria ) { //noinspection SimplifyStreamApiCallChains return shellIdentifiers.stream() - .filter( identifier -> identifier.getKey().equals( ShellIdentifier.GLOBAL_ASSET_ID_KEY ) - || visibilityCriteria.visibleSpecificAssetIdNames().contains( identifier.getKey() ) ) + .filter( identifier -> isSisSpecificAssetIdVisible( identifier, visibilityCriteria ) ) //TODO: Do we need to clear the list of external subject Ids? .map( identifier -> { Optional.ofNullable( identifier.getExternalSubjectId() ) @@ -191,6 +191,13 @@ private Set filterSpecificAssetIdsByTenantId( Set visibleSpecificAssetIdNamesRegardlessOfValues = shellVisibilityCriteria.visibleSpecificAssetIdNamesRegardlessOfValues(); + Map> visibleSpecificAssetIdWhenMatchingValues = shellVisibilityCriteria.visibleSpecificAssetIdWhenMatchingValues(); + return identifier.getKey().equals( ShellIdentifier.GLOBAL_ASSET_ID_KEY ) + || visibleSpecificAssetIdNamesRegardlessOfValues.contains( identifier.getKey() ) + || visibleSpecificAssetIdWhenMatchingValues.getOrDefault( identifier.getKey(), Set.of() ).contains( identifier.getValue() ); } } 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 1a2ea719..2a6100ae 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 @@ -24,6 +24,7 @@ import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.UUID; @@ -664,10 +665,6 @@ public void testGetAllShellsWithDefaultClosedFilteredSpecificAssetIdsByTenantId( @Test public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exception { - AssetAdministrationShellDescriptor shellPayload = TestUtil - .createCompleteAasDescriptor( keyPrefix + "semanticId", "http://example.com/" ); - shellPayload.setId( keyPrefix ); - shellPayload.setSpecificAssetIds( null ); SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue", @@ -680,11 +677,22 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio SpecificAssetId asset5 = TestUtil.createSpecificAssetId( "manufacturerPartId", keyPrefix + "wildcardAllowed", List.of( getExternalSubjectIdWildcardPrefix() ) ); - shellPayload.setSpecificAssetIds( List.of( asset1, asset2, asset3, asset4, asset5 ) ); + List specificAssetIds = List.of( asset1, asset2, asset3, asset4, asset5 ); + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3, asset5 ); + testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + public void testGetShellWithFilteredSpecificAssetIdsByTenantId( List specificAssetIds, List expectedSpecificAssetIds ) + throws Exception { + AssetAdministrationShellDescriptor shellPayload = TestUtil + .createCompleteAasDescriptor( keyPrefix + "semanticId", "http://example.com/" ); + shellPayload.setId( keyPrefix ); + shellPayload.setSpecificAssetIds( specificAssetIds ); performShellCreateRequest( mapper.writeValueAsString( shellPayload ) ); String shellId = shellPayload.getId(); String encodedShellId = getEncodedValue( shellId ); + // Owner of tenant has access to all specificAssetIds mvc.perform( MockMvcRequestBuilders @@ -696,11 +704,13 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isOk() ) .andExpect( jsonPath( "$.id", equalTo( shellId ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - containsInAnyOrder( "tenantTwoAssetIdValue", "tenantThreeAssetIdValue", "withoutTenantAssetIdValue", "ignoreWildcard", - keyPrefix + "wildcardAllowed" ) ) ); + .andExpect( jsonPath( "$.specificAssetIds[*].name", hasItems( specificAssetIds.stream().map( SpecificAssetId::getName ).toArray() ) ) ) + .andExpect( jsonPath( "$.specificAssetIds[*].value", hasItems( specificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ); // test with tenant two + ArrayList hiddenSpecificAssetIds = new ArrayList<>( specificAssetIds ); + hiddenSpecificAssetIds.removeAll( expectedSpecificAssetIds ); + mvc.perform( MockMvcRequestBuilders .get( SINGLE_SHELL_BASE_PATH, encodedShellId ) @@ -711,10 +721,10 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isOk() ) .andExpect( jsonPath( "$.id", equalTo( shellId ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - hasItems( "tenantTwoAssetIdValue", "withoutTenantAssetIdValue", keyPrefix + "wildcardAllowed" ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - not( hasItems( "tenantThreeAssetIdValue", "ignoreWildcard" ) ) ) ); + .andExpect( jsonPath( "$.specificAssetIds[*].name", hasItems( expectedSpecificAssetIds.stream().map( SpecificAssetId::getName ).toArray() ) ) ) + .andExpect( jsonPath( "$.specificAssetIds[*].value", hasItems( expectedSpecificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ) + .andExpect( + jsonPath( "$.specificAssetIds[*].value", not( hasItems( hiddenSpecificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ) ); } @Test diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java index 809a76f9..defcd4da 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java @@ -208,19 +208,194 @@ public void testGetAllShellsWithDefaultClosedFilteredSpecificAssetIdsByTenantId( } @Test + @DisplayName( "Test GetShell with filtered specificAssetId by tenantId" ) public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exception { + // Create and save rule accessControlRuleRepository.saveAllAndFlush( List.of( - TestUtil.createAccessRule( TestUtil.PUBLIC_READABLE, + // Rule for BPN + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), - TestUtil.createAccessRule( jwtTokenFactory.tenantTwo().getTenantId(), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ), - TestUtil.createAccessRule( jwtTokenFactory.tenantThree().getTenantId(), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantThree().getTenantId(), + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue" ), + // Rule for visible specificAssetIds Set.of( keyPrefix + "CustomerPartId2" ), Set.of( keyPrefix + "semanticId" ) ) ) ); - super.testGetShellWithFilteredSpecificAssetIdsByTenantId(); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + // Define specificAsset with wildcard which not allowed. (Only manufacturerPartId is defined in application.yml) + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "BPID", "ignoreWildcard", List.of( getExternalSubjectIdWildcardPrefix() ) ); + // Define specificAsset with wildcard which is allowed. (Only manufacturerPartId is defined in application.yml) + SpecificAssetId asset5 = TestUtil.createSpecificAssetId( "manufacturerPartId", keyPrefix + "wildcardAllowed", + List.of( getExternalSubjectIdWildcardPrefix() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4, asset5 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3, asset5 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where the specific mandatory Rule match over ANY rule by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndMandatoryRuleMatchedOverAnyByTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + // Rule for BPN + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where the ANY Rule matched by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndAnyRuleMatchedByTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "PartInstanceId", "OwnerAssetidValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset2, asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where mandatory rule not match and disable specificAssetId by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndMandatoryRuleNotMatchedTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "PartInstanceId", "OwnerAssetidValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys and multiple rules where first rule with mandatory rule not match and the second rule matched with any by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndMultipleRulesTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "MaterialNumber", "notMatchedValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "PartInstanceId", "OwnerAssetidValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); } @Test diff --git a/docs/README.md b/docs/README.md index 2ca8fd9d..2c23ef0c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -790,8 +790,14 @@ The example policy above can be split into multiple parts when read. 1. The first access rule (`$.policy.accessRules[0]`) defines the *bpn* (*externalSubjectId*) of the tenant to whom the policy applies. 2. The second access rule (`$.policy.accessRules[1]`) defines the *mandatorySpecificAssetIds* which must be present in the *Digital Twin* in order for the rule to be applicable. The rule will become applicable only if __all__ *specificAssetId* name-value pairs of the rule are present in the *Digital Twin*. 3. Effect - Defines which parts of the matching *Digital Twins* should be visible when the client's *externalSubjectId* matches the rule's. - 1. The third access rule (`$.policy.accessRules[2]`) defines the *visibleSpecificAssetIdNames*. These are the names of the *specificAssetIds* from the *Digital Twin* which should be visible when the rule matches. - 2. The fourth access rule (`$.policy.accessRules[3]`) defines the *visibleSemanticIds*. These *semanticIds* are identifying the *submodelDescriptors* from the *Digital Twin* which should be visible when the rule matches. + 1. The third access rule (`$.policy.accessRules[2]`) defines the *visibleSpecificAssetIdNames*. When the rule matches, the *specificAssetIds* from the + *Digital Twin* with these names should be visible using one of the cases below: + 1. When the same name is present as a name in the *mandatorySpecificAssetIds* and the *visibleSpecificAssetIdNames*, then the rule will only make a + *specificAssetId* from the *Digital Twin* when the *specificAssetId* is listed as an item of the *mandatorySpecificAssetIds*. + 2. Otherwise, if the name is only present as a *visibleSpecificAssetIdNames* without being present on the *mandatorySpecificAssetIds* as well, the rule + will make visible any *specificAssetId* from the *Digital Twin* if the name of the *specificAssetId* matches the name from the *visibleSpecificAssetIdNames*, + regardless of the value of the *specificAssetId* in the *Digital Twin*. + 2. The fourth access rule (`$.policy.accessRules[3]`) defines the *visibleSemanticIds*. These *semanticIds* are identifying the *submodelDescriptors* from the *Digital Twin* which should be visible when the rule matches. ##### How the rule evaluation works? @@ -843,7 +849,10 @@ The process is similar to the lookup shells, the filtering and access control of 2. The list of shells fetched in the previous step is filtered by applying the access control rules to them one-by-one. 3. The process is repeated until we have the desired number of *Digital Twins* or there are no more *Digital Twins* to fetch. 4. The visible properties of the visible *Digital Twins* are returned. - + 1. If the list of *specificAssetIds* in the shell has *multiple* entries with the same name, then the following rules apply: + 1. Usecase 1: A rule includes a specificAssetId (for example customerPartId=123) as *mandatorySpecificAssetId and visibleSpecificAssetId*. The Shell has multiple entries with the same name and *one of the entry* matched the value from mandatorySpecificAssetId, then only the matched entry is visible. + 2. Usecase 2: A rule includes a specificAssetId (for example customerPartId=123) as *mandatorySpecificAssetId and visibleSpecificAssetId*. The Shell has multiple entries with the same name and *none of the entries* matched the value from mandatorySpecificAssetId, then no entries with the same name is visible. + ###### Get Shell by AAS Id - `GET {{baseUrl}}/api/v3/shell-descriptors/:aasIdentifier` To determine the visibility of a single *Digital Twin*, we can simply: diff --git a/pom.xml b/pom.xml index 742dfc8c..5e944e36 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.3 + 3.2.4 @@ -66,7 +66,7 @@ - 3.2.3 + 3.2.4 1.6.14 1.18.24 1.5.20