Skip to content

Commit

Permalink
feat: 修复SVN Proxy Head请求获取projectId失败 #1335
Browse files Browse the repository at this point in the history
  • Loading branch information
cnlkl committed Oct 27, 2023
1 parent e49b37e commit e9989bf
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ import com.tencent.bkrepo.common.security.crypto.CryptoConfiguration
import com.tencent.bkrepo.common.security.exception.SecurityExceptionHandler
import com.tencent.bkrepo.common.security.http.HttpAuthConfiguration
import com.tencent.bkrepo.common.security.http.core.HttpAuthProperties
import com.tencent.bkrepo.common.security.interceptor.devx.DevxProperties
import com.tencent.bkrepo.common.security.interceptor.devx.DevxSrcIpInterceptor
import com.tencent.bkrepo.common.security.interceptor.devx.DevXAccessInterceptor
import com.tencent.bkrepo.common.security.interceptor.devx.DevXProperties
import com.tencent.bkrepo.common.security.manager.AuthenticationManager
import com.tencent.bkrepo.common.security.manager.PermissionManager
import com.tencent.bkrepo.common.security.manager.edge.EdgePermissionManager
Expand All @@ -51,6 +51,7 @@ import com.tencent.bkrepo.common.security.service.ServiceAuthConfiguration
import com.tencent.bkrepo.common.service.cluster.ClusterProperties
import com.tencent.bkrepo.repository.api.NodeClient
import com.tencent.bkrepo.repository.api.RepositoryClient
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
import org.springframework.boot.context.properties.EnableConfigurationProperties
Expand All @@ -71,7 +72,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
ActuatorAuthConfiguration::class,
CryptoConfiguration::class
)
@EnableConfigurationProperties(DevxProperties::class)
@EnableConfigurationProperties(DevXProperties::class)
class SecurityAutoConfiguration {

@Bean
Expand Down Expand Up @@ -110,15 +111,25 @@ class SecurityAutoConfiguration {

@Bean
@ConditionalOnProperty(value = ["devx.enabled"])
fun devxSrcIpInterceptorConfigure(properties: DevxProperties): WebMvcConfigurer {
fun devXAccessInterceptorConfigure(
properties: DevXProperties,
devXAccessInterceptor: DevXAccessInterceptor,
): WebMvcConfigurer {
return object : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
// 不应用到服务间调用
registry.addInterceptor(DevxSrcIpInterceptor(properties))
registry.addInterceptor(devXAccessInterceptor)
// 需要在[httpAuthInterceptor]之后执行才能取得用户信息, 100为随机取值
.order(properties.interceptorOrder)
.excludePathPatterns("/service/**", "/replica/**")
}
}
}

@Bean
@ConditionalOnProperty(value = ["devx.enabled"])
@ConditionalOnMissingBean
fun devXAccessInterceptor(properties: DevXProperties): DevXAccessInterceptor {
return DevXAccessInterceptor(properties)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import javax.servlet.http.HttpServletResponse
/**
* 云研发源ip拦截器,只允许项目的云桌面ip通过
* */
open class DevxSrcIpInterceptor(private val devxProperties: DevxProperties) : HandlerInterceptor {
open class DevXAccessInterceptor(private val devXProperties: DevXProperties) : HandlerInterceptor {
private val httpClient = OkHttpClient.Builder().build()
private val projectIpsCache: LoadingCache<String, Set<String>> = CacheBuilder.newBuilder()
.maximumSize(MAX_CACHE_PROJECT_SIZE)
Expand All @@ -59,30 +59,30 @@ open class DevxSrcIpInterceptor(private val devxProperties: DevxProperties) : Ha

override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
val user = SecurityUtils.getUserId()
if (!devxProperties.enabled || user in devxProperties.userWhiteList) {
if (!devXProperties.enabled || user in devXProperties.userWhiteList) {
return true
}

if (devxProperties.srcHeaderName.isNullOrEmpty() || devxProperties.srcHeaderValues.size < 2) {
if (devXProperties.srcHeaderName.isNullOrEmpty() || devXProperties.srcHeaderValues.size < 2) {
throw SystemErrorException(
CommonMessageCode.SYSTEM_ERROR,
"devx srcHeaderName or srcHeaderValues not configured"
)
}

val headerValue = request.getHeader(devxProperties.srcHeaderName)
val headerValue = request.getHeader(devXProperties.srcHeaderName)
return when (headerValue) {
devxProperties.srcHeaderValues[0] -> {
devXProperties.srcHeaderValues[0] -> {
getProjectId(request)?.let { projectId ->
val srcIp = HttpContextHolder.getClientAddress()
checkIpBelongToProject(projectId, srcIp)
}
true
}

devxProperties.srcHeaderValues[1] -> {
devxProperties.restrictedUserPrefix.forEach { checkUserSuffixAndPrefix(user, prefix = it) }
devxProperties.restrictedUserSuffix.forEach { checkUserSuffixAndPrefix(user, suffix = it) }
devXProperties.srcHeaderValues[1] -> {
devXProperties.restrictedUserPrefix.forEach { checkUserSuffixAndPrefix(user, prefix = it) }
devXProperties.restrictedUserSuffix.forEach { checkUserSuffixAndPrefix(user, suffix = it) }
true
}

Expand Down Expand Up @@ -118,9 +118,9 @@ open class DevxSrcIpInterceptor(private val devxProperties: DevxProperties) : Ha
}

private fun listIpFromProject(projectId: String): Set<String> {
val apiAuth = ApiAuth(devxProperties.appCode, devxProperties.appSecret)
val apiAuth = ApiAuth(devXProperties.appCode, devXProperties.appSecret)
val token = apiAuth.toJsonString().replace(System.lineSeparator(), "")
val workspaceUrl = devxProperties.workspaceUrl
val workspaceUrl = devXProperties.workspaceUrl
val request = Request.Builder()
.url("$workspaceUrl?project_id=$projectId")
.header("X-Bkapi-Authorization", token)
Expand All @@ -133,7 +133,7 @@ open class DevxSrcIpInterceptor(private val devxProperties: DevxProperties) : Ha
return emptySet()
}
val ips = HashSet<String>()
devxProperties.projectCvmWhiteList[projectId]?.let { ips.addAll(it) }
devXProperties.projectCvmWhiteList[projectId]?.let { ips.addAll(it) }
return response.body!!.byteStream().readJsonString<QueryResponse>().data.mapTo(ips) {
it.inner_ip.substringAfter('.')
}
Expand All @@ -158,7 +158,7 @@ open class DevxSrcIpInterceptor(private val devxProperties: DevxProperties) : Ha
)

companion object {
private val logger = LoggerFactory.getLogger(DevxSrcIpInterceptor::class.java)
private val logger = LoggerFactory.getLogger(DevXAccessInterceptor::class.java)
private const val MAX_CACHE_PROJECT_SIZE = 1000L
private const val CACHE_EXPIRE_TIME = 60L
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import org.springframework.core.Ordered
* 云研发配置
* */
@ConfigurationProperties("devx")
data class DevxProperties(
data class DevXProperties(
/**
* 是否开启云研发相关配置
* */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@

package com.tencent.bkrepo.svn.config

import com.tencent.bkrepo.common.security.interceptor.devx.DevXAccessInterceptor
import com.tencent.bkrepo.common.security.interceptor.devx.DevXProperties
import com.tencent.bkrepo.svn.interceptor.ChangeAncestorProxyHandler
import com.tencent.bkrepo.svn.interceptor.ProxyInterceptor
import com.tencent.bkrepo.svn.interceptor.SvnDevXAccessInterceptor
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.Ordered
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
Expand All @@ -46,4 +51,10 @@ class SvnConfiguration(
.order(Ordered.HIGHEST_PRECEDENCE + 1)
super.addInterceptors(registry)
}

@Bean
@ConditionalOnProperty(value = ["devx.enabled"])
fun devXAccessInterceptor(properties: DevXProperties): DevXAccessInterceptor {
return SvnDevXAccessInterceptor(properties)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@

package com.tencent.bkrepo.svn.interceptor

import com.tencent.bkrepo.common.security.interceptor.devx.DevxProperties
import com.tencent.bkrepo.common.security.interceptor.devx.DevxSrcIpInterceptor
import com.tencent.bkrepo.common.security.interceptor.devx.DevXProperties
import com.tencent.bkrepo.common.security.interceptor.devx.DevXAccessInterceptor
import com.tencent.bkrepo.svn.utils.SvnProxyHelper.getRepoId
import javax.servlet.http.HttpServletRequest

class DevxSrcIpInterceptor(devxProperties: DevxProperties) : DevxSrcIpInterceptor(devxProperties) {
class SvnDevXAccessInterceptor(devxProperties: DevXProperties) : DevXAccessInterceptor(devxProperties) {
override fun getProjectId(request: HttpServletRequest): String? {
return getRepoId(request)?.projectId
}
Expand Down

0 comments on commit e9989bf

Please sign in to comment.