Multitenancy in SDC 71/132171/9
authorKartik Hegde <kh00735564@techmahindra.com>
Sat, 12 Nov 2022 08:59:11 +0000 (14:29 +0530)
committerKartik Hegde <kh00735564@techmahindra.com>
Wed, 21 Dec 2022 12:04:30 +0000 (12:04 +0000)
Issue-ID: SDC-4215
Change-Id: Ie24ba38acc9f1998d4a7e722e8f98456dab9201d
Signed-off-by: Kartik Hegde <kh00735564@techmahindra.com>
73 files changed:
asdctool/src/main/resources/config/error-configuration.yaml
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
catalog-be/src/main/java/org/openecomp/sdc/be/catalog/impl/ComponentMessage.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/filters/MultitenancyFilter.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-be/src/main/resources/config/error-configuration.yaml
catalog-be/src/main/webapp/WEB-INF/keycloak.json [new file with mode: 0644]
catalog-be/src/main/webapp/WEB-INF/web.xml
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionaryExtractor.java
catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ComponentMetadataData.java
catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ResourceMetadataData.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/catalog/CatalogComponent.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java
catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentMetadata.java
catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceMetadata.java
common-app-api/src/main/java/org/openecomp/sdc/common/util/Multitenancy.java [new file with mode: 0644]
common-app-api/src/main/resources/multitenancy.json [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ServiceMetadataDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFieldsExtractor.java
docs/logging.rst
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/main/java/org/openecomp/sdcrests/item/rest/Items.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/main/java/org/openecomp/sdcrests/item/rest/mapping/MapItemToDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/main/java/org/openecomp/sdcrests/item/rest/services/ItemsImpl.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/test/java/org/openecomp/sdcrests/item/rest/services/ItemsImplTest.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-types/src/main/java/org/openecomp/sdcrests/item/types/ItemDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/MultitenancyKeycloakFilter.java [new file with mode: 0644]
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/keycloak.json [new file with mode: 0644]
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-services/src/main/java/org/openecomp/sdcrests/vendorlicense/rest/VendorLicenseModels.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-services/src/main/java/org/openecomp/sdcrests/vendorlicense/rest/mapping/MapVendorLicenseModelEntityToDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-services/src/main/java/org/openecomp/sdcrests/vendorlicense/rest/mapping/MapVendorLicenseModelRequestDtoToVendorLicenseModelEntity.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-services/src/main/java/org/openecomp/sdcrests/vendorlicense/rest/services/VendorLicenseModelsImpl.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-types/src/main/java/org/openecomp/sdcrests/vendorlicense/types/VendorLicenseModelEntityDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-license-rest/vendor-license-rest-types/src/main/java/org/openecomp/sdcrests/vendorlicense/types/VendorLicenseModelRequestDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/VendorSoftwareProducts.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/MapItemToVspDetailsDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/MapVspDescriptionDtoToItem.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/MapVspDescriptionDtoToVspDetails.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/MapVspDetailsToDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/VendorSoftwareProductsImpl.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-types/src/main/java/org/openecomp/sdcrests/vendorsoftwareproducts/types/VspDescriptionDto.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-types/src/main/java/org/openecomp/sdcrests/vendorsoftwareproducts/types/VspDetailsDto.java
openecomp-be/backend/openecomp-sdc-vendor-license-manager/src/test/java/org/openecomp/sdc/vendorlicense/impl/VendorLicenseModelTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/VendorSoftwareProductManagerImplTest.java
openecomp-be/lib/openecomp-sdc-vendor-license-lib/openecomp-sdc-vendor-license-api/src/main/java/org/openecomp/sdc/vendorlicense/dao/types/VendorLicenseModelEntity.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-api/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/VendorSoftwareProductConstants.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-api/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/dao/type/VspDetails.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/dao/impl/zusammen/VendorSoftwareProductInfoDaoZusammenImpl.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/dao/impl/zusammen/convertor/ElementToVSPGeneralConvertor.java
openecomp-be/lib/openecomp-sdc-versioning-lib/openecomp-sdc-versioning-api/src/main/java/org/openecomp/sdc/versioning/types/Item.java
openecomp-be/lib/openecomp-sdc-versioning-lib/openecomp-sdc-versioning-core/src/main/java/org/openecomp/sdc/versioning/dao/impl/zusammen/ItemZusammenDaoImpl.java
pom.xml

index ba29ce6..5bd933a 100644 (file)
@@ -1988,6 +1988,13 @@ errors:
     messageId: "SVC4691"
   }
 
