diff --git a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java index 4d54c2e3ad0bbaee5d719022999b34a735022257..9dc67f2473913fb27836036b62abb8339266cdd4 100644 --- a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java +++ b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java @@ -23,8 +23,9 @@ */ package de.ozgcloud.admin; -import de.ozgcloud.admin.common.user.CurrentUserService; -import de.ozgcloud.admin.common.user.UserRole; +import java.util.ArrayList; +import java.util.List; + import org.springframework.boot.autoconfigure.data.rest.RepositoryRestProperties; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -32,11 +33,10 @@ import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.stereotype.Component; +import de.ozgcloud.admin.common.user.CurrentUserService; +import de.ozgcloud.admin.common.user.UserRole; import lombok.RequiredArgsConstructor; -import java.util.ArrayList; -import java.util.List; - @Component @RequiredArgsConstructor public class RootModelAssembler implements RepresentationModelAssembler<Root, EntityModel<Root>> { @@ -49,15 +49,14 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En @Override public EntityModel<Root> toModel(Root root) { List<Link> links = buildRootModelLinks(); - return EntityModel.of( - root, - links); + return EntityModel.of(root, links); } List<Link> buildRootModelLinks() { List<Link> links = new ArrayList<>(); var rootLinkBuilder = WebMvcLinkBuilder.linkTo(RootController.class); links.add(rootLinkBuilder.withSelfRel()); + if (currentUserService.hasRole(UserRole.ADMIN_ADMIN)) { links.add(buildConfigLink()); } @@ -68,7 +67,6 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En var rootLinkBuilder = WebMvcLinkBuilder.linkTo(RootController.class); return Link.of( rootLinkBuilder.toUriComponentsBuilder().replacePath(restProperties.getBasePath()).toUriString(), - REL_CONFIGURATION - ); + REL_CONFIGURATION); } } diff --git a/src/main/java/de/ozgcloud/admin/security/SecurityConfiguration.java b/src/main/java/de/ozgcloud/admin/security/SecurityConfiguration.java index 5c01f460971563cb4bdb94b88d0af9157db9c3f3..9d8cd455bdd726f2d31207ac96c8740cb4139dbd 100644 --- a/src/main/java/de/ozgcloud/admin/security/SecurityConfiguration.java +++ b/src/main/java/de/ozgcloud/admin/security/SecurityConfiguration.java @@ -23,6 +23,14 @@ */ package de.ozgcloud.admin.security; +import static java.util.stream.Collectors.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; @@ -31,9 +39,15 @@ import org.springframework.security.config.annotation.method.configuration.Enabl import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.core.oidc.StandardClaimNames; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.web.SecurityFilterChain; import de.ozgcloud.admin.common.user.UserRole; +import de.ozgcloud.admin.environment.OAuth2Properties; import lombok.RequiredArgsConstructor; @Configuration @@ -42,14 +56,13 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class SecurityConfiguration { - private final AdminAuthenticationEntryPoint authenticationEntryPoint; - static final String RESOURCE_ACCESS_KEY = "resource_access"; - static final String SIMPLE_GRANT_AUTHORITY_PREFIX = "ROLE_"; - static final String ROLES_KEY = "roles"; + private final AdminAuthenticationEntryPoint authenticationEntryPoint; + private final OAuth2Properties oAuth2Properties; + @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { @@ -61,8 +74,6 @@ public class SecurityConfiguration { http.authorizeHttpRequests(requests -> requests .requestMatchers(HttpMethod.GET, "/api/environment").permitAll() -// .requestMatchers("/api/configuration").hasRole(UserRole.DATENBEAUFTRAGUNG) -// .requestMatchers("/api/configuration/**").hasRole(UserRole.DATENBEAUFTRAGUNG) .requestMatchers("/api/configuration").hasAnyRole(UserRole.ADMIN_ADMIN, UserRole.DATENBEAUFTRAGUNG) .requestMatchers("/api/configuration/**").hasAnyRole(UserRole.ADMIN_ADMIN, UserRole.DATENBEAUFTRAGUNG) .requestMatchers("/api").authenticated() @@ -74,37 +85,46 @@ public class SecurityConfiguration { return http.build(); } - /* - * @Bean JwtAuthenticationConverter jwtAuthenticationConverter() { var - * jwtConverter = new JwtAuthenticationConverter(); - * jwtConverter.setJwtGrantedAuthoritiesConverter( - * this::convertJwtToGrantedAuthorities); - * jwtConverter.setPrincipalClaimName(StandardClaimNames.PREFERRED_USERNAME); - * return jwtConverter; } - */ - /* - * Set<GrantedAuthority> convertJwtToGrantedAuthorities(Jwt jwt) { return - * getRolesFromJwt(jwt) .stream() .map(this::mapRoleStringToGrantedAuthority) - * .collect(toSet()); } - * - * private GrantedAuthority mapRoleStringToGrantedAuthority(String role) { - * return new SimpleGrantedAuthority(SIMPLE_GRANT_AUTHORITY_PREFIX + role); } - * - * List<String> getRolesFromJwt(Jwt jwt) { return - * Optional.ofNullable(jwt.getClaimAsMap(RESOURCE_ACCESS_KEY)) - * .flatMap(resourceAccessMap -> getMap(resourceAccessMap, - * oAuth2Properties.getResource())) .flatMap(adminClientMap -> - * getList(adminClientMap, ROLES_KEY)) .orElse(Collections.emptyList()); } - * - * @SuppressWarnings("unchecked") private Optional<Map<String, Object>> - * getMap(Map<String, Object> map, String mapKey) { return - * Optional.ofNullable(map.get(mapKey)) .filter(Map.class::isInstance) .map(obj - * -> (Map<String, Object>) obj); } - * - * @SuppressWarnings("unchecked") private Optional<List<String>> - * getList(Map<String, Object> map, String mapKey) { return - * Optional.ofNullable(map.get(mapKey)) .filter(List.class::isInstance) .map(obj - * -> (List<String>) obj); } - */ + + // TODO OZG-4954 replace with spring defaults + @Bean + JwtAuthenticationConverter jwtAuthenticationConverter() { + var jwtConverter = new JwtAuthenticationConverter(); + jwtConverter.setJwtGrantedAuthoritiesConverter(this::convertJwtToGrantedAuthorities); + jwtConverter.setPrincipalClaimName(StandardClaimNames.PREFERRED_USERNAME); + return jwtConverter; + } + + Set<GrantedAuthority> convertJwtToGrantedAuthorities(Jwt jwt) { + return getRolesFromJwt(jwt) + .stream() + .map(this::mapRoleStringToGrantedAuthority) + .collect(toSet()); + } + + private GrantedAuthority mapRoleStringToGrantedAuthority(String role) { + return new SimpleGrantedAuthority(SIMPLE_GRANT_AUTHORITY_PREFIX + role); + } + + List<String> getRolesFromJwt(Jwt jwt) { + return Optional.ofNullable(jwt.getClaimAsMap(RESOURCE_ACCESS_KEY)) + .flatMap(resourceAccessMap -> getMap(resourceAccessMap, oAuth2Properties.getResource())) + .flatMap(adminClientMap -> getList(adminClientMap, ROLES_KEY)) + .orElse(Collections.emptyList()); + } + + @SuppressWarnings("unchecked") + private Optional<Map<String, Object>> getMap(Map<String, Object> map, String mapKey) { + return Optional.ofNullable(map.get(mapKey)) + .filter(Map.class::isInstance) + .map(obj -> (Map<String, Object>) obj); + } + + @SuppressWarnings("unchecked") + private Optional<List<String>> getList(Map<String, Object> map, String mapKey) { + return Optional.ofNullable(map.get(mapKey)) + .filter(List.class::isInstance) + .map(obj -> (List<String>) obj); + } }