From 4f902ea08a543c3a1771db515911fae720f7114f Mon Sep 17 00:00:00 2001 From: yaoxuwan Date: Fri, 1 Nov 2024 18:07:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=A0=A1=E9=AA=8Cdev?= =?UTF-8?q?x=20token=20#2223?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 支持校验devx token #2223 * feat: 支持校验devx token #2223 --- .../interceptor/devx/DevXProperties.kt | 12 +++++++ .../fs/server/pojo/DevxLoginResponse.kt | 3 +- .../bkrepo/fs/server/handler/LoginHandler.kt | 19 ++++++++--- .../fs/server/request/DevxLoginRequest.kt | 32 +++++++++++++++++ .../fs/server/response/DevxTokenInfo.kt | 34 +++++++++++++++++++ .../fs/server/utils/DevxWorkspaceUtils.kt | 30 ++++++++++++++++ 6 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/request/DevxLoginRequest.kt create mode 100644 src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/response/DevxTokenInfo.kt diff --git a/src/backend/common/common-security/src/main/kotlin/com/tencent/bkrepo/common/security/interceptor/devx/DevXProperties.kt b/src/backend/common/common-security/src/main/kotlin/com/tencent/bkrepo/common/security/interceptor/devx/DevXProperties.kt index 03ed0819f3..d54195a26f 100644 --- a/src/backend/common/common-security/src/main/kotlin/com/tencent/bkrepo/common/security/interceptor/devx/DevXProperties.kt +++ b/src/backend/common/common-security/src/main/kotlin/com/tencent/bkrepo/common/security/interceptor/devx/DevXProperties.kt @@ -131,4 +131,16 @@ data class DevXProperties( * 应用devX拦截器的接口 */ var includePatterns: List = emptyList(), + + /** + * 校验devx token接口url + */ + var validateTokenUrl: String = "", + + /** + * 校验devx token接口的认证token + */ + var authToken: String = "", + + ) diff --git a/src/backend/fs/api-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/pojo/DevxLoginResponse.kt b/src/backend/fs/api-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/pojo/DevxLoginResponse.kt index b15c000d0e..cc796258be 100644 --- a/src/backend/fs/api-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/pojo/DevxLoginResponse.kt +++ b/src/backend/fs/api-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/pojo/DevxLoginResponse.kt @@ -29,5 +29,6 @@ package com.tencent.bkrepo.fs.server.pojo data class DevxLoginResponse( val projectId: String, - val token: String + val token: String, + val workspaceName: String ) diff --git a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/handler/LoginHandler.kt b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/handler/LoginHandler.kt index 6f52a15ab7..3cd2eaab72 100644 --- a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/handler/LoginHandler.kt +++ b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/handler/LoginHandler.kt @@ -32,6 +32,7 @@ import com.tencent.bkrepo.auth.pojo.user.CreateUserRequest import com.tencent.bkrepo.auth.pojo.user.CreateUserToProjectRequest import com.tencent.bkrepo.common.api.constant.BASIC_AUTH_PREFIX import com.tencent.bkrepo.common.api.constant.HttpHeaders +import com.tencent.bkrepo.common.api.constant.StringPool import com.tencent.bkrepo.common.api.util.BasicAuthUtils import com.tencent.bkrepo.common.artifact.constant.PROJECT_ID import com.tencent.bkrepo.common.artifact.constant.REPO_NAME @@ -42,6 +43,7 @@ import com.tencent.bkrepo.fs.server.constant.JWT_CLAIMS_PERMIT import com.tencent.bkrepo.fs.server.constant.JWT_CLAIMS_REPOSITORY import com.tencent.bkrepo.fs.server.context.ReactiveArtifactContextHolder import com.tencent.bkrepo.fs.server.pojo.DevxLoginResponse +import com.tencent.bkrepo.fs.server.request.DevxLoginRequest import com.tencent.bkrepo.fs.server.request.IoaLoginRequest import com.tencent.bkrepo.fs.server.service.PermissionService import com.tencent.bkrepo.fs.server.utils.DevxWorkspaceUtils @@ -86,11 +88,20 @@ class LoginHandler( } suspend fun devxLogin(request: ServerRequest): ServerResponse { - val workspace = DevxWorkspaceUtils.getWorkspace().awaitSingleOrNull() ?: throw AuthenticationException() + val devxToken = request.bodyToMono(DevxLoginRequest::class.java).awaitSingleOrNull()?.token val repoName = request.pathVariable(REPO_NAME) - val userId = createUser(workspace) - val token = createToken(workspace.projectId, repoName, userId) - val response = DevxLoginResponse(workspace.projectId, token) + val response = if (devxToken.isNullOrEmpty()) { + val workspace = DevxWorkspaceUtils.getWorkspace().awaitSingleOrNull() ?: throw AuthenticationException() + val userId = createUser(workspace) + val token = createToken(workspace.projectId, repoName, userId) + DevxLoginResponse(workspace.projectId, token, StringPool.EMPTY) + } else { + val devxTokenInfo = DevxWorkspaceUtils.validateToken(devxToken).awaitSingle() + createUser(devxTokenInfo.userId) + val token = createToken(devxTokenInfo.projectId, repoName, devxTokenInfo.userId) + DevxLoginResponse(devxTokenInfo.projectId, token, devxTokenInfo.workspaceName) + } + return ReactiveResponseBuilder.success(response) } diff --git a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/request/DevxLoginRequest.kt b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/request/DevxLoginRequest.kt new file mode 100644 index 0000000000..1069930d65 --- /dev/null +++ b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/request/DevxLoginRequest.kt @@ -0,0 +1,32 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.fs.server.request + +data class DevxLoginRequest( + val token: String? +) diff --git a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/response/DevxTokenInfo.kt b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/response/DevxTokenInfo.kt new file mode 100644 index 0000000000..8904396f99 --- /dev/null +++ b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/response/DevxTokenInfo.kt @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.fs.server.response + +data class DevxTokenInfo( + val userId: String, + val projectId: String, + val workspaceName: String +) diff --git a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/utils/DevxWorkspaceUtils.kt b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/utils/DevxWorkspaceUtils.kt index 8889e1b739..f8ea63ae4b 100644 --- a/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/utils/DevxWorkspaceUtils.kt +++ b/src/backend/fs/boot-fs-server/src/main/kotlin/com/tencent/bkrepo/fs/server/utils/DevxWorkspaceUtils.kt @@ -30,6 +30,8 @@ package com.tencent.bkrepo.fs.server.utils import com.github.benmanes.caffeine.cache.AsyncLoadingCache import com.github.benmanes.caffeine.cache.Caffeine import com.google.common.util.concurrent.ThreadFactoryBuilder +import com.tencent.bkrepo.common.api.exception.ErrorCodeException +import com.tencent.bkrepo.common.api.message.CommonMessageCode import com.tencent.bkrepo.common.api.util.toJsonString import com.tencent.bkrepo.common.security.interceptor.devx.ApiAuth import com.tencent.bkrepo.common.security.interceptor.devx.DevXCvmWorkspace @@ -38,8 +40,12 @@ import com.tencent.bkrepo.common.security.interceptor.devx.DevXWorkSpace import com.tencent.bkrepo.common.security.interceptor.devx.PageResponse import com.tencent.bkrepo.common.security.interceptor.devx.QueryResponse import com.tencent.bkrepo.fs.server.context.ReactiveRequestContextHolder +import com.tencent.bkrepo.fs.server.response.DevxTokenInfo +import com.tencent.devops.api.pojo.Response +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.reactor.awaitSingle import kotlinx.coroutines.reactor.mono +import kotlinx.coroutines.withContext import org.slf4j.LoggerFactory import org.springframework.core.ParameterizedTypeReference import org.springframework.http.HttpStatus @@ -53,6 +59,7 @@ import reactor.netty.http.client.HttpClient import reactor.netty.http.client.PrematureCloseException import reactor.netty.resources.ConnectionProvider import reactor.util.retry.RetryBackoffSpec +import java.net.URLDecoder import java.time.Duration import java.util.concurrent.Executors @@ -170,6 +177,29 @@ class DevxWorkspaceUtils( } } + suspend fun validateToken(devxToken: String): Mono { + val token = withContext(Dispatchers.IO) { + URLDecoder.decode(devxToken, Charsets.UTF_8.name()) + } + return httpClient + .get() + .uri("${devXProperties.validateTokenUrl}?dToken=$token") + .header("X-DEVOPS-BK-TOKEN", devXProperties.authToken) + .exchangeToMono { + mono { parseDevxTokenInfo(it) } + } + } + + private suspend fun parseDevxTokenInfo(response: ClientResponse): DevxTokenInfo { + return if (response.statusCode() != HttpStatus.OK) { + val errorMsg = response.awaitBody() + logger.error("${response.statusCode()} $errorMsg") + throw ErrorCodeException(CommonMessageCode.RESOURCE_EXPIRED, "token") + } else { + response.awaitBody>().data!! + } + } + private fun WebClient.RequestHeadersSpec<*>.doRequest( type: ParameterizedTypeReference>, handler: (res: QueryResponse?) -> R