+  #---------SVC4950-----------------------------
+  MISSING_TENANT_NAME: {
+    code: 400,
+    message: "Error: Missing Tenant name.",
+    messageId: "SVC4950"
+  }
+
   #---------POL4692------------------------------
   MISSING_OLD_COMPONENT_INSTANCE: {
     code: 400  ,
index 32bbf73..a9df460 100644 (file)
@@ -2822,6 +2822,14 @@ errors:
         message: "Capability '%1' not found in '%2' '%3'."
         messageId: "SVC4186"
 
+    #---------SVC4950-----------------------------
+    MISSING_TENANT_NAME: {
+        code: 400,
+        message: "Error: Missing Tenant name.",
+        messageId: "SVC4950"
+    }
+
+
     #---------SVC4001------------------------------
     NOT_PERMITTED_SPECIAL_CHARS: {
         code: 406,
index 69a04e1..34e2add 100644 (file)
@@ -85,6 +85,9 @@ public class ComponentMessage extends CatalogComponent implements IComponentMess
         setIsHighestVersion(component.isHighestVersion()); // isHighestVersion
 
         setDescription(component.getDescription()); // description
+
+        setTenant(component.getTenant()); // tenant
+
         if (component.getTags() != null) {
             setTags(component.getTags()); // tags
         }
index 9c2c070..51444a2 100644 (file)
@@ -797,6 +797,7 @@ public final class ImportUtils {
         public static final String ESCAPED_DOUBLE_QUOTE = "\"";
         public static final String QUOTE = "'";
         public static final String VF_DESCRIPTION = "Nested VF in service";
+        public static final String TENANT = "tenant";
 
         private Constants() {
         }
index cb57ab3..619a923 100644 (file)
@@ -1411,6 +1411,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic {
         resourceMetaData.setIcon(ImportUtils.Constants.DEFAULT_ICON);
         resourceMetaData.setContactId(user.getUserId());
         resourceMetaData.setVendorName(resourceVf.getVendorName());
+        resourceMetaData.setTenant(resourceVf.getTenant());
         resourceMetaData.setVendorRelease(resourceVf.getVendorRelease());
         resourceMetaData.setModel(resourceVf.getModel());
         // Setting tag
@@ -1444,6 +1445,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic {
         cvfc.setContactId(csarInfo.getModifier().getUserId());
         cvfc.setCreatorUserId(csarInfo.getModifier().getUserId());
         cvfc.setVendorName(resourceVf.getVendorName());
+        cvfc.setTenant(resourceVf.getTenant());
         cvfc.setVendorRelease(resourceVf.getVendorRelease());
         cvfc.setModel(resourceVf.getModel());
         cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber());
index 79b3c96..076dd50 100644 (file)
@@ -330,6 +330,7 @@ public class ResourceImportManager {
             resource.setIcon(resourceMetaData.getResourceIconPath());
             resource.setResourceVendorModelNumber(resourceMetaData.getResourceVendorModelNumber());
             resource.setResourceType(ResourceTypeEnum.valueOf(resourceMetaData.getResourceType()));
+            resource.setTenant(resourceMetaData.getTenant());
             if (resourceMetaData.getVendorName() != null) {
                 resource.setVendorName(resourceMetaData.getVendorName());
             }
index 6f10aae..595603e 100644 (file)
@@ -62,6 +62,7 @@ public class ServiceImportManager {
     public void populateServiceMetadata(UploadServiceInfo serviceMetaData, Service service) {
         if (service != null && serviceMetaData != null) {
             service.setDescription(serviceMetaData.getDescription());
+            service.setTenant(serviceMetaData.getTenant());
             service.setTags(serviceMetaData.getTags());
             service.setCategories(serviceMetaData.getCategories());
             service.setContactId(serviceMetaData.getContactId());
index 43b88fd..41babdf 100644 (file)
@@ -917,6 +917,7 @@ public class ServiceImportParseLogic {
         cvfc.setContactId(csarInfo.getModifier().getUserId());
         cvfc.setCreatorUserId(csarInfo.getModifier().getUserId());
         cvfc.setVendorName(resourceVf.getVendorName());
+        cvfc.setTenant(resourceVf.getTenant());
         cvfc.setVendorRelease(resourceVf.getVendorRelease());
         cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber());
         cvfc.setToscaResourceName(buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), nodeName).getLeft());
@@ -982,6 +983,7 @@ public class ServiceImportParseLogic {
         resourceMetaData.setIcon(ImportUtils.Constants.DEFAULT_ICON);
         resourceMetaData.setContactId(user.getUserId());
         resourceMetaData.setVendorName(resourceVf.getVendorName());
+        resourceMetaData.setTenant(resourceVf.getTenant());
         resourceMetaData.setVendorRelease(resourceVf.getVendorRelease());
         // Setting tag
         List<String> tags = new ArrayList<>();
@@ -1306,6 +1308,7 @@ public class ServiceImportParseLogic {
         cvfc.setContactId(csarInfo.getModifier().getUserId());
         cvfc.setCreatorUserId(csarInfo.getModifier().getUserId());
         cvfc.setVendorName("cmri");
+        cvfc.setTenant("tenant");
         cvfc.setVendorRelease("1.0");
         cvfc.setResourceVendorModelNumber("");
         cvfc.setToscaResourceName(buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), nodeName).getLeft());
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/filters/MultitenancyFilter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/filters/MultitenancyFilter.java
new file mode 100644 (file)
index 0000000..45dbbad
--- /dev/null
@@ -0,0 +1,270 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Tech-Mahindra Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.filters;
+
+import org.keycloak.adapters.*;
+import org.keycloak.adapters.servlet.FilterRequestAuthenticator;
+import org.keycloak.adapters.servlet.OIDCFilterSessionStore;
+import org.keycloak.adapters.servlet.OIDCServletHttpFacade;
+import org.keycloak.adapters.spi.*;
+import org.openecomp.sdc.common.util.Multitenancy;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+
+public class MultitenancyFilter implements Filter {
+
+    private static final Logger log = Logger.getLogger("" + MultitenancyFilter.class);
+
+    public static final String SKIP_PATTERN_PARAM = "keycloak.config.skipPattern";
+
+    public static final String ID_MAPPER_PARAM = "keycloak.config.idMapper";
+
+    public static final String CONFIG_RESOLVER_PARAM = "keycloak.config.resolver";
+
+    public static final String CONFIG_FILE_PARAM = "keycloak.config.file";
+
+    public static final String CONFIG_PATH_PARAM = "keycloak.config.path";
+
+    protected AdapterDeploymentContext deploymentContext;
+
+    protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
+
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+
+    protected Pattern skipPattern;
+
+    private final KeycloakConfigResolver definedConfigResolver;
+
+    boolean keycloak;
+
+    String path = "/WEB-INF/keycloak.json";
+
+    /**
+     * Constructor that can be used to define a {@code KeycloakConfigResolver} that will be used at initialization to
+     * provide the {@code KeycloakDeployment}.
+     * @param definedConfigResolver the resolver
+     */
+    public MultitenancyFilter(KeycloakConfigResolver definedConfigResolver) {
+        this.definedConfigResolver = definedConfigResolver;
+    }
+
+    public MultitenancyFilter() {
+        this(null);
+    }
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        String skipPatternDefinition = filterConfig.getInitParameter(SKIP_PATTERN_PARAM);
+        if (skipPatternDefinition != null) {
+            skipPattern = Pattern.compile(skipPatternDefinition, Pattern.DOTALL);
+        }
+
+        String idMapperClassName = filterConfig.getInitParameter(ID_MAPPER_PARAM);
+        if (idMapperClassName != null) {
+            try {
+                final Class<?> idMapperClass = getClass().getClassLoader().loadClass(idMapperClassName);
+                final Constructor<?> idMapperConstructor = idMapperClass.getDeclaredConstructor();
+                Object idMapperInstance = null;
+                // for KEYCLOAK-13745 test
+                if (idMapperConstructor.getModifiers() == Modifier.PRIVATE) {
+                    idMapperInstance = idMapperClass.getMethod("getInstance").invoke(null);
+                } else {
+                    idMapperInstance = idMapperConstructor.newInstance();
+                }
+                if(idMapperInstance instanceof SessionIdMapper) {
+                    this.idMapper = (SessionIdMapper) idMapperInstance;
+                } else {
+                    log.log(Level.WARNING, "SessionIdMapper class {0} is not instance of org.keycloak.adapters.spi.SessionIdMapper", idMapperClassName);
+                }
+            } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
+                log.log(Level.WARNING, "SessionIdMapper class could not be instanced", e);
+            }
+        }
+
+        if (definedConfigResolver != null) {
+            deploymentContext = new AdapterDeploymentContext(definedConfigResolver);
+            log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", definedConfigResolver.getClass());
+        } else {
+            String configResolverClass = filterConfig.getInitParameter(CONFIG_RESOLVER_PARAM);
+            if (configResolverClass != null) {
+                try {
+                    KeycloakConfigResolver configResolver = (KeycloakConfigResolver) getClass().getClassLoader().loadClass(configResolverClass).getDeclaredConstructor().newInstance();
+                    deploymentContext = new AdapterDeploymentContext(configResolver);
+                    log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
+                } catch (Exception ex) {
+                    log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is not configured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
+                    deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                }
+            } else {
+                String fp = filterConfig.getInitParameter(CONFIG_FILE_PARAM);
+                InputStream is = null;
+                if (fp != null) {
+                    try {
+                        is = new FileInputStream(fp);
+                    } catch (FileNotFoundException e) {
+                        throw new RuntimeException(e);
+                    }
+                } else {
+                    String pathParam = filterConfig.getInitParameter(CONFIG_PATH_PARAM);
+                    if (pathParam != null) path = pathParam;
+                    is = filterConfig.getServletContext().getResourceAsStream(path);
+                }
+                KeycloakDeployment kd = createKeycloakDeploymentFrom(is);
+                deploymentContext = new AdapterDeploymentContext(kd);
+                log.fine("Keycloak is using a per-deployment configuration.");
+            }
+        }
+        filterConfig.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+        nodesRegistrationManagement = new NodesRegistrationManagement();
+    }
+
+    private KeycloakDeployment createKeycloakDeploymentFrom(InputStream is) {
+        if (is == null) {
+            log.fine("No adapter configuration. Keycloak is not configured and will deny all requests.");
+            return new KeycloakDeployment();
+        }
+        return KeycloakDeploymentBuilder.build(is);
+    }
+
+
+    @Override
+    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
+        log.fine("Keycloak OIDC Filter");
+        Multitenancy keyaccess= new Multitenancy();
+        keycloak= keyaccess.multiTenancyCheck();
+
+        HttpServletRequest request = (HttpServletRequest) req;
+        HttpServletResponse response = (HttpServletResponse) res;
+
+        if (!keycloak) {
+            chain.doFilter(req, res);
+            return;
+        }
+
+        if (shouldSkip(request)) {
+            chain.doFilter(req, res);
+            return;
+        }
+
+        OIDCServletHttpFacade facade = new OIDCServletHttpFacade(request, response);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment == null || !deployment.isConfigured()) {
+            response.sendError(403);
+            log.fine("deployment not configured");
+            return;
+        }
+
+        PreAuthActionsHandler preActions = new PreAuthActionsHandler(new org.openecomp.sdc.be.filters.MultitenancyFilter.IdMapperUserSessionManagement(), deploymentContext, facade);
+
+        if (preActions.handleRequest()) {
+            return;
+        }
+
+
+        nodesRegistrationManagement.tryRegister(deployment);
+        OIDCFilterSessionStore tokenStore = new OIDCFilterSessionStore(request, facade, 100000, deployment, idMapper);
+        tokenStore.checkCurrentToken();
+
+
+        FilterRequestAuthenticator authenticator = new FilterRequestAuthenticator(deployment, tokenStore, facade, request, 8443);
+        AuthOutcome outcome = authenticator.authenticate();
+        if (outcome == AuthOutcome.AUTHENTICATED) {
+            log.fine("AUTHENTICATED");
+            if (facade.isEnded()) {
+                return;
+            }
+            AuthenticatedActionsHandler actions = new AuthenticatedActionsHandler(deployment, facade);
+            if (actions.handledRequest()) {
+                return;
+            } else {
+                HttpServletRequestWrapper wrapper = tokenStore.buildWrapper();
+                chain.doFilter(wrapper, res);
+                return;
+            }
+        }
+        AuthChallenge challenge = authenticator.getChallenge();
+        if (challenge != null) {
+            log.fine("challenge");
+            challenge.challenge(facade);
+            return;
+        }
+        response.sendError(403);
+
+    }
+
+    /**
+     * Decides whether this {@link Filter} should skip the given {@link HttpServletRequest} based on the configured {@link org.keycloak.adapters.servlet.KeycloakOIDCFilter#skipPattern}.
+     * Patterns are matched against the {@link HttpServletRequest#getRequestURI() requestURI} of a request without the context-path.
+     * A request for {@code /myapp/index.html} would be tested with {@code /index.html} against the skip pattern.
+     * Skipped requests will not be processed further by {@link org.keycloak.adapters.servlet.KeycloakOIDCFilter} and immediately delegated to the {@link FilterChain}.
+     *
+     * @param request the request to check
+     * @return {@code true} if the request should not be handled,
+     * {@code false} otherwise.
+     */
+    private boolean shouldSkip(HttpServletRequest request) {
+
+        if (skipPattern == null) {
+            return false;
+        }
+
+        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+        return skipPattern.matcher(requestPath).matches();
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+
+    private class IdMapperUserSessionManagement implements UserSessionManagement {
+        @Override
+        public void logoutAll() {
+            if (idMapper != null) {
+                idMapper.clear();
+            }
+        }
+
+        @Override
+        public void logoutHttpSessions(List<String> ids) {
+            log.fine("**************** logoutHttpSessions");
+            for (String id : ids) {
+                idMapper.removeSession(id);
+            }
+
+        }
+    }
+}
index 5e4085c..5783192 100644 (file)
@@ -33,6 +33,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -79,9 +81,10 @@ import org.openecomp.sdc.be.ui.model.UiCategories;
 import org.openecomp.sdc.be.user.UserBusinessLogic;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.stereotype.Controller;
-
+import org.keycloak.representations.AccessToken;
 @Path("/v1/")
 /**
  *
@@ -522,8 +525,23 @@ public class ElementServlet extends BeGenericServlet {
                 log.debug("failed to get followed resources services ");
                 return buildErrorResponse(followedResourcesServices.right().value());
             }
-            Object data = RepresentationUtils.toRepresentation(followedResourcesServices.left().value());
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), data);
+            Multitenancy keyaccess= new Multitenancy();
+            if (keyaccess.multiTenancyCheck()) {
+                AccessToken.Access realmAccess = keyaccess.getAccessToken(request).getRealmAccess();
+                Set<String> realmroles = realmAccess.getRoles();
+                Map<String, List<? extends Component>> dataResponse = new HashMap<>();
+               followedResourcesServices.left().value().entrySet().stream()
+                        .forEach(component->{component.setValue(component.getValue().stream().filter(cm->realmroles.stream()
+                                .anyMatch(role->cm.getTenant().equals(role))).collect(Collectors.toList()));
+                            dataResponse.put(component.getKey(), component.getValue());
+                        });
+                Object data = RepresentationUtils.toRepresentation(dataResponse);
+                return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), data);
+            }
+            else{
+                Object data = RepresentationUtils.toRepresentation(followedResourcesServices.left().value());
+                return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), data);
+            }
         } catch (Exception e) {
             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Followed Resources / Services Categories");
             log.debug("Getting followed resources/services failed with exception", e);
index d84e40c..08f26ff 100644 (file)
@@ -35,6 +35,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -56,6 +57,7 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
 import org.glassfish.jersey.media.multipart.FormDataParam;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.keycloak.representations.AccessToken;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
@@ -87,6 +89,7 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.springframework.stereotype.Controller;
 
 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
@@ -115,11 +118,12 @@ public class ResourcesServlet extends AbstractValidationsServlet {
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
     @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource", responses = {
-        @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
-        @ApiResponse(responseCode = "201", description = "Resource created"),
-        @ApiResponse(responseCode = "403", description = "Restricted operation"),
-        @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
-        @ApiResponse(responseCode = "409", description = "Resource already exist")})
+            @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
+            @ApiResponse(responseCode = "201", description = "Resource created"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+            @ApiResponse(responseCode = "409", description = "Resource already exist"),
+            @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")})
     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
     public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,
                                    @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId)
@@ -148,14 +152,33 @@ public class ResourcesServlet extends AbstractValidationsServlet {
                     response = buildErrorResponse(convertResponse.right().value());
                     return response;
                 }
+                Multitenancy keyaccess = new Multitenancy();
                 Resource resource = convertResponse.left().value();
-                Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
-                Object representation = RepresentationUtils.toRepresentation(createdResource);
-                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
-                responseWrapper.setInnerElement(response);
-                loggerSupportability
-                    .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
-                        "Resource successfully created user {}", userId);
+                if (keyaccess.multiTenancyCheck())
+                {
+                        AccessToken.Access realmAccess = keyaccess.getAccessToken(request).getRealmAccess();
+                        Set<String> realmroles = realmAccess.getRoles();
+                        boolean match = realmroles.contains(resource.getTenant());
+                        if (match) {
+                            Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
+                            Object representation = RepresentationUtils.toRepresentation(createdResource);
+                            response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
+                            responseWrapper.setInnerElement(response);
+                            loggerSupportability
+                                    .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
+                                            "Resource successfully created user {}", userId);
+                        } else {
+                            return Response.status(401, "Unauthorized Tenant").build();
+                        }
+                } else {
+                    Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
+                    Object representation = RepresentationUtils.toRepresentation(createdResource);
+                    response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
+                    responseWrapper.setInnerElement(response);
+                    loggerSupportability
+                            .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
+                                    "Resource successfully created user {}", userId);
+                }
             }
             return responseWrapper.getInnerElement();
         } catch (final IOException | ZipException e) {
index fcac7dc..3c2b72b 100644 (file)
@@ -41,6 +41,7 @@ import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -92,10 +93,11 @@ import org.openecomp.sdc.common.log.elements.LoggerSupportability;
 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
 import org.openecomp.sdc.common.log.enums.StatusCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.stereotype.Controller;
-
+import org.keycloak.representations.AccessToken;
 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
 @Path("/v1/catalog")
 @Server(url = "/sdc2/rest")
@@ -127,7 +129,8 @@ public class ServiceServlet extends AbstractValidationsServlet {
         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Service.class)))),
         @ApiResponse(responseCode = "201", description = "Service created"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
-        @ApiResponse(responseCode = "409", description = "Service already exist")})
+        @ApiResponse(responseCode = "409", description = "Service already exist"),
+            @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")})
     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
     public Response createService(@Parameter(description = "Service object to be created", required = true) String data,
                                   @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
@@ -141,15 +144,35 @@ public class ServiceServlet extends AbstractValidationsServlet {
         if (convertResponse.isRight()) {
             throw new ByResponseFormatComponentException(convertResponse.right().value());
         }
+        Multitenancy keyaccess = new Multitenancy();
         Service service = convertResponse.left().value();
-        Either<Service, ResponseFormat> actionResponse = serviceBusinessLogic.createService(service, modifier);
-        if (actionResponse.isRight()) {
-            log.debug("Failed to create service");
-            throw new ByResponseFormatComponentException(actionResponse.right().value());
+        if (keyaccess.multiTenancyCheck()) {
+            AccessToken.Access realmAccess = keyaccess.getAccessToken(request).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+            boolean match = realmroles.contains(service.getTenant());
+            if (match) {
+                Either<Service, ResponseFormat> actionResponse = serviceBusinessLogic.createService(service, modifier);
+                if (actionResponse.isRight()) {
+                    log.debug("Failed to create service");
+                    throw new ByResponseFormatComponentException(actionResponse.right().value());
+                }
+                loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
+                        "Service {} has been created by user {} ", service.getName(), userId);
+                return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
+            } else {
+                log.debug("Unauthorized Tenant");
+                return Response.status(401, "Unauthorized Tenant").build();
+            }
+        } else {
+            Either<Service, ResponseFormat> actionResponse = serviceBusinessLogic.createService(service, modifier);
+            if (actionResponse.isRight()) {
+                log.debug("Failed to create service");
+                throw new ByResponseFormatComponentException(actionResponse.right().value());
+            }
+            loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
+                    "Service {} has been created by user {} ", service.getName(), userId);
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
         }
-        loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
-            "Service {} has been created by user {} ", service.getName(), userId);
-        return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
     }
 
     public Either<Service, ResponseFormat> parseToService(String serviceJson, User user) {
index ff6d015..68795e1 100644 (file)
@@ -546,6 +546,7 @@ public class ToscaExportHandler {
                 }
                 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
+                toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
                 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
                 break;
index 6bed75e..c53efc2 100644 (file)
@@ -2822,6 +2822,14 @@ errors:
         message: "Capability '%1' not found in '%2' '%3'."
         messageId: "SVC4186"
 
+
+#---------SVC4950-----------------------------
+    MISSING_TENANT_NAME: {
+        code: 400,
+        message: "Error: Missing Tenant name.",
+        messageId: "SVC4950"
+        }
+
     #---------SVC4001------------------------------
     NOT_PERMITTED_SPECIAL_CHARS: {
         code: 406,
diff --git a/catalog-be/src/main/webapp/WEB-INF/keycloak.json b/catalog-be/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644 (file)
index 0000000..d037661
--- /dev/null
@@ -0,0 +1,11 @@
+{
+"realm": "sdc",
+"auth-server-url": "http://10.32.243.37:31613/",
+"ssl-required": "external",
+"resource": "sdc-app",
+"public-client":true,
+"bearer-only":true,
+"use-resource-role-mappings": true,
+"principal-attribute":"preferred_username",
+"confidential-port": 0
+}
index 9761b38..8bd9811 100644 (file)
         <url-pattern>/sdc/*</url-pattern>
     </filter-mapping>
 
+    <filter>
+        <filter-name>MultitenancyFilter</filter-name>
+        <filter-class>org.openecomp.sdc.be.filters.MultitenancyFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>MultitenancyFilter</filter-name>
+        <url-pattern>/keycloak/*</url-pattern>
+        <url-pattern>/sdc2/rest/v1/catalog/resources/*</url-pattern>
+        <url-pattern>/sdc2/rest/v1/catalog/services/*</url-pattern>
+        <url-pattern> /sdc2/rest/v1/followed</url-pattern>
+    </filter-mapping>
+
     <error-page>
         <exception-type>java.lang.RuntimeException</exception-type>
         <location>/sdc2/rest/v1/catalog/handleException/</location>
index 9fb0efb..60d45ea 100644 (file)
@@ -38,6 +38,9 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.HashMap;
+import java.util.stream.Collectors;
+import org.junit.Assert;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -68,6 +71,8 @@ import org.openecomp.sdc.exception.ResponseFormat;
 
 class ElementBusinessLogicTest extends BaseBusinessLogicMock {
 
+    private static final boolean MULTITENANCY_ENABLED = true;
+    private static final String TEST_TENANT = "test_tenant";
     private User user;
 
     @Mock
@@ -319,4 +324,83 @@ class ElementBusinessLogicTest extends BaseBusinessLogicMock {
         assertTrue(elementBusinessLogic.getBaseTypes("CAT01", user.getUserId(), null).isRight());
     }
 
+
+    @Test
+    void testGetFollowed_withMultitenancyValidTenant_thenReturnsSuccess() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        user.setUserId("admin1");
+        user.setRole(Role.ADMIN.name());
+        Set<Component> resources = new HashSet<>();
+        Set<Component> services = new HashSet<>();
+       Resource resource = new Resource();
+        Service service = new Service();
+        service.setTenant(TEST_TENANT);
+        resource.setTenant(TEST_TENANT);
+        Assert.assertNotNull(service.getTenant());
+        Assert.assertNotNull(resource.getTenant());
+        resources.add(resource);
+        services.add(service);
+        Assert.assertNotNull(getTestRoles());
+        Assert.assertTrue(getTestRoles().contains(TEST_TENANT));
+
+        when(toscaOperationFacade.getFollowed(any(), anySet(), any(), eq(ComponentTypeEnum.RESOURCE)))
+                .thenReturn(Either.left(resources));
+        when(toscaOperationFacade.getFollowed(any(), anySet(), any(), eq(ComponentTypeEnum.SERVICE)))
+                .thenReturn(Either.left(services));
+        Map<String, List<? extends Component>> result = elementBusinessLogic.getFollowed(user).left().value();
+        Set<String> realmroles =getTestRoles();
+        Map<String, List<? extends Component>> dataResponse = new HashMap<>();
+        result.entrySet().stream()
+                .forEach(component->{component.setValue(component.getValue().stream().filter(cm->realmroles.stream()
+                        .anyMatch(role->cm.getTenant().equals(role))).collect(Collectors.toList()));
+                    dataResponse.put(component.getKey(), component.getValue());
+                });
+        assertEquals(result.size(), dataResponse.values().size());
+        assertEquals(1, dataResponse.get("services").size());
+        assertEquals(1, dataResponse.get("resources").size());
+    }
+
+    @Test
+        void testGetFollowed_withMultitenancyInValidTenant_thenReturnsEmptyList() {
+        String INVALID_TENANT="invalid_tenant";
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        user.setUserId("admin1");
+        user.setRole(Role.ADMIN.name());
+        Set<Component> resources = new HashSet<>();
+        Set<Component> services = new HashSet<>();
+        Resource resource = new Resource();
+        Service service = new Service();
+        service.setTenant(INVALID_TENANT);
+        resource.setTenant(INVALID_TENANT);
+        Assert.assertNotNull(service.getTenant());
+        Assert.assertNotNull(resource.getTenant());
+        resources.add(resource);
+        services.add(service);
+        Assert.assertNotNull(getTestRoles());
+
+        when(toscaOperationFacade.getFollowed(any(), anySet(), any(), eq(ComponentTypeEnum.RESOURCE)))
+                .thenReturn(Either.left(resources));
+        when(toscaOperationFacade.getFollowed(any(), anySet(), any(), eq(ComponentTypeEnum.SERVICE)))
+                .thenReturn(Either.left(services));
+        Map<String, List<? extends Component>> result = elementBusinessLogic.getFollowed(user).left().value();
+        Set<String> realmroles =getTestRoles();
+        Map<String, List<? extends Component>> dataResponse = new HashMap<>();
+        result.entrySet().stream()
+                .forEach(component->{component.setValue(component.getValue().stream().filter(cm->realmroles.stream()
+                        .anyMatch(role->cm.getTenant().equals(role))).collect(Collectors.toList()));
+                    dataResponse.put(component.getKey(), component.getValue());
+                });
+
+        assertEquals(result.size(), dataResponse.values().size(),"No Data available for "+INVALID_TENANT);
+        assertEquals(0, dataResponse.get("services").size());
+        assertEquals(0, dataResponse.get("resources").size());
+    }
+
+    private Set<String> getTestRoles(){
+        Set<String> roles = new HashSet<>();
+        roles.add("test_admin");
+        roles.add("test_tenant");
+        return roles;
+    }
+
 }
\ No newline at end of file
index 714ec20..e973571 100644 (file)
@@ -47,12 +47,16 @@ import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.servlet.ServletContext;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.hamcrest.MatcherAssert;
+import org.junit.Assert;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -171,6 +175,8 @@ class ResourceBusinessLogicTest {
     private static final String GENERIC_VF_NAME = "org.openecomp.resource.abstract.nodes.VF";
     private static final String GENERIC_CR_NAME = "org.openecomp.resource.abstract.nodes.CR";
     private static final String GENERIC_PNF_NAME = "org.openecomp.resource.abstract.nodes.PNF";
+    private static final boolean MULTITENANCY_ENABLED = true;
+    private static final String TEST_TENANT = "test_tenant";
 
     private final ServletContext servletContext = Mockito.mock(ServletContext.class);
     private IElementOperation mockElementDao;
@@ -2556,4 +2562,55 @@ class ResourceBusinessLogicTest {
         assertEquals(ActionStatus.COMPONENT_IN_USE_BY_ANOTHER_COMPONENT, actualOperationException.getActionStatus());
         assertEquals("resource_name", actualOperationException.getParams()[0]);
     }
+
+
+    @Test
+    void testCreateResource_withMultitenancyWithTenant_Success() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        Resource resource = createResourceObject(false);
+        resource.setTenant(TEST_TENANT);
+        Resource createdResource = null;
+        try {
+            when(toscaOperationFacade
+                    .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE))
+                    .thenReturn(Either.left(false));
+            createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null);
+            assertThat(createResourceObject(true)).isEqualTo(createdResource);
+            MatcherAssert.assertThat("Unauthorized Tenant", getTestRoles().contains(resource.getTenant()));
+        } catch (ComponentException e) {
+            assertThat(Integer.valueOf(200)).isEqualTo(e.getResponseFormat()
+                    .getStatus());
+        }
+    }
+
+    @Test
+    void testCreateResource_withMultitenancyWithInvalidTenant_Failure() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        Resource resource = createResourceObject(false);
+        resource.setTenant("invalid_tenant");
+        Resource createdResource = null;
+        try {
+            MatcherAssert.assertThat("Unauthorized Tenant", !getTestRoles().contains(resource.getTenant()));
+            when(toscaOperationFacade
+                    .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE))
+                    .thenReturn(Either.left(false));
+            createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null);
+
+            assertThat(createResourceObject(true)).isEqualTo(createdResource);
+            MatcherAssert.assertThat("Unauthorized Tenant", !getTestRoles().contains(resource.getTenant()));
+        } catch (ComponentException e) {
+            assertThat(new Integer(200)).isEqualTo(e.getResponseFormat()
+                    .getStatus());
+        }
+    }
+
+    private Set<String> getTestRoles(){
+        Set<String> roles = new HashSet<>();
+        roles.add("test_admin");
+        roles.add("test_tenant");
+        return roles;
+    }
+
 }
index 69938cd..a5f823b 100644 (file)
@@ -30,6 +30,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.Mockito.when;
 
@@ -44,8 +46,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
+import java.util.Set;
+import java.util.HashSet;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.hamcrest.MatcherAssert;
+import org.junit.Assert;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
@@ -83,6 +89,8 @@ class ServiceBusinessLogicTest extends ServiceBusinessLogicBaseTestSetup {
 
     private final static String DEFAULT_ICON = "defaulticon";
     private static final String ALREADY_EXIST = "alreadyExist";
+    private static final boolean MULTITENANCY_ENABLED = true;
+    private static final String TEST_TENANT = "test_tenant";
 
     @Test
     void testGetComponentAuditRecordsCertifiedVersion() {
@@ -1069,4 +1077,39 @@ class ServiceBusinessLogicTest extends ServiceBusinessLogicBaseTestSetup {
         return propertyList;
     }
 
+
+    @Test
+    void testCreateService_withMultitenancyValidTenant_Success() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        Service service = createServiceObject(false);
+        service.setTenant(TEST_TENANT);
+        when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService));
+        Either<Service, ResponseFormat> createResponse = bl.createService(service, user);
+
+        if (createResponse.isRight()) {
+            assertEquals(new Integer(200), createResponse.right().value().getStatus());
+        }
+        MatcherAssert.assertThat("Unauthorized Tenant", getTestRoles().contains(service.getTenant()));
+        assertEquals(TEST_TENANT, service.getTenant());
+        assertEqualsServiceObject(createServiceObject(true), createResponse.left().value());
+    }
+
+
+    @Test
+   void testCreateService_withMultitenancyInvalidTenant_Failure() {
+        Service service = createServiceObject(false);
+        service.setTenant("invalid_tenant");
+        when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService));
+        Either<Service, ResponseFormat> createResponse = bl.createService(service, user);
+        MatcherAssert.assertThat("Unauthorized Tenant", !getTestRoles().contains(service.getTenant()));
+        assertNotEquals(TEST_TENANT, service.getTenant());
+        assertEqualsServiceObject(createServiceObject(true), createResponse.left().value());
+    }
+
+    private Set<String> getTestRoles(){
+        Set<String> roles = new HashSet<>();
+        roles.add("test_admin");
+        roles.add("test_tenant");
+        return roles;
+    }
 }
index cd5a6e5..0150ebe 100644 (file)
@@ -150,5 +150,7 @@ public enum ActionStatus {
     COMPONENT_PROPERTY_NOT_FOUND,
     INVALID_COMPONENT_TYPE,
     DATA_TYPE_PROPERTY_ALREADY_EXISTS,
-    UNEXPECTED_ERROR
+    UNEXPECTED_ERROR,
+    //Tenant
+    MISSING_TENANT, TENANT_NAME_EXCEEDS_LIMIT, INVALID_TENANT_NAME, UNAUTHORIZED_TENANT
 }
index c689298..15fc013 100644 (file)
@@ -50,6 +50,7 @@ public enum GraphPropertiesDictionary {
     CONSTRAINTS                        ("constraints",                         String.class,                   false,          false),
     CONTACT_ID                 ("contactId",                           String.class,                           false,          false),
     VENDOR_NAME                        ("vendorName",                          String.class,                           false,          false),
+    TENANT                     ("tenant",                                  String.class,                               false,          false),
     VENDOR_RELEASE             ("vendorRelease",                       String.class,                           false,          false),
     MODEL               ("model",                   String.class,               false,      false),
     MODEL_TYPE          ("modelType",               String.class,               false,      false),
index 3b11743..da32017 100644 (file)
@@ -136,6 +136,10 @@ public class GraphPropertiesDictionaryExtractor {
         return (String) properties.get(GraphPropertiesDictionary.VENDOR_NAME.getProperty());
     }
 
+    public String getTenant() {
+        return (String) properties.get(GraphPropertiesDictionary.TENANT.getProperty());
+    }
+
     public String getVendorRelease() {
         return (String) properties.get(GraphPropertiesDictionary.VENDOR_RELEASE.getProperty());
     }
index 602d53e..7f05f56 100644 (file)
@@ -63,6 +63,7 @@ public abstract class ComponentMetadataData extends GraphNode {
         metadataDataDefinition.setImportedToscaChecksum(extractor.getImportedToscaChecksum());
         metadataDataDefinition.setInvariantUUID(extractor.getInvariantUuid());
         metadataDataDefinition.setModel(extractor.getModel());
+        metadataDataDefinition.setTenant(extractor.getTenant());
         componentInstanceCounter = extractor.getInstanceCounter();
     }
 
@@ -92,6 +93,7 @@ public abstract class ComponentMetadataData extends GraphNode {
         addIfExists(map, GraphPropertiesDictionary.IMPORTED_TOSCA_CHECKSUM, metadataDataDefinition.getImportedToscaChecksum());
         addIfExists(map, GraphPropertiesDictionary.INVARIANT_UUID, metadataDataDefinition.getInvariantUUID());
         addIfExists(map, GraphPropertiesDictionary.MODEL, metadataDataDefinition.getModel());
+        addIfExists(map, GraphPropertiesDictionary.TENANT, metadataDataDefinition.getTenant());
         return map;
     }
 
index 1b5f948..6eb5693 100644 (file)
@@ -47,6 +47,7 @@ public class ResourceMetadataData extends ComponentMetadataData {
         resourceMetadataDataDefinition.setLicenseType(extractor.getLicenseType());
         resourceMetadataDataDefinition.setToscaResourceName(extractor.getToscaResourceName());
         resourceMetadataDataDefinition.setCsarVersionId(extractor.getCsarVersionId());
+        resourceMetadataDataDefinition.setTenant(extractor.getTenant());
     }
 
     @Override
@@ -61,6 +62,7 @@ public class ResourceMetadataData extends ComponentMetadataData {
         addIfExists(graphMap, GraphPropertiesDictionary.LICENSE_TYPE, resourceMetadataDataDefinition.getLicenseType());
         addIfExists(graphMap, GraphPropertiesDictionary.TOSCA_RESOURCE_NAME, resourceMetadataDataDefinition.getToscaResourceName());
         addIfExists(graphMap, GraphPropertiesDictionary.CSAR_VERSION_ID, resourceMetadataDataDefinition.getCsarVersionId());
+        addIfExists(graphMap, GraphPropertiesDictionary.TENANT, resourceMetadataDataDefinition.getTenant());
         return graphMap;
     }
 }
index 0e9c44a..1fd02da 100644 (file)
@@ -213,6 +213,14 @@ public abstract class Component implements PropertiesOwner {
         componentMetadataDefinition.getMetadataDataDefinition().setDescription(description);
     }
 
+    public String getTenant() {
+        return componentMetadataDefinition.getMetadataDataDefinition().getTenant();
+    }
+
+    public void setTenant(String tenant) {
+        componentMetadataDefinition.getMetadataDataDefinition().setTenant(tenant);
+    }
+
     public LifecycleStateEnum getLifecycleState() {
         if (componentMetadataDefinition.getMetadataDataDefinition().getState() != null) {
             return LifecycleStateEnum.valueOf(componentMetadataDefinition.getMetadataDataDefinition().getState());
index 0b54e0b..f0fbc5d 100644 (file)
@@ -113,6 +113,14 @@ public class Resource extends Component implements Serializable {
         getResourceMetadataDataDefinition().setVendorName(vendorName);
     }
 
+    public String getTenant() {
+        return getResourceMetadataDataDefinition().getTenant();
+    }
+
+    public void setTenant(String tenant) {
+        getResourceMetadataDataDefinition().setTenant(tenant);
+    }
+
     public String getVendorRelease() {
         return getResourceMetadataDataDefinition().getVendorRelease();
     }
index bc8efb5..061a78b 100644 (file)
@@ -197,6 +197,10 @@ public class Service extends Component {
         getMetadataDefinition().setVendorName(vendorName);
     }
 
+    public void setTenant(String tenant) {
+        getMetadataDefinition().setTenant(tenant);
+    }
+
     public void setVendorRelease(String vendorRelease) {
         getMetadataDefinition().setVendorRelease(vendorRelease);
     }
index e853b64..b3d0c53 100644 (file)
@@ -42,6 +42,7 @@ public class UploadResourceInfo {
     private String resourceIconPath;
     private String icon;
     private String vendorName;
+    private String tenant;
     private String vendorRelease;
     private String resourceVendorModelNumber;
     private String resourceType = "VFC";
index 1c12a3e..d709947 100644 (file)
@@ -58,6 +58,7 @@ public class UploadServiceInfo {
     private String serviceIconPath;
     private String icon;
     private String vendorName;
+    private String tenant;
     private String vendorRelease;
     private String serviceVendorModelNumber;
     private String serviceType = "";
index f65c84f..cd056ee 100644 (file)
@@ -54,6 +54,7 @@ public class CatalogComponent {
     private String lastUpdaterUserId;
     private List<CategoryDefinition> categories;
     private String model;
+    private String tenant;
 
     public List<String> getTags() {
         return tags == null ? Collections.emptyList() : ImmutableList.copyOf(tags);
index caedbee..65c109c 100644 (file)
@@ -1372,6 +1372,7 @@ public abstract class ToscaElementOperation extends BaseOperation {
             catalogComponent.setLastUpdateDate((lastUpdateDate != null ? (Long) lastUpdateDate : 0L));
             catalogComponent.setDistributionStatus((String) metadatObj.get(JsonPresentationFields.DISTRIBUTION_STATUS.getPresentation()));
             catalogComponent.setDescription((String) metadatObj.get(JsonPresentationFields.DESCRIPTION.getPresentation()));
+            catalogComponent.setTenant((String) metadatObj.get(JsonPresentationFields.TENANT.getPresentation()));
             catalogComponent.setSystemName((String) metadatObj.get(JsonPresentationFields.SYSTEM_NAME.getPresentation()));
             catalogComponent.setUuid((String) metadatObj.get(JsonPresentationFields.UUID.getPresentation()));
             catalogComponent.setInvariantUUID((String) metadatObj.get(JsonPresentationFields.INVARIANT_UUID.getPresentation()));
index a246a1a..7924e09 100644 (file)
@@ -814,6 +814,7 @@ public class ModelConverter {
         component.setConformanceLevel((String) toscaElement.getMetadataValue(JsonPresentationFields.CONFORMANCE_LEVEL));
         component.setIcon((String) toscaElement.getMetadataValue(JsonPresentationFields.ICON));
         component.setDescription((String) toscaElement.getMetadataValue(JsonPresentationFields.DESCRIPTION));
+        component.setTenant((String) toscaElement.getMetadataValue(JsonPresentationFields.TENANT));
         component.setTags((List<String>) toscaElement.getMetadataValue(JsonPresentationFields.TAGS));
         component.setInvariantUUID((String) toscaElement.getMetadataValue(JsonPresentationFields.INVARIANT_UUID));
         component.setContactId((String) toscaElement.getMetadataValue(JsonPresentationFields.CONTACT_ID));
@@ -1381,6 +1382,7 @@ public class ModelConverter {
         toscaElement.setMetadataValue(JsonPresentationFields.IS_DELETED, component.getIsDeleted());
         toscaElement.setMetadataValue(JsonPresentationFields.ICON, component.getIcon());
         toscaElement.setMetadataValue(JsonPresentationFields.DESCRIPTION, component.getDescription());
+        toscaElement.setMetadataValue(JsonPresentationFields.TENANT, component.getTenant());
         toscaElement.setMetadataValue(JsonPresentationFields.TAGS, component.getTags());
         toscaElement.setMetadataValue(JsonPresentationFields.INVARIANT_UUID, component.getInvariantUUID());
         toscaElement.setMetadataValue(JsonPresentationFields.CONTACT_ID, component.getContactId());
index a0d7873..d760614 100644 (file)
@@ -33,7 +33,7 @@ public abstract class UiComponentMetadata {
 
     private String uniqueId;
     private String name; // archiveName
-
+    private String tenant;
     private String version; // archiveVersion
     private Boolean isHighestVersion;
     private Long creationDate;
@@ -100,5 +100,6 @@ public abstract class UiComponentMetadata {
         this.archiveTime = metadata.getArchiveTime();
         this.isVspArchived = metadata.isVspArchived();
         this.model = metadata.getModel();
+        this.tenant = metadata.getTenant();
     }
 }
index 9cc5294..b8b9d72 100644 (file)
@@ -44,6 +44,7 @@ public class UiResourceMetadata extends UiComponentMetadata {
     private List<String> derivedFrom;
     private Map<String, String> categorySpecificMetadata;
     private String csarVersionId;
+    private String tenant;
 
     public UiResourceMetadata(List<CategoryDefinition> categories, List<String> derivedFrom, ResourceMetadataDataDefinition metadata) {
         super(categories, metadata);
@@ -57,5 +58,6 @@ public class UiResourceMetadata extends UiComponentMetadata {
         this.derivedFrom = derivedFrom;
         this.categorySpecificMetadata = metadata.getCategorySpecificMetadata();
         this.csarVersionId = metadata.getCsarVersionId();
+        this.tenant = metadata.getTenant();
     }
 }
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/Multitenancy.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/Multitenancy.java
new file mode 100644 (file)
index 0000000..c91f3e3
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Tech-Mahindra Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.openecomp.sdc.common.util;
+
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.representations.AccessToken;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+
+/**
+ * To check the Multitenancy
+ */
+
+public class Multitenancy {
+    private static final Logger log = Logger.getLogger(Multitenancy.class);
+    private boolean keycloak;
+    public AccessToken getAccessToken(HttpServletRequest request){
+     KeycloakPrincipal principal = (KeycloakPrincipal) request.getUserPrincipal();
+        return  principal.getKeycloakSecurityContext().getToken();
+    }
+
+    public boolean multiTenancyCheck() {
+        log.info("Checking the Multitenancy ");
+        try (InputStream ioStream = Multitenancy.class.getResourceAsStream("/multitenancy.json");
+             BufferedReader br = new BufferedReader(new InputStreamReader(ioStream, StandardCharsets.UTF_8))) {
+            keycloak = (boolean) ((JSONObject) new JSONParser().parse(br)).get("multitenancy");
+        } catch (Exception e) {
+            log.debug("Multitenancy Exception", e);
+        }
+        log.info("Multitenancy= {}",keycloak);
+        return keycloak;
+    }
+}
diff --git a/common-app-api/src/main/resources/multitenancy.json b/common-app-api/src/main/resources/multitenancy.json
new file mode 100644 (file)
index 0000000..43405f4
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "multitenancy": false
+}
\ No newline at end of file
index 4b94adb..0a1c03a 100644 (file)
@@ -49,6 +49,7 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio
     private Long creationDate;
     private Long lastUpdateDate;
     private String description;
+    private String tenant;
     private String state;
     private List<String> tags;
     private String conformanceLevel;
@@ -84,6 +85,7 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio
         this.creationDate = other.getCreationDate();
         this.lastUpdateDate = other.getLastUpdateDate();
         this.description = other.getDescription();
+        this.tenant = other.getTenant();
         this.state = other.getState();
         this.tags = new ArrayList<>(other.getTags() != null ? other.getTags() : new LinkedList<>());
         this.icon = other.getIcon();
@@ -114,6 +116,7 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio
         this.creationDate = extractor.getCreationDate();
         this.lastUpdateDate = extractor.getLastUpdateDate();
         this.description = extractor.getDescription();
+        this.tenant = extractor.getTenant();
         this.state = extractor.getState();
         this.tags = extractor.getTags();
         this.icon = extractor.getIcon();
index b9a0dc7..2456b67 100644 (file)
@@ -42,6 +42,7 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti
     private ResourceTypeEnum importServiceType = ResourceTypeEnum.SERVICE;
     private String toscaServiceName;
     private String vendorName;
+    private String tenant;
     private String vendorRelease;
 
     public ServiceMetadataDataDefinition(JsonPresentationFieldsExtractor extractor) {
index 6e845a0..ad10a63 100644 (file)
@@ -72,6 +72,7 @@ public enum JsonPresentationFields {
     MODEL("model", null),
     NORMATIVE("normative", null),
     DATA_TYPES("data_types", GraphPropertyEnum.DATA_TYPES),
+    TENANT("tenant", null),
 
     ////Inputs
     ANNOTATIONS("annotations", null),
index f497066..3808ac7 100644 (file)
@@ -177,4 +177,9 @@ public class JsonPresentationFieldsExtractor {
     public Boolean isNormative() {
         return (Boolean) properties.get(JsonPresentationFields.NORMATIVE.getPresentation());
     }
+
+    public String getTenant() {
+        return (String) properties.get(JsonPresentationFields.TENANT.getPresentation());
+    }
+
 }
index 777068b..a59f340 100644 (file)
@@ -3764,3 +3764,14 @@ Response Types
       message: "Error: Interface operation input  parameter name should not be empty",
       messageId: "SVC46703"
     }
+
+---------SVC4750-----------------------------
+==============================================
+
+::
+
+    MISSING_TENANT_NAME: {
+      code: 400,
+      message: "Error: Missing Tenant name.",
+      messageId: "SVC4750"
+    }
\ No newline at end of file
index 066acb9..a2c0e39 100644 (file)
@@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tags;
+import javax.servlet.http.HttpServletRequest;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -35,6 +36,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.openecomp.sdc.versioning.types.Item;
@@ -61,7 +63,7 @@ public interface Items {
                   @QueryParam("permission") String permissionFilter,
                   @Parameter(description = "Filter by onboarding method", schema = @Schema(type = "string", allowableValues = {"NetworkPackage", "manual"}))
                   @QueryParam("onboardingMethod") String onboardingMethodFilter,
-                  @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user);
+                  @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user, @Context HttpServletRequest hreq);
 
     @GET
     @Path("/{itemId}")
index 9fb6ebd..af3568c 100644 (file)
@@ -35,12 +35,15 @@ import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
 import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
+import org.keycloak.representations.AccessToken;
 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
 import org.openecomp.sdc.be.csar.storage.StorageFactory;
 import org.openecomp.sdc.common.errors.ErrorCode.ErrorCodeBuilder;
 import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
 import org.openecomp.sdc.logging.api.Logger;
@@ -116,15 +119,27 @@ public class ItemsImpl implements Items {
 
     @Override
     public Response list(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter, String permissionFilter,
-                         String onboardingMethodFilter, String user) {
+                         String onboardingMethodFilter, String user, HttpServletRequest hreq) {
         Predicate<Item> itemPredicate = createItemPredicate(itemStatusFilter, versionStatusFilter, itemTypeFilter, onboardingMethodFilter,
             permissionFilter, user);
         GenericCollectionWrapper<ItemDto> results = new GenericCollectionWrapper<>();
         MapItemToDto mapper = new MapItemToDto();
-        getManagersProvider().getItemManager().list(itemPredicate).stream()
-            .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
-            .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
-        return Response.ok(results).build();
+        Multitenancy keyaccess= new Multitenancy();
+        if (keyaccess.multiTenancyCheck()) {
+            AccessToken.Access realmAccess = keyaccess.getAccessToken(hreq).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+        realmroles.stream().forEach(role ->  getManagersProvider().getItemManager().list(itemPredicate).stream()
+                .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
+                .filter(item -> item.getTenant().contains(role))
+                .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class))));
+            return Response.ok(results).build();
+        }
+        else{
+            getManagersProvider().getItemManager().list(itemPredicate).stream()
+                    .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
+                    .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
+            return Response.ok(results).build();
+        }
     }
 
     @Override
