Skip to content

Commit

Permalink
Merge pull request #75 develop
Browse files Browse the repository at this point in the history
  • Loading branch information
MichiBaum authored Nov 4, 2024
2 parents 2a8192f + b5ff496 commit 59913ea
Show file tree
Hide file tree
Showing 105 changed files with 3,627 additions and 2,196 deletions.
11 changes: 11 additions & 0 deletions admin-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
Expand Down Expand Up @@ -65,6 +70,12 @@
<version>1.0.0-TEST-9</version>
</dependency>

<dependency>
<groupId>com.michibaum</groupId>
<artifactId>authentication-library</artifactId>
<version>1.0.0-TEST-9</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import org.springframework.boot.Banner
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.boot.runApplication
import org.springframework.cloud.openfeign.EnableFeignClients

@SpringBootApplication
@EnableAdminServer
@EnableDiscoveryClient
@EnableScheduling
@EnableFeignClients(basePackages = ["com.michibaum.authentication_library"])
class AdminServiceApplication

fun main(args: Array<String>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.michibaum.admin_service
package com.michibaum.admin_service.notifier

import org.springframework.boot.context.properties.ConfigurationProperties

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.michibaum.admin_service
package com.michibaum.admin_service.notifier

import com.michibaum.discord.api.DiscordClient
import com.michibaum.discord.api.dtos.CreateMessageDto
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.michibaum.admin_service
package com.michibaum.admin_service.notifier

import com.michibaum.discord.api.DiscordClient
import de.codecentric.boot.admin.server.config.AdminServerNotifierAutoConfiguration
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository
import de.codecentric.boot.admin.server.notify.Notifier
import org.springframework.boot.autoconfigure.AutoConfiguration
import org.springframework.boot.autoconfigure.AutoConfigureBefore
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.context.annotation.Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.michibaum.admin_service.security

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "spring.boot.admin.client")
data class AdminServiceCredentials(
var username: String = "",
var password: String = ""
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.michibaum.admin_service.security

import com.michibaum.authentication_library.AuthenticationClient
import com.michibaum.authentication_library.security.ServletAuthenticationFilter
import com.michibaum.authentication_library.security.ServletDelegateAuthenticationManager
import com.michibaum.authentication_library.security.SpecificAuthenticationManager
import com.michibaum.authentication_library.security.basic.BasicAuthenticationManager
import com.michibaum.authentication_library.security.basic.CredentialsValidator
import com.michibaum.authentication_library.security.basic.servlet.BasicAuthenticationConverter
import com.michibaum.authentication_library.security.jwt.JwsValidator
import com.michibaum.authentication_library.security.jwt.JwtAuthenticationManager
import com.michibaum.authentication_library.security.jwt.servlet.JwtAuthenticationConverter
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Lazy
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.web.authentication.AuthenticationConverter

@Configuration
class SecurityBeansConfiguration {

@Bean
fun adminServiceCredentials(): AdminServiceCredentials =
AdminServiceCredentials()



@Bean
fun jwsValidator(@Lazy authenticationClient: AuthenticationClient): JwsValidator =
JwsValidator(authenticationClient)

@Bean
fun credentialsValidator(adminServiceCredentials: AdminServiceCredentials): CredentialsValidator =
CredentialsValidator { basic ->
adminServiceCredentials.username == basic.getUsername() &&
adminServiceCredentials.password == basic.getPassword()
}



@Bean
fun jwtAuthenticationManager(jwsValidator: JwsValidator): SpecificAuthenticationManager =
JwtAuthenticationManager(jwsValidator)

@Bean
fun basicAuthenticationManager(credentialsValidator: CredentialsValidator): SpecificAuthenticationManager =
BasicAuthenticationManager(credentialsValidator)

@Bean
fun authenticationManager(specificAuthenticationManagers: List<SpecificAuthenticationManager>): AuthenticationManager =
ServletDelegateAuthenticationManager(specificAuthenticationManagers)



@Bean
fun jwtAuthenticationConverter(): AuthenticationConverter =
JwtAuthenticationConverter()

@Bean
fun basicAuthenticationConverter(): AuthenticationConverter =
BasicAuthenticationConverter()



@Bean
fun authenticationFilter(authenticationManager: AuthenticationManager, authenticationConverters: List<AuthenticationConverter>) =
ServletAuthenticationFilter(authenticationManager, authenticationConverters)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.michibaum.admin_service.security

import com.michibaum.authentication_library.security.ServletAuthenticationFilter
import com.michibaum.permission_library.Permissions
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.AuthenticationFilter
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter


@Configuration
@EnableWebSecurity
@EnableMethodSecurity
class SecurityConfiguration {

@Bean
fun securityFilterChain(
http: HttpSecurity,
authenticationFilter: ServletAuthenticationFilter
): SecurityFilterChain {
return http
.authorizeHttpRequests {
it.requestMatchers(
"/actuator",
"/actuator/**"
).hasAnyAuthority(Permissions.ADMIN_SERVICE.name)
.anyRequest().authenticated()
}
.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
.httpBasic { httpBasicSpec -> httpBasicSpec.disable() }
.formLogin { formLoginSpec -> formLoginSpec.disable() }
.csrf { csrfSpec -> csrfSpec.disable() }
.logout { logoutSpec -> logoutSpec.disable() }
.build()
}

}
7 changes: 7 additions & 0 deletions admin-service/src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ server:
spring:
boot:
admin:
client:
username: admin_username
password: admin_password
ui:
public-url: http://localhost:8082
notify:
custom-discord:
enabled: false
instance-auth:
default-user-name: admin_username
default-password: admin_password
enabled: true

eureka:
client:
Expand Down
3 changes: 3 additions & 0 deletions admin-service/src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ spring:
channel-id: ${DISCORD_ADMIN_SERVICE_LOG_CHANNEL}
boot:
admin:
client:
username: ${ADMIN_SERVICE_USERNAME}
password: ${ADMIN_SERVICE_PASSWORD}
ui:
public-url: https://admin.michibaum.ch
instance-auth:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,120 @@
package com.michibaum.admin_service

import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.reactive.server.WebTestClient
import java.util.*

@ExtendWith(SpringExtension::class)
@AutoConfigureMockMvc
@SpringBootTest
@SpringBootTest(properties = [
"spring.boot.admin.client.username=someUsername",
"spring.boot.admin.client.password=somePasswööörd"
])
class ActuatorIT {

@Autowired
lateinit var webClient: WebTestClient

@Test
fun `actuator is allowed without authentication`(){
fun `actuator without authentication returns 401`(){
// GIVEN

// WHEN
webClient.get()
.uri("/actuator")
.exchange()
.expectStatus()
.isOk
.isUnauthorized

// THEN

}

@Test
fun `actuator health is allowed without authentication`(){
fun `actuator health without authentication returns 401`(){
// GIVEN

// WHEN
webClient.get()
.uri("/actuator/health")
.exchange()
.expectStatus()
.isOk
.isUnauthorized

// THEN

}

@Test
fun `actuator info is allowed without authentication`(){
fun `actuator info without authentication returns 401`(){
// GIVEN

// WHEN
webClient.get()
.uri("/actuator/info")
.exchange()
.expectStatus()
.isOk
.isUnauthorized

// THEN

}

@Test
fun `actuator with authentication returns 200`(){
// GIVEN
val basicAuth = "someUsername:somePasswööörd"
val basicAuthEncoded = Base64.getEncoder().encodeToString(basicAuth.toByteArray())

// WHEN
webClient.get()
.uri("/actuator")
.headers { it.setBasicAuth(basicAuthEncoded) }
.exchange()
.expectStatus()
.isOk // TODO returns 302 redirect to / because of success authentication

// THEN

}

@Test
fun `actuator health with authentication returns 200`(){
// GIVEN
val basicAuth = "someUsername:somePasswööörd"
val basicAuthEncoded = Base64.getEncoder().encodeToString(basicAuth.toByteArray())

// WHEN
webClient.get()
.uri("/actuator/health")
.headers { it.setBasicAuth(basicAuthEncoded) }
.exchange()
.expectStatus()
.isOk // TODO returns 302 redirect to / because of success authentication

// THEN

}

@Test
fun `actuator info with authentication returns 200`(){
// GIVEN
val basicAuth = "someUsername:somePasswööörd"
val basicAuthEncoded = Base64.getEncoder().encodeToString(basicAuth.toByteArray())

// WHEN
webClient.get()
.uri("/actuator/info")
.headers { it.setBasicAuth(basicAuthEncoded) }
.exchange()
.expectStatus()
.isOk // TODO returns 302 redirect to / because of success authentication

// THEN

Expand Down
Loading

0 comments on commit 59913ea

Please sign in to comment.