Skip to content

Commit

Permalink
Merge pull request #37 from DiSSCo/feature/add-rbac
Browse files Browse the repository at this point in the history
Put create/update/delete behind admin role
  • Loading branch information
samleeflang authored Mar 22, 2024
2 parents 001bd97 + 2401b9d commit 2f930f5
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/.trivyignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Date: Feb 27, 2024
# Notes: Issue with libexpat, parsing large tokens can trigger a denial of service
# Needs to be fixed in Docker Image.
CVE-2023-52425
# Date: March 21, 2024
# Issue: Vulnerability in spring-web
# Solution: Spring boot needs to update its version of spring
CVE-2024-22259

# Date: March 21, 2024
# Issue: Vulnerability in spring-security-core
# Solution: Spring boot needs to update its version of spring
CVE-2024-22257
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import eu.dissco.orchestration.backend.exception.ProcessingFailedException;
import eu.dissco.orchestration.backend.properties.ApplicationProperties;
import eu.dissco.orchestration.backend.service.SourceSystemService;
import freemarker.template.TemplateException;
import io.kubernetes.client.openapi.ApiException;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,39 @@

import jakarta.validation.constraints.NotNull;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.stereotype.Component;

@Component
public class JwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {

private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();

@Override
public AbstractAuthenticationToken convert(@NotNull Jwt jwt) {
Collection<GrantedAuthority> authorities =
converterToStream(jwt).collect(Collectors.toSet());
return new JwtAuthenticationToken(jwt, authorities, getPrincipalClaimName(jwt));
return new JwtAuthenticationToken(jwt, extractRoles(jwt), getPrincipalClaimName(jwt));
}

private Stream<GrantedAuthority> converterToStream(Jwt jwt) {
return Optional.of(jwtGrantedAuthoritiesConverter.convert(jwt)).stream()
.flatMap(Collection::stream);
private Set<GrantedAuthority> extractRoles(Jwt jwt) {
Set<GrantedAuthority> authorities = new HashSet<>();
if (jwt.getClaims().containsKey("resource_access")) {
((Map<String, Object>) jwt.getClaims().get("resource_access")).forEach((k, v) -> {
Map<String, Object> resourceAccess = (Map<String, Object>) v;
resourceAccess.forEach((k1, v1) -> {
if (k1.equals("roles")) {
((Collection<String>) v1).forEach(
role -> authorities.add((GrantedAuthority) () -> "ROLE_" + role));
}
});
});
}
return authorities;
}

private String getPrincipalClaimName(Jwt jwt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
.requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll()
.requestMatchers(HttpMethod.GET, "**").permitAll()
.anyRequest().authenticated());
.requestMatchers(EndpointRequest.to(HealthEndpoint.class))
.permitAll()
.requestMatchers(HttpMethod.GET, "**")
.permitAll()
.anyRequest()
.hasRole("orchestration-admin"));

http.oauth2ResourceServer(jwtoauth2ResourceServer -> jwtoauth2ResourceServer.jwt((
jwt -> jwt.jwtAuthenticationConverter(jwtAuthConverter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package eu.dissco.orchestration.backend.security;

import static org.assertj.core.api.Assertions.assertThat;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.oauth2.jwt.Jwt;

@ExtendWith(MockitoExtension.class)
class JwtAuthConverterTest {

private JwtAuthConverter converter;

@BeforeEach
void setup() {
converter = new JwtAuthConverter();
}

@Test
void testEmptyToken() {
// Given
var jwt = new Jwt("SomeRandomStringWithTheFullValue", Instant.now(), Instant.now(),
Map.of("kid", "SomeRandom", "typ", "JWT", "alg", "RS256"),
Map.of("sub", "adf294ba-bb03-4962-8042-a37f1648458e"));

// When
var token = converter.convert(jwt);

// Then
assertThat(token.isAuthenticated()).isTrue();
assertThat(token.getName()).isEqualTo("adf294ba-bb03-4962-8042-a37f1648458e");
assertThat(token.getAuthorities()).isEmpty();
}

@Test
void testTokenRoles() {
// Given
var jwt = new Jwt("SomeRandomStringWithTheFullValue", Instant.now(), Instant.now(),
Map.of("kid", "SomeRandom", "typ", "JWT", "alg", "RS256"),
Map.of("sub", "adf294ba-bb03-4962-8042-a37f1648458e",
"resource_access", Map.of("orchestration-service",
Map.of("roles", List.of("orchestration-admin")))));

// When
var token = converter.convert(jwt);

// Then
assertThat(token.isAuthenticated()).isTrue();
assertThat(token.getName()).isEqualTo("adf294ba-bb03-4962-8042-a37f1648458e");
assertThat(token.getAuthorities()).hasSize(1);
}

}

0 comments on commit 2f930f5

Please sign in to comment.