index 25de083..da3e6f3 100644 (file)
@@ -22,6 +22,7 @@ package org.openecomp.sdcrests.item.rest.services;
 import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -39,7 +40,11 @@ import io.minio.MinioClient;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import javax.ws.rs.core.Response;
+
+import org.junit.Assert;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -58,6 +63,7 @@ import org.openecomp.sdc.versioning.ItemManager;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
 import org.openecomp.sdcrests.item.types.ItemActionRequestDto;
 
 @ExtendWith(MockitoExtension.class)
@@ -71,6 +77,8 @@ class ItemsImplTest {
     private static final String CREDENTIALS = "credentials";
     private static final String TEMP_PATH = "tempPath";
     private static final String UPLOAD_PARTSIZE = "uploadPartSize";
+    private static final boolean MULTITENANCY_ENABLED = true;
+    private static final String TEST_TENANT = "test_tenant";
 
     @Mock
     private ManagersProvider managersProvider;
@@ -190,7 +198,7 @@ class ItemsImplTest {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
         when(managersProvider.getItemManager()).thenReturn(itemManager);
-        Response response = items.list(null, null, null, null, null, USER);
+        Response response = items.list(null, null, null, null, null, USER, null);
         assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
     }
 
@@ -201,4 +209,78 @@ class ItemsImplTest {
         versions.add(new Version("3"));
         return versions;
     }
+
+    @Test
+    void getItemList_withMultitenancyValidTenant_ReturnSuccessList() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+        Assert.assertNotNull(getTestRoles());
+        items.initActionSideAffectsMap();
+        items.setManagersProvider(managersProvider);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        Response response = items.list(null, null, null, null, null, USER, null);
+        assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
+        List<Item> expectedItems=new ArrayList<>();
+        List<Item> actualItems=getAllItems();
+        getTestRoles().stream().forEach(role -> getAllItems().stream()
+                .filter(item -> item.getTenant()!=null)
+                .filter(item -> item.getTenant().contains(role))
+                .forEach(item -> expectedItems.add(item)));
+        assertNotSame(expectedItems.size(), actualItems.size());
+    }
+
+
+    @Test
+    void getItemList_withMultitenancyInvalidTenant_ReturnsEmptylList() {
+        Assert.assertTrue(MULTITENANCY_ENABLED);
+
+        Assert.assertNotNull(getTestRoles());
+        String tenant= "invalid tenant";
+        items.initActionSideAffectsMap();
+        items.setManagersProvider(managersProvider);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        Response response = items.list(null, null, null, null, null, USER, null);
+        assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
+        List<Item> expectedItems=new ArrayList<>();
+        List<Item> actualItems=getAllItems();
+        assertNotNull(tenant);
+        getTestRoles().stream().forEach(role -> getAllItems().stream()
+                .filter(item -> item.getTenant()!=null)
+                .filter(item -> item.getTenant().contains(tenant))
+                .forEach(item -> expectedItems.add(item)));
+        Assert.assertEquals(expectedItems.size(), 0);
+        Assert.assertNotEquals(expectedItems.containsAll(actualItems), actualItems.containsAll(expectedItems));
+    }
+
+
+    private List<Item> getAllItems(){
+        List<Item> items=new ArrayList<>();
+
+        Item itemOne = new Item();
+        itemOne.setType(ItemType.vlm.name());
+        itemOne.setOwner(USER);
+        itemOne.setStatus(ItemStatus.ACTIVE);
+        itemOne.setName("TEST_VENDOR_ONE");
+        itemOne.setDescription("TEST_DESCRIPTION");
+        itemOne.setTenant(TEST_TENANT);
+
+        Item itemTwo = new Item();
+        itemTwo.setType(ItemType.vsp.name());
+        itemTwo.setOwner(USER);
+        itemTwo.setStatus(ItemStatus.ACTIVE);
+        itemTwo.setName("TEST_VSP_ONE");
+        itemTwo.setDescription("TEST_DESCRIPTION");
+        itemTwo.setTenant("admin_tenant");
+
+        items.add(itemOne);
+        items.add(itemTwo);
+        return items;
+    }
+
+
+    private Set<String> getTestRoles(){
+        Set<String> roles = new HashSet<>();
+        roles.add("test_admin");
+        roles.add("test_tenant");
+        return roles;
+    }
 }
index 34ad19f..5e2810c 100644 (file)
@@ -32,6 +32,7 @@ public class ItemDto {
     private String description;
     private String owner;
     private String status;
+    private String tenant;
     private Map<String, Object> properties;
 
     public void setId(final String id) {
@@ -58,4 +59,11 @@ public class ItemDto {
         this.status = ValidationUtils.sanitizeInputString(status);
     }
 
+    public void setTenant(final String tenant) {
+        if(tenant != null) {
+            this.tenant = ValidationUtils.sanitizeInputString(tenant);
+        }
+        else this.tenant=tenant;
+    }
+
 }
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/MultitenancyKeycloakFilter.java b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/MultitenancyKeycloakFilter.java
new file mode 100644 (file)
index 0000000..8cb87e3
--- /dev/null
@@ -0,0 +1,286 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Tech-Mahindra Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.server.filters;
+
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.PreAuthActionsHandler;
+import org.keycloak.adapters.servlet.FilterRequestAuthenticator;
+import org.keycloak.adapters.servlet.OIDCFilterSessionStore;
+import org.keycloak.adapters.servlet.OIDCServletHttpFacade;
+import org.keycloak.adapters.spi.AuthChallenge;
+import org.keycloak.adapters.spi.AuthOutcome;
+import org.keycloak.adapters.spi.InMemorySessionIdMapper;
+import org.keycloak.adapters.spi.SessionIdMapper;
+import org.keycloak.adapters.spi.UserSessionManagement;
+import org.openecomp.sdc.common.util.Multitenancy;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+
+
+public class MultitenancyKeycloakFilter implements Filter {
+
+    private static final Logger log = Logger.getLogger("" + MultitenancyKeycloakFilter.class);
+
+    public static final String SKIP_PATTERN_PARAM = "keycloak.config.skipPattern";
+
+    public static final String ID_MAPPER_PARAM = "keycloak.config.idMapper";
+
+    public static final String CONFIG_RESOLVER_PARAM = "keycloak.config.resolver";
+
+    public static final String CONFIG_FILE_PARAM = "keycloak.config.file";
+
+    public static final String CONFIG_PATH_PARAM = "keycloak.config.path";
+
+    protected AdapterDeploymentContext deploymentContext;
+
+    protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
+
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+
+    protected Pattern skipPattern;
+
+    private final KeycloakConfigResolver definedconfigResolver;
+
+    boolean keycloak;
+
+    /**
+     * Constructor that can be used to define a {@code KeycloakConfigResolver} that will be used at initialization to
+     * provide the {@code KeycloakDeployment}.
+     * @param definedconfigResolver the resolver
+     */
+    public MultitenancyKeycloakFilter(KeycloakConfigResolver definedconfigResolver) {
+        this.definedconfigResolver = definedconfigResolver;
+    }
+
+    public MultitenancyKeycloakFilter() {
+        this(null);
+    }
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        String skipPatternDefinition = filterConfig.getInitParameter(SKIP_PATTERN_PARAM);
+        if (skipPatternDefinition != null) {
+            skipPattern = Pattern.compile(skipPatternDefinition, Pattern.DOTALL);
+        }
+
+        String idMapperClassName = filterConfig.getInitParameter(ID_MAPPER_PARAM);
+        if (idMapperClassName != null) {
+            try {
+                final Class<?> idMapperClass = getClass().getClassLoader().loadClass(idMapperClassName);
+                final Constructor<?> idMapperConstructor = idMapperClass.getDeclaredConstructor();
+                Object idMapperInstance = null;
+                // for KEYCLOAK-13745 test
+                if (idMapperConstructor.getModifiers() == Modifier.PRIVATE) {
+                    idMapperInstance = idMapperClass.getMethod("getInstance").invoke(null);
+                } else {
+                    idMapperInstance = idMapperConstructor.newInstance();
+                }
+                if(idMapperInstance instanceof SessionIdMapper) {
+                    this.idMapper = (SessionIdMapper) idMapperInstance;
+                } else {
+                    log.log(Level.WARNING, "SessionIdMapper class {0} is not instance of org.keycloak.adapters.spi.SessionIdMapper", idMapperClassName);
+                }
+            } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
+                log.log(Level.WARNING, "SessionIdMapper class could not be instanced", e);
+            }
+        }
+
+        if (definedconfigResolver != null) {
+            deploymentContext = new AdapterDeploymentContext(definedconfigResolver);
+            log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", definedconfigResolver.getClass());
+        } else {
+            String configResolverClass = filterConfig.getInitParameter(CONFIG_RESOLVER_PARAM);
+            if (configResolverClass != null) {
+                try {
+                    KeycloakConfigResolver configResolver = (KeycloakConfigResolver) getClass().getClassLoader().loadClass(configResolverClass).getDeclaredConstructor().newInstance();
+                    deploymentContext = new AdapterDeploymentContext(configResolver);
+                    log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
+                } catch (Exception ex) {
+                    log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
+                    deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                }
+            } else {
+                String fp = filterConfig.getInitParameter(CONFIG_FILE_PARAM);
+                InputStream is = null;
+                if (fp != null) {
+                    try {
+                        is = new FileInputStream(fp);
+                    } catch (FileNotFoundException e) {
+                        log.log(Level.FINE, "config file is empty",e);
+                    }
+                } else {
+                    String path = "/WEB-INF/keycloak.json";
+                    String pathParam = filterConfig.getInitParameter(CONFIG_PATH_PARAM);
+                    if (pathParam != null) path = pathParam;
+                    is = filterConfig.getServletContext().getResourceAsStream(path);
+                }
+                KeycloakDeployment kd = createKeycloakDeploymentFrom(is);
+                deploymentContext = new AdapterDeploymentContext(kd);
+                log.fine("Keycloak is using a per-deployment configuration.");
+            }
+        }
+        filterConfig.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+        nodesRegistrationManagement = new NodesRegistrationManagement();
+    }
+
+    private KeycloakDeployment createKeycloakDeploymentFrom(InputStream is) {
+        if (is == null) {
+            log.fine("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
+            return new KeycloakDeployment();
+        }
+        return KeycloakDeploymentBuilder.build(is);
+    }
+
+
+    @Override
+    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
+        log.fine("Keycloak OIDC Filter");
+        Multitenancy keyaccess= new Multitenancy();
+        keycloak= keyaccess.multiTenancyCheck();
+
+        HttpServletRequest request = (HttpServletRequest) req;
+        HttpServletResponse response = (HttpServletResponse) res;
+
+        if (!keycloak) {
+            chain.doFilter(req, res);
+            return;
+        }
+
+        if (shouldSkip(request)) {
+            chain.doFilter(req, res);
+            return;
+        }
+
+        OIDCServletHttpFacade facade = new OIDCServletHttpFacade(request, response);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment == null || !deployment.isConfigured()) {
+            response.sendError(403);
+            log.fine("deployment not configured");
+            return;
+        }
+
+        PreAuthActionsHandler preActions = new PreAuthActionsHandler(new org.openecomp.server.filters.MultitenancyKeycloakFilter.IdMapperUserSessionManagement(), deploymentContext, facade);
+
+        if (preActions.handleRequest()) {
+         return;
+        }
+
+
+        nodesRegistrationManagement.tryRegister(deployment);
+        OIDCFilterSessionStore tokenStore = new OIDCFilterSessionStore(request, facade, 100000, deployment, idMapper);
+        tokenStore.checkCurrentToken();
+
+
+        FilterRequestAuthenticator authenticator = new FilterRequestAuthenticator(deployment, tokenStore, facade, request, 8443);
+        AuthOutcome outcome = authenticator.authenticate();
+        if (outcome == AuthOutcome.AUTHENTICATED) {
+            log.fine("AUTHENTICATED");
+            if (facade.isEnded()) {
+                return;
+            }
+            AuthenticatedActionsHandler actions = new AuthenticatedActionsHandler(deployment, facade);
+            if (actions.handledRequest()) {
+                return;
+            } else {
+                HttpServletRequestWrapper wrapper = tokenStore.buildWrapper();
+                chain.doFilter(wrapper, res);
+                return;
+            }
+        }
+        AuthChallenge challenge = authenticator.getChallenge();
+        if (challenge != null) {
+            log.fine("challenge");
+            challenge.challenge(facade);
+            return;
+        }
+        response.sendError(403);
+
+    }
+
+    /**
+     * Decides whether this {@link Filter} should skip the given {@link HttpServletRequest} based on the configured {@link org.keycloak.adapters.servlet.KeycloakOIDCFilter#skipPattern}.
+     * Patterns are matched against the {@link HttpServletRequest#getRequestURI() requestURI} of a request without the context-path.
+     * A request for {@code /myapp/index.html} would be tested with {@code /index.html} against the skip pattern.
+     * Skipped requests will not be processed further by {@link org.keycloak.adapters.servlet.KeycloakOIDCFilter} and immediately delegated to the {@link FilterChain}.
+     *
+     * @param request the request to check
+     * @return {@code true} if the request should not be handled,
+     * {@code false} otherwise.
+     */
+    private boolean shouldSkip(HttpServletRequest request) {
+
+        if (skipPattern == null) {
+            return false;
+        }
+
+        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+        return skipPattern.matcher(requestPath).matches();
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+
+    private class IdMapperUserSessionManagement implements UserSessionManagement {
+        @Override
+        public void logoutAll() {
+            if (idMapper != null) {
+                idMapper.clear();
+            }
+        }
+
+        @Override
+        public void logoutHttpSessions(List<String> ids) {
+            log.fine("**************** logoutHttpSessions");
+            for (String id : ids) {
+                log.finest(id);
+                idMapper.removeSession(id);
+            }
+
+        }
+    }
+}
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/keycloak.json b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644 (file)
index 0000000..d037661
--- /dev/null
@@ -0,0 +1,11 @@
+{
+"realm": "sdc",
+"auth-server-url": "http://10.32.243.37:31613/",
+"ssl-required": "external",
+"resource": "sdc-app",
+"public-client":true,
+"bearer-only":true,
+"use-resource-role-mappings": true,
+"principal-attribute":"preferred_username",
+"confidential-port": 0
+}
index 31400f8..7d2edf4 100644 (file)
         <listener-class>org.openecomp.server.listeners.OnboardingAppStartupListener</listener-class>
     </listener>
 
