Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 权限接入与蓝鲸权限中心联动 #2698 #2711

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,12 @@ enum class ActionTypeMapping(val resType: String, val pAction: String) {
NODE_WRITE(ResourceType.NODE.name, PermissionAction.WRITE.name),
NODE_DELETE(ResourceType.NODE.name, PermissionAction.DELETE.name);

fun id() = this.name.toLowerCase()
fun id() = this.name.lowercase()

companion object {

fun lookup(resType: String, pAction: String): ActionTypeMapping {
return values().find { it.resType == resType && it.pAction == pAction }
?: throw IllegalArgumentException("No enum for resType $resType and pAction $pAction!")
return values().find { it.resType == resType && it.pAction == pAction } ?: PROJECT_MANAGE
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,8 @@ import com.tencent.bk.sdk.iam.service.impl.TokenServiceImpl
import com.tencent.bk.sdk.iam.service.v2.impl.V2ManagerServiceImpl
import com.tencent.bk.sdk.iam.service.v2.impl.V2PolicyServiceImpl
import com.tencent.bkrepo.auth.condition.MultipleAuthCondition
import com.tencent.bkrepo.auth.service.bkiamv3.IamEsbClient
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Conditional
import org.springframework.context.annotation.Configuration
Expand Down Expand Up @@ -98,10 +96,7 @@ class BkiamConfiguration {
@Autowired defaultHttpClientServiceImpl: DefaultHttpClientServiceImpl,
@Autowired iamConfiguration: IamConfiguration
) = GrantServiceImpl(defaultHttpClientServiceImpl, iamConfiguration)

@Bean
@ConditionalOnMissingBean
fun iamEsbService() = IamEsbClient()


// 接入V3(RBAC)
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class ServiceBkiamV3ResourceController : ServiceBkiamV3ResourceClient {
override fun createRepoManage(userId: String, projectId: String, repoName: String): Response<String?> {
bkIamV3Service?.let {
val repoGradeId = lockAction(projectId) {
bkIamV3Service!!.createGradeManager(userId, projectId, repoName)
bkIamV3Service!!.createGradeManager(userId, projectId, repoName)
}
return ResponseBuilder.success(repoGradeId)
} ?: return ResponseBuilder.success()
Expand All @@ -67,9 +67,9 @@ class ServiceBkiamV3ResourceController : ServiceBkiamV3ResourceClient {
} ?: return ResponseBuilder.success(true)
}

override fun getExistRbacDefaultGroupProjectIds(projectIds: List<String>): Response<Map<String, Boolean>> {
override fun getExistRbacDefaultGroupProjectIds(projectIdList: List<String>): Response<Map<String, Boolean>> {
bkIamV3Service?.let {
return ResponseBuilder.success(bkIamV3Service!!.getExistRbacDefaultGroupProjectIds(projectIds))
return ResponseBuilder.success(bkIamV3Service!!.getExistRbacDefaultGroupProjectIds(projectIdList))
} ?: return ResponseBuilder.success(emptyMap())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ 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.auth.service.bkiamv3.BkIamV3Service
import com.tencent.bkrepo.common.api.pojo.Response
import com.tencent.bkrepo.common.lock.service.LockOperation
import com.tencent.bkrepo.common.security.util.SecurityUtils
import com.tencent.bkrepo.common.service.util.ResponseBuilder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.GetMapping
Expand All @@ -49,6 +53,12 @@ class RepoModeController(
permissionService: PermissionService
) : OpenResource(permissionService) {

@Autowired
private var bkIamV3Service: BkIamV3Service? = null

@Autowired
lateinit var lockOperation: LockOperation

@GetMapping("/query")
fun getStatus(
@RequestParam projectId: String,
Expand All @@ -66,14 +76,38 @@ class RepoModeController(
with(request) {
preCheckProjectAdmin(projectId)
repoModeService.createOrUpdateConfig(
projectId,
repoName,
accessControlMode,
officeDenyGroupSet,
bkiamv3Check
projectId = projectId,
repoName = repoName,
accessControlMode = accessControlMode,
officeDenyGroupSet = officeDenyGroupSet,
bkiamv3Check = bkiamv3Check
)
if (bkIamV3Service != null && bkiamv3Check) {
lockAction(projectId) {
val userId = SecurityUtils.getUserId()
bkIamV3Service!!.createGradeManager(userId, projectId, repoName)
}
}
return ResponseBuilder.success(repoModeService.getAccessControlStatus(projectId, repoName))
}
}

fun <T> lockAction(projectId: String, action: () -> T): T {
val lockKey = "${AUTH_LOCK_KEY_PREFIX}$projectId"
val lock = lockOperation.getLock(lockKey)
return if (lockOperation.getSpinLock(lockKey, lock)) {
try {
action()
} finally {
lockOperation.close(lockKey, lock)
}
} else {
action()
}
}

companion object {
const val AUTH_LOCK_KEY_PREFIX = "auth:lock:gradeCreate:"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ class RepoAuthConfigDao : SimpleMongoDao<TRepoAuthConfig>() {
)
}

fun checkByProject(projectId: String): Boolean {
return this.exists(
Query.query(
Criteria.where(TRepoAuthConfig::projectId.name).`is`(projectId)
.and(TRepoAuthConfig::bkiamv3Check.name).`is`(true)
)
)
}

fun upsertProjectRepo(
projectId: String,
repoName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.tencent.bkrepo.auth.pojo.permission
import com.tencent.bkrepo.auth.pojo.enums.AccessControlMode

data class RepoModeStatus(
val id: String,
val id: String?,
val accessControlMode: AccessControlMode?,
val officeDenyGroupSet: Set<String> = emptySet(),
val bkiamv3Check: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ interface RepoModeService {

fun getAccessControlStatus(projectId: String, repoName: String): RepoModeStatus

fun bkiamv3Check(projectId: String, repoName: String): Boolean

fun projectBkiamv3Check(projectId: String): Boolean

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,23 @@ class DevopsPermissionServiceImpl constructor(
}

override fun checkPermission(request: CheckPermissionRequest): Boolean {

logger.debug("devops check permission request [$request]")
// 校验平台账号操作范围
if (request.appId != null && !checkPlatformPermission(request)) return false

// bkiamv3权限校验
if (matchBkiamv3Cond(request)) {
// 当有v3权限时,返回成功;如没有v3权限则按devops账号体系继续进行判断
if (checkBkIamV3Permission(request)) return true
// repo,node权限兼容bkiam权限与devops权限
if (matchBkiamv3Cond(request.projectId, request.repoName) && matchDevopsRepoCond(request.repoName)) {
return checkBkIamV3Permission(request) || checkDevopsPermission(request)
}

// 采用bkiamv3权限
if (matchBkiamv3Cond(request.projectId, request.repoName) && !matchDevopsRepoCond(request.repoName)) {
return checkBkIamV3Permission(request)
}

// project,read权限
if (matchBkiamv3ProjectCond(request)) {
return checkBkIamV3Permission(request) || checkDevopsPermission(request)
}

return checkDevopsPermission(request)
Expand Down Expand Up @@ -155,8 +164,6 @@ class DevopsPermissionServiceImpl constructor(

private fun checkDevopsPermission(request: CheckPermissionRequest): Boolean {
with(request) {
logger.debug("check devops permission request [$request]")

// 用户不存在
val user = getUserInfo(uid) ?: return false
// 系统管理员用户
Expand Down Expand Up @@ -199,15 +206,20 @@ class DevopsPermissionServiceImpl constructor(
}
}

private fun matchDevopsRepoCond(repoName: String?): Boolean {
return repoName != null && defaultRepoList.contains(repoName)
}


private fun checkProjectPermission(context: CheckPermissionContext): Boolean {
with(context) {
// 只有用户为非项目管理员,代码才会走到这里, action为MANAGE需要项目管理员权限
if (action == MANAGE.name) {
logger.debug("project request need manage permission [$context]")
return false
}
// 项目权限暂时以devops为准
return isDevopsProjectMember(userId, projectId, action)
|| checkBkIamV3ProjectPermission(projectId, userId, action)
}
}

Expand Down Expand Up @@ -304,5 +316,6 @@ class DevopsPermissionServiceImpl constructor(

companion object {
private val logger = LoggerFactory.getLogger(DevopsPermissionServiceImpl::class.java)
private val defaultRepoList = listOf(CUSTOM, PIPELINE, LOG, REPORT)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,14 @@

package com.tencent.bkrepo.auth.service.bkiamv3

import com.tencent.bkrepo.auth.constant.CUSTOM
import com.tencent.bkrepo.auth.constant.LOG
import com.tencent.bkrepo.auth.constant.PIPELINE
import com.tencent.bkrepo.auth.constant.REPORT
import com.tencent.bkrepo.auth.dao.AccountDao
import com.tencent.bkrepo.auth.dao.PermissionDao
import com.tencent.bkrepo.auth.dao.PersonalPathDao
import com.tencent.bkrepo.auth.dao.RepoAuthConfigDao
import com.tencent.bkrepo.auth.dao.UserDao
import com.tencent.bkrepo.auth.dao.repository.RoleRepository
import com.tencent.bkrepo.auth.pojo.enums.ActionTypeMapping
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction
import com.tencent.bkrepo.auth.pojo.enums.ResourceType
import com.tencent.bkrepo.auth.pojo.permission.CheckPermissionRequest
import com.tencent.bkrepo.auth.service.local.PermissionServiceImpl
Expand All @@ -46,7 +43,6 @@ import com.tencent.bkrepo.common.api.constant.StringPool
import com.tencent.bkrepo.common.metadata.service.project.ProjectService
import com.tencent.bkrepo.common.metadata.service.repo.RepositoryService
import org.slf4j.LoggerFactory
import java.util.Locale

/**
* 对接蓝鲸权限中心V3 RBAC
Expand Down Expand Up @@ -95,69 +91,43 @@ open class BkIamV3PermissionServiceImpl(
/**
* 判断仓库创建时是否开启权限校验
*/
fun matchBkiamv3Cond(request: CheckPermissionRequest): Boolean {
fun matchBkiamv3Cond(projectId: String?, repoName: String?): Boolean {
if (!bkiamV3Service.checkIamConfiguration()) return false
return bkiamV3Service.checkBkiamv3Config(projectId, repoName)
}

/**
* 是否需要采用iamv3项目校验
*/
fun matchBkiamv3ProjectCond(request: CheckPermissionRequest): Boolean {
with(request) {
if (!bkiamV3Service.checkIamConfiguration()) return false
return bkiamV3Service.checkBkiamv3Config(projectId, repoName)
return request.resourceType == ResourceType.PROJECT.name &&
request.action == PermissionAction.READ.name &&
bkiamV3Service.checkBkiamv3ProjectConfig(projectId)
}
}

fun checkBkIamV3Permission(request: CheckPermissionRequest): Boolean {
with(request) {
if (projectId == null) return false
if (projectId == null) {
return false
}
val resourceId = bkiamV3Service.getResourceId(
resourceType, projectId, repoName, path
) ?: StringPool.EMPTY
return if (checkDefaultRepository(resourceType, resourceId, repoName)) {
checkBkIamV3ProjectPermission(projectId!!, uid, action)
} else {
bkiamV3Service.validateResourcePermission(
userId = uid,
projectId = projectId!!,
repoName = repoName,
resourceType = resourceType.lowercase(Locale.getDefault()),
action = convertActionType(resourceType, action),
resourceId = resourceId,
appId = appId
)
}
return bkiamV3Service.validateResourcePermission(
userId = uid,
projectId = projectId!!,
repoName = repoName,
resourceType = resourceType.lowercase(),
action = convertActionType(resourceType, action),
resourceId = resourceId,
appId = appId
)
}
}

/**
* 针对默认创建的4个仓库不开启v3-rbac校验,只校验项目权限
*/
private fun checkDefaultRepository(resourceType: String, resourceId: String, repoName: String?): Boolean {
return when (resourceType) {
ResourceType.SYSTEM.toString() -> false
ResourceType.PROJECT.toString() -> false
ResourceType.REPO.toString() -> {
defaultRepoList.contains(resourceId)
}
ResourceType.NODE.toString() -> {
defaultRepoList.contains(repoName)
}
else -> false
}
}

fun checkBkIamV3ProjectPermission(projectId: String, userId: String, action: String): Boolean {
logger.info("v3 checkBkIamV3ProjectPermission userId: $userId, projectId: $projectId, action: $action")
return bkiamV3Service.validateResourcePermission(
userId = userId,
projectId = projectId,
repoName = null,
resourceType = ResourceType.PROJECT.id(),
action = try {
convertActionType(ResourceType.PROJECT.name, action)
} catch (e: IllegalArgumentException) {
ActionTypeMapping.PROJECT_MANAGE.id()
},
resourceId = projectId,
appId = null
)
}

private fun listV3PermissionRepo(projectId: String, userId: String): List<String> {
val pList = bkiamV3Service.listPermissionResources(
userId = userId,
Expand Down Expand Up @@ -185,10 +155,7 @@ open class BkIamV3PermissionServiceImpl(
}
}

private fun mergeResult(
list: List<String>,
v3list: List<String>
): List<String> {
private fun mergeResult(list: List<String>, v3list: List<String>): List<String> {
val set = mutableSetOf<String>()
set.addAll(list)
set.addAll(v3list)
Expand All @@ -197,7 +164,6 @@ open class BkIamV3PermissionServiceImpl(

companion object {
private val logger = LoggerFactory.getLogger(BkIamV3PermissionServiceImpl::class.java)
private val defaultRepoList = listOf(CUSTOM, PIPELINE, LOG, REPORT)
}
}

Loading
Loading