Define auditor aware principal (#2654)

Allowing for cusomising auditor by extenders

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-09-05 16:07:46 +03:00
committed by GitHub
parent 1f71e01318
commit c31e5b1265
3 changed files with 21 additions and 10 deletions

View File

@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware.AuditorAwarePrincipal;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@@ -140,11 +141,11 @@ public interface SecurityContextSerializer {
@Serial
private static final long serialVersionUID = 1L;
private String principal;
private String[] authorities;
private boolean authenticated;
private String tenant;
private boolean controller;
private String auditor;
private String[] authorities;
private boolean authenticated;
SecCtxInfo(final SecurityContext securityContext) {
final Authentication authentication = securityContext.getAuthentication();
@@ -158,7 +159,7 @@ public interface SecurityContextSerializer {
// keep the auditor, ofr audit purposes,
// sets principal to the resolved auditor and then deserialized authentication will return it as principal
// since the class is not known to auditor aware - it shall used default - principal as auditor
principal = SpringSecurityAuditorAware.resolveAuditor(authentication);
auditor = SpringSecurityAuditorAware.resolveAuditor(authentication);
authorities = authentication.getAuthorities().stream().map(Object::toString).toArray(String[]::new);
authenticated = authentication.isAuthenticated();
}
@@ -166,6 +167,7 @@ public interface SecurityContextSerializer {
private SecurityContext toSecurityContext() {
final SecurityContext ctx = SecurityContextHolder.createEmptyContext();
final Object details = tenant == null ? null : new TenantAwareAuthenticationDetails(tenant, controller);
final AuditorAwarePrincipal principal = () -> auditor;
final Collection<? extends GrantedAuthority> grantedAuthorities =
Stream.of(authorities).map(SimpleGrantedAuthority::new).toList();
ctx.setAuthentication(new Authentication() {
@@ -202,7 +204,7 @@ public interface SecurityContextSerializer {
@Override
public String getName() {
return principal;
return auditor;
}
});
return ctx;

View File

@@ -63,16 +63,25 @@ public class SpringSecurityAuditorAware implements AuditorAware<String> {
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails && tenantAwareDetails.controller()) {
return "CONTROLLER_PLUG_AND_PLAY";
}
if (authentication.getPrincipal() instanceof UserDetails userDetails) {
final Object principal = authentication.getPrincipal();
if (principal instanceof AuditorAwarePrincipal auditorAwarePrincipal) {
return auditorAwarePrincipal.getAuditor();
}
if (principal instanceof UserDetails userDetails) {
return userDetails.getUsername();
}
if (authentication.getPrincipal() instanceof OidcUser oidcUser) {
if (principal instanceof OidcUser oidcUser) {
return oidcUser.getPreferredUsername();
}
return authentication.getPrincipal().toString();
return principal.toString();
}
private static boolean isAuthenticationInvalid(final Authentication authentication) {
return authentication == null || !authentication.isAuthenticated() || authentication.getPrincipal() == null;
}
public interface AuditorAwarePrincipal {
String getAuditor();
}
}

View File

@@ -42,7 +42,7 @@ class SecurityContextSerializerTest {
final String serialized = JSON_SERIALIZATION.serialize(securityContext);
final SecurityContext deserialized = JSON_SERIALIZATION.deserialize(serialized);
final Authentication authentication = deserialized.getAuthentication();
assertThat(authentication.getPrincipal()).hasToString("user");
assertThat(SpringSecurityAuditorAware.resolveAuditor(authentication)).hasToString("user");
assertThat(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).toList()).isEqualTo(AUTHORITIES);
assertThat(authentication.isAuthenticated()).isTrue();
assertThat(authentication.getDetails()).isEqualTo(details);
@@ -76,7 +76,7 @@ class SecurityContextSerializerTest {
assertThat(oldSerialized).isNotEqualTo(newSerialized);
final Authentication deserializedOld = JSON_SERIALIZATION.deserialize(oldSerialized).getAuthentication();
final Authentication deserializedNew = JSON_SERIALIZATION.deserialize(newSerialized).getAuthentication();
assertThat(deserializedOld.getPrincipal()).hasToString(deserializedNew.getPrincipal().toString());
assertThat(SpringSecurityAuditorAware.resolveAuditor(deserializedOld)).hasToString(SpringSecurityAuditorAware.resolveAuditor(deserializedNew));
assertThat(deserializedOld.getAuthorities()).isEqualTo(deserializedNew.getAuthorities());
assertThat(deserializedOld.isAuthenticated()).isEqualTo(deserializedNew.isAuthenticated());
}