+    <!--KEYCLOAK FILTER -->
+    <filter>
+        <filter-name>Keycloak Filter</filter-name>
+        <filter-class>org.openecomp.server.filters.MultitenancyKeycloakFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>Keycloak Filter</filter-name>
+        <url-pattern>/keycloak/*</url-pattern>
+        <url-pattern>/v1.0/vendor-license-models/*</url-pattern>
+        <url-pattern>/v1.0/vendor-software-products</url-pattern>
+        <url-pattern>*/actions</url-pattern>
+        <url-pattern>/v1.0/items/*</url-pattern>
+    </filter-mapping>
+
     <filter>
         <filter-name>dataValidatorFilter</filter-name>
         <filter-class>org.openecomp.sdc.common.filters.DataValidatorFilter</filter-class>
index 0636b6e..1c942d4 100644 (file)
@@ -45,6 +45,8 @@ import org.openecomp.sdcrests.vendorlicense.types.VendorLicenseModelActionReques
 import org.openecomp.sdcrests.vendorlicense.types.VendorLicenseModelEntityDto;
 import org.openecomp.sdcrests.vendorlicense.types.VendorLicenseModelRequestDto;
 import org.springframework.validation.annotation.Validated;
+import javax.ws.rs.core.Context;
+import javax.servlet.http.HttpServletRequest;
 
 @Path("/v1.0/vendor-license-models")
 @Produces(MediaType.APPLICATION_JSON)
@@ -61,13 +63,13 @@ public interface VendorLicenseModels {
                                @Parameter(description = "Filter to only return Vendor License Models at this status."
                                    + "Currently supported values: 'ACTIVE' , 'ARCHIVED'."
                                    + "Default value = 'ACTIVE'.") @QueryParam("Status") String itemStatus,
-                               @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(RestConstants.USER_ID_HEADER_PARAM) String user);
+                               @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(RestConstants.USER_ID_HEADER_PARAM) String user , @Context HttpServletRequest req);
 
     @POST
     @Path("/")
-    @Operation(description = "Create vendor license model")
+    @Operation(description = "Create vendor license model", responses = @ApiResponse(responseCode = "401", description = "Unauthorized Tenant"))
     Response createLicenseModel(@Valid VendorLicenseModelRequestDto request,
-                                @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(RestConstants.USER_ID_HEADER_PARAM) String user);
+                                @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(RestConstants.USER_ID_HEADER_PARAM) String user, @Context HttpServletRequest req);
 
     @DELETE
     @Path("/{vlmId}")
index ac722a5..d22751d 100644 (file)
@@ -15,6 +15,7 @@
  */
 package org.openecomp.sdcrests.vendorlicense.rest.services;
 
