Add basic auth 63/116263/12
authorxuegao <xue.gao@intl.att.com>
Wed, 9 Dec 2020 15:01:22 +0000 (16:01 +0100)
committerChristophe Closset <christophe.closset@intl.att.com>
Tue, 19 Jan 2021 13:51:47 +0000 (13:51 +0000)
Adding basic auth for SDC apis.

Issue-ID: OJSI-90
Signed-off-by: xuegao <xue.gao@intl.att.com>
Change-Id: Ie84e6bab8d8526f7f4d21a36bba52d8fe9abebbb
Signed-off-by: xuegao <xue.gao@intl.att.com>
26 files changed:
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/attributes/default.rb
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_2_setup_configuration.rb
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb
catalog-be/src/main/java/org/openecomp/sdc/be/filters/BasicAuthenticationFilter.java
catalog-be/src/main/resources/config/configuration.yaml
catalog-be/src/main/webapp/WEB-INF/web.xml
catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/attributes/default.rb
catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_2_setup_configuration.rb
catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/FE-configuration.yaml.erb
catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java
catalog-ui/src/app/ng2/services/authentication.service.ts
catalog-ui/src/app/services/components/component-service.ts
catalog-ui/src/app/services/components/resource-service.ts
catalog-ui/src/app/services/components/service-service.ts
catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts
catalog-ui/src/app/services/configuration-ui-service.ts
catalog-ui/src/app/services/data-types-service.ts
catalog-ui/src/app/services/ecomp-service.ts
catalog-ui/src/app/services/sdc-version-service.ts
common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java
common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/BasicAuthenticationFilter.java [new file with mode: 0644]
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb

index d8c7377..40411f2 100644 (file)
@@ -24,6 +24,12 @@ default['DCAE']['BE'][:http_port] = 8082
 default['DCAE']['BE'][:https_port] = 8444
 default['DCAE_BE_VIP'] = "dcae-be"
 
+#BasicAuth
+default['basic_auth']['enabled'] = false
+default['basic_auth'][:user_name] = "testName"
+default['basic_auth'][:user_pass] = "testPass"
+default['basic_auth']['excludedUrls'] = "/sdc2/rest/healthCheck,/sdc2/rest/v1/user,/sdc2/rest/v1/user/jh0003,/sdc2/rest/v1/screen,/sdc2/rest/v1/consumers,/sdc2/rest/v1/catalog/uploadType/datatypes,/sdc2/rest/v1/catalog/upload/multipart"
+
 #Cassandra
 default['cassandra']['cassandra_port'] = 9042
 default['cassandra']['datacenter_name'] = "DC-"
index 2e66e2d..cdb9f82 100644 (file)
@@ -46,6 +46,9 @@ template "catalog-be-config" do
                 :catalog_ip => node['Nodes']['BE'],
                 :catalog_port => node['BE'][:http_port],
                 :ssl_port => node['BE'][:https_port],
+                :basic_auth_flag => node['basic_auth']['enabled'],
+                :user_name => node['basic_auth'][:user_name],
+                :user_pass => node['basic_auth'][:user_pass],
                 :cassandra_ip => node['Nodes']['CS'].join(",").gsub(/[|]/, ''),
                 :cassandra_port => node['cassandra']['cassandra_port'],
                 :rep_factor => replication_factor,
index 8e62c4f..1e1888e 100644 (file)
@@ -95,7 +95,11 @@ authCookie:
   excludedUrls: [<%= node['access_restriction']['excluded_urls'] %>]
   onboardingExcludedUrls: [<%= node['access_restriction']['excluded_urls_onboarding'] %>]
 
-
+basicAuth:
+  enabled: <%= @basic_auth_flag %>
+  userName: <%= @user_name %>
+  userPass: <%= @user_pass %>
+  excludedUrls: "/sdc2/rest/healthCheck,/sdc2/rest/v1/user,/sdc2/rest/v1/user/jh0003,/sdc2/rest/v1/screen,/sdc2/rest/v1/consumers,/sdc2/rest/v1/catalog/uploadType/datatypes,/sdc2/rest/v1/catalog/upload/multipart,/sdc2/rest/v1/catalog/uploadType/capability,/sdc2/rest/v1/catalog/uploadType/relationship,/sdc2/rest/v1/catalog/uploadType/interfaceLifecycle,/sdc2/rest/v1/catalog/uploadType/categories,/sdc2/rest/v1/catalog/uploadType/grouptypes,/sdc2/rest/v1/catalog/uploadType/policytypes,/sdc2/rest/v1/catalog/uploadType/annotationtypes"
 
 cassandraConfig:
     cassandraHosts: [<%= @cassandra_ip %>]
