Skip to content

Commit

Permalink
Complement tests with integration tests calling the broker API.
Browse files Browse the repository at this point in the history
Ensure that there cannot be duplicate instance with same instance name.
  • Loading branch information
pdechamboux committed Feb 14, 2020
1 parent e97a08d commit ca186da
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 122 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ In order to produce your configured service package, do the following:

It produces a jar file which contains the whole code for the service as well as the releases of Matomo to be proposed for service instantiation.

If you want to run unit tests for your configuration, there are three things you not to know or do:
If you want to run unit tests for your configuration, there are three things you need to know or to do:

1. The tests expect that you have configured your service with only one Matomo release.

Expand Down
49 changes: 49 additions & 0 deletions src/main/adminapi/SecurityAuthorities.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright 2020 Orange and the original author or authors.
*
* 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
*
* https://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.
*/
package com.orange.oss.matomocfservice.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

/**
* @author P. Déchamboux
*
*/
@Configuration
public class SecurityAuthorities {
private final static Logger LOGGER = LoggerFactory.getLogger(SecurityAuthorities.class);
public static final String ROLE_ADMIN = "ADMIN";
public static final String ROLE_BROKER_USER = "BROKER_USER";
public static final String ROLE_FULL_ACCESS = "FULL_ACCESS";
public static final String ROLE_READ_ONLY = "READ_ONLY";
@Value("${matomo-service.security.adminName}")
private String adminName;
@Value("${matomo-service.security.adminPassword}")
private String adminPassword;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
LOGGER.debug("CONFIG::security: configureGlobal");
auth.inMemoryAuthentication()
.withUser(adminName)
.password(/*"{noop}" + */adminPassword)
.roles(ROLE_ADMIN, ROLE_BROKER_USER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public ApplicationInformation defaultApplicationInformation() {

@EventListener(ApplicationReadyEvent.class)
public void initializeAfterStartup() {
LOGGER.debug("CONFIG - run initialization code after application startup has completed");
LOGGER.debug("CONFIG::ApplicationConfiguration - run initialization code after application startup has completed");
matomoReleases.initialize();
cfMgr.initialize();
instanceIdMgr.initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
*
*/
@Configuration
public class BrokerApiVersionConfiguration {
public class BrokerConfiguration {

@Bean
public BrokerApiVersion brokerApiVersion() {
return new BrokerApiVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.servicebroker.exception.ServiceInstanceDoesNotExistException;
import org.springframework.cloud.servicebroker.exception.ServiceInstanceExistsException;
import org.springframework.cloud.servicebroker.model.instance.CreateServiceInstanceRequest;
import org.springframework.cloud.servicebroker.model.instance.CreateServiceInstanceResponse;
import org.springframework.cloud.servicebroker.model.instance.DeleteServiceInstanceRequest;
Expand Down Expand Up @@ -80,6 +79,7 @@ private String getPlatformId(String platformId) {
public Mono<CreateServiceInstanceResponse> createServiceInstance(CreateServiceInstanceRequest request) {
LOGGER.debug("BROKER::createServiceInstance: platformId={}, serviceId={}", request.getPlatformInstanceId(), request.getServiceInstanceId());
LOGGER.debug("BROKER:: platform={}, serviceDefId={}", request.getContext().getPlatform(), request.getServiceDefinitionId());
LOGGER.debug("REQUEST={}", request);
PMatomoInstance.PlatformKind pfkind;
String instname;
switch (request.getContext().getPlatform()) {
Expand All @@ -92,6 +92,7 @@ public Mono<CreateServiceInstanceResponse> createServiceInstance(CreateServiceIn
pfkind = PMatomoInstance.PlatformKind.OTHER;
instname = "";
}
LOGGER.debug("BROKER:: instanceName={}", instname);
String errmsg = miServ.createMatomoInstance(
request.getServiceInstanceId(),
instname,
Expand Down Expand Up @@ -166,15 +167,6 @@ public Mono<DeleteServiceInstanceResponse> deleteServiceInstance(DeleteServiceIn
@Override
public Mono<UpdateServiceInstanceResponse> updateServiceInstance(UpdateServiceInstanceRequest request) {
LOGGER.debug("BROKER::updateServiceInstance: platformId={}, instanceId={}", request.getPlatformInstanceId(), request.getServiceInstanceId());
String instn;
switch (request.getContext().getPlatform()) {
case "cloudfoundry":
instn = (String)request.getContext().getProperty("instance_name");
break;
default:
LOGGER.warn("BROKER:: unknown kind of platform -> " + request.getContext().getPlatform());
instn = "";
}
String emsg = miServ.updateMatomoInstance(
request.getServiceInstanceId(),
getPlatformId(request.getPlatformInstanceId()),
Expand Down Expand Up @@ -219,7 +211,7 @@ private String getVersion(Map<String, Object> parameters) {
instversion = matomoReleases.getLatestReleaseName();
} else if (! matomoReleases.isVersionAvailable(instversion)) {
LOGGER.warn("SERV::getVersion: version {} is not supported -> switch to default one.", instversion);
throw new RuntimeException("Version <" + instversion + "> is not supported by this Matomo CF Service!!");
instversion = matomoReleases.getDefaultReleaseName();
}
LOGGER.debug("SERV::getVersion: {}", instversion);
return instversion;
Expand Down Expand Up @@ -254,13 +246,16 @@ private int getInstances(Map<String, Object> parameters, String planid) {
if (planid.equals(ServiceCatalogConfiguration.PLANMATOMOSHARDB_UUID)) {
instances = CLUSTERSIZE_DEFAULT;
} else {
instances = (Integer) parameters.get(PARAM_INSTANCES);
if (instances == null) {
instances = CLUSTERSIZE_DEFAULT;
} else if (instances < CLUSTERSIZE_DEFAULT) {
String sinstances = (String) parameters.get(PARAM_INSTANCES);
if (sinstances == null) {
instances = CLUSTERSIZE_DEFAULT;
} else if (instances > MAX_INSTANCES) {
instances = MAX_INSTANCES;
} else {
instances = Integer.decode(sinstances);
if (instances < CLUSTERSIZE_DEFAULT) {
instances = CLUSTERSIZE_DEFAULT;
} else if (instances > MAX_INSTANCES) {
instances = MAX_INSTANCES;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
@Repository
public interface PMatomoInstanceRepository extends JpaRepository<PMatomoInstance, String> {
Optional<PMatomoInstance> findByUuid(String id);
Optional<PMatomoInstance> findByName(String name);
List<PMatomoInstance> findByPlatform(PPlatform pf);
List<PMatomoInstance> findByPlatformAndLastOperation(PPlatform pf, String lastop);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,8 @@

package com.orange.oss.matomocfservice.web.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;

/**
Expand All @@ -34,13 +27,30 @@
public class McfsAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
private final static Logger LOGGER = LoggerFactory.getLogger(McfsAuthenticationEntryPoint.class);

@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
LOGGER.debug("SECU:: authent entry point");
response.sendRedirect(request.getContextPath() + "/login");
}
// @Override
// public void commence(HttpServletRequest request,
// HttpServletResponse response,
// AuthenticationException authException) throws IOException, ServletException {
// LOGGER.debug("SECU:: authent entry point: {}", request.toString());
// LOGGER.debug("AuthType: {}", request.getAuthType());
// LOGGER.debug("ContextPath: {}", request.getContextPath());
// LOGGER.debug("CharacterEncoding: {}", request.getCharacterEncoding());
// LOGGER.debug("LocalAddr: {}", request.getLocalAddr());
// LOGGER.debug("LocalName: {}", request.getLocalName());
// LOGGER.debug("LocalPort: {}", request.getLocalPort());
// LOGGER.debug("Method: {}", request.getMethod());
// Enumeration<String> headerNames = request.getHeaderNames();
// while(headerNames.hasMoreElements()) {
// String headerName = headerNames.nextElement();
// LOGGER.debug(" Header Name - {}, Value - {}", headerName, request.getHeader(headerName));
// }
// Enumeration<String> params = request.getParameterNames();
// while(params.hasMoreElements()){
// String paramName = params.nextElement();
// LOGGER.debug(" Parameter Name - {}, Value - {}", paramName, request.getParameter(paramName));
// }
// response.sendRedirect(request.getContextPath() + "/login");
// }

@Override
public void afterPropertiesSet() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import com.orange.oss.matomocfservice.web.security.SecurityConfig.McfsLogoutSuccessHandler;

/**
* @author P. Déchamboux
*
Expand All @@ -48,11 +46,11 @@ protected void configure(HttpSecurity http) throws Exception {
// .anyRequest().hasRole(SecurityConfig.ROLE_ADMIN)
.and().httpBasic()
.realmName(SecurityConfig.REALM_NAME).authenticationEntryPoint(new McfsAuthenticationEntryPoint())
.and().formLogin()
.successHandler(new McfsAuthenticationSuccessHandler(adminSessionTimeout))
.and().logout().permitAll()
.logoutSuccessHandler(new McfsLogoutSuccessHandler())
.invalidateHttpSession(true)
// .and().formLogin()
// .successHandler(new McfsAuthenticationSuccessHandler(adminSessionTimeout))
// .and().logout().permitAll()
// .logoutSuccessHandler(new McfsLogoutSuccessHandler())
// .invalidateHttpSession(true)
.and().csrf().disable();
http.sessionManagement().maximumSessions(SecurityConfig.MAX_SESSIONS).expiredUrl("/login?expired=true");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@

package com.orange.oss.matomocfservice.web.security;

import java.io.IOException;

import javax.annotation.PostConstruct;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -31,8 +26,6 @@
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
* @author P. Déchamboux
Expand Down Expand Up @@ -60,17 +53,17 @@ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
.roles(ROLE_ADMIN);
}

public static class McfsLogoutSuccessHandler implements LogoutSuccessHandler {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
LOGGER.debug("CONFIG::security: logout!!");
// Currently logout success url="/"
response.sendRedirect(request.getContextPath());
}
}
// public static class McfsLogoutSuccessHandler implements LogoutSuccessHandler {
// private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
//
// @Override
// public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
// Authentication authentication) throws IOException, ServletException {
// LOGGER.debug("CONFIG::security: logout!!");
// // Currently logout success url="/"
// response.sendRedirect(request.getContextPath());
// }
// }

@PostConstruct
public void afterInitialize() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
@Service
public class MatomoInstanceService extends OperationStatusService {
private final static Logger LOGGER = LoggerFactory.getLogger(MatomoInstanceService.class);
private final static String NOTINSTALLED = "NOT_INST";
@Autowired
private PMatomoInstanceRepository miRepo;
@Autowired
Expand Down Expand Up @@ -119,12 +118,10 @@ public String getInstanceUrl(String mi_uuid) {
public String createMatomoInstance(String uuid, String instname, PlatformKind pfkind, String apiinfolocation,
String planid, String pfid, Parameters parameters) {
Assert.notNull(uuid, "instance uuid mustn't be null");
Assert.notNull(instname, "instance name mustn't be null");
Assert.notNull(pfkind, "platform kind mustn't be null");
Assert.notNull(planid, "planid mustn't be null");
Assert.notNull(parameters, "parameters mustn't be null");
if (instname == null) {
instname = "none";
}
if (apiinfolocation == null) {
apiinfolocation = "";
}
Expand All @@ -134,23 +131,30 @@ public String createMatomoInstance(String uuid, String instname, PlatformKind pf
LOGGER.error("Cannot create any kind of instance: service unavailable (retry later on)");
return "Cannot create any kind of instance: service unavailable (retry later on)";
}
EntityManager em = beginTx();
PMatomoInstance pmi;
try {
if (getMatomoInstance(uuid, pfid) != null) {
LOGGER.error("Matomo Instance with ID=" + uuid + " already exists in Platform with ID=" + pfid);
return "Matomo Instance with ID=" + uuid + " already exists in Platform with ID=" + pfid;
synchronized (this) {
EntityManager em = beginTx();
try {
if (getMatomoInstance(uuid, pfid) != null) {
LOGGER.error("Matomo Instance with ID=" + uuid + " already exists in Platform with ID=" + pfid);
return "Matomo Instance with ID=" + uuid + " already exists in Platform with ID=" + pfid;
}
if (miRepo.findByName(instname).isPresent()) {
LOGGER.error(
"Matomo Instance with name=" + instname + " already exists in Platform with ID=" + pfid);
return "Matomo Instance with name=" + instname + " already exists in Platform with ID=" + pfid;
}
PPlatform ppf = getPPlatform(pfid);
pmi = new PMatomoInstance(uuid, instanceIdMgr.allocateInstanceId(), instname, pfkind, apiinfolocation,
planid, ppf, parameters);
savePMatomoInstance(pmi, OperationState.IN_PROGRESS);
} catch (Exception e) {
return "Error while initializing creation: " + e.getMessage();
} finally {
commitTx(em);
}
PPlatform ppf = getPPlatform(pfid);
pmi = new PMatomoInstance(uuid, instanceIdMgr.allocateInstanceId(), instname, pfkind,
apiinfolocation, planid, ppf, parameters);
savePMatomoInstance(pmi, OperationState.IN_PROGRESS);
matomoReleases.createLinkedTree(parameters.getVersion(), pmi.getIdUrlStr());
} catch (Exception e) {
return "Error while initializing creation: " + e.getMessage();
} finally {
commitTx(em);
}
matomoReleases.createLinkedTree(parameters.getVersion(), pmi.getIdUrlStr());
Mono<Void> createdb = (properties.getDbCreds(planid).isDedicatedDb())
? cfMgr.createDedicatedDb(pmi.getIdUrlStr(), planid)
: Mono.empty();
Expand Down Expand Up @@ -245,16 +249,11 @@ public String deleteMatomoInstance(String uuid, String platformId) {
}
pmi.setLastOperation(POperationStatus.OpCode.DELETE_SERVICE_INSTANCE);
savePMatomoInstance(pmi, OperationState.IN_PROGRESS);
if (pmi.getInstalledVersion().equals(NOTINSTALLED)) {
savePMatomoInstance(pmi, OperationState.SUCCEEDED);
instanceIdMgr.freeInstanceId(pmi.getIdUrl());
pmi.setConfigFileContent(null);
return "Nothing to delete for instance with ID=" + pmi.getUuid();
}
// delete data associated with the instance under deletion
cfMgr.deleteAssociatedDbSchema(pmi);
} catch (Exception e) {
throw e;
LOGGER.warn("SERV::deleteMatomoInstance: KO -> Exception: " + e.getMessage());
return null;
} finally {
commitTx(em);
}
Expand Down Expand Up @@ -328,11 +327,6 @@ public String updateMatomoInstance(String uuid, String pfid, Parameters paramete
}
pmi.setLastOperation(POperationStatus.OpCode.UPDATE_SERVICE_INSTANCE);
savePMatomoInstance(pmi, OperationState.IN_PROGRESS);
if (pmi.getInstalledVersion().equals(NOTINSTALLED)) {
LOGGER.warn("Nothing to update (not installed) for instance with ID=" + pmi.getUuid());
savePMatomoInstance(pmi, OperationState.SUCCEEDED).getUuid();
return null;
}
if (pmi.getAutomaticVersionUpgrade() != parameters.isAutoVersionUpgrade()) {
pmi.setAutomaticVersionUpgrade(parameters.isAutoVersionUpgrade());
savePMatomoInstance(pmi, null);
Expand Down Expand Up @@ -362,7 +356,7 @@ public String updateMatomoInstance(String uuid, String pfid, Parameters paramete
savePMatomoInstance(pmi, null);
}
} catch (Exception e) {
return "";
return "KO -> Exception: " + e.getMessage();
} finally {
commitTx(em);
}
Expand Down
Loading

0 comments on commit ca186da

Please sign in to comment.