+import org.keycloak.representations.AccessToken;
 import org.openecomp.core.dao.UniqueValueDaoFactory;
 import org.openecomp.core.util.UniqueValueUtil;
 import org.openecomp.sdc.activitylog.ActivityLogManager;
@@ -22,6 +23,7 @@ import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
 import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.healing.factory.HealingManagerFactory;
 import org.openecomp.sdc.itempermissions.PermissionsManager;
@@ -65,12 +67,23 @@ import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
+import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.*;
+import static org.openecomp.sdcrests.vendorlicense.types.VendorLicenseModelActionRequestDto.VendorLicenseModelAction.Submit;
+
 import javax.inject.Named;
 import javax.ws.rs.core.Response;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -142,38 +155,87 @@ public class VendorLicenseModelsImpl implements VendorLicenseModels {
     }
 
     @Override
-    public Response listLicenseModels(String versionStatus, String itemStatus, String user) {
+    public Response listLicenseModels(String versionStatus, String itemStatus, String user, HttpServletRequest hreq) {
         Predicate<Item> itemPredicate = createItemPredicate(versionStatus, itemStatus, user);
         GenericCollectionWrapper<ItemDto> results = new GenericCollectionWrapper<>();
         MapItemToDto mapper = new MapItemToDto();
-        asdcItemManager.list(itemPredicate).stream().sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
-            .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
-        return Response.ok(results).build();
+        Multitenancy keyaccess= new Multitenancy();
+        if (keyaccess.multiTenancyCheck()) {
+            AccessToken.Access realmAccess = keyaccess.getAccessToken(hreq).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+            realmroles.stream().forEach(role -> asdcItemManager.list(itemPredicate).stream().sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
+                    .filter(item -> item.getTenant().contains(role))
+                    .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class))));
+            return Response.ok(results).build();
+        }
+        else
+        {
+            asdcItemManager.list(itemPredicate).stream().sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
+                    .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
+            return Response.ok(results).build();
+        }
     }
 
     @Override