index 8c81464..cc4a11f 100644 (file)
@@ -24,9 +24,14 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import fj.data.Either;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
 import org.apache.commons.codec.binary.Base64;
+import org.glassfish.jersey.server.ContainerRequest;
 import org.onap.sdc.security.Passwords;
 import org.openecomp.sdc.be.components.impl.ConsumerBusinessLogic;
+import org.openecomp.sdc.be.config.Configuration;
+import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
@@ -59,6 +64,8 @@ public class BasicAuthenticationFilter implements ContainerRequestFilter {
     private static final Logger log = Logger.getLogger(BasicAuthenticationFilter.class);
     private static final String COMPONENT_UTILS_FAILED = "Authentication Filter Failed to get component utils.";
     private static final String CONSUMER_BL_FAILED = "Authentication Filter Failed to get consumerBL.";
+    private static final ConfigurationManager configurationManager = ConfigurationManager.getConfigurationManager();
+    private static final Configuration.BasicAuthConfig basicAuthConf = configurationManager.getConfiguration().getBasicAuth();
 
     @Context
     private HttpServletRequest sr;
@@ -70,8 +77,15 @@ public class BasicAuthenticationFilter implements ContainerRequestFilter {
 
     @Override
     public void filter(ContainerRequestContext requestContext) throws IOException {
+        audit.startLog(requestContext);
 
-               audit.startLog(requestContext);
+        if (!basicAuthConf.getEnabled()) {
+            return;
+        }
+        List<String> excludedUrls = Arrays.asList(basicAuthConf.getExcludedUrls().split(","));
+        if (excludedUrls.contains(((ContainerRequest) requestContext).getRequestUri().getPath())) {
+            return;
+        }
 
         String authHeader = requestContext.getHeaderString(Constants.AUTHORIZATION_HEADER);
         if (authHeader != null) {
@@ -79,24 +93,23 @@ public class BasicAuthenticationFilter implements ContainerRequestFilter {
             String failedToRetrieveAuthErrorMsg = "Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.";
             if (st.hasMoreTokens()) {
                 String basic = st.nextToken();
-
                 if ("Basic".equalsIgnoreCase(basic)) {
                     String credentials = new String(Base64.decodeBase64(st.nextToken()), StandardCharsets.UTF_8);
                     log.debug("Credentials: {}", credentials);
                     checkUserCredentials(requestContext, credentials);
                 } else {
-                                       log.error(failedToRetrieveAuthErrorMsg);
+                    log.error(failedToRetrieveAuthErrorMsg);
                     authInvalidHeaderError(requestContext);
                 }
             } else {
-                               log.error(failedToRetrieveAuthErrorMsg);
+                log.error(failedToRetrieveAuthErrorMsg);
                 authInvalidHeaderError(requestContext);
             }
-
         } else {
-                       log.error("Authentication Filter Failed no authorization header");
+            log.error("Authentication Filter Failed no authorization header");
             authRequiredError(requestContext);
         }
+
     }
 
        private void checkUserCredentials(ContainerRequestContext requestContext, String credentials) {
@@ -105,17 +118,14 @@ public class BasicAuthenticationFilter implements ContainerRequestFilter {
             String userName = credentials.substring(0, p).trim();
             String password = credentials.substring(p + 1).trim();
 
-            ConsumerBusinessLogic consumerBL = getConsumerBusinessLogic();
-            if (consumerBL == null) {
-                               abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
-            } else {
-                Either<ConsumerDefinition, ResponseFormat> result = consumerBL.getConsumer(userName);
-                validatePassword(requestContext, userName, password, result);
+            if (!userName.equals(basicAuthConf.getUserName()) || !password.equals(basicAuthConf.getUserPass())) {
+                log.error("Authentication Failed. Invalid userName or password");
+                authInvalidPasswordError(requestContext, userName);
             }
+          authSuccessful(requestContext, userName);
         } else {
-                       log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
+            log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
             authInvalidHeaderError(requestContext);
-
         }
     }
 
@@ -130,12 +140,7 @@ public class BasicAuthenticationFilter implements ContainerRequestFilter {
             }
         } else {
             ConsumerDefinition consumerCredentials = result.left().value();
-            if (!Passwords.isExpectedPassword(password, consumerCredentials.getConsumerSalt(), consumerCredentials.getConsumerPassword())) {
-                               log.error("Authentication Filter Failed invalid password");
-                               authInvalidPasswordError(requestContext, userName);
-            } else {
-                               authSuccessful(requestContext, userName);
-            }
+
         }
     }
 
index 298862e..4042b01 100644 (file)
@@ -114,6 +114,12 @@ neo4j:
     user: neo4j
     password: "12345"
 
+basicAuth:
+  enabled: false
+  userName: "testName"
+  userPass: "testPass"
+  excludedUrls: ""
+
 cassandraConfig:
     cassandraHosts: [192.168.33.10]
     cassandraPort: 9042
index 23a0831..ca71eee 100644 (file)
@@ -17,6 +17,7 @@
             <param-name>jersey.config.server.provider.classnames</param-name>
             <param-value>
                 org.glassfish.jersey.media.multipart.MultiPartFeature,
+                org.openecomp.sdc.be.filters.BasicAuthenticationFilter,
                 org.openecomp.sdc.be.filters.BeServletFilter,
                 org.openecomp.sdc.be.filters.ComponentsAvailabilityFilter,
                 org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature,
         <url-pattern>/sdc/*</url-pattern>
     </filter-mapping>
 
+<!--
+    <filter>
+        <filter-name>basicAuthFilter</filter-name>
+        <filter-class>
+            org.openecomp.sdc.be.filters.BasicAuthenticationFilter
+        </filter-class>
+        <init-param>
+            <param-name>excludedUrls</param-name>
+            <param-value>/sdc2/rest/healthCheck,/sdc2/rest/v1/user,/sdc2/rest/v1/user/jh0003,/sdc2/rest/v1/screen,/sdc2/rest/v1/consumers,/sdc2/rest/v1/catalog/uploadType/datatypes,/sdc2/rest/v1/catalog/upload/multipart</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>basicAuthFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>-->
+
     <!--    <filter>-->
     <!--        <filter-name>beRestrictionAccessFilter</filter-name>-->
     <!--        <filter-class>-->
index 4d65cf7..7f66138 100644 (file)
@@ -18,3 +18,8 @@ default['ONBOARDING_BE'][:https_port] = 8445
 default['DCAE']['FE'][:http_port] = 8183
 default['DCAE']['FE'][:https_port] = 9444
 default['DCAE_FE_VIP'] = "dcaed-fe"
+
+#BasicAuth
+default['basic_auth']['enabled'] = true
+default['basic_auth'][:user_name] = "testName"
+default['basic_auth'][:user_pass] = "testPass"
\ No newline at end of file
index 7de9dbc..640b5b8 100644 (file)
@@ -10,6 +10,9 @@ template "catalog-fe-config" do
       :kb_host_ip   => node['Nodes']['KB'],
       :catalog_port => node['BE'][:http_port],
       :ssl_port     => node['BE'][:https_port],
+      :basic_auth_flag => node['basic_auth']['enabled'],
+      :user_name => node['basic_auth'][:user_name],
+      :user_pass => node['basic_auth'][:user_pass],
       :dcae_fe_vip  => node['DCAE_FE_VIP']
    })
 end
index fcdc45e..688bded 100644 (file)
@@ -39,6 +39,11 @@ healthCheckSocketTimeoutInMs: 5000
 
 healthCheckIntervalInSeconds: 5
 
+basicAuth:
+  enabled: <%= @basic_auth_flag %>
+  userName: <%= @user_name %>
+  userPass: <%= @user_pass %>
+
 onboarding:
     hostFe: <%= @fe_host_ip %>
     <% if node[:disableHttp] -%>
index 8f76cb9..337a8ae 100644 (file)
 package org.openecomp.sdc.fe.servlets;
 
 import com.google.common.annotations.VisibleForTesting;
+import java.util.Base64;
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.http.HttpHeader;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.fe.config.Configuration;
+import org.openecomp.sdc.fe.config.Configuration.BasicAuthConfig;
 import org.openecomp.sdc.fe.config.Configuration.CatalogFacadeMsConfig;
 import org.openecomp.sdc.fe.config.ConfigurationManager;
 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
@@ -37,7 +41,6 @@ import org.openecomp.sdc.fe.impl.LogHandler;
 import org.openecomp.sdc.fe.utils.BeProtocol;
 
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.net.MalformedURLException;
 import java.net.URL;
 
@@ -96,14 +99,18 @@ public class FeProxyServlet extends SSLProxyServlet {
        }
 
        @Override
-       protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) {
-               try {
-                       logFeResponse(request, response);
-               } catch (Exception e) {
-                       FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response");
-            log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet onProxyResponseSuccess", "sdc-FE", "Unexpected FE response logging error: ", e);
+       protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest)
+       {
+               Configuration config = getConfiguration(clientRequest);
+               if (config == null) {
+                       log.error("failed to retrieve configuration.");
+               }
+               BasicAuthConfig basicAuth = config.getBasicAuth();
+               if (basicAuth.getEnabled()) {
+                       proxyRequest.header(HttpHeader.AUTHORIZATION,
+                               "Basic " + Base64.getEncoder().encodeToString((basicAuth.getUserName() + ":" + basicAuth.getUserPass()).getBytes()));
                }
-               super.onProxyResponseSuccess(request, proxyResponse, response);
+               super.addProxyHeaders(clientRequest, proxyRequest);
        }
 
        private void logFeRequest(HttpServletRequest httpRequest){
index 52ca643..a77770a 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -31,7 +31,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
 export class AuthenticationService {
 
     private _loggedinUser:IUserProperties;
-    
+
     constructor(private cookieService:Cookie2Service, private http: HttpClient, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig, private cacheService: CacheService) {
         this.cookieService = cookieService;
     }
index bece12d..f22562f 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -208,7 +208,7 @@ export class ComponentService implements IComponentService {
         });
         return deferred.promise;
     };
-    
+
     public importComponent = (component: Component): ng.IPromise<Component> => {
         component.vendorName = "xfr";
         component.vendorRelease = "xfr";
index 3a00da1..9481736 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index 6c318bd..25811b2 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index b47c5e0..4ad403c 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -17,7 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
-/**
+ /**
  * Created by obarda on 3/13/2016.
  */
 'use strict';
@@ -73,12 +73,12 @@ export class LeftPaletteLoaderService {
             _.forEach(leftPaletteComponentMetadata, (componentMetadata:ComponentMetadata) => {
                 this.leftPanelComponents.push(new LeftPaletteComponent(LeftPaletteMetadataTypes.Component, componentMetadata));
             });
-            
+
             /* add groups */
             this.restangular.one('/groupTypes').get({'internalComponentType': componentInternalType}).then((leftPaletteGroupTypes:GroupTpes) => {
                 _.forEach(leftPaletteGroupTypes, (groupMetadata: GroupMetadata) => {
                     this.leftPanelComponents.push(new LeftPaletteComponent(LeftPaletteMetadataTypes.Group, groupMetadata));
-                }); 
+                });
                 this.EventListenerService.notifyObservers(EVENTS.LEFT_PALETTE_UPDATE_EVENT);
             });
 
@@ -86,7 +86,7 @@ export class LeftPaletteLoaderService {
             this.restangular.one('/policyTypes').get({'internalComponentType': componentInternalType}).then((leftPalettePolicyTypes:PolicyTpes) => {
                 _.forEach(leftPalettePolicyTypes, (policyMetadata: PolicyMetadata) => {
                     this.leftPanelComponents.push(new LeftPaletteComponent(LeftPaletteMetadataTypes.Policy, policyMetadata));
-                }); 
+                });
                 this.EventListenerService.notifyObservers(EVENTS.LEFT_PALETTE_UPDATE_EVENT);
             });
         });
