From 2b1bd95e754df058a05ec784a5d240fe6f47ae3e Mon Sep 17 00:00:00 2001 From: Joze RIHTARSIC <joze.rihtarsic@ext.ec.europa.eu> Date: Thu, 11 Oct 2018 09:36:59 +0200 Subject: [PATCH] - update the authentication to fix the bamboo plans --- .../eu/europa/ec/edelivery/smp/SMPRole.java | 26 ---------- .../conversion/CaseSensitivityNormalizer.java | 6 ++- .../ec/edelivery/smp/data/dao/UserDao.java | 21 -------- .../data/dao/utils/SMPSchemaGenerator.java | 4 +- .../smp/data/model/DBUserAuthority.java | 41 --------------- .../smp/services/ServiceGroupService.java | 14 ++++- .../edelivery/smp/testutil/SignatureUtil.java | 1 - .../mysql-4.1_integration_test_data.sql | 51 +++++++++++++++++++ .../SMPAuthenticationProvider.java | 33 +++++------- .../ec/edelivery/smp/auth/SMPAuthority.java | 24 +++++++++ .../europa/ec/edelivery/smp/auth/SMPRole.java | 23 +++++++++ .../controllers/ServiceGroupController.java | 9 ++-- .../ServiceMetadataController.java | 12 +++-- .../src/main/resources/spring-security.xml | 17 +++++-- .../security/SecurityConfigurationTest.java | 7 --- .../smp/server/security/SignatureUtil.java | 1 - .../security/SignatureValidatorTest.java | 2 +- .../webapp_integration_test_data.sql | 18 ++++--- 18 files changed, 169 insertions(+), 141 deletions(-) delete mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java delete mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java create mode 100644 smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql rename smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/{config => auth}/SMPAuthenticationProvider.java (67%) create mode 100644 smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java create mode 100644 smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java deleted file mode 100644 index 0323f1606..000000000 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java +++ /dev/null @@ -1,26 +0,0 @@ -package eu.europa.ec.edelivery.smp; - -public enum SMPRole { - - SMP_ADMIN("ROLE_SMP_ADMIN"), - SERVICE_GROUP_ADMIN("ROLE_SERVICE_GROUP_ADMIN"), - SYSTEM_ADMIN("ROLE_SYSTEM_ADMIN"); - - // static constants for annotations! - public static final String S_ROLE_SYSTEM_ADMIN = "ROLE_SYSTEM_ADMIN"; - public static final String S_ROLE_SMP_ADMIN = "ROLE_SMP_ADMIN"; - public static final String S_ROLE_SERVICE_GROUP_ADMIN = "ROLE_SERVICE_GROUP_ADMIN"; - - - String code; - SMPRole(String code){ - this.code = code; - } - - public String getCode() { - return code; - } - - - -} diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java index 9fa25c8e5..b66ba56f8 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java @@ -66,7 +66,11 @@ public class CaseSensitivityNormalizer { } public String normalizeParticipantId(String participantId) { - return asString(normalize(asParticipantId(participantId))); + return asString(normalizeParticipant(participantId)); + } + + public ParticipantIdentifierType normalizeParticipant(String participantId) { + return normalize(asParticipantId(participantId)); } private static void toLowerCaseStringList(List<String> strings) { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java index 4c1857331..ac81494b6 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java @@ -14,18 +14,14 @@ package eu.europa.ec.edelivery.smp.data.dao; import eu.europa.ec.edelivery.smp.data.model.DBUser; -import eu.europa.ec.edelivery.smp.data.model.DBUserAuthority; import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import org.apache.commons.lang3.StringUtils; -import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Repository; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import javax.persistence.TypedQuery; import javax.transaction.Transactional; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_CERT_ID_MULTIPLE_ENTRY; @@ -38,23 +34,6 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_USER public class UserDao extends BaseDao<DBUser> { - public List<GrantedAuthority> getUserRoles(String username) { - - List<GrantedAuthority> lstRes = new ArrayList<>(); - // all users are SERVICEGROUP_ADMIN - lstRes.add(DBUserAuthority.S_ROLE_SERVICEGROUP_ADMIN); - - List<DBUserAuthority> lst = memEManager - .createNamedQuery("DBUserAuthority.getRolesForUsernameNativeQuery") - .setParameter( "username",username) - .getResultList(); - - if (!lst.isEmpty()){ - lstRes.addAll(lst); - } - System.out.println("Got roles: " + lstRes.size() + " " + lstRes); - return lstRes; - } /** * Perstis user to database. Before that test if user has identifiers diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java index fed2435ca..45cb6a335 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java @@ -127,7 +127,6 @@ public class SMPSchemaGenerator { try { directory = new File(Thread.currentThread().getContextClassLoader().getResource(pckgname.replace('.', '/')).getFile()); } catch (NullPointerException x) { - System.out.println("Nullpointer"); throw new ClassNotFoundException(pckgname + " does not appear to be a valid package"); } if (directory.exists()) { @@ -139,8 +138,7 @@ public class SMPSchemaGenerator { classes.add(Class.forName(pckgname + '.' + files[i].substring(0, files[i].length() - 6))); } } - } else { - System.out.println("Directory does not exist"); + } else { ; throw new ClassNotFoundException("Package: "+pckgname + " does not eixsts!"); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java deleted file mode 100644 index e87210342..000000000 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java +++ /dev/null @@ -1,41 +0,0 @@ -package eu.europa.ec.edelivery.smp.data.model; - -import org.springframework.security.core.GrantedAuthority; - -import javax.persistence.*; - -@NamedNativeQueries({ - @NamedNativeQuery( - name = "DBUserAuthority.getRolesForUsernameNativeQuery", - query = "SELECT 'SMP_ADMIN' AS AUTHORITY FROM smp_user WHERE isadmin = 1 and username=:username " + - "UNION ALL " + - "SELECT CONCAT(businessIdentifierScheme, CONCAT('::', businessIdentifier)) AS AUTHORITY FROM smp_ownership WHERE username=:username", - resultSetMapping = "RoleDTO" - )}) - -@SqlResultSetMapping( - name = "RoleDTO", - classes = @ConstructorResult - ( - targetClass = DBUserAuthority.class, - columns = { - @ColumnResult(name = "authority", type = String.class) - } - ) -) -public class DBUserAuthority implements GrantedAuthority { - - public static DBUserAuthority S_ROLE_SERVICEGROUP_ADMIN = new DBUserAuthority("ROLE_SERVICEGROUP_ADMIN"); - - - public DBUserAuthority(String authority) { - this.authority = authority; - } - - String authority; - - @Override - public String getAuthority() { - return authority; - } -} diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java index e5be6f258..ca7ab211c 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java @@ -102,7 +102,6 @@ public class ServiceGroupService { LOG.businessDebug(SMPMessageCode.BUS_SAVE_SERVICE_GROUP,domain,normalizedParticipantId.getValue(), normalizedParticipantId.getScheme() ); String newOwnerName = defineGroupOwner(serviceGroupOwner, authenticatedUser); - Optional<DBUser> newOwner = userDao.findUserByIdentifier(newOwnerName); if (!newOwner.isPresent()) { SMPRuntimeException ex = new SMPRuntimeException(USER_NOT_EXISTS); @@ -193,6 +192,19 @@ public class ServiceGroupService { } } + /** + * Method validates if user owner with identifier is owner of servicegroup + * @param ownerIdentifier + * @param dbsg + */ + @Transactional + public boolean isServiceGroupOwner(String ownerIdentifier, String serviceGroupIdentifier ){ + ParticipantIdentifierType pt = caseSensitivityNormalizer.normalizeParticipant(serviceGroupIdentifier); + Optional<DBServiceGroup> osg = serviceGroupDao.findServiceGroup(pt.getValue(), pt.getScheme()); + Optional<DBUser> own = userDao.findUserByIdentifier(ownerIdentifier); + return osg.isPresent() && own.isPresent() && osg.get().getUsers().contains(own.get()); + } + @Transactional public void deleteServiceGroup(ParticipantIdentifierType serviceGroupId) { diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java index ec64ae795..45021d040 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java @@ -177,7 +177,6 @@ public class SignatureUtil { // Marshalling and parsing the document - signature validation fails without this stinky "magic". // _Probably_ SUN's implementation doesn't import correctly signatures between two different documents. String strUnwrapped = marshall(docUnwrapped); - System.out.println(strUnwrapped); return parseDocument(strUnwrapped); } diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql new file mode 100644 index 000000000..5b6e51ab8 --- /dev/null +++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql @@ -0,0 +1,51 @@ +-- Copyright 2018 European Commission | CEF eDelivery +-- +-- Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence"); +-- You may not use this work except in compliance with the Licence. +-- +-- You may obtain a copy of the Licence attached in file: LICENCE-EUPL-v1.2.pdf +-- +-- Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu', 'SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'the_admin', '', 'SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO', 'SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi', 'SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (5, 'test', '', 'SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (6, 'test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy', 'SMP_ADMIN', 1); + + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (10, 'EHEALTH_SMP_EC', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (10, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (11, 'EHEALTH_ż_ẞ_Ẅ_,O', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (11, 'CN=EHEALTH_ż_ẞ_Ẅ_,O=European_ż_ẞ_Ẅ_Commission,C=BE:f71ee8b11cb3b787', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (12, 'EHEALTH_SMP_1000000007', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (12, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (13, 'EHEALTH_SMP_EC1', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (13, 'CN=EHEALTH_SMP_EC/emailAddress\=CEF-EDELIVERY-SUPPORT@ec.europa.eu,O=European Commission,C=BE:f71ee8b11cb3b787', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (14, 'EHEALTH_SMP_1000000007', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (14, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (15, 'EHEALTH&SMP_EC', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (15, 'CN=EHEALTH&SMP_EC,O=European&Commission,C=B&E:f71ee8b11cb3b787', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (16, 'EHEALTH_SMP_EC2', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (16, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:000000000000100f', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (17, 'SMP_1000000007', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (17, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (18, 'SMP_1000000007', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (18, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null); + +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (19, 'SMP_1000000181,O=DIGIT,C=DK:123456789', '$2a$10$v2d/2E99dWHBM2ipTIip1enyaRKBTi.Xj/Iz0K8g0gjHBWdKRsHaC', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (19, 'CN=SMP_1000000181,O=DIGIT,C=DK:123456789', null,null); + +-- insert domain +insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SIGNATURE_KEY_ALIAS) values (1, 'domain','subdomain','sig-key'); + diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java similarity index 67% rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java index f752e546f..dda846c4a 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java @@ -1,4 +1,4 @@ -package eu.europa.ec.edelivery.smp.config; +package eu.europa.ec.edelivery.smp.auth; import eu.europa.ec.edelivery.smp.data.dao.UserDao; import eu.europa.ec.edelivery.smp.data.model.DBUser; @@ -8,12 +8,10 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCrypt; import java.util.Collections; -import java.util.List; +import java.util.Optional; public class SMPAuthenticationProvider implements AuthenticationProvider { @@ -30,29 +28,22 @@ public class SMPAuthenticationProvider implements AuthenticationProvider { String username = auth.getName(); String password = auth.getCredentials().toString(); - DBUser usr = mUserDao.find(username); - System.out.println("GOT user " +username + " username " + usr ); - if (usr == null){ + Optional<DBUser> oUsr = mUserDao.findUserByIdentifier(username); + if (!oUsr.isPresent()){ //https://www.owasp.org/index.php/Authentication_Cheat_Sheet // Do not reveal the status of an existing account. Not to use UsernameNotFoundException throw new BadCredentialsException("Login failed; Invalid userID or password"); } - System.out.println("Check print"); - if (!BCrypt.checkpw(password, usr.getPassword())) { - throw new BadCredentialsException("Login failed; Invalid userID or password"); - } - System.out.println("get roles"); - List<GrantedAuthority> roles ; + DBUser usr = oUsr.get(); try { - roles = mUserDao.getUserRoles(username); - - }catch (Exception ex) { - ex.printStackTrace(System.out); - return null; + if (!BCrypt.checkpw(password, usr.getPassword())) { + throw new BadCredentialsException("Login failed; Invalid userID or password"); + } + }catch (java.lang.IllegalArgumentException ex){ + // password is not hashed + throw new BadCredentialsException("Login failed; Invalid userID or password"); } - - System.out.println("Got roles: " + roles.size() + " " + roles); - return new UsernamePasswordAuthenticationToken(username, password,roles); + return new UsernamePasswordAuthenticationToken(username, password,Collections.singletonList(new SMPAuthority(usr.getRole()))); } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java new file mode 100644 index 000000000..8a64b60ec --- /dev/null +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java @@ -0,0 +1,24 @@ +package eu.europa.ec.edelivery.smp.auth; + +import org.springframework.security.core.GrantedAuthority; + + +public class SMPAuthority implements GrantedAuthority { + + // static constants for annotations! + public static final String S_AUTHORITY_SYSTEM_ADMIN = "ROLE_SYSTEM_ADMIN"; + public static final String S_AUTHORITY_SMP_ADMIN = "ROLE_SMP_ADMIN"; + public static final String S_AUTHORITY_SERVICE_GROUP_ADMIN = "ROLE_SERVICE_GROUP_ADMIN"; + + + String role; + + public SMPAuthority(String role) { + this.role = role; + } + + @Override + public String getAuthority() { + return "ROLE_"+role; + } +} diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java new file mode 100644 index 000000000..12d1d4e27 --- /dev/null +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java @@ -0,0 +1,23 @@ +package eu.europa.ec.edelivery.smp.auth; + +public enum SMPRole { + + SMP_ADMIN("SMP_ADMIN"), + SERVICE_GROUP_ADMIN("SERVICE_GROUP_ADMIN"), + SYSTEM_ADMIN("SYSTEM_ADMIN"); + + + + + String code; + SMPRole(String code){ + this.code = code; + } + + public String getCode() { + return code; + } + + + +} diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java index 191d410b6..0d114eabd 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java @@ -13,7 +13,7 @@ package eu.europa.ec.edelivery.smp.controllers; -import eu.europa.ec.edelivery.smp.SMPRole; +import eu.europa.ec.edelivery.smp.auth.SMPAuthority; import eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter; import eu.europa.ec.edelivery.smp.services.ServiceGroupService; import eu.europa.ec.edelivery.smp.services.ServiceMetadataService; @@ -34,7 +34,6 @@ import org.springframework.security.access.annotation.Secured; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; -import java.io.UnsupportedEncodingException; import java.util.List; import static eu.europa.ec.smp.api.Identifiers.asParticipantId; @@ -78,14 +77,14 @@ public class ServiceGroupController { @PutMapping - // @Secured({SMPRole.S_ROLE_SMP_ADMIN, SMPRole.S_ROLE_SYSTEM_ADMIN}) + @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN}) public ResponseEntity saveServiceGroup( @PathVariable String serviceGroupId, @RequestHeader(name = "ServiceGroup-Owner", required = false) String serviceGroupOwner, @RequestHeader(name = "Domain", required = false) String domain, @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException { - log.info("PUT ServiceGroup: {} domain {} owner {} \n{}", serviceGroupId,domain, serviceGroupOwner, body); + log.info("PUT ServiceGroup: {} domain {} owner {} \n{}", serviceGroupId,domain, serviceGroupOwner, new String(body)); // Validations BdxSmpOasisValidator.validateXSD(body); @@ -101,7 +100,7 @@ public class ServiceGroupController { } @DeleteMapping - @Secured({SMPRole.S_ROLE_SYSTEM_ADMIN, SMPRole.S_ROLE_SMP_ADMIN}) + @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN}) public void deleteServiceGroup(@PathVariable String serviceGroupId) { log.info("DELETE ServiceGroup: {}", serviceGroupId); diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java index 7e3320773..be71c1191 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java @@ -14,6 +14,7 @@ package eu.europa.ec.edelivery.smp.controllers; import eu.europa.ec.edelivery.smp.conversion.ServiceMetadataConverter; +import eu.europa.ec.edelivery.smp.services.ServiceGroupService; import eu.europa.ec.edelivery.smp.services.ServiceMetadataService; import eu.europa.ec.edelivery.smp.validation.ServiceMetadataValidator; import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException; @@ -48,6 +49,9 @@ public class ServiceMetadataController { @Autowired private ServiceMetadataService serviceMetadataService; + @Autowired + private ServiceGroupService serviceGroupService; + @Autowired private ServiceMetadataPathBuilder pathBuilder; @@ -64,14 +68,15 @@ public class ServiceMetadataController { } @PutMapping - @PreAuthorize("hasAnyAuthority('ROLE_SMP_ADMIN', @caseSensitivityNormalizer.normalizeParticipantId(#serviceGroupId))") + @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" + + " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)") public ResponseEntity saveServiceMetadata( @PathVariable String serviceGroupId, @PathVariable String serviceMetadataId, @RequestHeader(name = "Domain", required = false) String domain, @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException { - log.info("PUT ServiceMetadata: {} - {}\n{}", serviceGroupId, serviceMetadataId, body); + log.info("PUT ServiceMetadata: {} - {}\n{}", serviceGroupId, serviceMetadataId, new String(body)); serviceMetadataValidator.validate(serviceGroupId, serviceMetadataId, body); @@ -83,7 +88,8 @@ public class ServiceMetadataController { } @DeleteMapping - @PreAuthorize("hasAnyAuthority('ROLE_SMP_ADMIN', @caseSensitivityNormalizer.normalizeParticipantId(#serviceGroupId))") + @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" + + " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)") public ResponseEntity deleteServiceMetadata(@PathVariable String serviceGroupId, @PathVariable String serviceMetadataId, @RequestHeader(name = "Domain", required = false) String domain ) { diff --git a/smp-webapp/src/main/resources/spring-security.xml b/smp-webapp/src/main/resources/spring-security.xml index 1c1797de5..9060d3bf6 100644 --- a/smp-webapp/src/main/resources/spring-security.xml +++ b/smp-webapp/src/main/resources/spring-security.xml @@ -36,18 +36,24 @@ <authentication-manager alias="smpAuthenticationManager"> - <authentication-provider> + <!-- authentication-provider> <password-encoder hash="bcrypt"/> <jdbc-user-service id="smpJdbcUserDetailsService" data-source-ref="dataSource" users-by-username-query="SELECT username, COALESCE(PASSWORD, 'dummy'), ACTIVE FROM SMP_USER WHERE USERNAME = ?" authorities-by-username-query="select username, ROLE FROM SMP_USER where USERNAME = ?"/> - </authentication-provider> - + </authentication-provider --> + <authentication-provider ref="smpAuthProvider"/> <authentication-provider ref="preauthAuthProvider"/> </authentication-manager> + <!-- user detail service is used only in preAhtProviders for cert authentication that is why search is only on cert table--> + <jdbc-user-service id="smpJdbcUserDetailsService" + data-source-ref="dataSource" + users-by-username-query="SELECT c.CERTIFICATE_ID AS USERNAME, 'dummy' AS PASWORD, u.ACTIVE FROM SMP_CERTIFICATE c INNER JOIN SMP_USER u ON (u.id = c.id) WHERE c.CERTIFICATE_ID = ?" + authorities-by-username-query="SELECT c.CERTIFICATE_ID AS USERNAME, u.ROLE FROM SMP_CERTIFICATE c INNER JOIN SMP_USER u ON (u.id = c.id) WHERE c.CERTIFICATE_ID = ?"/> + <b:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> <b:property name="preAuthenticatedUserDetailsService"> @@ -75,4 +81,9 @@ <b:property name="allowUrlEncodedSlash" value="${encodedSlashesAllowedInUrl}"/> </b:bean> + <b:bean id="smpAuthProvider" class="eu.europa.ec.edelivery.smp.auth.SMPAuthenticationProvider"> + </b:bean> + + + </b:beans> diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java index 89edba85f..866b17ef5 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java @@ -60,13 +60,6 @@ public class SecurityConfigurationTest { public static final String BLUE_COAT_VALID_HEADER = "sno=66&subject=C=BE,O=org,CN=comon name&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=C=x,O=y,CN=z"; public static final String TEST_USERNAME_BLUE_COAT = "CN=comon name,O=org,C=BE:0000000000000066"; - //both passwords represent the same value - clear and hashed - /* - private DBUser userHashedPass = createUser(TEST_USERNAME_HASHED_PASS, "$2a$06$k.Q/6anG4Eq/nNTZ0C1UIuAKxpr6ra5oaMkMSrlESIyA5jKEsUdyS"); - private DBUser userClearPass = createUser(TEST_USERNAME_CLEAR_PASS, PASSWORD); - private DBUser userBlueCoat = createUser(TEST_USERNAME_BLUE_COAT, null); - */ - @Autowired private WebApplicationContext context; diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java index 5abf7ac88..f5a91eba1 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java @@ -122,7 +122,6 @@ public class SignatureUtil { InputStream is = ((Reference) i.next()).getDigestInputStream(); // Display the data. byte[] a = IOUtils.readFully(is, 0, true); - System.out.println(new String(a)); } // Check core validation status. diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java index 798157fb9..1d5c4a2e3 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java @@ -74,7 +74,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @Transactional @Rollback(true) @Sql("classpath:/webapp_integration_test_data.sql") -public class SignatureValidatorTest/* extends AbstractTest*/ { +public class SignatureValidatorTest { private static final String C14N_METHOD = CanonicalizationMethod.INCLUSIVE; private static final String PARSER_DISALLOW_DTD_PARSING_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; diff --git a/smp-webapp/src/test/resources/webapp_integration_test_data.sql b/smp-webapp/src/test/resources/webapp_integration_test_data.sql index 9db7a51a9..49116f27d 100644 --- a/smp-webapp/src/test/resources/webapp_integration_test_data.sql +++ b/smp-webapp/src/test/resources/webapp_integration_test_data.sql @@ -8,12 +8,18 @@ -- Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'test_admin', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'ROLE_SMP_ADMIN', 1); -insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'test_user_hashed_pass', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'ROLE_SMP_ADMIN',1); -insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'test_user_clear_pass', 'test123', 'ROLE_SMP_ADMIN',1); -insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'CN=comon name,O=org,C=BE:0000000000000066', '', 'ROLE_SMP_ADMIN', 1); -insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (5, 'CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 'ROLE_SMP_ADMIN', 1); -insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (6, 'CN=utf-8_ż_SMP,O=EC,C=BE:0000000000000666', 'ROLE_SMP_ADMIN', 1); +insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'test_admin', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'SMP_ADMIN', 1); +insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'test_user_hashed_pass', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'SMP_ADMIN',1); +insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'test_user_clear_pass', 'test123', 'SMP_ADMIN',1); +insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'cert1', '', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (4, 'CN=comon name,O=org,C=BE:0000000000000066', null,null); + +insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (5, 'cert2', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (5, 'CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', null,null); + +insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (6, 'Cert2', 'SMP_ADMIN', 1); +insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (6, 'CN=utf-8_ż_SMP,O=EC,C=BE:0000000000000666', null,null); + insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED) values (1, 'urn:australia:ncpb', 'ehealth-actorid-qns', 1); insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED) values (2, 'urn:brazil:ncpb', 'ehealth-actorid-qns', 1); -- GitLab