-    public Response createLicenseModel(VendorLicenseModelRequestDto request, String user) {
-        Item item = new Item();
-        item.setType(ItemType.vlm.name());
-        item.setOwner(user);
-        item.setStatus(ItemStatus.ACTIVE);
-        item.setName(request.getVendorName());
-        item.setDescription(request.getDescription());
-        uniqueValueUtil.validateUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
-        item = asdcItemManager.create(item);
-        uniqueValueUtil.createUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
-        Version version = versioningManager.create(item.getId(), new Version(), null);
-        VendorLicenseModelEntity vlm = new MapVendorLicenseModelRequestDtoToVendorLicenseModelEntity()
-            .applyMapping(request, VendorLicenseModelEntity.class);
-        vlm.setId(item.getId());
-        vlm.setVersion(version);
-        vendorLicenseManager.createVendorLicenseModel(vlm);
-        versioningManager.publish(item.getId(), version, "Initial vlm:" + vlm.getVendorName());
-        ItemCreationDto itemCreationDto = new ItemCreationDto();
-        itemCreationDto.setItemId(item.getId());
-        itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
-        activityLogManager.logActivity(new ActivityLogEntity(vlm.getId(), version, ActivityType.Create, user, true, "", ""));
-        return Response.ok(itemCreationDto).build();
+    public Response createLicenseModel(VendorLicenseModelRequestDto request, String user, HttpServletRequest hreq) {
+        Multitenancy keyaccess= new Multitenancy();
+        if (keyaccess.multiTenancyCheck()) {
+            AccessToken.Access realmAccess = keyaccess.getAccessToken(hreq).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+            boolean match = realmroles.contains(request.getTenant());
+            if (match) {
+                Item item = new Item();
+                item.setType(ItemType.vlm.name());
+                item.setOwner(user);
+                item.setStatus(ItemStatus.ACTIVE);
+                item.setName(request.getVendorName());
+                item.setDescription(request.getDescription());
+                item.setTenant(request.getTenant());
+                uniqueValueUtil.validateUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
+                item = asdcItemManager.create(item);
+                uniqueValueUtil.createUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
+                Version version = versioningManager.create(item.getId(), new Version(), null);
+                VendorLicenseModelEntity vlm = new MapVendorLicenseModelRequestDtoToVendorLicenseModelEntity()
+                        .applyMapping(request, VendorLicenseModelEntity.class);
+                vlm.setId(item.getId());
+                vlm.setVersion(version);
+                vendorLicenseManager.createVendorLicenseModel(vlm);
+                versioningManager.publish(item.getId(), version, "Initial vlm:" + vlm.getVendorName());
+                ItemCreationDto itemCreationDto = new ItemCreationDto();
+                itemCreationDto.setItemId(item.getId());
+                itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
+                activityLogManager.logActivity(new ActivityLogEntity(vlm.getId(), version, ActivityType.Create, user, true, "", ""));
+                return Response.ok(itemCreationDto).build();
+            }
+            else {
+                LOGGER.error("Unauthorized tenant");
+                return Response.status(401, "Unauthorized tenant").build();
+            }
+        }
+        else
+        {
+            Item item = new Item();
+            item.setType(ItemType.vlm.name());
+            item.setOwner(user);
+            item.setStatus(ItemStatus.ACTIVE);
+            item.setName(request.getVendorName());
+            item.setDescription(request.getDescription());
+            uniqueValueUtil.validateUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
+            item = asdcItemManager.create(item);
+            uniqueValueUtil.createUniqueValue(VendorLicenseConstants.UniqueValues.VENDOR_NAME, item.getName());
+            Version version = versioningManager.create(item.getId(), new Version(), null);
+            VendorLicenseModelEntity vlm = new MapVendorLicenseModelRequestDtoToVendorLicenseModelEntity()
+                    .applyMapping(request, VendorLicenseModelEntity.class);
+            vlm.setId(item.getId());
+            vlm.setVersion(version);
+            vendorLicenseManager.createVendorLicenseModel(vlm);
+            versioningManager.publish(item.getId(), version, "Initial vlm:" + vlm.getVendorName());
+            ItemCreationDto itemCreationDto = new ItemCreationDto();
+            itemCreationDto.setItemId(item.getId());
+            itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
+            activityLogManager.logActivity(new ActivityLogEntity(vlm.getId(), version, ActivityType.Create, user, true, "", ""));
+            return Response.ok(itemCreationDto).build();
+        }
     }
 
     @Override
index 2c64764..020539a 100644 (file)
 package org.openecomp.sdcrests.vendorlicense.types;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
 
+@Getter
+@Setter
 @Schema(description = "VendorLicenseModelEntity")
 public class VendorLicenseModelEntityDto extends VendorLicenseModelRequestDto {
 
@@ -33,4 +37,6 @@ public class VendorLicenseModelEntityDto extends VendorLicenseModelRequestDto {
     public void setId(String id) {
         this.id = id;
     }
+
+    private String tenant;
 }
index ba8fd96..bb93a21 100644 (file)
@@ -38,6 +38,9 @@ public class VendorLicenseModelRequestDto {
     @NotNull
     private String iconRef;
 
+    @Size(max = 25)
+    private String tenant;
+
     public void setVendorName(final String vendorName) {
         this.vendorName = ValidationUtils.sanitizeInputString(vendorName);
     }
@@ -45,4 +48,11 @@ public class VendorLicenseModelRequestDto {
     public void setDescription(final String description) {
         this.description = ValidationUtils.sanitizeInputString(description);
     }
+
+    public void setTenant(final String tenant) {
+        if(tenant != null){
+            this.tenant = ValidationUtils.sanitizeInputString(tenant);
+        }
+        else this.tenant=tenant;
+    }
 }
index fbe7d37..347cc4b 100644 (file)
@@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tags;
 import java.io.File;
 import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
@@ -40,6 +41,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.openecomp.sdcrests.item.types.ItemCreationDto;
@@ -62,8 +64,9 @@ public interface VendorSoftwareProducts extends VspEntities {
 
     @POST
     @Path("/")
-    @Operation(description = "Create a new vendor software product", responses = @ApiResponse(content = @Content(schema = @Schema(implementation = ItemCreationDto.class))))
-    Response createVsp(@Valid VspRequestDto vspRequestDto, @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user);
+    @Operation(description = "Create a new vendor software product", responses = {@ApiResponse(content = @Content(schema = @Schema(implementation = ItemCreationDto.class)))
+            , @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")})
+    Response createVsp(@Valid VspRequestDto vspRequestDto, @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user, @Context HttpServletRequest req);
 
     @GET
     @Path("/")
@@ -71,9 +74,9 @@ public interface VendorSoftwareProducts extends VspEntities {
     Response listVsps(@Parameter(description = "Filter to return only Vendor Software Products with at"
         + " least one version at this status. Currently supported values: 'Certified' , 'Draft'") @QueryParam("versionFilter") String versionStatus,
                       @Parameter(description = "Filter to only return Vendor Software Products at this status."
-                          + "Currently supported values: 'ACTIVE' , 'ARCHIVED'."
-                          + "Default value = 'ACTIVE'.") @QueryParam("Status") String itemStatus,
-                      @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user);
+                              + "Currently supported values: 'ACTIVE' , 'ARCHIVED'."
+                              + "Default value = 'ACTIVE'.") @QueryParam("Status") String itemStatus,
+                      @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user, @Context HttpServletRequest req);
 
     @GET
     @Path("/{vspId}")
@@ -116,7 +119,7 @@ public interface VendorSoftwareProducts extends VspEntities {
 
     @GET
     @Path("/validation-vsp")
-    Response getValidationVsp(@NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user) throws Exception;
+    Response getValidationVsp(@NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user, @Context HttpServletRequest hreq) throws Exception;
 
     @PUT
     @Path("/{vspId}/versions/{versionId}/actions")
index 0543c20..d833a1b 100644 (file)
@@ -29,6 +29,7 @@ public class MapVspDescriptionDtoToItem extends MappingBase<VspDescriptionDto, I
     @Override
     public void doMapping(VspDescriptionDto source, Item target) {
         target.setName(source.getName());
+        target.setTenant(source.getTenant());
         target.setDescription(source.getDescription());
         target.addProperty(VspItemProperty.VENDOR_ID, source.getVendorId());
         target.addProperty(VspItemProperty.VENDOR_NAME, source.getVendorName());
index 418a512..3a989ec 100644 (file)
@@ -38,6 +38,9 @@ public class MapVspDescriptionDtoToVspDetails extends MappingBase<VspDescription
         target.setIcon(source.getIcon());
         target.setVendorName(source.getVendorName());
         target.setVendorId(source.getVendorId());
+        if (source.getTenant() != null) {
+            target.setTenant(source.getTenant());
+        }
         if (source.getLicensingVersion() != null && source.getLicenseType() != LicenseType.EXTERNAL) {
             target.setVlmVersion(new Version(source.getLicensingVersion()));
         }
index 897327e..519f789 100644 (file)
@@ -40,6 +40,7 @@ public class MapVspDetailsToDto extends MappingBase<VspDetails, VspDetailsDto> {
         target.setSubCategory(source.getSubCategory());
         target.setVendorId(source.getVendorId());
         target.setVendorName(source.getVendorName());
+        target.setTenant(source.getTenant());
         target.setLicensingVersion(source.getVlmVersion() == null ? null : source.getVlmVersion().getId());
         if (StringUtils.isNotBlank(source.getLicenseType())) {
             target.setLicenseType(LicenseType.valueOf(source.getLicenseType()));
index b424db9..c859414 100644 (file)
@@ -42,6 +42,7 @@ import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.MapUtils;
 import org.openecomp.core.dao.UniqueValueDaoFactory;
@@ -55,6 +56,7 @@ import org.openecomp.sdc.be.csar.storage.StorageFactory;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.common.util.Multitenancy;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.healing.factory.HealingManagerFactory;
@@ -116,6 +118,7 @@ import org.openecomp.sdcrests.vsp.rest.mapping.MapVspDetailsToDto;
 import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Service;
+import org.keycloak.representations.AccessToken;
 
 @Named
 @Service("vendorSoftwareProducts")
@@ -173,12 +176,15 @@ public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {
     }
 
     @Override
-    public Response createVsp(VspRequestDto vspRequestDto, String user) {
-        ItemCreationDto vspCreationDto = createVspItem(vspRequestDto, user);
-        return Response.ok(vspCreationDto).build();
-    }
+    public Response createVsp(VspRequestDto vspRequestDto, String user, HttpServletRequest hreq) {
+        ItemCreationDto vspCreationDto = createVspItem(vspRequestDto, user, hreq);
+        if (vspCreationDto != null) {
+            return Response.ok(vspCreationDto).build();
+        }
+        else return Response.status(401, "Unauthorized Tenant").build();
+        }
 
-    private ItemCreationDto createVspItem(VspRequestDto vspRequestDto, String user) {
+    private ItemCreationDto createVspItem(VspRequestDto vspRequestDto, String user, HttpServletRequest hreq) {
         OnboardingMethod onboardingMethod = null;
         try {
             onboardingMethod = OnboardingMethod.valueOf(vspRequestDto.getOnboardingMethod());
@@ -188,34 +194,69 @@ public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {
         }
         ItemCreationDto itemCreationDto = null;
         if (onboardingMethod == NetworkPackage || onboardingMethod == OnboardingMethod.Manual) {
-            itemCreationDto = createItem(vspRequestDto, user, onboardingMethod);
+            itemCreationDto = createItem(vspRequestDto, user, onboardingMethod, hreq);
         } else {
             throwUnknownOnboardingMethodException(new IllegalArgumentException("Wrong parameter Onboarding Method"));
         }
         return itemCreationDto;
     }
 
-    private ItemCreationDto createItem(VspRequestDto vspRequestDto, String user, OnboardingMethod onboardingMethod) {
-        Item item = new MapVspDescriptionDtoToItem().applyMapping(vspRequestDto, Item.class);
-        item.setType(ItemType.vsp.name());
-        item.setOwner(user);
-        item.setStatus(ItemStatus.ACTIVE);
-        item.addProperty(VspItemProperty.ONBOARDING_METHOD, onboardingMethod.name());
-        uniqueValueUtil.validateUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
-        item = itemManager.create(item);
-        uniqueValueUtil.createUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
-        Version version = versioningManager.create(item.getId(), new Version(), null);
-        VspDetails vspDetails = new MapVspDescriptionDtoToVspDetails().applyMapping(vspRequestDto, VspDetails.class);
-        vspDetails.setId(item.getId());
-        vspDetails.setVersion(version);
-        vspDetails.setOnboardingMethod(vspRequestDto.getOnboardingMethod());
-        vendorSoftwareProductManager.createVsp(vspDetails);
-        versioningManager.publish(item.getId(), version, "Initial vsp:" + vspDetails.getName());
-        ItemCreationDto itemCreationDto = new ItemCreationDto();
-        itemCreationDto.setItemId(item.getId());
-        itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
-        activityLogManager.logActivity(new ActivityLogEntity(vspDetails.getId(), version, ActivityType.Create, user, true, "", ""));
-        return itemCreationDto;
+    private ItemCreationDto createItem(VspRequestDto vspRequestDto, String user, OnboardingMethod onboardingMethod , HttpServletRequest hreq) {
+        Multitenancy keyaccess= new Multitenancy();
+        if (keyaccess.multiTenancyCheck()) {
+           AccessToken.Access realmAccess = keyaccess.getAccessToken(hreq).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+            boolean match = realmroles.contains(vspRequestDto.getTenant());
+            if (match) {
+                Item item = new MapVspDescriptionDtoToItem().applyMapping(vspRequestDto, Item.class);
+                item.setType(ItemType.vsp.name());
+                item.setOwner(user);
+                item.setTenant(item.getTenant());
+                item.setStatus(ItemStatus.ACTIVE);
+                item.addProperty(VspItemProperty.ONBOARDING_METHOD, onboardingMethod.name());
+                uniqueValueUtil.validateUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
+                item = itemManager.create(item);
+                uniqueValueUtil.createUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
+                Version version = versioningManager.create(item.getId(), new Version(), null);
+                VspDetails vspDetails = new MapVspDescriptionDtoToVspDetails().applyMapping(vspRequestDto, VspDetails.class);
+                vspDetails.setId(item.getId());
+                vspDetails.setVersion(version);
+                vspDetails.setOnboardingMethod(vspRequestDto.getOnboardingMethod());
+                vendorSoftwareProductManager.createVsp(vspDetails);
+                versioningManager.publish(item.getId(), version, "Initial vsp:" + vspDetails.getName());
+                ItemCreationDto itemCreationDto = new ItemCreationDto();
+                itemCreationDto.setItemId(item.getId());
+                itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
+                activityLogManager.logActivity(new ActivityLogEntity(vspDetails.getId(), version, ActivityType.Create, user, true, "", ""));
+                return itemCreationDto;
+            }
+            else {
+                LOGGER.error("Unauthorized tenant");
+                return null;
+            }
+        }
+        else {
+            Item item = new MapVspDescriptionDtoToItem().applyMapping(vspRequestDto, Item.class);
+            item.setType(ItemType.vsp.name());
+            item.setOwner(user);
+            item.setStatus(ItemStatus.ACTIVE);
+            item.addProperty(VspItemProperty.ONBOARDING_METHOD, onboardingMethod.name());
+            uniqueValueUtil.validateUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
+            item = itemManager.create(item);
+            uniqueValueUtil.createUniqueValue(VENDOR_SOFTWARE_PRODUCT_NAME, item.getName());
+            Version version = versioningManager.create(item.getId(), new Version(), null);
+            VspDetails vspDetails = new MapVspDescriptionDtoToVspDetails().applyMapping(vspRequestDto, VspDetails.class);
+            vspDetails.setId(item.getId());
+            vspDetails.setVersion(version);
+            vspDetails.setOnboardingMethod(vspRequestDto.getOnboardingMethod());
+            vendorSoftwareProductManager.createVsp(vspDetails);
+            versioningManager.publish(item.getId(), version, "Initial vsp:" + vspDetails.getName());
+            ItemCreationDto itemCreationDto = new ItemCreationDto();
+            itemCreationDto.setItemId(item.getId());
+            itemCreationDto.setVersion(new MapVersionToDto().applyMapping(version, VersionDto.class));
+            activityLogManager.logActivity(new ActivityLogEntity(vspDetails.getId(), version, ActivityType.Create, user, true, "", ""));
+            return itemCreationDto;
+        }
     }
 
     private void throwUnknownOnboardingMethodException(IllegalArgumentException e) {
@@ -224,11 +265,25 @@ public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {
     }
 
     @Override
-    public Response listVsps(String versionStatus, String itemStatus, String user) {
-        GenericCollectionWrapper<VspDetailsDto> results = new GenericCollectionWrapper<>();
-        MapItemToVspDetailsDto mapper = new MapItemToVspDetailsDto();
-        getVspList(versionStatus, itemStatus, user).forEach(vspItem -> results.add(mapper.applyMapping(vspItem, VspDetailsDto.class)));
-        return Response.ok(results).build();
+    public Response listVsps(String versionStatus, String itemStatus, String user, HttpServletRequest hreq ) {
+        Multitenancy keyaccess = new Multitenancy();
+        if (keyaccess.multiTenancyCheck()) {
+           AccessToken.Access realmAccess = keyaccess.getAccessToken(hreq).getRealmAccess();
+            Set<String> realmroles = realmAccess.getRoles();
+            Predicate<Item> itemPredicate = createItemPredicate(versionStatus, itemStatus, user);
+            GenericCollectionWrapper<VspDetailsDto> results = new GenericCollectionWrapper<>();
+            MapItemToVspDetailsDto mapper = new MapItemToVspDetailsDto();
+            realmroles.stream().forEach(role -> itemManager.list(itemPredicate).stream().sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
+                    .filter(vspItem -> vspItem.getTenant().contains(role))
+                    .forEach(vspItem -> results.add(mapper.applyMapping(vspItem, VspDetailsDto.class))));
+            return Response.ok(results).build();
+        }
+        else {
+            GenericCollectionWrapper<VspDetailsDto> results = new GenericCollectionWrapper<>();
+            MapItemToVspDetailsDto mapper = new MapItemToVspDetailsDto();
+            getVspList(versionStatus, itemStatus, user).forEach(vspItem -> results.add(mapper.applyMapping(vspItem, VspDetailsDto.class)));
+            return Response.ok(results).build();
+        }
     }
 
     @Override
@@ -427,12 +482,12 @@ public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {
     }
 
     @Override
-    public Response getValidationVsp(String user) {
-        ItemCreationDto validationVsp = retrieveValidationVsp();
+    public Response getValidationVsp(String user, HttpServletRequest hreq) {
+        ItemCreationDto validationVsp = retrieveValidationVsp(hreq);
         return Response.ok(validationVsp).build();
     }
 
-    private ItemCreationDto retrieveValidationVsp() {
+    private ItemCreationDto retrieveValidationVsp(HttpServletRequest req) {
         synchronized (VALIDATION_VSP_CACHE_LOCK) {
             if (cachedValidationVsp != null) {
                 return cachedValidationVsp;
@@ -441,7 +496,7 @@ public class VendorSoftwareProductsImpl implements VendorSoftwareProducts {
             validationVspRequest.setOnboardingMethod(NetworkPackage.toString());
             validationVspRequest.setName(VALIDATION_VSP_NAME);
             try {
-                cachedValidationVsp = createVspItem(validationVspRequest, VALIDATION_VSP_USER);
+                cachedValidationVsp = createVspItem(validationVspRequest, VALIDATION_VSP_USER, req);
                 return cachedValidationVsp;
             } catch (CoreException vspCreateException) {
                 LOGGER.debug("Failed to create validation VSP", vspCreateException);
index e5f4ae0..c194c4f 100644 (file)
@@ -51,6 +51,7 @@ public class VspDescriptionDto {
     private LicenseType licenseType;
     private LicensingData licensingData;
     private List<String> selectedModelList;
+    private String tenant;
 
     public void setName(final String name) {
         this.name = ValidationUtils.sanitizeInputString(name);
@@ -64,6 +65,13 @@ public class VspDescriptionDto {
         this.description = ValidationUtils.sanitizeInputString(description);
     }
 
+    public void setTenant(final String tenant) {
+        if( tenant != null) {
+            this.tenant = ValidationUtils.sanitizeInputString(tenant);
+        }
+        else this.tenant=tenant;
+    }
+
     public void setSelectedModelList(final List<String> selectedModelList) {
         if (CollectionUtils.isEmpty(selectedModelList)) {
             this.selectedModelList = new ArrayList<>();
index 89b555c..30c1c03 100644 (file)
 package org.openecomp.sdc.vendorlicense.impl;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.*;
 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
+import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.vendorlicense.VendorLicenseConstants;
 import org.openecomp.sdc.vendorlicense.dao.*;
 import org.openecomp.sdc.vendorlicense.dao.types.VendorLicenseModelEntity;
 import org.openecomp.sdc.vendorlicense.facade.VendorLicenseFacade;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
+import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
 
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashSet;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.*;
-
+import static org.hamcrest.MatcherAssert.assertThat;
 
 /**
  * Created by ayalaben on 7/19/2017
@@ -53,6 +61,10 @@ public class VendorLicenseModelTest {
   public static final Version VERSION01 = new Version(0, 1);
   private static final Version VERSION10 = new Version(1, 0);
 
+  private static final boolean MULTITENANCY_ENABLED = true;
+
+  private static final String TEST_TENANT = "test_tenant";
+
   @Mock
   private VersioningManager versioningManagerMcok;
   @Mock
@@ -154,4 +166,93 @@ public class VendorLicenseModelTest {
 //    vendorSoftwareProductManager.getVsp(VSP_ID, notExistversion);
 //  }
 
+
+  @Test
+  public void testCreate_withMultitenancyValidTenant_Success() {
+    Assert.assertEquals(MULTITENANCY_ENABLED,true);
+    VendorLicenseModelEntity vlmEntity = new VendorLicenseModelEntity();
+    vlmEntity.setId(vlm1_id);
+    vlmEntity.setVersion(VERSION01);
+    vlmEntity.setTenant(TEST_TENANT);
+    assertThat("Unauthorized Tenant", getTestRoles().contains(vlmEntity.getTenant()));
+    vendorLicenseManager.createVendorLicenseModel(vlmEntity);
+    verify(vendorLicenseModelDaoMcok).create(vlmEntity);
+  }
+
+ @Test
+  public void testCreate_withMultitenancyInvalidTenant_Failure() {
+    String invalidTenant="invalid_tenant";
+    Assert.assertEquals(MULTITENANCY_ENABLED,true);
+    VendorLicenseModelEntity vlmEntity = new VendorLicenseModelEntity();
+    vlmEntity.setId(vlm1_id);
+    vlmEntity.setVersion(VERSION01);
+    vlmEntity.setTenant(invalidTenant);
+    Assert.assertFalse(getTestRoles().contains(invalidTenant));
+    Assert.assertNotNull(vlmEntity.getTenant());
+    vendorLicenseManager.createVendorLicenseModel(vlmEntity);
+    assertThat("Unauthorized Tenant", !getTestRoles().contains(vlmEntity.getTenant()));
+  }
+
+  @Test
+  public void testListVLM_multitenancyWithTenant_FilterList() {
+    Assert.assertEquals(MULTITENANCY_ENABLED,true);
+    Assert.assertNotNull(getTestRoles());
+    assertThat("Unauthorized Tenant", getTestRoles().contains(TEST_TENANT));
+    String tenant = TEST_TENANT;
+    Assert.assertNotNull(tenant);
+    List<Item> expectedItems=new ArrayList<>();
+      getTestRoles().stream().forEach(role -> getLicenseModelItems().stream()
+              .filter(item -> item.getTenant().contains(role))
+              .forEach(item -> expectedItems.add(item)));
+    Assert.assertEquals(expectedItems.size(), 1);
+  }
+
+  @Test
+  public void testListVLM_multitenancyWithInvalidTenant_ReturnEmptylist() {
+    Assert.assertEquals(MULTITENANCY_ENABLED,true);
+    Assert.assertNotNull(getTestRoles());
+    String tenant= "invalid_tenant";
+    List<Item> expectedItems=new ArrayList<>();
+    List<Item> actualItems=getLicenseModelItems();
+    Assert.assertNotNull(tenant);
+    getTestRoles().stream().forEach(role -> getLicenseModelItems().stream()
+            .filter(item -> item.getTenant()!=null)
+            .filter(item -> item.getTenant().contains(tenant))
+            .forEach(item -> expectedItems.add(item)));
+
+    Assert.assertEquals(expectedItems.size(), 0);
+    Assert.assertNotEquals(expectedItems.containsAll(actualItems), actualItems.containsAll(expectedItems));
+  }
+
+  private Set<String> getTestRoles(){
+    Set<String> roles = new HashSet<>();
+    roles.add("test_admin");
+    roles.add("test_tenant");
+    return roles;
+  }
+
+  private List<Item> getLicenseModelItems(){
+    List<Item> items=new ArrayList<>();
+
+    Item itemOne = new Item();
+    itemOne.setType(ItemType.vlm.name());
+    itemOne.setOwner(USER1);
+    itemOne.setStatus(ItemStatus.ACTIVE);
+    itemOne.setName("TEST_VENDOR_ONE");
+    itemOne.setDescription("TEST_DESCRIPTION");
+    itemOne.setTenant(TEST_TENANT);
+
+    Item itemTwo = new Item();
+    itemTwo.setType(ItemType.vlm.name());
+    itemTwo.setOwner(USER1);
+    itemTwo.setStatus(ItemStatus.ACTIVE);
+    itemTwo.setName("TEST_VENDOR_TWO");
+    itemTwo.setDescription("TEST_DESCRIPTION");
+    itemTwo.setTenant("admin_tenant");
+
+    items.add(itemOne);
+    items.add(itemTwo);
+    return items;
+  }
+
 }
index 2371bac..81e7e53 100644 (file)
@@ -44,9 +44,12 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.Optional;
 import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -66,6 +69,7 @@ import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.ErrorCategory;
 import org.openecomp.sdc.common.errors.ErrorCode;
+import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.healing.api.HealingManager;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
 import org.openecomp.sdc.vendorlicense.facade.VendorLicenseFacade;
@@ -91,6 +95,8 @@ import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTempl
 import org.openecomp.sdc.versioning.ActionVersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
+import org.openecomp.sdc.versioning.types.Item;
+import org.openecomp.sdc.versioning.types.ItemStatus;
 import org.openecomp.sdc.versioning.types.VersionInfo;
 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
 
@@ -101,6 +107,8 @@ class VendorSoftwareProductManagerImplTest {
     private static final Version VERSION10 = new Version("1, 0");
     private static final String USER1 = "vspTestUser1";
     private static final String USER2 = "vspTestUser2";
+    private static final boolean MULTITENANCY_ENABLED = true;
+    private static final String TEST_TENANT = "test_tenant";
 
     @Mock
     private ActionVersioningManager versioningManagerMock;
@@ -553,4 +561,100 @@ class VendorSoftwareProductManagerImplTest {
         assertEquals(actual.getFeatureGroups(), expected.getFeatureGroups());
     }
 
+    @Test
+    void createVSP_withMultitenancy_Success() {
+        assertEquals(MULTITENANCY_ENABLED, true);
+        assertNotNull(getTestRoles());
+        doReturn("{}")
+                .when(vendorSoftwareProductManager).getVspQuestionnaireSchema(nullable(SchemaTemplateInput.class));
+        VspDetails vspToCreate =
+                createVspDetails(null, null, "Vsp1", "Test-vsp", "vendorName", "vlm1Id", "icon",
+                        "category", "subCategory", "123", null);
+        vspToCreate.setTenant(TEST_TENANT);
+        assertThat("Unauthorized Tenant", getTestRoles().contains(vspToCreate.getTenant()));
+        VspDetails vsp = vendorSoftwareProductManager.createVsp(vspToCreate);
+
+        assertNotNull(vsp);
+        vspToCreate.setId(vsp.getId());
+        vspToCreate.setVersion(VERSION01);
+        assertVspsEquals(vsp, vspToCreate);
+        assertEquals(vsp.getTenant(), vspToCreate.getTenant());
+    }
+
+    @Test
+    void createVSP_withMultitenancy_Failure() {
+        assertEquals(MULTITENANCY_ENABLED, true);
+        assertNotNull(getTestRoles());
+        doReturn("{}")
+                .when(vendorSoftwareProductManager).getVspQuestionnaireSchema(nullable(SchemaTemplateInput.class));
+        VspDetails vspToCreate =
+                createVspDetails(null, null, "Vsp1", "Test-vsp", "vendorName", "vlm1Id", "icon",
+                        "category", "subCategory", "123", null);
+        vspToCreate.setTenant("invalid_tenant");
+        VspDetails vsp = vendorSoftwareProductManager.createVsp(vspToCreate);
+
+        assertEquals(vsp.getTenant(), vspToCreate.getTenant());
+        assertThat("Unauthorized Tenant", !getTestRoles().contains(vsp.getTenant()));
+    }
+
+    private Set<String> getTestRoles(){
+        Set<String> roles = new HashSet<>();
+        roles.add("test_admin");
+        roles.add("test_tenant");
+        return roles;
+    }
+
+    @Test
+    public void testListVSP_multitenancyWithTenant_FilterList() {
+        Assert.assertEquals(MULTITENANCY_ENABLED,true);
+        Assert.assertNotNull(getTestRoles());
+        assertThat("Unauthorized Tenant", getTestRoles().contains(TEST_TENANT));
+        List<Item> expectedItems=new ArrayList<>();
+        getTestRoles().stream().forEach(role -> getVSPItems().stream()
+                .filter(item -> item.getTenant()!=null)
+                .filter(item -> item.getTenant().contains(role))
+                .forEach(item -> expectedItems.add(item)));
+        Assert.assertEquals(expectedItems.size(), 1);
+    }
+
+    @Test
+    public void testListVSP_multitenancyWithInvalidTenant_ReturnEmptylist() {
+        Assert.assertEquals(MULTITENANCY_ENABLED,true);
+        Assert.assertNotNull(getTestRoles());
+        String tenant= "invalid_tenant";
+        List<Item> expectedItems=new ArrayList<>();
+        List<Item> actualItems=getVSPItems();
+        Assert.assertNotNull(tenant);
+        getTestRoles().stream().forEach(role -> getVSPItems().stream()
+                .filter(item -> item.getTenant()!=null)
+                .filter(item -> item.getTenant().contains(tenant))
+                .forEach(item -> expectedItems.add(item)));
+
+        Assert.assertEquals(expectedItems.size(), 0);
+        Assert.assertNotEquals(expectedItems.containsAll(actualItems), actualItems.containsAll(expectedItems));
+    }
+
+    private List<Item> getVSPItems(){
+        List<Item> items=new ArrayList<>();
+
+        Item itemOne = new Item();
+        itemOne.setType(ItemType.vsp.name());
+        itemOne.setOwner(USER1);
+        itemOne.setStatus(ItemStatus.ACTIVE);
+        itemOne.setName("TEST_VSP_ONE");
+        itemOne.setDescription("TEST_DESCRIPTION");
+        itemOne.setTenant(TEST_TENANT);
+
+        Item itemTwo = new Item();
+        itemTwo.setType(ItemType.vsp.name());
+        itemTwo.setOwner(USER1);
+        itemTwo.setStatus(ItemStatus.ACTIVE);
+        itemTwo.setName("TEST_VSP_TWO");
+        itemTwo.setDescription("TEST_DESCRIPTION");
+        itemTwo.setTenant("admin_tenant");
+
+        items.add(itemOne);
+        items.add(itemTwo);
+        return items;
+    }
 }
index f6e155b..9b9ae13 100644 (file)
@@ -25,9 +25,13 @@ import com.datastax.driver.mapping.annotations.Frozen;
 import com.datastax.driver.mapping.annotations.PartitionKey;
 import com.datastax.driver.mapping.annotations.Table;
 import java.util.Objects;
+import lombok.Getter;
+import lombok.Setter;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.dao.types.VersionableEntity;
 
+@Getter
+@Setter
 @Table(keyspace = "dox", name = "vendor_license_model")
 public class VendorLicenseModelEntity implements VersionableEntity {
 
@@ -42,6 +46,7 @@ public class VendorLicenseModelEntity implements VersionableEntity {
     private String vendorName;
     private String description;
     private String oldVersion;
+    private String tenant;
     @Column(name = "icon")
     private String iconRef;
     @Computed("writetime(vendor_name)")
@@ -123,7 +128,7 @@ public class VendorLicenseModelEntity implements VersionableEntity {
 
     @Override
     public int hashCode() {
-        return Objects.hash(id, version, vendorName, description, iconRef);
+        return Objects.hash(id, version, vendorName, description, iconRef, tenant);
     }
 
     @Override
@@ -136,6 +141,6 @@ public class VendorLicenseModelEntity implements VersionableEntity {
         }
         VendorLicenseModelEntity that = (VendorLicenseModelEntity) obj;
         return Objects.equals(id, that.id) && Objects.equals(version, that.version) && Objects.equals(vendorName, that.vendorName) && Objects
-            .equals(description, that.description) && Objects.equals(iconRef, that.iconRef);
+                .equals(description, that.description) && Objects.equals(iconRef, that.iconRef) && Objects.equals(tenant, that.tenant);
     }
 }
index 86c1bd1..20d8e3a 100644 (file)
@@ -30,6 +30,7 @@ public final class VendorSoftwareProductConstants {
     public final class UniqueValues {
 
         public static final String VENDOR_SOFTWARE_PRODUCT_NAME = "Vendor Software Product name";
+        public static final String TENANT = "tenant";
         public static final String PROCESS_NAME = "Process name";
         public static final String NETWORK_NAME = "Network name";
         public static final String COMPONENT_NAME = "ComponentData name";
index 6e17679..fe174b8 100644 (file)
@@ -203,6 +203,9 @@ public class VendorSoftwareProductInfoDaoZusammenImpl implements VendorSoftwareP
         info.addProperty(InfoPropertyName.SUB_CATEGORY.getValue(), vspDetails.getSubCategory());
         info.addProperty(InfoPropertyName.VENDOR_ID.getValue(), vspDetails.getVendorId());
         info.addProperty(InfoPropertyName.VENDOR_NAME.getValue(), vspDetails.getVendorName());
+        if(vspDetails.getTenant() !=null) {
+            info.addProperty(InfoPropertyName.TENANT.getValue(), vspDetails.getTenant());
+        }
         if (vspDetails.getVlmVersion() != null) {
             info.addProperty(InfoPropertyName.VENDOR_VERSION.getValue(), vspDetails.getVlmVersion().getId());
         }
@@ -226,6 +229,7 @@ public class VendorSoftwareProductInfoDaoZusammenImpl implements VendorSoftwareP
         SUB_CATEGORY("subCategory"),
         VENDOR_ID("vendorId"),
         VENDOR_NAME("vendorName"),
+        TENANT("tenant"),
         VENDOR_VERSION("vendorVersion"),
         LICENSE_TYPE("licenseType"),
         LICENSE_AGREEMENT("licenseAgreement"),
index 016c80a..365dbb6 100644 (file)
@@ -67,6 +67,7 @@ public class ElementToVSPGeneralConvertor extends ElementConvertor<VspDetails> {
         vspDetails.setSubCategory(info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.SUB_CATEGORY.getValue()));
         vspDetails.setVendorId(info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.VENDOR_ID.getValue()));
         vspDetails.setVendorName(info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.VENDOR_NAME.getValue()));
+        vspDetails.setTenant(info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.TENANT.getValue()));
         if (info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.VENDOR_VERSION.getValue()) != null) {
             vspDetails
                 .setVlmVersion(new Version(info.getProperty(VendorSoftwareProductInfoDaoZusammenImpl.InfoPropertyName.VENDOR_VERSION.getValue())));
index e2e7b1c..868faf4 100644 (file)
@@ -102,6 +102,9 @@ public class ItemZusammenDaoImpl implements ItemDao {
             case ITEM_OWNER:
                 item.setOwner((String) propertyValue);
                 break;
+            case TENANT:
+                item.setTenant((String) propertyValue);
+                break;
             case ITEM_STATUS:
                 item.setStatus(ItemStatus.valueOf((String) propertyValue));
                 break;
@@ -121,6 +124,9 @@ public class ItemZusammenDaoImpl implements ItemDao {
         info.setDescription(item.getDescription());
         info.addProperty(ItemInfoProperty.ITEM_TYPE.getName(), item.getType());
         info.addProperty(ItemInfoProperty.ITEM_OWNER.getName(), item.getOwner());
+        if (item.getTenant() != null) {
+            info.addProperty(ItemInfoProperty.TENANT.getName(), item.getTenant());
+        }
         if (item.getStatus() != null) {
             info.addProperty(ItemInfoProperty.ITEM_STATUS.getName(), item.getStatus());
         }
@@ -135,7 +141,8 @@ public class ItemZusammenDaoImpl implements ItemDao {
         ITEM_TYPE("item_type"),
         ITEM_VERSIONS_STATUSES("item_versions_statuses"),
         ITEM_OWNER("Owner"),
-        ITEM_STATUS("status");
+        ITEM_STATUS("status"),
+        TENANT("Tenant");
 
         private final String name;
 
diff --git a/pom.xml b/pom.xml
index d48ba89..a0cbb93 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -88,6 +88,9 @@ Modifications copyright (c) 2018-2019 Nokia
         <org.owasp.esapi.version>2.4.0.0</org.owasp.esapi.version>
         <org.dom4j.version>2.1.3</org.dom4j.version>
 
+        <!-- Keycloak authentication-->
+        <keycloak.version>18.0.0</keycloak.version>
+
         <!-- JSON and YAML Parsing -->
         <jackson.version>2.12.7</jackson.version>
         <jackson-annotations.version>${jackson.version}</jackson-annotations.version>
@@ -324,6 +327,68 @@ Modifications copyright (c) 2018-2019 Nokia
             <version>${mockito.version}</version>
             <scope>test</scope>
         </dependency>
+
+        <!-- KEYCLOAK Authentication and authorization-->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-servlet-filter-adapter</artifactId>
+            <version>${keycloak.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-authz-client</artifactId>
+            <version>${keycloak.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-spring-security-adapter</artifactId>
+            <version>${keycloak.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <version>${keycloak.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-common</artifactId>
+            <version>${keycloak.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>${servlet-api.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+            <version>5.6.3</version>
+        </dependency>
     </dependencies>
 
     <reporting>