Skip to content

Commit

Permalink
Added tests in gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
MichiBaum committed Sep 30, 2024
1 parent 4d6ed0d commit edb6533
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ package com.michibaum.gatewayservice

import com.michibaum.authentication_library.AuthenticationClient
import com.michibaum.authentication_library.JWSValidator
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.context.annotation.Lazy
import org.springframework.http.HttpStatus
import org.springframework.http.server.reactive.ServerHttpResponse
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import java.security.interfaces.RSAPublicKey

@Component
class AuthenticationFilter(
private val authenticationClient: AuthenticationClient
) : GatewayFilter, JWSValidator() {
class AuthenticationFilter: GatewayFilter, JWSValidator() {

private val logger = LoggerFactory.getLogger(AuthenticationFilter::class.java)

fun valid(token: String, publicKey: RSAPublicKey): Boolean {
fun isValid(token: String, publicKey: RSAPublicKey): Boolean {
return this.validate(token, publicKey)
}

@Autowired
@Lazy
// Cycling Dependencies
lateinit var authenticationClient: AuthenticationClient

/**
* Filters the incoming request based on the presence and validity of the Authorization header.
*
Expand All @@ -36,29 +36,25 @@ class AuthenticationFilter(
chain: GatewayFilterChain?
): Mono<Void> {
exchange?.let {
logger.info(requestLog(it))
val authHeaders = it.request.headers["Authorization"]
val headerExists = authHeaders?.size == 1

return if (headerExists) {
val dto = authenticationClient.publicKey()
val publicKey = dto.key as RSAPublicKey

val authHeader = authHeaders?.get(0)
var dto = authenticationClient.publicKey()
var publicKey = dto.key as RSAPublicKey
if (valid(authHeader ?: "", publicKey)) {
logger.info(requestLog(it))
if (isValid(authHeader ?: "", publicKey)) {
chain?.filter(exchange) ?: Mono.empty() // Continue the filter chain if it isn't null. If it is null, return an empty Mono.
} else {
logger.info(requestLog(exchange))
handleAuthenticationFailure(it)
}
} else {
logger.info(requestLog(exchange))
handleAuthenticationFailure(it)
}
}

logger.info(requestLog(exchange))
return Mono.error(Exception("ServerWebExchange or GatewayFilterChain is null"))
return Mono.error(Exception("ServerWebExchange is null"))
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import com.michibaum.permission_library.PermissionUtil
import org.slf4j.LoggerFactory
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono


class AuthorizationPreFilter() : GatewayFilter {

private val logger = LoggerFactory.getLogger(AuthorizationPreFilter::class.java)
Expand All @@ -18,7 +18,6 @@ class AuthorizationPreFilter() : GatewayFilter {
}

override fun filter(exchange: ServerWebExchange?, chain: GatewayFilterChain?): Mono<Void> {
logger.info(requestLog(exchange))
exchange?.let {
permissions[0].toPermissionString()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.michibaum.gatewayservice

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class FilterConfig {

@Bean
fun authenticationFilter(): AuthenticationFilter {
return AuthenticationFilter()
}

@Bean
fun authorizationPreFilter(): AuthorizationPreFilter {
return AuthorizationPreFilter()
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.michibaum.gatewayservice

import com.michibaum.authentication_library.AuthenticationClient
import com.michibaum.permission_library.Permissions
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.route.RouteLocator
Expand All @@ -8,10 +9,11 @@ import org.springframework.cloud.gateway.route.builder.filters
import org.springframework.cloud.gateway.route.builder.routes
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.security.interfaces.RSAPublicKey

@Configuration
class RoutesConfiguration(
// private val authenticationFilter: GatewayFilter
val authenticationFilter: AuthenticationFilter
) {

companion object {
Expand Down Expand Up @@ -41,7 +43,7 @@ class RoutesConfiguration(
route {
host(ADMIN_SERVICE_HOST)
filters {
// authenticationFilter
authenticationFilter
AuthorizationPreFilter(Permissions.AdminService.CAN_SEND_REQUEST)
}
uri(ADMIN_SERVICE_URI)
Expand All @@ -56,23 +58,23 @@ class RoutesConfiguration(
route {
host(JAVADOC_SERVICE_HOST)
filters {
// authenticationFilter
authenticationFilter
AuthorizationPreFilter(Permissions.JavaDocService.CAN_READ)
}
uri(JAVADOC_SERVICE_URI)
}
route {
host(REGISTRY_SERVICE_HOST)
filters {
// authenticationFilter
authenticationFilter
AuthorizationPreFilter()
}
uri(REGISTRY_SERVICE_URI)
}
route {
host(USERMANAGEMENT_SERVICE_HOST)
filters {
// authenticationFilter
authenticationFilter
AuthorizationPreFilter()
}
uri(USERMANAGEMENT_SERVICE_URI)
Expand Down
1 change: 1 addition & 0 deletions gateway-service/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ spring:
client:
health-indicator:
include-description: true

main:
allow-bean-definition-overriding: true
boot:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.web.reactive.server.WebTestClient

@SpringBootTest
@SpringBootTest(properties = [
"spring.cloud.openfeign.client.config.authentication-service.url=http://localhost:8899",
"spring.cloud.openfeign.micrometer.enabled=false", // Disable micrometer for openfeign client because of exception if url set like above
"eureka.client.enabled=false"
])
@AutoConfigureMockMvc
class AuthenticationClientIT {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.michibaum.gatewayservice

import com.michibaum.authentication_library.AuthenticationClient
import io.mockk.*
import org.junit.jupiter.api.Assertions.*
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.cloud.gateway.filter.GatewayFilterChain
import org.springframework.http.HttpStatus
import org.springframework.http.server.reactive.ServerHttpResponse
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono

@ExtendWith(MockitoExtension::class)
class AuthenticationFilterUT{

private val authenticationClient: AuthenticationClient = mockk()

@BeforeEach

@Test
fun `exchange null returns error`(){
// GIVEN
val authenticationFilter = AuthenticationFilter()
authenticationFilter.authenticationClient = this.authenticationClient

val gatewayFilterChain: GatewayFilterChain = mockk()

// WHEN
val result = authenticationFilter.filter(null, gatewayFilterChain)

//THEN
assertThrows(
Exception::class.java,
result::block,
"ServerWebExchange is null"
)
}

@Test
fun `authorization header does not exist`(){
// GIVEN
val authenticationFilter = AuthenticationFilter()
authenticationFilter.authenticationClient = this.authenticationClient

val gatewayFilterChain: GatewayFilterChain = mockk()
val httpResponse: ServerHttpResponse = mockk {
every { setStatusCode(any()) } returns true
every { setComplete() } returns Mono.empty()
}
val serverWebExchange: ServerWebExchange = mockk{
every { response } returns httpResponse
every { request } returns mockk {
every { headers } returns mockk {
every { headers["Authorization"] } returns null
}
}
}

// WHEN
authenticationFilter.filter(serverWebExchange, gatewayFilterChain)

//THEN
verify (exactly = 1) { httpResponse.setStatusCode(HttpStatus.FORBIDDEN) }

}

}
11 changes: 1 addition & 10 deletions gateway-service/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ server:
url-charset: UTF-8
port: 80


spring:
threads:
virtual:
Expand All @@ -14,14 +13,6 @@ spring:
application:
name: gateway-service
cloud:
openfeign:
client:
config:
authentication-service:
url: http://localhost:8899
micrometer:
# Disable micrometer for openfeign client because of exception if url set like above
enabled: false
gateway:
httpclient:
wiretap: true
Expand All @@ -46,7 +37,7 @@ eureka:
instance:
prefer-ip-address: true
client:
enabled: false
enabled: true
fetch-registry: true
register-with-eureka: true
refresh:
Expand Down

0 comments on commit edb6533

Please sign in to comment.