Add support for "username" to be set as auditor (#2661)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -21,6 +21,8 @@ import java.util.Collection;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
@@ -28,6 +30,7 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware.AuditorAwarePrincipal;
|
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware.AuditorAwarePrincipal;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAwareUser;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
@@ -103,7 +106,7 @@ public interface SecurityContextSerializer {
|
|||||||
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
private static final boolean FALLBACK_TO_JAVA_SERIALIZATION =
|
private static final boolean FALLBACK_TO_JAVA_SERIALIZATION =
|
||||||
!Boolean.getBoolean("hawkbit.security.contextSerializer.json.no-fallback-to-java");
|
!Boolean.getBoolean("org.hawkbit.security.contextSerializer.json.no-fallback-to-java");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String serialize(final SecurityContext securityContext) {
|
public String serialize(final SecurityContext securityContext) {
|
||||||
@@ -143,8 +146,11 @@ public interface SecurityContextSerializer {
|
|||||||
|
|
||||||
private String tenant;
|
private String tenant;
|
||||||
private boolean controller;
|
private boolean controller;
|
||||||
|
// auditor / username (authentication principal name)
|
||||||
private String auditor;
|
private String auditor;
|
||||||
|
@JsonProperty(required = true)
|
||||||
private String[] authorities;
|
private String[] authorities;
|
||||||
|
@JsonProperty(defaultValue = "true")
|
||||||
private boolean authenticated;
|
private boolean authenticated;
|
||||||
|
|
||||||
SecCtxInfo(final SecurityContext securityContext) {
|
SecCtxInfo(final SecurityContext securityContext) {
|
||||||
@@ -152,10 +158,10 @@ public interface SecurityContextSerializer {
|
|||||||
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails) {
|
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails) {
|
||||||
tenant = tenantAwareDetails.tenant();
|
tenant = tenantAwareDetails.tenant();
|
||||||
controller = tenantAwareDetails.controller();
|
controller = tenantAwareDetails.controller();
|
||||||
} else {
|
} else if (authentication.getPrincipal() instanceof TenantAwareUser tenantAwareUser) {
|
||||||
tenant = null;
|
tenant = tenantAwareUser.getTenant();
|
||||||
controller = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep the auditor, ofr audit purposes,
|
// keep the auditor, ofr audit purposes,
|
||||||
// sets principal to the resolved auditor and then deserialized authentication will return it as principal
|
// 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
|
// since the class is not known to auditor aware - it shall used default - principal as auditor
|
||||||
@@ -164,6 +170,12 @@ public interface SecurityContextSerializer {
|
|||||||
authenticated = authentication.isAuthenticated();
|
authenticated = authentication.isAuthenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allows setting for auditor also as username (so supported auditor/username in json)
|
||||||
|
@JsonSetter("username")
|
||||||
|
private void setUsername(final String username) {
|
||||||
|
this.auditor = username;
|
||||||
|
}
|
||||||
|
|
||||||
private SecurityContext toSecurityContext() {
|
private SecurityContext toSecurityContext() {
|
||||||
final SecurityContext ctx = SecurityContextHolder.createEmptyContext();
|
final SecurityContext ctx = SecurityContextHolder.createEmptyContext();
|
||||||
final Object details = tenant == null ? null : new TenantAwareAuthenticationDetails(tenant, controller);
|
final Object details = tenant == null ? null : new TenantAwareAuthenticationDetails(tenant, controller);
|
||||||
|
|||||||
@@ -81,6 +81,24 @@ class SecurityContextSerializerTest {
|
|||||||
assertThat(deserializedOld.isAuthenticated()).isEqualTo(deserializedNew.isAuthenticated());
|
assertThat(deserializedOld.isAuthenticated()).isEqualTo(deserializedNew.isAuthenticated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUsername() {
|
||||||
|
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||||
|
final UsernamePasswordAuthenticationToken userPassAuthentication = new UsernamePasswordAuthenticationToken(
|
||||||
|
"user", null, AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList());
|
||||||
|
final TenantAwareAuthenticationDetails details = new TenantAwareAuthenticationDetails("my_tenant", false);
|
||||||
|
userPassAuthentication.setDetails(details);
|
||||||
|
securityContext.setAuthentication(userPassAuthentication);
|
||||||
|
|
||||||
|
final String serialized = JSON_SERIALIZATION.serialize(securityContext).replace("auditor", "username");
|
||||||
|
final SecurityContext deserialized = JSON_SERIALIZATION.deserialize(serialized);
|
||||||
|
final Authentication authentication = deserialized.getAuthentication();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
private static String bigString(final int length) {
|
private static String bigString(final int length) {
|
||||||
final StringBuilder sb = new StringBuilder(length);
|
final StringBuilder sb = new StringBuilder(length);
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user