From 27fa75194efcf77c93b645ef7b412668ac3f5d38 Mon Sep 17 00:00:00 2001 From: xuegao Date: Wed, 9 Dec 2020 16:01:22 +0100 Subject: [PATCH] Add basic auth Adding basic auth for SDC apis. Issue-ID: OJSI-90 Signed-off-by: xuegao Change-Id: Ie84e6bab8d8526f7f4d21a36bba52d8fe9abebbb Signed-off-by: xuegao --- .../cookbooks/sdc-catalog-be/attributes/default.rb | 6 + .../recipes/BE_2_setup_configuration.rb | 3 + .../templates/default/BE-configuration.yaml.erb | 6 +- .../sdc/be/filters/BasicAuthenticationFilter.java | 45 +++---- .../src/main/resources/config/configuration.yaml | 6 + catalog-be/src/main/webapp/WEB-INF/web.xml | 18 +++ .../cookbooks/sdc-catalog-fe/attributes/default.rb | 5 + .../recipes/FE_2_setup_configuration.rb | 3 + .../templates/default/FE-configuration.yaml.erb | 5 + .../openecomp/sdc/fe/servlets/FeProxyServlet.java | 23 ++-- .../src/app/ng2/services/authentication.service.ts | 6 +- .../app/services/components/component-service.ts | 6 +- .../app/services/components/resource-service.ts | 4 +- .../src/app/services/components/service-service.ts | 4 +- .../utils/composition-left-palette-service.ts | 12 +- .../src/app/services/configuration-ui-service.ts | 4 +- catalog-ui/src/app/services/data-types-service.ts | 4 +- catalog-ui/src/app/services/ecomp-service.ts | 4 +- catalog-ui/src/app/services/sdc-version-service.ts | 4 +- .../org/openecomp/sdc/be/config/Configuration.java | 49 ++++++++ .../org/openecomp/sdc/fe/config/Configuration.java | 40 +++++++ .../server/filters/BasicAuthenticationFilter.java | 133 +++++++++++++++++++++ .../src/main/webapp/WEB-INF/web.xml | 9 +- .../sdc-onboard-backend/attributes/default.rb | 6 + .../recipes/ON_5_setup_configuration.rb | 3 + .../templates/default/configuration.yaml.erb | 8 +- 26 files changed, 361 insertions(+), 55 deletions(-) create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/BasicAuthenticationFilter.java diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/attributes/default.rb b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/attributes/default.rb index d8c737728d..40411f2041 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/attributes/default.rb +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/attributes/default.rb @@ -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-" diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_2_setup_configuration.rb b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_2_setup_configuration.rb index 2e66e2da98..cdb9f82729 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_2_setup_configuration.rb +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/recipes/BE_2_setup_configuration.rb @@ -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, diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb index 8e62c4fbf6..1e1888e95b 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb @@ -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 %>] diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/filters/BasicAuthenticationFilter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/filters/BasicAuthenticationFilter.java index 8c81464ac5..cc4a11f6d9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/filters/BasicAuthenticationFilter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/filters/BasicAuthenticationFilter.java @@ -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 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 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); - } + } } diff --git a/catalog-be/src/main/resources/config/configuration.yaml b/catalog-be/src/main/resources/config/configuration.yaml index 298862e79f..4042b0192b 100644 --- a/catalog-be/src/main/resources/config/configuration.yaml +++ b/catalog-be/src/main/resources/config/configuration.yaml @@ -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 diff --git a/catalog-be/src/main/webapp/WEB-INF/web.xml b/catalog-be/src/main/webapp/WEB-INF/web.xml index 23a08319ff..ca71eee221 100644 --- a/catalog-be/src/main/webapp/WEB-INF/web.xml +++ b/catalog-be/src/main/webapp/WEB-INF/web.xml @@ -17,6 +17,7 @@ jersey.config.server.provider.classnames 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, @@ -173,6 +174,23 @@ /sdc/* + + diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/attributes/default.rb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/attributes/default.rb index 4d65cf72c5..7f66138f92 100644 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/attributes/default.rb +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/attributes/default.rb @@ -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 diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_2_setup_configuration.rb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_2_setup_configuration.rb index 7de9dbc3d5..640b5b8d77 100644 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_2_setup_configuration.rb +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/recipes/FE_2_setup_configuration.rb @@ -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 diff --git a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/FE-configuration.yaml.erb b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/FE-configuration.yaml.erb index fcdc45ecf4..688bdedb3c 100644 --- a/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/FE-configuration.yaml.erb +++ b/catalog-fe/sdc-frontend/chef-repo/cookbooks/sdc-catalog-fe/templates/default/FE-configuration.yaml.erb @@ -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] -%> diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java index 8f76cb95ab..337a8ae100 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java @@ -21,13 +21,17 @@ 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){ diff --git a/catalog-ui/src/app/ng2/services/authentication.service.ts b/catalog-ui/src/app/ng2/services/authentication.service.ts index 52ca643833..a77770a34e 100644 --- a/catalog-ui/src/app/ng2/services/authentication.service.ts +++ b/catalog-ui/src/app/ng2/services/authentication.service.ts @@ -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; } diff --git a/catalog-ui/src/app/services/components/component-service.ts b/catalog-ui/src/app/services/components/component-service.ts index bece12d4f0..f22562f439 100644 --- a/catalog-ui/src/app/services/components/component-service.ts +++ b/catalog-ui/src/app/services/components/component-service.ts @@ -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.vendorName = "xfr"; component.vendorRelease = "xfr"; diff --git a/catalog-ui/src/app/services/components/resource-service.ts b/catalog-ui/src/app/services/components/resource-service.ts index 3a00da1171..9481736152 100644 --- a/catalog-ui/src/app/services/components/resource-service.ts +++ b/catalog-ui/src/app/services/components/resource-service.ts @@ -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. diff --git a/catalog-ui/src/app/services/components/service-service.ts b/catalog-ui/src/app/services/components/service-service.ts index 6c318bd6d6..25811b2fdf 100644 --- a/catalog-ui/src/app/services/components/service-service.ts +++ b/catalog-ui/src/app/services/components/service-service.ts @@ -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. diff --git a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts index b47c5e019b..4ad403c2c4 100644 --- a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts +++ b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts @@ -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); }); }); diff --git a/catalog-ui/src/app/services/configuration-ui-service.ts b/catalog-ui/src/app/services/configuration-ui-service.ts index 463a974ccc..8f6b485f69 100644 --- a/catalog-ui/src/app/services/configuration-ui-service.ts +++ b/catalog-ui/src/app/services/configuration-ui-service.ts @@ -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. diff --git a/catalog-ui/src/app/services/data-types-service.ts b/catalog-ui/src/app/services/data-types-service.ts index 84fe42e9f3..0237b2f3de 100644 --- a/catalog-ui/src/app/services/data-types-service.ts +++ b/catalog-ui/src/app/services/data-types-service.ts @@ -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. diff --git a/catalog-ui/src/app/services/ecomp-service.ts b/catalog-ui/src/app/services/ecomp-service.ts index c8ed31a0bc..eabf7a16ae 100644 --- a/catalog-ui/src/app/services/ecomp-service.ts +++ b/catalog-ui/src/app/services/ecomp-service.ts @@ -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. diff --git a/catalog-ui/src/app/services/sdc-version-service.ts b/catalog-ui/src/app/services/sdc-version-service.ts index 6ab867e4f4..86cdf23260 100644 --- a/catalog-ui/src/app/services/sdc-version-service.ts +++ b/catalog-ui/src/app/services/sdc-version-service.ts @@ -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. diff --git a/common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java b/common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java index 4ec7a16a5c..4ebacffa0e 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java @@ -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; } diff --git a/common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java b/common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java index b2e58f5766..e437034ea0 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java @@ -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 index 0000000000..c1eef1cd95 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/BasicAuthenticationFilter.java @@ -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 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; + } + } +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml index 1e41ed246c..09d2fb16b4 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml @@ -61,7 +61,10 @@ RestrictionAccessFilter /* - + + BasicAuth + org.openecomp.server.filters.BasicAuthenticationFilter + AuthN org.openecomp.server.filters.ActionAuthenticationFilter @@ -74,6 +77,10 @@ cross-origin /* + + BasicAuth + /1.0/* + AuthN /workflow/v1.0/actions/* diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb index 077b70d2c3..2018a835f2 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb @@ -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,,.*" diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb index 80fc57efcb..d767ddd1c8 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb @@ -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], diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb index d73799fcd3..54d01a2436 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb @@ -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 -- 2.16.6