index 463a974..8f6b485 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index 84fe42e..0237b2f 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index c8ed31a..eabf7a1 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index 6ab867e..86cdf23 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
index 4ec7a16..4ebacff 100644 (file)
@@ -118,6 +118,8 @@ public class Configuration extends BasicConfiguration {
 
     private DcaeConfig dcae;
 
+    private BasicAuthConfig basicAuth;
+
     private CassandrConfig cassandraConfig;
 
     private SwitchoverDetectorConfig switchoverDetector;
@@ -1175,6 +1177,53 @@ public class Configuration extends BasicConfiguration {
 
     }
 
+    public BasicAuthConfig getBasicAuth() {
+        return basicAuth;
+    }
+
+    public void setBasicAuth(BasicAuthConfig basicAuth) {
+        this.basicAuth = basicAuth;
+    }
+
+    public static class BasicAuthConfig {
+        boolean enabled;
+        String userName;
+        String userPass;
+        String excludedUrls;
+
+        public boolean getEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+
+        public String getUserName() {
+            return userName;
+        }
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+
+        public String getUserPass() {
+            return userPass;
+        }
+
+        public void setUserPass(String userPass) {
+            this.userPass = userPass;
+        }
+
+        public String getExcludedUrls() {
+            return excludedUrls;
+        }
+
+        public void setExcludedUrls(String excludedUrls) {
+            this.excludedUrls = excludedUrls;
+        }
+    }
+
     public DcaeConfig getDcae() {
         return dcae;
     }
index b2e58f5..e437034 100644 (file)
@@ -61,6 +61,8 @@ public class Configuration extends BasicConfiguration {
 
     private CookieConfig authCookie;
 
+    private BasicAuthConfig basicAuth;
+
     private CatalogFacadeMsConfig catalogFacadeMs;
     /**
      * be http context
@@ -265,6 +267,14 @@ public class Configuration extends BasicConfiguration {
         this.authCookie = authCookie;
     }
 
+    public BasicAuthConfig getBasicAuth() {
+        return basicAuth;
+    }
+
+    public void setBasicAuth(BasicAuthConfig basicAuth) {
+        this.basicAuth = basicAuth;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder().append(format("backend host: %s%n", beHost))
@@ -456,6 +466,36 @@ public class Configuration extends BasicConfiguration {
         }
     }
 
+    public static class BasicAuthConfig {
+        boolean enabled = false;
+        String userName = "";
+        String userPass = "";
+
+        public boolean getEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+
+        public String getUserName() {
+            return userName;
+        }
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+
+        public String getUserPass() {return userPass;
+        }
+
+        public void setUserPass(String userPass) {
+            this.userPass = userPass;
+        }
+
+    }
+
     public static class CatalogFacadeMsConfig {
         String protocol;
         String host;
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/BasicAuthenticationFilter.java b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/BasicAuthenticationFilter.java
new file mode 100644 (file)
index 0000000..c1eef1c
--- /dev/null
@@ -0,0 +1,133 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2021 AT&T 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 com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+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 org.onap.sdc.tosca.services.YamlUtil;
+import org.openecomp.sdc.be.config.Configuration.BasicAuthConfig;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Base64;
+import org.openecomp.sdcrests.item.rest.services.catalog.notification.EntryNotConfiguredException;
+
+public class BasicAuthenticationFilter implements Filter {
+
+  private static final Logger log = LoggerFactory.getLogger(BasicAuthenticationFilter.class);
+  private static final String CONFIG_FILE_PROPERTY = "configuration.yaml";
+  private static final String CONFIG_SECTION = "basicAuth";
+
+  @Override
+  public void destroy() {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
+      throws IOException, ServletException {
+      String file = Objects.requireNonNull(System.getProperty(CONFIG_FILE_PROPERTY),
+        "Config file location must be specified via system property " + CONFIG_FILE_PROPERTY);
+      Object config = getAuthenticationConfiguration(file);
+      ObjectMapper mapper = new ObjectMapper();
+      BasicAuthConfig basicAuthConfig = mapper.convertValue(config, BasicAuthConfig.class);
+      HttpServletRequest httpRequest = (HttpServletRequest) arg0;
+      HttpServletRequestWrapper servletRequest = new HttpServletRequestWrapper(httpRequest);
+
+      // BasicAuth is disabled
+      if (!basicAuthConfig.getEnabled()) {
+         arg2.doFilter(servletRequest, arg1);
+         return;
+      }
+
+      List<String> excludedUrls = Arrays.asList(basicAuthConfig.getExcludedUrls().split(","));
+      if (excludedUrls.contains(httpRequest.getServletPath() + httpRequest.getPathInfo())) {
+        // this url is included in the excludeUrls list, no need for authentication
+        arg2.doFilter(servletRequest, arg1);
+        return;
+      }
+
+
+      // Get the basicAuth info from the header
+      String authorizationHeader = httpRequest.getHeader("Authorization");
+      if (authorizationHeader == null || authorizationHeader.isEmpty()) {
+        ((HttpServletResponse) arg1).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        return;
+      }
+
+      String base64Credentials =
+          httpRequest.getHeader("Authorization").replace("Basic", "").trim();
+      if (verifyCredentials(basicAuthConfig, base64Credentials)) {
+          arg2.doFilter(servletRequest, arg1);
+      } else {
+          ((HttpServletResponse) arg1).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+      }
+  }
+
+  @Override
+  public void init(FilterConfig config) throws ServletException {
+  }
+
+  private static Object getAuthenticationConfiguration(String file) throws IOException {
+    InputStream fileInput = new FileInputStream(file);
+    YamlUtil yamlUtil = new YamlUtil();
+
+    Map<?, ?> configuration = Objects.requireNonNull(yamlUtil.yamlToMap(fileInput), "Configuration cannot be empty");
+    Object authenticationConfig = configuration.get(CONFIG_SECTION);
+    if (authenticationConfig == null) {
+      throw new EntryNotConfiguredException(CONFIG_SECTION + " section");
+    }
+    return authenticationConfig;
+  }
+
+  private boolean verifyCredentials (BasicAuthConfig basicAuthConfig, String credential) {
+    String decodedCredentials = new String(Base64.getDecoder().decode(credential));
+    int p = decodedCredentials.indexOf(':');
+    if (p != -1) {
+      String userName = decodedCredentials.substring(0, p).trim();
+      String password = decodedCredentials.substring(p + 1).trim();
+      if (!userName.equals(basicAuthConfig.getUserName()) || !password.equals(basicAuthConfig.getUserPass())) {
+        log.error("Authentication failed. Invalid user name or password");
+        return false;
+      }
+      return true;
+    } else {
+      log.error("Failed to decode credentials");
+      return false;
+    }
+  }
+}
index 1e41ed2..09d2fb1 100644 (file)
         <filter-name>RestrictionAccessFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
-
+    <filter>
+        <filter-name>BasicAuth</filter-name>
+        <filter-class>org.openecomp.server.filters.BasicAuthenticationFilter</filter-class>
+    </filter>
     <filter>
         <filter-name>AuthN</filter-name>
         <filter-class>org.openecomp.server.filters.ActionAuthenticationFilter</filter-class>
         <filter-name>cross-origin</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
+    <filter-mapping>
+        <filter-name>BasicAuth</filter-name>
+        <url-pattern>/1.0/*</url-pattern>
+    </filter-mapping>
     <filter-mapping>
         <filter-name>AuthN</filter-name>
         <url-pattern>/workflow/v1.0/actions/*</url-pattern>
index 077b70d..2018a83 100644 (file)
@@ -20,6 +20,12 @@ default['cassandra']['socket_read_timeout'] = 20000
 default['cassandra']['socket_connect_timeout'] = 20000
 default['cassandra']['janusgraph_connection_timeout'] = 10000
 
+#Basicauth
+default['basic_auth']['enabled'] = false
+default['basic_auth'][:user_name] = "userName"
+default['basic_auth'][:user_pass] = "userPass"
+default['basic_auth']['excludedUrls'] = ""
+
 #ExternalTesting
 default['EXTTEST']['ep1_config'] = "vtp,VTP,true,http://refrepo:8702/onapapi/vnfsdk-marketplace,onap.*"
 default['EXTTEST']['ep2_config'] = "repository,Repository,false,,.*"
index 80fc57e..d767ddd 100644 (file)
@@ -17,6 +17,9 @@ template "onboard-be-config" do
       :cassandra_usr                   => node['cassandra'][:cassandra_user],
       :cassandra_truststore_password   => node['cassandra'][:truststore_password],
       :cassandra_ssl_enabled           => "#{ENV['cassandra_ssl_enabled']}",
+      :basic_auth_enabled              => node['basic_auth']['enabled'],
+      :basic_auth_username             => node['basic_auth'][:user_name],
+      :basic_auth_password             => node['basic_auth'][:user_pass],
       :catalog_notification_url        => node['ONBOARDING_BE']['catalog_notification_url'],
       :catalog_be_http_port            => node['BE'][:http_port],
       :catalog_be_ssl_port             => node['BE'][:https_port],
index d73799f..54d01a2 100644 (file)
@@ -43,4 +43,10 @@ authCookie:
   # redirect variable name from portal.properties file
   redirectURL: "redirect_url"
   excludedUrls: ['/.*']
-  onboardingExcludedUrls: ['/.*']
\ No newline at end of file
+  onboardingExcludedUrls: ['/.*']
+
+basicAuth:
+  enabled: <%= @basic_auth_enabled %>
+  userName: <%= @basic_auth_username %>
+  userPass: <%= @basic_auth_password %>
+  excludedUrls: ""
\ No newline at end of file