Fix Sonar findings (#2553)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -36,14 +36,16 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
|
||||
private final TargetManagement targetManagement;
|
||||
private final TenantConfigHelper tenantConfigHelper;
|
||||
|
||||
public MgmtTargetGroupResource(final TargetManagement targetManagement, final SystemSecurityContext systemSecurityContext,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
public MgmtTargetGroupResource(
|
||||
final TargetManagement targetManagement,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final SystemSecurityContext systemSecurityContext) {
|
||||
this.targetManagement = targetManagement;
|
||||
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtTarget>> getAssignedTargets(String group, int pagingOffsetParam, int pagingLimitParam, String sortParam) {
|
||||
public ResponseEntity<PagedList<MgmtTarget>> getAssignedTargets(
|
||||
final String group, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
|
||||
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTargetSortParam(sortParam));
|
||||
|
||||
final Page<Target> targets = targetManagement.findTargetsByGroup(group, false, pageable);
|
||||
@@ -53,7 +55,8 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtTarget>> getAssignedTargetsWithSubgroups(String groupFilter, boolean subgroups, int pagingOffsetParam, int pagingLimitParam, String sortParam) {
|
||||
public ResponseEntity<PagedList<MgmtTarget>> getAssignedTargetsWithSubgroups(
|
||||
final String groupFilter, final boolean subgroups, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
|
||||
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTargetSortParam(sortParam));
|
||||
|
||||
final Page<Target> targets = targetManagement.findTargetsByGroup(groupFilter, subgroups, pageable);
|
||||
@@ -63,31 +66,29 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> assignTargetsToGroup(String group, List<String> controllerIds) {
|
||||
public ResponseEntity<Void> assignTargetsToGroup(final String group, final List<String> controllerIds) {
|
||||
return assignTargets(group, controllerIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> assignTargetsToGroupWithSubgroups(String group, List<String> controllerIds) {
|
||||
public ResponseEntity<Void> assignTargetsToGroupWithSubgroups(final String group, final List<String> controllerIds) {
|
||||
return assignTargets(group, controllerIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> assignTargetsToGroupWithRsql(String group, String rsql) {
|
||||
targetManagement.assignTargetGroupWithRsql(group, rsql);
|
||||
return ResponseEntity.ok().build();
|
||||
public ResponseEntity<Void> assignTargetsToGroupWithRsql(final String group, final String rsql) {
|
||||
return assignTargetsToGroupWithRsql0(group, rsql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> unassignTargetsFromGroup(List<String> controllerIds) {
|
||||
public ResponseEntity<Void> unassignTargetsFromGroup(final List<String> controllerIds) {
|
||||
targetManagement.assignTargetsWithGroup(null, controllerIds);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> unassignTargetsFromGroupByRsql(String rsql) {
|
||||
targetManagement.assignTargetGroupWithRsql(null, rsql);
|
||||
return ResponseEntity.ok().build();
|
||||
public ResponseEntity<Void> unassignTargetsFromGroupByRsql(final String rsql) {
|
||||
return assignTargetsToGroupWithRsql0(null, rsql);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,12 +99,16 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> assignTargetsToGroup(final String group, final String rsql) {
|
||||
targetManagement.assignTargetGroupWithRsql(group, rsql);
|
||||
return ResponseEntity.ok().build();
|
||||
return assignTargetsToGroupWithRsql0(group, rsql);
|
||||
}
|
||||
|
||||
private ResponseEntity<Void> assignTargets(final String group, final List<String> controllerIds) {
|
||||
targetManagement.assignTargetsWithGroup(group, controllerIds);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseEntity<Void> assignTargetsToGroupWithRsql0(final String group, final String rsql) {
|
||||
targetManagement.assignTargetGroupWithRsql(group, rsql);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.im.authentication;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class Hierarchy {
|
||||
|
||||
public static final String DEFAULT =
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -18,7 +22,6 @@ import java.util.concurrent.Callable;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.im.authentication.SpRole;
|
||||
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
|
||||
@@ -166,7 +169,7 @@ public class SystemSecurityContext {
|
||||
* wraps the original authentication object. The wrapped object contains the necessary {@link SpRole#SYSTEM_ROLE}
|
||||
* which is allowed to execute all secured methods.
|
||||
*/
|
||||
@Getter
|
||||
@SuppressWarnings("java:S4275") // java:S4275 - intentionally returns the "hold" objects
|
||||
public static final class SystemCodeAuthentication implements Authentication {
|
||||
|
||||
@Serial
|
||||
@@ -174,14 +177,14 @@ public class SystemSecurityContext {
|
||||
|
||||
private static final List<SimpleGrantedAuthority> AUTHORITIES = List.of(new SimpleGrantedAuthority(SpRole.SYSTEM_ROLE));
|
||||
|
||||
private final Object credentials;
|
||||
private final Object details;
|
||||
private final Object principal;
|
||||
private final Holder credentials;
|
||||
private final Holder details;
|
||||
private final Holder principal;
|
||||
|
||||
private SystemCodeAuthentication(final Authentication oldAuthentication) {
|
||||
credentials = oldAuthentication != null ? oldAuthentication.getCredentials() : null;
|
||||
details = oldAuthentication != null ? oldAuthentication.getDetails() : null;
|
||||
principal = oldAuthentication != null ? oldAuthentication.getPrincipal() : null;
|
||||
credentials = new Holder(oldAuthentication != null ? oldAuthentication.getCredentials() : null);
|
||||
details = new Holder(oldAuthentication != null ? oldAuthentication.getDetails() : null);
|
||||
principal = new Holder(oldAuthentication != null ? oldAuthentication.getPrincipal() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -194,6 +197,21 @@ public class SystemSecurityContext {
|
||||
return AUTHORITIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return credentials.obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDetails() {
|
||||
return details.obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return principal.obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthenticated() {
|
||||
return true;
|
||||
@@ -203,5 +221,28 @@ public class SystemSecurityContext {
|
||||
public void setAuthenticated(final boolean isAuthenticated) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// Serializable wrapper that ensures that the content will be serialized only if it is Serializable
|
||||
private static class Holder implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Object obj;
|
||||
|
||||
private Holder(final Object obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Serial
|
||||
private void writeObject(final ObjectOutputStream oos) throws IOException {
|
||||
oos.writeObject(obj instanceof Serializable ? obj : null);
|
||||
}
|
||||
|
||||
@Serial
|
||||
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
obj = ois.readObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
class SystemCodeAuthenticationTest {
|
||||
|
||||
private static final SystemSecurityContext SYSTEM_SECURITY_CONTEXT = new SystemSecurityContext(new TenantAware() {
|
||||
|
||||
@Override
|
||||
public String getCurrentTenant() {
|
||||
return "tenant";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentUsername() {
|
||||
return "user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T runAsTenant(final String tenant, final TenantRunner<T> tenantRunner) {
|
||||
return tenantRunner.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T runAsTenantAsUser(final String tenant, final String username, final TenantRunner<T> tenantRunner) {
|
||||
return tenantRunner.run();
|
||||
}
|
||||
});
|
||||
|
||||
@Test
|
||||
void testSerializationWithoutNull() {
|
||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||
auth.setDetails("string details");
|
||||
test(auth);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerializationWithNullPrincipal() {
|
||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||
auth.setDetails("string details");
|
||||
test(auth);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerializationWithNullCredentials() {
|
||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||
auth.setDetails("string details");
|
||||
test(auth);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerializationWithNullDetails() {
|
||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||
auth.setDetails(null);
|
||||
test(auth);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerializationWitAllNull() {
|
||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||
auth.setDetails(null);
|
||||
test(auth);
|
||||
}
|
||||
|
||||
private static void test(final UsernamePasswordAuthenticationToken auth) {
|
||||
final SecurityContext sc = SecurityContextHolder.createEmptyContext();
|
||||
sc.setAuthentication(auth);
|
||||
SecurityContextHolder.setContext(sc);
|
||||
SYSTEM_SECURITY_CONTEXT.runAsSystemAsTenant(() -> {
|
||||
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||
Assertions.assertThat(currentAuth.getClass().getSimpleName()).isEqualTo("SystemCodeAuthentication");
|
||||
Assertions.assertThat(currentAuth.getPrincipal()).isEqualTo(auth.getPrincipal());
|
||||
Assertions.assertThat(currentAuth.getCredentials()).isEqualTo(auth.getCredentials());
|
||||
Assertions.assertThat(currentAuth.getAuthorities()).isEqualTo(List.of(new SimpleGrantedAuthority("ROLE_SYSTEM_CODE")));
|
||||
Assertions.assertThat(currentAuth.getDetails()).isEqualTo(auth.getDetails());
|
||||
|
||||
final Authentication serializedAndDeserializedAuth = serializeAndDeserialize(currentAuth);
|
||||
Assertions.assertThat(serializedAndDeserializedAuth.getClass().getSimpleName()).isEqualTo("SystemCodeAuthentication");
|
||||
Assertions.assertThat(serializedAndDeserializedAuth.getPrincipal()).isEqualTo(auth.getPrincipal());
|
||||
Assertions.assertThat(serializedAndDeserializedAuth.getCredentials()).isEqualTo(auth.getCredentials());
|
||||
Assertions.assertThat(serializedAndDeserializedAuth.getAuthorities()).isEqualTo(List.of(new SimpleGrantedAuthority("ROLE_SYSTEM_CODE")));
|
||||
Assertions.assertThat(serializedAndDeserializedAuth.getDetails()).isEqualTo(auth.getDetails());
|
||||
return null;
|
||||
}, "tenant");
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T serializeAndDeserialize(final T object) throws IOException, ClassNotFoundException {
|
||||
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
try (final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
|
||||
oos.writeObject(object);
|
||||
oos.flush();
|
||||
}
|
||||
try (final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
|
||||
return (T) ois.readObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user