mirror of https://github.com/usbharu/Hideout.git
test: Inboxのセキュリティテストを追加
This commit is contained in:
parent
3a0d91de79
commit
ee0ad59d40
|
@ -202,6 +202,8 @@ dependencies {
|
|||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")
|
||||
|
||||
intTestImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
intTestImplementation("org.springframework.security:spring-security-test")
|
||||
|
||||
}
|
||||
|
||||
detekt {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package activitypub.inbox
|
||||
|
||||
import dev.usbharu.hideout.SpringApplication
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
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.boot.test.context.TestConfiguration
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.test.context.support.WithAnonymousUser
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.post
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.context.WebApplicationContext
|
||||
import util.TestTransaction
|
||||
import util.WithHttpSignature
|
||||
|
||||
@SpringBootTest(classes = [SpringApplication::class])
|
||||
@AutoConfigureMockMvc
|
||||
@Transactional
|
||||
class InboxTest {
|
||||
|
||||
@Autowired
|
||||
private lateinit var context: WebApplicationContext
|
||||
|
||||
private lateinit var mockMvc: MockMvc
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(context)
|
||||
.apply<DefaultMockMvcBuilder>(springSecurity())
|
||||
.build()
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithAnonymousUser
|
||||
fun `匿名でinboxにPOSTしたら401`() {
|
||||
mockMvc
|
||||
.post("/inbox") {
|
||||
content = "{}"
|
||||
contentType = MediaType.APPLICATION_JSON
|
||||
}
|
||||
.andExpect { status { isUnauthorized() } }
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithHttpSignature
|
||||
fun 有効なHttpSignatureでPOSTしたら202() {
|
||||
mockMvc
|
||||
.post("/inbox") {
|
||||
content = "{}"
|
||||
contentType = MediaType.APPLICATION_JSON
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isAccepted() } }
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithAnonymousUser
|
||||
fun `匿名でuser-inboxにPOSTしたら401`() {
|
||||
mockMvc
|
||||
.post("/users/hoge/inbox") {
|
||||
content = "{}"
|
||||
contentType = MediaType.APPLICATION_JSON
|
||||
}
|
||||
.andExpect { status { isUnauthorized() } }
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithHttpSignature
|
||||
fun 有効なHttpSignaturesでPOSTしたら202() {
|
||||
mockMvc
|
||||
.post("/users/hoge/inbox") {
|
||||
content = "{}"
|
||||
contentType = MediaType.APPLICATION_JSON
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isAccepted() } }
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
class Configuration {
|
||||
@Bean
|
||||
fun testTransaction() = TestTransaction
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package util
|
||||
|
||||
import org.springframework.core.annotation.AliasFor
|
||||
import org.springframework.security.test.context.support.TestExecutionEvent
|
||||
import org.springframework.security.test.context.support.WithSecurityContext
|
||||
import java.lang.annotation.Inherited
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Inherited
|
||||
@MustBeDocumented
|
||||
@WithSecurityContext(factory = WithHttpSignatureSecurityContextFactory::class)
|
||||
annotation class WithHttpSignature(
|
||||
@get:AliasFor(
|
||||
annotation = WithSecurityContext::class
|
||||
) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD
|
||||
)
|
|
@ -0,0 +1,39 @@
|
|||
package util
|
||||
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser
|
||||
import dev.usbharu.httpsignature.common.HttpHeaders
|
||||
import dev.usbharu.httpsignature.common.HttpMethod
|
||||
import dev.usbharu.httpsignature.common.HttpRequest
|
||||
import org.springframework.security.core.context.SecurityContext
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.test.context.support.WithSecurityContextFactory
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
|
||||
import java.net.URL
|
||||
|
||||
class WithHttpSignatureSecurityContextFactory : WithSecurityContextFactory<WithHttpSignature> {
|
||||
|
||||
private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy()
|
||||
|
||||
override fun createSecurityContext(annotation: WithHttpSignature): SecurityContext {
|
||||
val httpSignatureUser = HttpSignatureUser(
|
||||
"user",
|
||||
"example.com",
|
||||
12345,
|
||||
true,
|
||||
true,
|
||||
mutableListOf()
|
||||
)
|
||||
val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken(
|
||||
"user", HttpRequest(
|
||||
URL("https://example.com/inbox"),
|
||||
HttpHeaders(mapOf()), HttpMethod.GET
|
||||
)
|
||||
)
|
||||
preAuthenticatedAuthenticationToken.details = httpSignatureUser
|
||||
preAuthenticatedAuthenticationToken.isAuthenticated = true
|
||||
val emptyContext = securityContextStrategy.createEmptyContext()
|
||||
emptyContext.authentication = preAuthenticatedAuthenticationToken
|
||||
return emptyContext
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -48,7 +48,6 @@ open class JsonLd {
|
|||
|
||||
class ContextDeserializer : JsonDeserializer<String>() {
|
||||
|
||||
|
||||
override fun deserialize(
|
||||
p0: com.fasterxml.jackson.core.JsonParser?,
|
||||
p1: com.fasterxml.jackson.databind.DeserializationContext?
|
||||
|
@ -72,7 +71,6 @@ class ContextSerializer : JsonSerializer<List<String>>() {
|
|||
}
|
||||
|
||||
override fun serialize(value: List<String>?, gen: JsonGenerator?, serializers: SerializerProvider) {
|
||||
|
||||
if (value.isNullOrEmpty()) {
|
||||
serializers.defaultSerializeNull(gen)
|
||||
return
|
||||
|
|
|
@ -24,7 +24,6 @@ open class Object : JsonLd {
|
|||
this.id = id
|
||||
}
|
||||
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Object) return false
|
||||
|
|
|
@ -59,7 +59,7 @@ import java.security.interfaces.RSAPrivateKey
|
|||
import java.security.interfaces.RSAPublicKey
|
||||
import java.util.*
|
||||
|
||||
@EnableWebSecurity(debug = false)
|
||||
@EnableWebSecurity(debug = true)
|
||||
@Configuration
|
||||
@Suppress("FunctionMaxLength", "TooManyFunctions")
|
||||
class SecurityConfig {
|
||||
|
@ -82,7 +82,7 @@ class SecurityConfig {
|
|||
HttpSignatureFilter::class.java
|
||||
)
|
||||
.authorizeHttpRequests {
|
||||
it.anyRequest().permitAll()
|
||||
it.anyRequest().authenticated()
|
||||
}
|
||||
.csrf {
|
||||
it.disable()
|
||||
|
@ -110,7 +110,6 @@ class SecurityConfig {
|
|||
AuthenticationEntryPointFailureHandler(HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
|
||||
authenticationEntryPointFailureHandler.setRethrowAuthenticationServiceException(false)
|
||||
httpSignatureFilter.setAuthenticationFailureHandler(authenticationEntryPointFailureHandler)
|
||||
|
||||
return httpSignatureFilter
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue