Skip to content

Commit

Permalink
feat: 支持仓库关闭默认权限 TencentBlueKing#2164
Browse files Browse the repository at this point in the history
* feat:目录权限新增配置---禁止根目录权限 TencentBlueKing#2166

* feat:目录权限新增配置---禁止根目录权限 TencentBlueKing#2166

* feat:目录权限新增配置---禁止根目录权限 TencentBlueKing#2166

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

* feat: 支持仓库关闭默认权限 TencentBlueKing#2164

---------

Co-authored-by: lannoy0523 <935275025@qq.com>
  • Loading branch information
owenlxu and lannoy0523 authored May 28, 2024
1 parent e48226d commit f273e29
Show file tree
Hide file tree
Showing 24 changed files with 517 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const val AUTH_API_ACCOUNT_PREFIX = "/api/account"
const val AUTH_SERVICE_ACCOUNT_PREFIX = "/service/account"
const val AUTH_API_OAUTH_PREFIX = "/api/oauth"
const val AUTH_SERVICE_OAUTH_PREFIX = "/service/oauth"
const val AUTH_API_AUTH_MODE_PREFIX = "/api/mode/repo"
const val AUTH_CLUSTER_TOKEN_INFO_PREFIX = "/cluster/temporary/token/info"
const val AUTH_CLUSTER_TOKEN_DELETE_PREFIX = "/cluster/temporary/token/delete"
const val AUTH_CLUSTER_TOKEN_DECREMENT_PREFIX = "/cluster/temporary/token/decrement"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import com.tencent.bkrepo.auth.condition.DevopsAuthCondition
import com.tencent.bkrepo.auth.condition.BkV3RbacAuthCondition
import com.tencent.bkrepo.auth.condition.LocalAuthCondition
import com.tencent.bkrepo.auth.dao.PersonalPathDao
import com.tencent.bkrepo.auth.dao.RepoAuthConfigDao
import com.tencent.bkrepo.auth.service.AccountService
import com.tencent.bkrepo.auth.service.PermissionService
import com.tencent.bkrepo.auth.service.RoleService
Expand Down Expand Up @@ -93,14 +94,16 @@ class AuthServiceConfig {
accountRepository: AccountRepository,
permissionDao: PermissionDao,
userDao: UserDao,
personalPathDao: PersonalPathDao
personalPathDao: PersonalPathDao,
repoAuthConfigDao: RepoAuthConfigDao
): PermissionService {
return PermissionServiceImpl(
roleRepository,
accountRepository,
permissionDao,
userDao,
personalPathDao,
repoAuthConfigDao,
repositoryClient,
projectClient
)
Expand All @@ -111,6 +114,7 @@ class AuthServiceConfig {
bkiamV3Service: BkIamV3Service,
userDao: UserDao,
personalPathDao: PersonalPathDao,
repoAuthConfigDao: RepoAuthConfigDao,
roleRepository: RoleRepository,
accountRepository: AccountRepository,
permissionDao: PermissionDao,
Expand All @@ -123,6 +127,7 @@ class AuthServiceConfig {
accountRepository,
permissionDao,
personalPathDao,
repoAuthConfigDao,
repoClient,
projectClient
)
Expand All @@ -136,6 +141,7 @@ class AuthServiceConfig {
permissionDao: PermissionDao,
userDao: UserDao,
personalPathDao: PersonalPathDao,
repoAuthConfigDao: RepoAuthConfigDao,
bkAuthConfig: DevopsAuthConfig,
bkAuthPipelineService: DevopsPipelineService,
bkAuthProjectService: DevopsProjectService,
Expand All @@ -147,6 +153,7 @@ class AuthServiceConfig {
permissionDao,
userDao,
personalPathDao,
repoAuthConfigDao,
bkAuthConfig,
bkAuthPipelineService,
bkAuthProjectService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ open class OpenResource(private val permissionService: PermissionService) {
fun preCheckUserInProject(type: AuthPermissionType, projectId: String, repoName: String?) {
val checkRequest = CheckPermissionRequest(
uid = SecurityUtils.getUserId(),
resourceType = ResourceType.PROJECT.toString(),
action = PermissionAction.WRITE.toString(),
resourceType = ResourceType.PROJECT.name,
action = PermissionAction.WRITE.name,
projectId = projectId,
appId = SecurityUtils.getPlatformId()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,26 @@ class ServicePermissionController @Autowired constructor(


/**
* 本接口不做权限校验,返回空列表时可能表示所有路径均有权限,也可能为无项目仓库权限,因此需要单独做仓库权限校验
* 本接口不做权限校验,status表明是否需要做校验
* OperationType IN 表示有权限的路径列表,需要做交集
* OperationType NIN 表示有无权限的路径列表,需要做差集
*/
override fun listPermissionPath(userId: String, projectId: String, repoName: String): Response<ListPathResult> {
val permissionPath = permissionService.listNoPermissionPath(userId, projectId, repoName)
val status = permissionPath.isNotEmpty()
val result = ListPathResult(status = status, path = mapOf(OperationType.NIN to permissionPath))
return ResponseBuilder.success(result)
val repoAccessControl = permissionService.checkRepoAccessControl(projectId, repoName)
if (repoAccessControl) {
val permissionPath = permissionService.listPermissionPath(userId, projectId, repoName)
if (permissionPath == null) {
val result = ListPathResult(status = false, path = mapOf(OperationType.IN to emptyList()))
return ResponseBuilder.success(result)
}
val result = ListPathResult(status = true, path = mapOf(OperationType.IN to permissionPath))
return ResponseBuilder.success(result)
} else {
val permissionPath = permissionService.listNoPermissionPath(userId, projectId, repoName)
val status = permissionPath.isNotEmpty()
val result = ListPathResult(status = status, path = mapOf(OperationType.NIN to permissionPath))
return ResponseBuilder.success(result)
}
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.auth.controller.user

import com.tencent.bkrepo.auth.controller.OpenResource
import com.tencent.bkrepo.auth.pojo.permission.RepoModeStatus
import com.tencent.bkrepo.auth.pojo.authconfig.RepoAuthStatusRequest
import com.tencent.bkrepo.auth.service.PermissionService
import com.tencent.bkrepo.auth.service.RepoModeService
import com.tencent.bkrepo.common.api.pojo.Response
import com.tencent.bkrepo.common.service.util.ResponseBuilder
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody

@RestController
@RequestMapping("/api/mode/repo")
class RepoModeController(
private val repoModeService: RepoModeService,
permissionService: PermissionService
) : OpenResource(permissionService) {

@GetMapping("/query")
fun getStatus(
@RequestParam projectId: String,
@RequestParam repoName: String,
): Response<RepoModeStatus> {
preCheckProjectAdmin(projectId)
val result = repoModeService.getAccessControlStatus(projectId, repoName)
return ResponseBuilder.success(result)
}

@PostMapping("/toggle")
fun toggleStatus(
@RequestBody request: RepoAuthStatusRequest
): Response<RepoModeStatus> {
with(request) {
preCheckProjectAdmin(projectId)
repoModeService.createOrUpdateConfig(projectId, repoName, status)
return ResponseBuilder.success(
repoModeService.getAccessControlStatus(projectId, repoName)
)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
*
* Copyright (C) 2019 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.auth.dao

import com.tencent.bkrepo.auth.model.TRepoAuthConfig
import com.tencent.bkrepo.common.mongo.dao.simple.SimpleMongoDao
import com.tencent.bkrepo.common.security.util.SecurityUtils
import org.springframework.data.mongodb.core.FindAndModifyOptions
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import org.springframework.stereotype.Repository
import java.time.LocalDateTime

@Repository
class RepoAuthConfigDao : SimpleMongoDao<TRepoAuthConfig>() {
fun findOneByProjectRepo(projectId: String, repoName: String): TRepoAuthConfig? {
return this.findOne(
Query.query(
Criteria.where(TRepoAuthConfig::projectId.name).`is`(projectId)
.and(TRepoAuthConfig::repoName.name).`is`(repoName)
)
)
}

fun upsertProjectRepo(projectId: String, repoName: String, status: Boolean): String {
val query = Query.query(
Criteria.where(TRepoAuthConfig::projectId.name).`is`(projectId)
.and(TRepoAuthConfig::repoName.name).`is`(repoName)
)
val options = FindAndModifyOptions().returnNew(true).upsert(true)
val update = Update().set(TRepoAuthConfig::accessControl.name, status)
.set(TRepoAuthConfig::lastModifiedBy.name, SecurityUtils.getUserId())
.set(TRepoAuthConfig::lastModifiedDate.name, LocalDateTime.now())
return this.findAndModify(query, update, options, TRepoAuthConfig::class.java)!!.id!!
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ class PermissionHelper constructor(
return request.projectId != null && request.action == READ.name && isProjectUser
}

fun getNoPermissionPathFromConfig(
fun getPermissionPathFromConfig(
userId: String,
roles: List<String>,
config: List<TPermission>
config: List<TPermission>,
include: Boolean
): List<String> {
val excludePath = mutableListOf<String>()
val includePath = mutableListOf<String>()
Expand Down Expand Up @@ -221,6 +222,9 @@ class PermissionHelper constructor(
}
}
}
if (include) {
return includePath.distinct()
}
val filterPath = includePath.distinct()
return excludePath.distinct().filter { !filterPath.contains(it) }
}
Expand Down Expand Up @@ -336,16 +340,14 @@ class PermissionHelper constructor(
return permissionDao.updateById(id, key, value)
}

fun checkNodeAction(request: CheckPermissionRequest, userRoles: List<String>?, isProjectUser: Boolean): Boolean {
fun checkNodeActionWithOutCtrl(
request: CheckPermissionRequest,
userRoles: List<String>?,
isProjectUser: Boolean
): Boolean {
with(request) {
var roles = userRoles
if (resourceType != NODE.name || path == null) return false
if (roles == null) {
val user = userDao.findFirstByUserId(uid) ?: run {
throw ErrorCodeException(AuthMessageCode.AUTH_USER_NOT_EXIST)
}
roles = user.roles
}
val roles = getUserRoles(uid, userRoles)
val result = permissionDao.listInPermission(projectId!!, repoName!!, uid, resourceType, roles)
result.forEach {
if (checkIncludePatternAction(it.includePattern, path!!, it.actions, action)) return true
Expand All @@ -363,16 +365,35 @@ class PermissionHelper constructor(
return isProjectUser
}

fun checkNodeActionWithCtrl(request: CheckPermissionRequest, userRoles: List<String>?): Boolean {
with(request) {
if (resourceType != NODE.name || path == null) return false
val roles = getUserRoles(uid, userRoles)
val result = permissionDao.listInPermission(projectId!!, repoName!!, uid, resourceType, roles)
result.forEach {
if (checkIncludePatternAction(it.includePattern, path!!, it.actions, action)) return true
}
val personalPathCheck = checkPersonalPath(uid, projectId!!, repoName!!, path!!)
if (personalPathCheck != null) return personalPathCheck
return false
}
}

private fun getUserRoles(userId: String, userRoles: List<String>?): List<String> {
var roles = userRoles
if (roles == null) {
val user = userDao.findFirstByUserId(userId) ?: run {
throw ErrorCodeException(AuthMessageCode.AUTH_USER_NOT_EXIST)
}
roles = user.roles
}
return roles
}

private fun checkPersonalPath(userId: String, projectId: String, repoName: String, path: String): Boolean? {
// check personal path
val personalPath = personalPathDao.findOneByProjectAndRepo(userId, projectId, repoName)
if (personalPath != null && path.startsWith(personalPath.fullPath)) return true

// check personal exclude path
val personalExcludePath = personalPathDao.listByProjectAndRepoAndExcludeUser(userId, projectId, repoName)
personalExcludePath.forEach {
if (path.startsWith(it.fullPath)) return false
}
return null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.tencent.bkrepo.auth.constant.AUTH_API_PERMISSION_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_API_OAUTH_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_API_USER_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_API_ROLE_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_API_AUTH_MODE_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_CLUSTER_PERMISSION_CHECK_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_CLUSTER_TOKEN_DECREMENT_PREFIX
import com.tencent.bkrepo.auth.constant.AUTH_CLUSTER_TOKEN_DELETE_PREFIX
Expand Down Expand Up @@ -241,6 +242,7 @@ class AuthInterceptor(
AUTH_API_ROLE_PREFIX,
AUTH_API_PERMISSION_PREFIX,
AUTH_API_OAUTH_PREFIX,
AUTH_API_AUTH_MODE_PREFIX

)

Expand Down
Loading

0 comments on commit f273e29

Please sign in to comment.