diff --git a/src/backend/auth/api-auth/src/main/kotlin/com/tencent/bkrepo/auth/pojo/enums/ResourceActionMapping.kt b/src/backend/auth/api-auth/src/main/kotlin/com/tencent/bkrepo/auth/pojo/enums/ResourceActionMapping.kt index 7de46b97c3..a6e13fa77d 100644 --- a/src/backend/auth/api-auth/src/main/kotlin/com/tencent/bkrepo/auth/pojo/enums/ResourceActionMapping.kt +++ b/src/backend/auth/api-auth/src/main/kotlin/com/tencent/bkrepo/auth/pojo/enums/ResourceActionMapping.kt @@ -28,26 +28,32 @@ package com.tencent.bkrepo.auth.pojo.enums enum class ResourceActionMapping(val resourceType: String, val actions: List) { - PROJECT_ACTIONS(ResourceType.PROJECT.id(), listOf( + PROJECT_ACTIONS( + ResourceType.PROJECT.id(), listOf( ActionTypeMapping.PROJECT_VIEW.id(), ActionTypeMapping.PROJECT_EDIT.id(), ActionTypeMapping.PROJECT_MANAGE.id(), ActionTypeMapping.REPO_CREATE.id() - )), - REPO_ACTIONS(ResourceType.REPO.id(), - listOf( - ActionTypeMapping.REPO_VIEW.id(), - ActionTypeMapping.REPO_EDIT.id(), - ActionTypeMapping.REPO_MANAGE.id(), - ActionTypeMapping.REPO_DELETE.id(), - ActionTypeMapping.NODE_CREATE.id() - )), - NODE_ACTIONS(ResourceType.NODE.id(), - listOf( - ActionTypeMapping.NODE_DELETE.id(), - ActionTypeMapping.NODE_DOWNLOAD.id(), - ActionTypeMapping.NODE_EDIT.id(), - ActionTypeMapping.NODE_WRITE.id(), - ActionTypeMapping.NODE_VIEW.id() - )); + ) + ), + REPO_ACTIONS( + ResourceType.REPO.id(), + listOf( + ActionTypeMapping.REPO_VIEW.id(), + ActionTypeMapping.REPO_EDIT.id(), + ActionTypeMapping.REPO_MANAGE.id(), + ActionTypeMapping.REPO_DELETE.id(), + ActionTypeMapping.NODE_CREATE.id() + ) + ), + NODE_ACTIONS( + ResourceType.NODE.id(), + listOf( + ActionTypeMapping.NODE_DELETE.id(), + ActionTypeMapping.NODE_DOWNLOAD.id(), + ActionTypeMapping.NODE_EDIT.id(), + ActionTypeMapping.NODE_WRITE.id(), + ActionTypeMapping.NODE_VIEW.id() + ) + ); } diff --git a/src/backend/build.gradle.kts b/src/backend/build.gradle.kts index cc4a29f7a9..d1b28482d1 100644 --- a/src/backend/build.gradle.kts +++ b/src/backend/build.gradle.kts @@ -76,6 +76,7 @@ allprojects { dependency("com.playtika.reactivefeign:feign-reactor-spring-cloud-starter:${Versions.ReactiveFeign}") dependency("com.tencent.bk.sdk:crypto-java-sdk:${Versions.CryptoJavaSdk}") dependency("org.apache.tika:tika-core:${Versions.TiKa}") + dependency("com.tencent.bk.sdk:spring-boot-bk-audit-starter:${Versions.Audit}") dependency("com.tencent.devops:devops-schedule-common:${Versions.DevopsBootSNAPSHOT}") dependency("com.tencent.devops:devops-schedule-model:${Versions.DevopsBootSNAPSHOT}") dependency("com.tencent.devops:devops-schedule-server:${Versions.DevopsBootSNAPSHOT}") diff --git a/src/backend/buildSrc/src/main/kotlin/Versions.kt b/src/backend/buildSrc/src/main/kotlin/Versions.kt index 2761fb08a3..7a7671d51c 100644 --- a/src/backend/buildSrc/src/main/kotlin/Versions.kt +++ b/src/backend/buildSrc/src/main/kotlin/Versions.kt @@ -71,4 +71,5 @@ object Versions { const val JavaCpp = "1.5.9" const val Notice = "1.0.0" const val SpringCloudFunction = "3.2.11" + const val Audit = "1.0.8" } diff --git a/src/backend/common/common-artifact/artifact-service/build.gradle.kts b/src/backend/common/common-artifact/artifact-service/build.gradle.kts index 42c9e945d4..20e2df9adc 100644 --- a/src/backend/common/common-artifact/artifact-service/build.gradle.kts +++ b/src/backend/common/common-artifact/artifact-service/build.gradle.kts @@ -49,6 +49,7 @@ dependencies { api("io.micrometer:micrometer-registry-prometheus") api("org.influxdb:influxdb-java") api("org.apache.commons:commons-text") + api("com.tencent.bk.sdk:spring-boot-bk-audit-starter") testImplementation("org.mockito.kotlin:mockito-kotlin") testImplementation("io.mockk:mockk") diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/ArtifactAutoConfiguration.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/ArtifactAutoConfiguration.kt index ad38ed91e4..c65ba0c094 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/ArtifactAutoConfiguration.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/ArtifactAutoConfiguration.kt @@ -31,6 +31,7 @@ package com.tencent.bkrepo.common.artifact +import com.tencent.bkrepo.common.artifact.audit.BkAuditConfiguration import com.tencent.bkrepo.common.artifact.cluster.ArtifactClusterConfiguration import com.tencent.bkrepo.common.artifact.cns.CnsConfiguration import com.tencent.bkrepo.common.artifact.event.ArtifactEventConfiguration @@ -70,5 +71,6 @@ import org.springframework.context.annotation.PropertySource ArtifactClusterConfiguration::class, CnsConfiguration::class, ArtifactRouterControllerConfiguration::class, + BkAuditConfiguration::class, ) class ArtifactAutoConfiguration diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ActionAuditContent.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ActionAuditContent.kt new file mode 100644 index 0000000000..200de35498 --- /dev/null +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ActionAuditContent.kt @@ -0,0 +1,91 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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.common.artifact.audit + +import com.tencent.bk.audit.constants.AuditAttributeNames.INSTANCE_ID +import com.tencent.bk.audit.constants.AuditAttributeNames.INSTANCE_NAME + +@Suppress("MaxLineLength") +object ActionAuditContent { + + private const val CONTENT_TEMPLATE = "[{{$INSTANCE_NAME}}]({{$INSTANCE_ID}})" + private const val PROJECT_CODE_CONTENT_TEMPLATE = "[{{@PROJECT_CODE}}]" + private const val REPO_NAME_CONTENT_TEMPLATE = "[{{@REPO_NAME}}]" + const val PROJECT_CODE_TEMPLATE = "@PROJECT_CODE" + const val REPO_NAME_TEMPLATE = "@REPO_NAME" + const val TOKEN_TEMPLATE = "@TOKEN" + const val DATE_TEMPLATE = "@DATE" + const val EXPIRES_DYAS_TEMPLATE = "@EXPIRES_DYAS" + const val NAME_TEMPLATE = "@NAME" + const val NEW_PROJECT_CODE_CONTENT_TEMPLATE = "@NEW_PROJECT_CODE" + const val NEW_REPO_NAME_CONTENT_TEMPLATE = "@NEW_REPO_NAME" + const val VERSION_TEMPLATE = "@VERSION" + + // 项目 + const val PROJECT_CREATE_CONTENT = "create project $CONTENT_TEMPLATE" + const val PROJECT_EDIT_CONTENT = "update project $CONTENT_TEMPLATE" + const val PROJECT_VIEW_CONTENT = "get project $CONTENT_TEMPLATE" + + //仓库 + const val REPO_VIEW_CONTENT = "get repo info $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_QUOTE_VIEW_CONTENT = "get quote of repo $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_QUOTE_EDIT_CONTENT = "update quote of repo $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_EXIST_CHECK_CONTENT = "check repo $CONTENT_TEMPLATE exist in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_CREATE_CONTENT = "create repo info $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_LIST_CONTENT = "list repos in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_EDIT_CONTENT = "update repo $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_DELETE_CONTENT = "delete repo $CONTENT_TEMPLATE in project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_REPLICATION_CREATE_CONTENT = "create replication task in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val REPO_REPLICATION_EXECUTE_CONTENT = "execute replication task [{{@NAME}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val REPO_PACKAGE_DELETE_CONTENT = "delete package [{{@NAME}}] in repo $CONTENT_TEMPLATE project $PROJECT_CODE_CONTENT_TEMPLATE" + const val REPO_PACKAGE_VERSION_DELETE_CONTENT = "delete version [{{@VERSION}}] of package [{{@NAME}}] in repo $CONTENT_TEMPLATE project $PROJECT_CODE_CONTENT_TEMPLATE" + + + // 节点 + const val NODE_SHARE_CREATE_CONTENT = "create share link for node info $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_SHARE_DOWNLOAD_CONTENT = "download share node $CONTENT_TEMPLATE with token [{{@TOKEN}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_DOWNLOAD_WITH_TOKEN_CONTENT = "download node $CONTENT_TEMPLATE with token [{{@TOKEN}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_UPLOAD_WITH_TOKEN_CONTENT = "upload node $CONTENT_TEMPLATE with token [{{@TOKEN}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + + const val NODE_VIEW_CONTENT = "get node info $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_CREATE_CONTENT = "create node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_DELETE_CONTENT = "delete node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_CLEAN_CONTENT = "clean node $CONTENT_TEMPLATE before [{{@DATE}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_EXPIRES_EDIT_CONTENT = "set [{{@EXPIRES_DYAS}}] expire days to node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_RENAME_CONTENT = "rename node $CONTENT_TEMPLATE to [{{@NAME}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_MOVE_CONTENT = "move node $CONTENT_TEMPLATE from repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE to [{{@NAME}}] in [{{@NEW_PROJECT_CODE}}]|[{{@NEW_REPO_NAME}}]" + const val NODE_COPY_CONTENT = "copy node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE to [{{@NAME}}] in [{{@NEW_PROJECT_CODE}}]|[{{@NEW_REPO_NAME}}]" + const val NODE_RESTORE_CONTENT = "restore node $CONTENT_TEMPLATE with deleted time [{{@DATE}}] in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_METADATA_VIEW_CONTENT = "get metadata of node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_METADATA_EDIT_CONTENT = "update metadata of node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_METADATA_FORBID_CONTENT = "forbid metadata of node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_METADATA_DELETE_CONTENT = "delete metadata of node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_UPLOAD_CONTENT = "upload node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + const val NODE_DOWNLOAD_CONTENT = "download node $CONTENT_TEMPLATE in repo $PROJECT_CODE_CONTENT_TEMPLATE|$REPO_NAME_CONTENT_TEMPLATE" + +} \ No newline at end of file diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditConfiguration.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditConfiguration.kt new file mode 100644 index 0000000000..df033a8776 --- /dev/null +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditConfiguration.kt @@ -0,0 +1,52 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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.common.artifact.audit + +import com.tencent.bk.audit.AuditRequestProvider +import com.tencent.bkrepo.common.artifact.metrics.ArtifactMetricsProperties +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Primary + +@Configuration +@ConditionalOnProperty(name = ["audit.enabled"], havingValue = "true", matchIfMissing = true) +class BkAuditConfiguration { + @Bean + @Primary + fun bkAuditRequestProvider( + artifactMetricsProperties: ArtifactMetricsProperties + ): AuditRequestProvider { + return BkAuditRequestProvider(artifactMetricsProperties) + } + + @Bean + fun bkAuditPostFilter(): BkAuditPostFilter { + return BkAuditPostFilter() + } +} diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditPostFilter.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditPostFilter.kt new file mode 100644 index 0000000000..ceced95a67 --- /dev/null +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditPostFilter.kt @@ -0,0 +1,65 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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. + */ + +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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.common.artifact.audit + +import com.tencent.bk.audit.filter.AuditPostFilter +import com.tencent.bk.audit.model.AuditEvent + +class BkAuditPostFilter: AuditPostFilter { + override fun map(auditEvent: AuditEvent): AuditEvent { + auditEvent.scopeType = "project" + return auditEvent + } +} \ No newline at end of file diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditRequestProvider.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditRequestProvider.kt new file mode 100644 index 0000000000..49f0b58ac3 --- /dev/null +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/BkAuditRequestProvider.kt @@ -0,0 +1,109 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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.common.artifact.audit + +import com.tencent.bk.audit.AuditRequestProvider +import com.tencent.bk.audit.constants.AccessTypeEnum +import com.tencent.bk.audit.constants.UserIdentifyTypeEnum +import com.tencent.bk.audit.exception.AuditException +import com.tencent.bk.audit.model.AuditHttpRequest +import com.tencent.bkrepo.common.artifact.metrics.ArtifactMetricsProperties +import com.tencent.bkrepo.common.artifact.metrics.TransferUserAgent +import com.tencent.bkrepo.common.artifact.util.TransferUserAgentUtil +import com.tencent.bkrepo.common.security.util.SecurityUtils +import com.tencent.bkrepo.common.service.util.HttpContextHolder +import com.tencent.bkrepo.common.service.util.SpringContextUtils +import org.slf4j.LoggerFactory +import org.springframework.web.context.request.RequestContextHolder +import org.springframework.web.context.request.ServletRequestAttributes +import javax.servlet.http.HttpServletRequest + +class BkAuditRequestProvider( + private val artifactMetricsProperties: ArtifactMetricsProperties, +) : AuditRequestProvider { + + override fun getRequest(): AuditHttpRequest { + val httpServletRequest = HttpContextHolder.getRequest() + return AuditHttpRequest(httpServletRequest) + } + + private fun getHttpServletRequest(): HttpServletRequest { + val requestAttributes = RequestContextHolder.getRequestAttributes() + if (requestAttributes == null) { + logger.error("Could not get RequestAttributes from RequestContext!") + throw AuditException("Parse http request error") + } + return (requestAttributes as ServletRequestAttributes).request + } + + override fun getUsername(): String { + return SecurityUtils.getUserId() + } + + override fun getUserIdentifyType(): UserIdentifyTypeEnum { + return UserIdentifyTypeEnum.PERSONAL + } + + override fun getUserIdentifyTenantId(): String? { + val httpServletRequest = getHttpServletRequest() + return httpServletRequest.getHeader(HEADER_USER_IDENTIFY_TENANT_ID) + } + + override fun getAccessType(): AccessTypeEnum { + val agent = TransferUserAgentUtil.getUserAgent( + webPlatformId = artifactMetricsProperties.webPlatformId, + host = artifactMetricsProperties.host, + builderAgentList = artifactMetricsProperties.builderAgentList, + clientAgentList = artifactMetricsProperties.clientAgentList + ) + return when (agent) { + TransferUserAgent.BK_WEB -> AccessTypeEnum.WEB + TransferUserAgent.BUILDER, + TransferUserAgent.BK_CLIENT -> AccessTypeEnum.CONSOLE + TransferUserAgent.OPENAPI -> AccessTypeEnum.API + else -> AccessTypeEnum.OTHER + } + } + + override fun getRequestId(): String? { + return SpringContextUtils.getTraceId() + } + + override fun getClientIp(): String { + return HttpContextHolder.getClientAddress() + } + + override fun getUserAgent(): String? { + return HttpContextHolder.getUserAgent() + } + + companion object { + private const val HEADER_USER_IDENTIFY_TENANT_ID = "X-User-Identify-Tenant-Id" + private val logger = LoggerFactory.getLogger(BkAuditRequestProvider::class.java) + } +} \ No newline at end of file diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ResourceAndActionConstants.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ResourceAndActionConstants.kt new file mode 100644 index 0000000000..1db8639fd5 --- /dev/null +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/audit/ResourceAndActionConstants.kt @@ -0,0 +1,54 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2022 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.common.artifact.audit + +const val PROJECT_CREATE_ACTION = "project_create" +const val PROJECT_MANAGE_ACTION = "project_manage" +const val PROJECT_DOWNLOAD_ACTION = "project_download" +const val PROJECT_EDIT_ACTION = "project_edit" +const val PROJECT_VIEW_ACTION = "project_view" +const val REPO_CREATE_ACTION = "repo_create" +const val REPO_MANAGE_ACTION = "repo_manage" +const val REPO_VIEW_ACTION = "repo_view" +const val REPO_DOWNLOAD_ACTION = "repo_download" +const val REPO_EDIT_ACTION = "repo_edit" +const val REPO_DELETE_ACTION = "repo_delete" +const val NODE_CREATE_ACTION = "node_create" +const val NODE_VIEW_ACTION = "node_view" +const val NODE_READ_ACTION = "node_read" +const val NODE_DOWNLOAD_ACTION = "node_download" +const val NODE_EDIT_ACTION = "node_edit" +const val NODE_WRITE_ACTION = "node_write" +const val NODE_DELETE_ACTION = "node_delete" + + +const val SYSTEM_RESOURCE = "system" +const val PROJECT_RESOURCE = "project" +const val REPO_RESOURCE = "repo" +const val NODE_RESOURCE = "node" +const val ENDPOINT_RESOURCE = "endpoint" diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/manager/StorageManager.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/manager/StorageManager.kt index 3993f58136..78ee7e6b7a 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/manager/StorageManager.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/manager/StorageManager.kt @@ -27,6 +27,7 @@ package com.tencent.bkrepo.common.artifact.manager +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.api.constant.HttpStatus import com.tencent.bkrepo.common.api.exception.ErrorCodeException import com.tencent.bkrepo.common.api.message.CommonMessageCode @@ -82,6 +83,7 @@ class StorageManager( ): NodeDetail { val affectedCount = storageService.store(request.sha256!!, artifactFile, storageCredentials) try { + ActionAuditContext.current().setInstance(request) return nodeService.createNode(request) } catch (exception: Exception) { if (affectedCount == 1) { diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/core/AbstractArtifactRepository.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/core/AbstractArtifactRepository.kt index ec19bf0a05..7de1bbe1d9 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/core/AbstractArtifactRepository.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/core/AbstractArtifactRepository.kt @@ -27,6 +27,7 @@ package com.tencent.bkrepo.common.artifact.repository.core +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.api.constant.HttpHeaders import com.tencent.bkrepo.common.api.constant.StringPool import com.tencent.bkrepo.common.api.exception.MethodNotAllowedException @@ -141,6 +142,11 @@ abstract class AbstractArtifactRepository : ArtifactRepository { val artifactResponse = this.onDownload(context) ?: throw ArtifactNotFoundException(context.artifactInfo.toString()) val throughput = artifactResourceWriter.write(artifactResponse) + if (artifactResponse.node != null) { + ActionAuditContext.current().setInstance(artifactResponse.node) + } else { + ActionAuditContext.current().setInstance(artifactResponse.nodes) + } this.onDownloadSuccess(context, artifactResponse, throughput) } catch (exception: ArtifactResponseException) { val principal = SecurityUtils.getPrincipal() diff --git a/src/backend/common/common-service/service-servlet/src/main/resources/logback-config.xml b/src/backend/common/common-service/service-servlet/src/main/resources/logback-config.xml index 1a0057f1f5..1255bb6b23 100644 --- a/src/backend/common/common-service/service-servlet/src/main/resources/logback-config.xml +++ b/src/backend/common/common-service/service-servlet/src/main/resources/logback-config.xml @@ -10,12 +10,35 @@ + + + + + + ${AUDIT_EVENT_LOG_FILE} + + ${AUDIT_EVENT_LOG_FILE}-%d{yyyy-MM-dd}.log.%i + 1GB + 3 + 5GB + + + ${AUDIT_EVENT_LOG_PATTERN} + UTF-8 + + + + + + + + ${logging.app.file} diff --git a/src/backend/composer/api-composer/build.gradle.kts b/src/backend/composer/api-composer/build.gradle.kts index 709034334e..9361a7502f 100644 --- a/src/backend/composer/api-composer/build.gradle.kts +++ b/src/backend/composer/api-composer/build.gradle.kts @@ -30,6 +30,7 @@ */ dependencies{ + api(project(":repository:api-repository")) implementation(project(":common:common-api")) implementation(project(":common:common-artifact:artifact-api")) compileOnly("org.springframework:spring-web") diff --git a/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerResourceController.kt b/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerResourceController.kt index 57bbf363bb..8bf95bd2d0 100644 --- a/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerResourceController.kt +++ b/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerResourceController.kt @@ -31,7 +31,15 @@ package com.tencent.bkrepo.composer.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.artifact.api.ArtifactFile +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.service.util.HttpContextHolder import com.tencent.bkrepo.composer.api.ComposerResource import com.tencent.bkrepo.composer.artifact.ComposerArtifactInfo @@ -45,6 +53,24 @@ class ComposerResourceController( @Autowired private val composerService: ComposerService ) : ComposerResource { + + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#composerArtifactInfo?.getArtifactFullPath()", + instanceNames = "#composerArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#composerArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#composerArtifactInfo?.repoName") + ], + scopeId = "#composerArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) override fun installRequire(composerArtifactInfo: ComposerArtifactInfo) { composerService.installRequire(composerArtifactInfo) } @@ -65,6 +91,23 @@ class ComposerResourceController( } } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#composerArtifactInfo?.getArtifactFullPath()", + instanceNames = "#composerArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#composerArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#composerArtifactInfo?.repoName") + ], + scopeId = "#composerArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) override fun deploy(composerArtifactInfo: ComposerArtifactInfo, file: ArtifactFile) { composerService.deploy(composerArtifactInfo, file) } diff --git a/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerWebResourceController.kt b/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerWebResourceController.kt index 9c939bad09..0f19094737 100644 --- a/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerWebResourceController.kt +++ b/src/backend/composer/biz-composer/src/main/kotlin/com/tencent/bkrepo/composer/controller/ComposerWebResourceController.kt @@ -27,7 +27,14 @@ package com.tencent.bkrepo.composer.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.composer.api.ComposerWebResource import com.tencent.bkrepo.composer.artifact.ComposerArtifactInfo @@ -38,11 +45,48 @@ import org.springframework.web.bind.annotation.RestController class ComposerWebResourceController( private val composerWebService: ComposerWebService ) : ComposerWebResource { + + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#composerArtifactInfo?.repoName", + instanceNames = "#composerArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#composerArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#composerArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) override fun deletePackage(composerArtifactInfo: ComposerArtifactInfo, packageKey: String): Response { composerWebService.deletePackage(composerArtifactInfo, packageKey) return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#composerArtifactInfo?.repoName", + instanceNames = "#composerArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#composerArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#composerArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) override fun deleteVersion( composerArtifactInfo: ComposerArtifactInfo, packageKey: String, diff --git a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanController.kt b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanController.kt index 227e2b04b6..2ad6d20855 100644 --- a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanController.kt +++ b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanController.kt @@ -27,10 +27,18 @@ package com.tencent.bkrepo.conan.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.conan.constant.CONANFILE import com.tencent.bkrepo.conan.constant.CONANINFO @@ -181,6 +189,23 @@ class ConanController( /** * 获取package下文件 */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(PACKAGE_REVISION_FILE_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.READ) fun getPackageRevisionFile( @@ -192,6 +217,23 @@ class ConanController( /** * 上传文件 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(PACKAGE_REVISION_FILE_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) fun uploadPackageRevisionFile( @@ -215,6 +257,23 @@ class ConanController( /** * 获取recipe下文件 */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(RECIPE_REVISION_FILE_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.READ) fun getRecipeRevisionFile( @@ -226,6 +285,23 @@ class ConanController( /** * 上传文件 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(RECIPE_REVISION_FILE_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) fun uploadRecipeRevisionFile( diff --git a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanDeleteController.kt b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanDeleteController.kt index a9723684ba..eb5c668d9d 100644 --- a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanDeleteController.kt +++ b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanDeleteController.kt @@ -27,10 +27,18 @@ package com.tencent.bkrepo.conan.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.constant.StringPool import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.conan.constant.DEFAULT_REVISION_V1 import com.tencent.bkrepo.conan.pojo.artifact.ConanArtifactInfo @@ -63,6 +71,23 @@ class ConanDeleteController( * Remove any existing recipes or its packages created. * Will remove all revisions, packages and package revisions (parent folder) */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(REMOVE_RECIPE_V1) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removeRecipe( @@ -75,12 +100,30 @@ class ConanDeleteController( /** * if packageIds is empty, then will remove all packages */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @PostMapping(REMOVE_PACKAGES_V1) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removePackages( @ArtifactPathVariable conanArtifactInfo: ConanArtifactInfo, @RequestBody removeRequest: PackageIdRemoveRequest ): ResponseEntity { + ActionAuditContext.current().setInstance(removeRequest) conanDeleteService.removePackages(conanArtifactInfo, DEFAULT_REVISION_V1, removeRequest.packageIds) return ConanCommonController.buildResponse(StringPool.EMPTY) } @@ -89,12 +132,30 @@ class ConanDeleteController( * The remove files is a part of the upload process, * where the revision in v1 will always be DEFAULT_REVISION_V1 */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @PostMapping(REMOVE_FILES_V1) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removeRecipeFiles( @ArtifactPathVariable conanArtifactInfo: ConanArtifactInfo, @RequestBody fileRemoveRequest: FileRemoveRequest ): ResponseEntity { + ActionAuditContext.current().setInstance(fileRemoveRequest) conanDeleteService.removeRecipeFiles(conanArtifactInfo, fileRemoveRequest.files) return ConanCommonController.buildResponse(StringPool.EMPTY) } @@ -103,6 +164,23 @@ class ConanDeleteController( * Remove any existing recipes or its packages created. * Will remove all revisions, packages and package revisions (parent folder) */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(REMOVE_RECIPE_V2, REMOVE_RECIPE_REVISIONS_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removeRecipeV2( @@ -118,6 +196,23 @@ class ConanDeleteController( * - If PRev is NOT specified but RRev is specified (package_recipe_revision_url) * it will remove all the package revisions */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(REMOVE_PACKAGE_RECIPE_REVISION_V2, REMOVE_PACKAGE_REVISION_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removePackagesV2( @@ -130,6 +225,23 @@ class ConanDeleteController( /** * Remove all packages from a RREV */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(REMOVE_ALL_PACKAGE_UNDER_REVISION_V2) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) fun removeAllPackagesV2( diff --git a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanUploadDownloadController.kt b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanUploadDownloadController.kt index f400fcc61d..9dd23e9b20 100644 --- a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanUploadDownloadController.kt +++ b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/ConanUploadDownloadController.kt @@ -27,10 +27,18 @@ package com.tencent.bkrepo.conan.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.conan.pojo.artifact.ConanArtifactInfo import com.tencent.bkrepo.conan.pojo.artifact.ConanArtifactInfo.Companion.UPLOAD_FILE_V1 @@ -50,6 +58,23 @@ class ConanUploadDownloadController( /** * 获取文件 */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(UPLOAD_FILE_V1, UPLOAD_PACKAGE_FILE_V1) @Permission(type = ResourceType.REPO, action = PermissionAction.READ) fun getFile( @@ -61,6 +86,23 @@ class ConanUploadDownloadController( /** * 上传文件 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#conanArtifactInfo?.getArtifactFullPath()", + instanceNames = "#conanArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#conanArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#conanArtifactInfo?.repoName") + ], + scopeId = "#conanArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(UPLOAD_FILE_V1, UPLOAD_PACKAGE_FILE_V1) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) fun uploadFile( diff --git a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/UserConanController.kt b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/UserConanController.kt index 2f958a6050..aac41e8dc8 100644 --- a/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/UserConanController.kt +++ b/src/backend/conan/biz-conan/src/main/kotlin/com/tencent/bkrepo/conan/controller/UserConanController.kt @@ -27,10 +27,17 @@ package com.tencent.bkrepo.conan.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.conan.pojo.ConanDomainInfo @@ -73,6 +80,23 @@ class UserConanController( return ResponseBuilder.success(conanDeleteService.detailVersion(artifactInfo, packageKey, version)) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包") @DeleteMapping(CONAN_PACKAGE_DELETE_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) @@ -86,6 +110,25 @@ class UserConanController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包版本") @DeleteMapping(CONAN_VERSION_DELETE_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) diff --git a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/CompressedBlobController.kt b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/CompressedBlobController.kt index cab45c63f9..0f32f45b70 100644 --- a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/CompressedBlobController.kt +++ b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/CompressedBlobController.kt @@ -27,9 +27,17 @@ package com.tencent.bkrepo.ddc.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.ddc.artifact.CompressedBlobArtifactInfo import com.tencent.bkrepo.ddc.component.PermissionHelper import com.tencent.bkrepo.ddc.service.CompressedBlobService @@ -50,6 +58,23 @@ class CompressedBlobController( private val permissionHelper: PermissionHelper, ) { + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @ApiOperation("获取压缩后的缓存") @GetMapping( "/{repoName}/{$PATH_VARIABLE_CONTENT_ID}", @@ -64,6 +89,23 @@ class CompressedBlobController( compressedBlobService.get(artifactInfo) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @ApiOperation("上传压缩后的缓存") @PutMapping("/{repoName}/{$PATH_VARIABLE_CONTENT_ID}", consumes = [MEDIA_TYPE_UNREAL_UNREAL_COMPRESSED_BUFFER]) fun put( diff --git a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/LegacyReferencesController.kt b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/LegacyReferencesController.kt index d3ced46ef3..1f460a4b48 100644 --- a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/LegacyReferencesController.kt +++ b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/LegacyReferencesController.kt @@ -27,9 +27,18 @@ package com.tencent.bkrepo.ddc.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.ddc.artifact.ReferenceArtifactInfo import com.tencent.bkrepo.ddc.artifact.ReferenceArtifactInfo.Companion.PATH_VARIABLE_BUCKET import com.tencent.bkrepo.ddc.artifact.ReferenceArtifactInfo.Companion.PATH_VARIABLE_REF_ID @@ -52,6 +61,24 @@ class LegacyReferencesController( private val referenceArtifactService: ReferenceArtifactService, private val permissionHelper: PermissionHelper, ) { + + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @ApiOperation("获取ref") @GetMapping( "/ddc/{repoName}/{${PATH_VARIABLE_BUCKET}}/{${PATH_VARIABLE_REF_ID}}.raw", @@ -71,6 +98,23 @@ class LegacyReferencesController( referenceArtifactService.downloadRef(artifactInfo) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping( "/ddc/{repoName}/{${PATH_VARIABLE_BUCKET}}/{${PATH_VARIABLE_REF_ID}}", consumes = [MediaType.APPLICATION_OCTET_STREAM_VALUE] @@ -85,6 +129,23 @@ class LegacyReferencesController( referenceArtifactService.createRef(artifactInfo, file) } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping("/ddc/{repoName}/{${PATH_VARIABLE_BUCKET}}/{${PATH_VARIABLE_REF_ID}}") fun delete( @ApiParam(value = "ddc ref", required = true) diff --git a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/ReferencesController.kt b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/ReferencesController.kt index c5ae5a29d9..ce7e37cb75 100644 --- a/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/ReferencesController.kt +++ b/src/backend/ddc/biz-ddc/src/main/kotlin/com/tencent/bkrepo/ddc/controller/ReferencesController.kt @@ -27,11 +27,19 @@ package com.tencent.bkrepo.ddc.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.common.api.exception.BadRequestException import com.tencent.bkrepo.common.api.message.CommonMessageCode.PARAMETER_INVALID import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.service.util.HttpContextHolder import com.tencent.bkrepo.ddc.artifact.ReferenceArtifactInfo import com.tencent.bkrepo.ddc.artifact.repository.DdcLocalRepository.Companion.HEADER_NAME_HASH @@ -58,6 +66,23 @@ class ReferencesController( private val permissionHelper: PermissionHelper, ) { + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @ApiOperation("获取ref") @GetMapping( "/{repoName}/{$PATH_VARIABLE_BUCKET}/{$PATH_VARIABLE_REF_ID}", @@ -79,6 +104,23 @@ class ReferencesController( referenceArtifactService.downloadRef(artifactInfo) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @ApiOperation("开始创建ref") @PutMapping( "/{repoName}/{$PATH_VARIABLE_BUCKET}/{$PATH_VARIABLE_REF_ID}", diff --git a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/artifact/GenericLocalRepository.kt b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/artifact/GenericLocalRepository.kt index f63fb0a8da..5c49f8be96 100644 --- a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/artifact/GenericLocalRepository.kt +++ b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/artifact/GenericLocalRepository.kt @@ -29,6 +29,7 @@ package com.tencent.bkrepo.generic.artifact import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.constant.CUSTOM import com.tencent.bkrepo.auth.constant.PIPELINE import com.tencent.bkrepo.common.api.constant.CharPool @@ -874,6 +875,7 @@ class GenericLocalRepository( md5 = fileInfo.md5, size = fileInfo.size ) + ActionAuditContext.current().setInstance(nodeRequest) nodeService.createNode(nodeRequest) return property } diff --git a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/GenericController.kt b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/GenericController.kt index 759a38e866..fa9a336e7e 100644 --- a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/GenericController.kt +++ b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/GenericController.kt @@ -31,6 +31,10 @@ package com.tencent.bkrepo.generic.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.exception.ErrorCodeException @@ -46,6 +50,11 @@ import com.tencent.bkrepo.common.artifact.message.ArtifactMessageCode import com.tencent.bkrepo.common.artifact.router.Router import com.tencent.bkrepo.common.artifact.util.PipelineRepoUtils import com.tencent.bkrepo.common.metadata.permission.PermissionManager +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.mongo.dao.util.Pages import com.tencent.bkrepo.common.query.model.QueryModel import com.tencent.bkrepo.common.security.permission.Permission @@ -85,12 +94,46 @@ class GenericController( private val compressedFileService: CompressedFileService, ) { + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(GENERIC_MAPPING_URI) @Permission(ResourceType.NODE, PermissionAction.WRITE) fun upload(@ArtifactPathVariable artifactInfo: GenericArtifactInfo, file: ArtifactFile) { uploadService.upload(artifactInfo, file) } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @Permission(ResourceType.NODE, PermissionAction.DELETE) @DeleteMapping(GENERIC_MAPPING_URI) fun delete( @@ -101,6 +144,23 @@ class GenericController( return ResponseBuilder.success() } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @Permission(ResourceType.NODE, PermissionAction.DOWNLOAD) @GetMapping(GENERIC_MAPPING_URI) @Router @@ -128,6 +188,23 @@ class GenericController( return ResponseBuilder.success() } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @Permission(ResourceType.NODE, PermissionAction.WRITE) @PutMapping(BLOCK_MAPPING_URI) fun completeBlockUpload( @@ -149,6 +226,23 @@ class GenericController( return ResponseBuilder.success(uploadService.listBlock(userId, uploadId, artifactInfo)) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#batchDownloadPaths?.paths", + instanceNames = "#batchDownloadPaths?.paths" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#repoName") + ], + scopeId = "#projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @RequestMapping(BATCH_MAPPING_URI, method = [RequestMethod.GET, RequestMethod.POST]) fun batchDownload( @PathVariable projectId: String, diff --git a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/TemporaryAccessController.kt b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/TemporaryAccessController.kt index 14d442c05a..661a010118 100644 --- a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/TemporaryAccessController.kt +++ b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/controller/TemporaryAccessController.kt @@ -27,6 +27,11 @@ package com.tencent.bkrepo.generic.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.token.TemporaryTokenCreateRequest import com.tencent.bkrepo.auth.pojo.token.TokenType @@ -39,6 +44,10 @@ import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable import com.tencent.bkrepo.common.artifact.metrics.ChunkArtifactTransferMetrics import com.tencent.bkrepo.common.artifact.router.Router import com.tencent.bkrepo.common.metadata.permission.PermissionManager +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.security.permission.Principal import com.tencent.bkrepo.common.security.permission.PrincipalType import com.tencent.bkrepo.common.service.util.HttpContextHolder @@ -104,6 +113,33 @@ class TemporaryAccessController( } } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()", + ), + attributes = [ + AuditAttribute( + name = ActionAuditContent.PROJECT_CODE_TEMPLATE, + value = "#artifactInfo?.projectId" + ), + AuditAttribute( + name = ActionAuditContent.REPO_NAME_TEMPLATE, + value = "#artifactInfo?.repoName" + ), + AuditAttribute( + name = ActionAuditContent.TOKEN_TEMPLATE, + value = "#token" + ) + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_SHARE_DOWNLOAD_CONTENT + ) @ApiOperation("下载分享文件") @Router @CrossOrigin @@ -115,11 +151,31 @@ class TemporaryAccessController( artifactInfo: GenericArtifactInfo ) { val downloadUser = downloadUserId ?: userId + ActionAuditContext.current().addExtendData("downloadUser", downloadUser) val tokenInfo = temporaryAccessService.validateToken(token, artifactInfo, TokenType.DOWNLOAD) temporaryAccessService.downloadByShare(downloadUser, tokenInfo.createdBy, artifactInfo) temporaryAccessService.decrementPermits(tokenInfo) } + + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.TOKEN_TEMPLATE, value = "#token") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_WITH_TOKEN_CONTENT + ) @Router @CrossOrigin @GetMapping("/download/$GENERIC_MAPPING_URI") @@ -132,6 +188,24 @@ class TemporaryAccessController( temporaryAccessService.decrementPermits(tokenInfo) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.TOKEN_TEMPLATE, value = "#token") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_WITH_TOKEN_CONTENT + ) @CrossOrigin @PutMapping("/upload/$GENERIC_MAPPING_URI") fun uploadByToken( diff --git a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/service/UploadService.kt b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/service/UploadService.kt index 801869ba46..198562119e 100644 --- a/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/service/UploadService.kt +++ b/src/backend/generic/biz-generic/src/main/kotlin/com/tencent/bkrepo/generic/service/UploadService.kt @@ -31,6 +31,7 @@ package com.tencent.bkrepo.generic.service +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.api.exception.BadRequestException import com.tencent.bkrepo.common.api.exception.ErrorCodeException import com.tencent.bkrepo.common.api.message.CommonMessageCode @@ -148,21 +149,21 @@ class UploadService( } // 保存节点 val repository = ArtifactContextHolder.getRepository(RepositoryCategory.LOCAL) as GenericLocalRepository - nodeService.createNode( - NodeCreateRequest( - projectId = artifactInfo.projectId, - repoName = artifactInfo.repoName, - folder = false, - fullPath = artifactInfo.getArtifactFullPath(), - sha256 = mergedFileInfo.sha256, - md5 = mergedFileInfo.md5, - size = mergedFileInfo.size, - overwrite = getBooleanHeader(HEADER_OVERWRITE), - operator = userId, - expires = getLongHeader(HEADER_EXPIRES), - nodeMetadata = repository.resolveMetadata(HttpContextHolder.getRequest()) - ) + val request = NodeCreateRequest( + projectId = artifactInfo.projectId, + repoName = artifactInfo.repoName, + folder = false, + fullPath = artifactInfo.getArtifactFullPath(), + sha256 = mergedFileInfo.sha256, + md5 = mergedFileInfo.md5, + size = mergedFileInfo.size, + overwrite = getBooleanHeader(HEADER_OVERWRITE), + operator = userId, + expires = getLongHeader(HEADER_EXPIRES), + nodeMetadata = repository.resolveMetadata(HttpContextHolder.getRequest()) ) + ActionAuditContext.current().setInstance(request) + nodeService.createNode(request) logger.info("User[${SecurityUtils.getPrincipal()}] complete upload [$artifactInfo] success.") } diff --git a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartManipulationController.kt b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartManipulationController.kt index aa7a567113..a1ebe42b3b 100644 --- a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartManipulationController.kt +++ b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartManipulationController.kt @@ -31,8 +31,16 @@ package com.tencent.bkrepo.helm.controller.api +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.artifact.api.ArtifactFileMap import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo.Companion.CHART_DELETE_VERSION_URL import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo.Companion.HELM_PUSH_PLUGIN_URL @@ -56,6 +64,23 @@ class ChartManipulationController( /** * helm push */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PostMapping(HELM_PUSH_URL, HELM_PUSH_PLUGIN_URL) @ResponseStatus(HttpStatus.CREATED) fun upload( @@ -69,6 +94,23 @@ class ChartManipulationController( /** * helm push prov */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PostMapping(HELM_PUSH_PROV_URL) @ResponseStatus(HttpStatus.CREATED) fun uploadProv( @@ -82,6 +124,23 @@ class ChartManipulationController( /** * delete chart version */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(CHART_DELETE_VERSION_URL) fun deleteVersion( @RequestAttribute userId: String, diff --git a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartRepositoryController.kt b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartRepositoryController.kt index 8f6c28a118..fed37cabb0 100644 --- a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartRepositoryController.kt +++ b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/ChartRepositoryController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.helm.controller.api +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo.Companion.HELM_INDEX_YAML_URL @@ -72,6 +79,23 @@ class ChartRepositoryController( /** * retrieved when you run helm install chartmuseum/mychart */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(HELM_INSTALL_URL) fun installTgz(@ArtifactPathVariable artifactInfo: HelmArtifactInfo) { chartRepositoryService.installTgz(artifactInfo) @@ -80,6 +104,23 @@ class ChartRepositoryController( /** * retrieved when you run helm install with the --verify flag */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(HELM_PROV_INSTALL_URL) fun installProv(@ArtifactPathVariable artifactInfo: HelmArtifactInfo) { chartRepositoryService.installProv(artifactInfo) diff --git a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/UserHelmController.kt b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/UserHelmController.kt index c0f1ab60b4..18f209a39c 100644 --- a/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/UserHelmController.kt +++ b/src/backend/helm/biz-helm/src/main/kotlin/com/tencent/bkrepo/helm/controller/api/UserHelmController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.helm.controller.api +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.helm.pojo.HelmDomainInfo import com.tencent.bkrepo.helm.pojo.artifact.HelmArtifactInfo @@ -76,6 +83,23 @@ class UserHelmController( return ResponseBuilder.success(chartRepositoryService.detailVersion(userId, artifactInfo, packageKey, version)) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包") @DeleteMapping(CHART_PACKAGE_DELETE_URL) fun deletePackage( @@ -88,6 +112,25 @@ class UserHelmController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包版本") @DeleteMapping(CHART_VERSION_DELETE_URL) fun deleteVersion( diff --git a/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/controller/ObjectController.kt b/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/controller/ObjectController.kt index cfa79cb0d1..9e10f86806 100644 --- a/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/controller/ObjectController.kt +++ b/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/controller/ObjectController.kt @@ -27,8 +27,16 @@ package com.tencent.bkrepo.lfs.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.lfs.artifact.LfsArtifactInfo import com.tencent.bkrepo.lfs.pojo.BatchRequest import com.tencent.bkrepo.lfs.pojo.BatchResponse @@ -53,11 +61,45 @@ class ObjectController( return objectService.batch(projectId, repoName, request) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#lfsArtifactInfo?.getArtifactFullPath()", + instanceNames = "#lfsArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#lfsArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#lfsArtifactInfo?.repoName") + ], + scopeId = "#lfsArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping("/{projectId}/{repoName}/**") fun upload(@ArtifactPathVariable lfsArtifactInfo: LfsArtifactInfo, file: ArtifactFile) { objectService.upload(lfsArtifactInfo, file) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#lfsArtifactInfo?.getArtifactFullPath()", + instanceNames = "#lfsArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#lfsArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#lfsArtifactInfo?.repoName") + ], + scopeId = "#lfsArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping("/{projectId}/{repoName}/**") fun download(@ArtifactPathVariable lfsArtifactInfo: LfsArtifactInfo) { objectService.download(lfsArtifactInfo) diff --git a/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenResourceController.kt b/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenResourceController.kt index 087c86ccab..7f147cc050 100644 --- a/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenResourceController.kt +++ b/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenResourceController.kt @@ -27,8 +27,17 @@ package com.tencent.bkrepo.maven.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.maven.artifact.MavenArtifactInfo import com.tencent.bkrepo.maven.service.MavenService import org.springframework.http.MediaType @@ -41,6 +50,24 @@ import org.springframework.web.bind.annotation.RestController class MavenResourceController( private val mavenService: MavenService ) { + + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#mavenArtifactInfo?.getArtifactFullPath()", + instanceNames = "#mavenArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#mavenArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#mavenArtifactInfo?.repoName") + ], + scopeId = "#mavenArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(MavenArtifactInfo.MAVEN_MAPPING_URI, produces = [MediaType.APPLICATION_JSON_VALUE]) fun deploy( @ArtifactPathVariable mavenArtifactInfo: MavenArtifactInfo, @@ -49,11 +76,45 @@ class MavenResourceController( return mavenService.deploy(mavenArtifactInfo, file) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#mavenArtifactInfo?.getArtifactFullPath()", + instanceNames = "#mavenArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#mavenArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#mavenArtifactInfo?.repoName") + ], + scopeId = "#mavenArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(MavenArtifactInfo.MAVEN_MAPPING_URI, produces = [MediaType.APPLICATION_JSON_VALUE]) fun dependency(@ArtifactPathVariable mavenArtifactInfo: MavenArtifactInfo) { mavenService.dependency(mavenArtifactInfo) } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#mavenArtifactInfo?.getArtifactFullPath()", + instanceNames = "#mavenArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#mavenArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#mavenArtifactInfo?.repoName") + ], + scopeId = "#mavenArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(MavenArtifactInfo.MAVEN_MAPPING_URI, produces = [MediaType.APPLICATION_JSON_VALUE]) fun deleteDependency(@ArtifactPathVariable mavenArtifactInfo: MavenArtifactInfo) { mavenService.deleteDependency(mavenArtifactInfo) diff --git a/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenWebController.kt b/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenWebController.kt index 987566ab8d..093a62cd13 100644 --- a/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenWebController.kt +++ b/src/backend/maven/biz-maven/src/main/kotlin/com/tencent/bkrepo/maven/controller/MavenWebController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.maven.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Page import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.maven.api.MavenWebResource import com.tencent.bkrepo.maven.artifact.MavenArtifactInfo @@ -48,11 +55,47 @@ class MavenWebController( private val mavenExtService: MavenExtService ) : MavenWebResource { + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#mavenArtifactInfo?.repoName", + instanceNames = "#mavenArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#mavenArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#mavenArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) override fun deletePackage(mavenArtifactInfo: MavenDeleteArtifactInfo, packageKey: String): Response { mavenService.delete(mavenArtifactInfo, packageKey, null) return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#mavenArtifactInfo?.repoName", + instanceNames = "#mavenArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#mavenArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#mavenArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) override fun deleteVersion( mavenArtifactInfo: MavenDeleteArtifactInfo, packageKey: String, diff --git a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/NpmClientController.kt b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/NpmClientController.kt index 409e22a2f4..d7acf11e99 100644 --- a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/NpmClientController.kt +++ b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/NpmClientController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.npm.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.constant.MediaTypes import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.service.util.HeaderUtils import com.tencent.bkrepo.common.service.util.HttpContextHolder import com.tencent.bkrepo.npm.artifact.NpmArtifactInfo @@ -150,6 +157,23 @@ class NpmClientController( /** * download tgz file */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping("/{projectId}/{repoName}/**/*.tgz") fun download( @ArtifactPathVariable artifactInfo: NpmArtifactInfo diff --git a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/UserNpmController.kt b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/UserNpmController.kt index d320010a9a..01c82d8902 100644 --- a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/UserNpmController.kt +++ b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/controller/UserNpmController.kt @@ -31,11 +31,18 @@ package com.tencent.bkrepo.npm.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable import com.tencent.bkrepo.common.artifact.util.PackageKeys +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.npm.artifact.NpmArtifactInfo @@ -62,6 +69,7 @@ class UserNpmController( private val npmWebService: NpmWebService ) { + @Permission(ResourceType.REPO, PermissionAction.READ) @ApiOperation("查询包的版本详情") @GetMapping("/version/detail/{projectId}/{repoName}") @@ -77,6 +85,23 @@ class UserNpmController( return ResponseBuilder.success(npmWebService.detailVersion(artifactInfo, packageKey, version)) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.DELETE) @ApiOperation("删除仓库下的包") @DeleteMapping("/package/delete/{projectId}/{repoName}") @@ -97,6 +122,25 @@ class UserNpmController( } } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.DELETE) @ApiOperation("删除仓库下的包版本") @DeleteMapping("/version/delete/{projectId}/{repoName}") diff --git a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/service/impl/NpmClientServiceImpl.kt b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/service/impl/NpmClientServiceImpl.kt index a850f65ed4..208baf6b5c 100644 --- a/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/service/impl/NpmClientServiceImpl.kt +++ b/src/backend/npm/biz-npm/src/main/kotlin/com/tencent/bkrepo/npm/service/impl/NpmClientServiceImpl.kt @@ -31,6 +31,10 @@ package com.tencent.bkrepo.npm.service.impl +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.util.JsonUtils.objectMapper @@ -42,6 +46,9 @@ import com.tencent.bkrepo.common.artifact.repository.context.ArtifactSearchConte import com.tencent.bkrepo.common.artifact.repository.context.ArtifactUploadContext import com.tencent.bkrepo.common.artifact.resolve.file.ArtifactFileFactory import com.tencent.bkrepo.common.artifact.util.PackageKeys +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.metadata.service.metadata.MetadataService import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.HttpContextHolder @@ -318,6 +325,23 @@ class NpmClientServiceImpl( } } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) private fun handlerPackagePublish( userId: String, artifactInfo: NpmArtifactInfo, diff --git a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetClientController.kt b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetClientController.kt index 0de819c911..4cda2d6f94 100644 --- a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetClientController.kt +++ b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetClientController.kt @@ -31,11 +31,20 @@ package com.tencent.bkrepo.nuget.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.constant.MediaTypes.APPLICATION_JSON import com.tencent.bkrepo.common.api.constant.MediaTypes.APPLICATION_XML import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.nuget.artifact.NugetArtifactInfo import com.tencent.bkrepo.nuget.artifact.NugetArtifactInfo.Companion.DELETE_V2 @@ -73,6 +82,23 @@ class NugetClientController( * Content-Type multipart/form-data * A package with the provided ID and version already exists, status code 409 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#publishInfo?.getArtifactFullPath()", + instanceNames = "#publishInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#publishInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#publishInfo?.repoName") + ], + scopeId = "#publishInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(PUBLISH_V2) @Permission(ResourceType.REPO, PermissionAction.WRITE) fun publish( @@ -82,6 +108,23 @@ class NugetClientController( nugetClientService.publish(userId, publishInfo) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(DOWNLOAD_V2) @Permission(ResourceType.REPO, PermissionAction.READ) fun download( @@ -102,6 +145,23 @@ class NugetClientController( /** * nuget delete [ options ] */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(DELETE_V2) @Permission(ResourceType.REPO, PermissionAction.DELETE) fun delete( diff --git a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetPackageContentController.kt b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetPackageContentController.kt index 19330508d3..308c80df5a 100644 --- a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetPackageContentController.kt +++ b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetPackageContentController.kt @@ -1,7 +1,14 @@ package com.tencent.bkrepo.nuget.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.nuget.artifact.NugetArtifactInfo import com.tencent.bkrepo.nuget.artifact.NugetArtifactInfo.Companion.DOWNLOAD_MANIFEST @@ -33,6 +40,23 @@ class NugetPackageContentController( * * return binary stream */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(DOWNLOAD_V3) @Permission(ResourceType.REPO, PermissionAction.READ) fun downloadPackageContent( @@ -48,6 +72,23 @@ class NugetPackageContentController( * * return xml document */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(DOWNLOAD_MANIFEST) @Permission(ResourceType.REPO, PermissionAction.READ) fun downloadPackageManifest( diff --git a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetWebController.kt b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetWebController.kt index 0195910f72..859ff34d4e 100644 --- a/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetWebController.kt +++ b/src/backend/nuget/biz-nuget/src/main/kotlin/com/tencent/bkrepo/nuget/controller/NugetWebController.kt @@ -1,8 +1,15 @@ package com.tencent.bkrepo.nuget.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.nuget.artifact.NugetArtifactInfo @@ -30,6 +37,24 @@ import org.springframework.web.bind.annotation.RestController class NugetWebController( private val nugetWebService: NugetWebService ) { + + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.DELETE) @ApiOperation("删除仓库下的包") @DeleteMapping(NUGET_EXT_DELETE_PACKAGE) @@ -43,6 +68,25 @@ class NugetWebController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.DELETE) @ApiOperation("删除仓库下的包版本") @DeleteMapping(NUGET_EXT_DELETE_VERSION) diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/artifact/repository/OciRegistryLocalRepository.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/artifact/repository/OciRegistryLocalRepository.kt index 9497ce4268..650be3f3c8 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/artifact/repository/OciRegistryLocalRepository.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/artifact/repository/OciRegistryLocalRepository.kt @@ -31,6 +31,10 @@ package com.tencent.bkrepo.oci.artifact.repository +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.constant.HttpStatus import com.tencent.bkrepo.common.api.constant.MediaTypes import com.tencent.bkrepo.common.artifact.api.ArtifactInfo @@ -44,6 +48,9 @@ import com.tencent.bkrepo.common.artifact.resolve.response.ArtifactChannel import com.tencent.bkrepo.common.artifact.resolve.response.ArtifactResource import com.tencent.bkrepo.common.artifact.stream.ArtifactInputStream import com.tencent.bkrepo.common.artifact.util.PackageKeys +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.service.util.HttpContextHolder import com.tencent.bkrepo.common.storage.innercos.http.HttpMethod import com.tencent.bkrepo.common.storage.message.StorageErrorException @@ -188,6 +195,23 @@ class OciRegistryLocalRepository( * blob 上传,直接使用post * Pushing a blob monolithically :A single POST request */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#context.artifactInfo?.getArtifactFullPath()", + instanceNames = "#context.artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#context?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#context?.repoName") + ], + scopeId = "#context?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) private fun postUpload(context: ArtifactUploadContext): ResponseProperty? { val artifactFile = context.getArtifactFile() val digest = OciDigest.fromSha256(artifactFile.getFileSha256()) @@ -230,6 +254,23 @@ class OciRegistryLocalRepository( * 1 blob POST with PUT 上传的put模块处理 * 2 blob POST PATCH with PUT 上传的put模块处理 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#context.artifactInfo?.getArtifactFullPath()", + instanceNames = "#context.artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#context?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#context?.repoName") + ], + scopeId = "#context?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) private fun putUploadBlob(context: ArtifactUploadContext): ResponseProperty { val artifactInfo = context.artifactInfo as OciBlobArtifactInfo val sha256 = artifactInfo.getDigestHex() diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciBlobController.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciBlobController.kt index 0f0f3a8ac9..a345b88113 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciBlobController.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciBlobController.kt @@ -31,9 +31,17 @@ package com.tencent.bkrepo.oci.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.artifact.api.ArtifactFile +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.oci.pojo.artifact.OciArtifactInfo.Companion.BOLBS_UPLOAD_FIRST_STEP_URL import com.tencent.bkrepo.oci.pojo.artifact.OciArtifactInfo.Companion.BOLBS_UPLOAD_SECOND_STEP_URL @@ -97,6 +105,23 @@ class OciBlobController( /** * 获取Blob文件 */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(BOLBS_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.READ) fun downloadBlob( @@ -109,6 +134,23 @@ class OciBlobController( * 删除blob文件 * 只能通过digest删除 */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(BOLBS_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) fun deleteBlob( diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciManifestController.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciManifestController.kt index 6c6f3f4b53..fde0405fda 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciManifestController.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/OciManifestController.kt @@ -31,9 +31,18 @@ package com.tencent.bkrepo.oci.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.artifact.api.ArtifactFile +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.oci.pojo.artifact.OciArtifactInfo.Companion.MANIFEST_URL import com.tencent.bkrepo.oci.pojo.artifact.OciManifestArtifactInfo @@ -56,6 +65,23 @@ class OciManifestController( * 上传manifest文件 * 可以通过digest或者tag去上传 */ + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PutMapping(MANIFEST_URL) @Permission(ResourceType.REPO, PermissionAction.WRITE) fun uploadManifests( @@ -69,6 +95,23 @@ class OciManifestController( * 下载manifest文件 * 可以通过digest或者tag去下载 */ + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(MANIFEST_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.READ) fun downloadManifests( @@ -81,6 +124,23 @@ class OciManifestController( * 删除manifest文件 * 可以通过digest和tag删除 */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(MANIFEST_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) fun deleteManifests( diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/UserOciController.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/UserOciController.kt index 3d24080a5f..a8982cfd93 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/UserOciController.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/controller/user/UserOciController.kt @@ -27,10 +27,17 @@ package com.tencent.bkrepo.oci.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.oci.constant.OCI_PACKAGE_NAME @@ -91,6 +98,23 @@ class UserOciController( ) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包") @DeleteMapping(OCI_PACKAGE_DELETE_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) @@ -104,6 +128,25 @@ class UserOciController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#artifactInfo?.repoName", + instanceNames = "#artifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @ApiOperation("删除仓库下的包版本") @DeleteMapping(OCI_VERSION_DELETE_URL) @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciBlobServiceImpl.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciBlobServiceImpl.kt index a10ebc551b..338f5a1921 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciBlobServiceImpl.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciBlobServiceImpl.kt @@ -31,6 +31,7 @@ package com.tencent.bkrepo.oci.service.impl +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.common.api.constant.CharPool import com.tencent.bkrepo.common.api.constant.HttpStatus @@ -166,6 +167,7 @@ class OciBlobServiceImpl( md5 = nodeProperty.md5!!, metadata = metadata ) + ActionAuditContext.current().setInstance(nodeCreateRequest) nodeService.createNode(nodeCreateRequest) val blobLocation = OciLocationUtils.blobLocation(ociDigest, this) val responseProperty = ResponseProperty( diff --git a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciOperationServiceImpl.kt b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciOperationServiceImpl.kt index 007cc1d245..710ebf4073 100644 --- a/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciOperationServiceImpl.kt +++ b/src/backend/oci/biz-oci/src/main/kotlin/com/tencent/bkrepo/oci/service/impl/OciOperationServiceImpl.kt @@ -27,6 +27,7 @@ package com.tencent.bkrepo.oci.service.impl +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.api.constant.DEFAULT_PAGE_NUMBER import com.tencent.bkrepo.common.api.constant.HttpHeaders import com.tencent.bkrepo.common.api.constant.StringPool @@ -407,6 +408,7 @@ class OciOperationServiceImpl( md5 = fileInfo.md5, sha256 = fileInfo.sha256 ) + ActionAuditContext.current().setInstance(newNodeRequest) nodeService.createNode(newNodeRequest) } else { storageManager.storeArtifactFile(request, artifactFile, storageCredentials) @@ -679,6 +681,7 @@ class OciOperationServiceImpl( md5 = nodeProperty.md5 ?: StringPool.UNKNOWN, userId = userId ) + ActionAuditContext.current().setInstance(nodeCreateRequest) nodeService.createNode(nodeCreateRequest) } val metadataMap = metadataService.listMetadata(projectId, repoName, fullPath) diff --git a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/artifact/repository/PypiLocalRepository.kt b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/artifact/repository/PypiLocalRepository.kt index 92a4e89c8a..4f81f103db 100644 --- a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/artifact/repository/PypiLocalRepository.kt +++ b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/artifact/repository/PypiLocalRepository.kt @@ -27,6 +27,10 @@ package com.tencent.bkrepo.pypi.artifact.repository +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.constant.StringPool import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactInfo @@ -43,6 +47,9 @@ import com.tencent.bkrepo.common.artifact.util.PackageKeys import com.tencent.bkrepo.common.metadata.service.packages.StageService import com.tencent.bkrepo.common.metadata.util.version.SemVersion import com.tencent.bkrepo.common.metadata.util.version.SemVersionParser +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE import com.tencent.bkrepo.common.query.enums.OperationType import com.tencent.bkrepo.common.query.model.PageLimit import com.tencent.bkrepo.common.query.model.QueryModel @@ -228,6 +235,23 @@ class PypiLocalRepository( /** * pypi 产品删除接口 */ + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactFullPath", + instanceNames = "#artifactFullPath" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#context?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#context?.repoName") + ], + scopeId = "#context?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) override fun remove(context: ArtifactRemoveContext) { val packageKey = HttpContextHolder.getRequest().getParameter("packageKey") val name = PackageKeys.resolvePypi(packageKey) diff --git a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiResourceController.kt b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiResourceController.kt index 769a43e5ec..d9f177f60d 100644 --- a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiResourceController.kt +++ b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiResourceController.kt @@ -31,7 +31,15 @@ package com.tencent.bkrepo.pypi.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.artifact.api.ArtifactFileMap +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.pypi.artifact.PypiArtifactInfo import com.tencent.bkrepo.pypi.artifact.PypiSimpleArtifactInfo import com.tencent.bkrepo.pypi.service.PypiService @@ -50,6 +58,24 @@ import org.springframework.web.bind.annotation.RestController class PypiResourceController( private var pypiService: PypiService ) { + + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#pypiArtifactInfo?.getArtifactFullPath()", + instanceNames = "#pypiArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#pypiArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#pypiArtifactInfo?.repoName") + ], + scopeId = "#pypiArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) @PostMapping(PypiArtifactInfo.PYPI_ROOT_POST_URI) fun upload(pypiArtifactInfo: PypiArtifactInfo, artifactFileMap: ArtifactFileMap) { logger.info("upload pypi package: $pypiArtifactInfo") @@ -75,6 +101,23 @@ class PypiResourceController( return pypiService.simple(artifactInfo) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) @GetMapping(PypiArtifactInfo.PYPI_PACKAGES_MAPPING_URI) fun packages(artifactInfo: PypiArtifactInfo) { logger.info("packages pypi package: $artifactInfo") diff --git a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiWebResourceController.kt b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiWebResourceController.kt index fc4029bd5c..309a7532d2 100644 --- a/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiWebResourceController.kt +++ b/src/backend/pypi/biz-pypi/src/main/kotlin/com/tencent/bkrepo/pypi/controller/PypiWebResourceController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.pypi.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Page import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.pypi.artifact.PypiArtifactInfo import com.tencent.bkrepo.pypi.service.PypiWebService @@ -50,6 +57,24 @@ import org.springframework.web.bind.annotation.RestController class PypiWebResourceController( private val pypiWebService: PypiWebService ) { + + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#pypiArtifactInfo?.repoName", + instanceNames = "#pypiArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#pypiArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#pypiArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) @ApiOperation("pypi包删除接口") @DeleteMapping(PypiArtifactInfo.PYPI_EXT_PACKAGE_DELETE) fun deletePackage(pypiArtifactInfo: PypiArtifactInfo, packageKey: String): Response { @@ -57,6 +82,25 @@ class PypiWebResourceController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#pypiArtifactInfo?.repoName", + instanceNames = "#pypiArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#pypiArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#pypiArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) @ApiOperation("pypi版本删除接口") @DeleteMapping(PypiArtifactInfo.PYPI_EXT_VERSION_DELETE) fun deleteVersion( diff --git a/src/backend/replication/biz-replication/src/main/kotlin/com/tencent/bkrepo/replication/controller/api/RemoteDistributionController.kt b/src/backend/replication/biz-replication/src/main/kotlin/com/tencent/bkrepo/replication/controller/api/RemoteDistributionController.kt index 6ad71220f6..acf4006a0c 100644 --- a/src/backend/replication/biz-replication/src/main/kotlin/com/tencent/bkrepo/replication/controller/api/RemoteDistributionController.kt +++ b/src/backend/replication/biz-replication/src/main/kotlin/com/tencent/bkrepo/replication/controller/api/RemoteDistributionController.kt @@ -27,9 +27,16 @@ package com.tencent.bkrepo.replication.controller.api +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.replication.pojo.cluster.ClusterNodeInfo @@ -57,6 +64,7 @@ import org.springframework.web.bind.annotation.RestController class RemoteDistributionController( private val remoteNodeService: RemoteNodeService ) { + @ApiOperation("创建远端集群节点") @Permission(ResourceType.REPO, PermissionAction.WRITE) @PostMapping("/create/{projectId}/{repoName}") @@ -150,9 +158,27 @@ class RemoteDistributionController( return ResponseBuilder.success() } + /** * 创建一次性分发任务 */ + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#repoName"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_REPLICATION_CREATE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.WRITE) @PostMapping("/create/runOnceTask/{projectId}/{repoName}") fun createRunOnceTask( @@ -166,9 +192,28 @@ class RemoteDistributionController( return ResponseBuilder.success() } + /** * 手动调用一次性执行任务 */ + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#repoName"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#name"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_REPLICATION_EXECUTE_CONTENT + ) @Permission(ResourceType.REPO, PermissionAction.WRITE) @PostMapping("/execute/runOnceTask/{projectId}/{repoName}") fun executeRunOnceTask( diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserMetadataController.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserMetadataController.kt index e0a6f332dd..7fccda0d93 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserMetadataController.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserMetadataController.kt @@ -31,12 +31,21 @@ package com.tencent.bkrepo.repository.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactInfo import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable import com.tencent.bkrepo.common.artifact.api.DefaultArtifactInfo.Companion.DEFAULT_MAPPING_URI +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_VIEW_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.security.util.SecurityUtils import com.tencent.bkrepo.common.service.util.ResponseBuilder @@ -65,6 +74,23 @@ class UserMetadataController( private val metadataService: MetadataService ) { + @AuditEntry( + actionId = NODE_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = NODE_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_METADATA_VIEW_CONTENT + ) @ApiOperation("查询元数据列表") @Permission(type = ResourceType.NODE, action = PermissionAction.READ) @GetMapping(DEFAULT_MAPPING_URI) @@ -77,6 +103,23 @@ class UserMetadataController( } } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_METADATA_EDIT_CONTENT + ) @ApiOperation("创建/更新元数据列表") @Permission(type = ResourceType.NODE, action = PermissionAction.WRITE) @PostMapping(DEFAULT_MAPPING_URI) @@ -94,11 +137,29 @@ class UserMetadataController( nodeMetadata = metadataSaveRequest.nodeMetadata?.map { it.copy(system = false) }, operator = SecurityUtils.getUserId() ) + ActionAuditContext.current().setInstance(request) metadataService.saveMetadata(request) return ResponseBuilder.success() } } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_METADATA_FORBID_CONTENT + ) @ApiOperation("创建/更新禁用元数据") @Permission(type = ResourceType.REPO, action = PermissionAction.UPDATE) @PostMapping("/forbid$DEFAULT_MAPPING_URI") @@ -114,11 +175,29 @@ class UserMetadataController( fullPath = getArtifactFullPath(), nodeMetadata = metadataSaveRequest.nodeMetadata ) + ActionAuditContext.current().setInstance(request) metadataService.addForbidMetadata(request) return ResponseBuilder.success() } } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_METADATA_DELETE_CONTENT + ) @ApiOperation("删除元数据") @Permission(type = ResourceType.NODE, action = PermissionAction.DELETE) @DeleteMapping(DEFAULT_MAPPING_URI) @@ -135,6 +214,7 @@ class UserMetadataController( keyList = metadataDeleteRequest.keyList, operator = SecurityUtils.getUserId() ) + ActionAuditContext.current().setInstance(request) metadataService.deleteMetadata(request, false) return ResponseBuilder.success() } diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserNodeController.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserNodeController.kt index 8db62f11cf..9f3d0f4790 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserNodeController.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserNodeController.kt @@ -31,6 +31,11 @@ package com.tencent.bkrepo.repository.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.exception.ErrorCodeException @@ -39,6 +44,12 @@ import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.artifact.api.ArtifactInfo import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable import com.tencent.bkrepo.common.artifact.api.DefaultArtifactInfo.Companion.DEFAULT_MAPPING_URI +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_VIEW_ACTION import com.tencent.bkrepo.common.artifact.message.ArtifactMessageCode import com.tencent.bkrepo.common.artifact.path.PathUtils import com.tencent.bkrepo.common.metadata.permission.PermissionManager @@ -96,6 +107,23 @@ class UserNodeController( private val permissionManager: PermissionManager, ) { + @AuditEntry( + actionId = NODE_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = NODE_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_VIEW_CONTENT + ) @ApiOperation("根据路径查看节点详情") @Permission(type = ResourceType.NODE, action = PermissionAction.READ) @GetMapping(DEFAULT_MAPPING_URI/* Deprecated */, "/detail/$DEFAULT_MAPPING_URI") @@ -108,6 +136,23 @@ class UserNodeController( return ResponseBuilder.success(node) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_CREATE_CONTENT + ) @ApiOperation("创建文件夹") @Permission(type = ResourceType.REPO, action = PermissionAction.WRITE) @PostMapping(DEFAULT_MAPPING_URI/* Deprecated */, "/mkdir/$DEFAULT_MAPPING_URI") @@ -124,11 +169,29 @@ class UserNodeController( overwrite = false, operator = userId, ) + ActionAuditContext.current().setInstance(createRequest) nodeService.createNode(createRequest) return ResponseBuilder.success() } } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @ApiOperation("删除节点") @Permission(type = ResourceType.NODE, action = PermissionAction.DELETE) @DeleteMapping(DEFAULT_MAPPING_URI/* Deprecated */, "/delete/$DEFAULT_MAPPING_URI") @@ -143,10 +206,28 @@ class UserNodeController( fullPath = getArtifactFullPath(), operator = userId, ) + ActionAuditContext.current().setInstance(deleteRequest) return ResponseBuilder.success(nodeService.deleteNode(deleteRequest)) } } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#fullPaths", + instanceNames = "#fullPaths" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#repoName") + ], + scopeId = "#projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @ApiOperation("批量删除节点") @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) @DeleteMapping("/batch/{projectId}/{repoName}") @@ -164,6 +245,7 @@ class UserNodeController( fullPaths = fullPaths, operator = userId, ) + ActionAuditContext.current().setInstance(nodesDeleteRequest) return ResponseBuilder.success(nodeService.deleteNodes(nodesDeleteRequest)) } @@ -189,6 +271,25 @@ class UserNodeController( return ResponseBuilder.success(nodeService.countDeleteNodes(nodesDeleteRequest)) } + + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.DATE_TEMPLATE, value = "#date") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_CLEAN_CONTENT + ) @ApiOperation("清理最后访问时间早于{date}的文件节点") @Permission(type = ResourceType.NODE, action = PermissionAction.DELETE) @DeleteMapping("/clean/$DEFAULT_MAPPING_URI") @@ -237,6 +338,24 @@ class UserNodeController( } } + @AuditEntry( + actionId = NODE_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = NODE_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.EXPIRES_DYAS_TEMPLATE, value = "#request?.expires") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_EXPIRES_EDIT_CONTENT + ) @ApiOperation("更新节点") @Permission(type = ResourceType.NODE, action = PermissionAction.UPDATE) @PostMapping("/update/$DEFAULT_MAPPING_URI") @@ -258,6 +377,24 @@ class UserNodeController( } } + @AuditEntry( + actionId = NODE_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = NODE_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#newFullPath") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_RENAME_CONTENT + ) @ApiOperation("重命名节点") @Permission(type = ResourceType.NODE, action = PermissionAction.UPDATE) @PostMapping("/rename/$DEFAULT_MAPPING_URI") @@ -275,6 +412,7 @@ class UserNodeController( newFullPath = newFullPath, operator = userId, ) + ActionAuditContext.current().setInstance(renameRequest) nodeService.renameNode(renameRequest) return ResponseBuilder.success() } @@ -297,11 +435,35 @@ class UserNodeController( newFullPath = newFullPath, operator = userId, ) + ActionAuditContext.current().setInstance(renameRequest) nodeService.renameNode(renameRequest) return ResponseBuilder.success() } } + @AuditEntry( + actionId = NODE_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = NODE_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#request?.srcFullPath", + instanceNames = "#request?.srcFullPath" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#request?.srcProjectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#request?.srcRepoName"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#request?.destFullPath"), + AuditAttribute( + name = ActionAuditContent.NEW_PROJECT_CODE_CONTENT_TEMPLATE, + value = "#request?.destProjectId" + ), + AuditAttribute(name = ActionAuditContent.NEW_REPO_NAME_CONTENT_TEMPLATE, value = "#request?.destRepoName"), + ], + scopeId = "#request?.srcProjectId", + content = ActionAuditContent.NODE_MOVE_CONTENT + ) @ApiOperation("移动节点") @PostMapping("/move") fun moveNode( @@ -320,11 +482,35 @@ class UserNodeController( overwrite = overwrite, operator = userId, ) + ActionAuditContext.current().setInstance(moveRequest) nodeService.moveNode(moveRequest) return ResponseBuilder.success() } } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#request?.srcFullPath", + instanceNames = "#request?.srcFullPath" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#request?.srcProjectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#request?.srcRepoName"), + AuditAttribute( + name = ActionAuditContent.NEW_PROJECT_CODE_CONTENT_TEMPLATE, + value = "#request?.destProjectId" + ), + AuditAttribute(name = ActionAuditContent.NEW_REPO_NAME_CONTENT_TEMPLATE, value = "#request?.destRepoName"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#request?.destFullPath") + ], + scopeId = "#request?.srcProjectId", + content = ActionAuditContent.NODE_COPY_CONTENT + ) @ApiOperation("复制节点") @PostMapping("/copy") fun copyNode( @@ -343,6 +529,7 @@ class UserNodeController( overwrite = overwrite, operator = userId, ) + ActionAuditContext.current().setInstance(copyRequest) nodeService.copyNode(copyRequest) return ResponseBuilder.success() } @@ -399,6 +586,24 @@ class UserNodeController( return ResponseBuilder.success(nodeService.listDeletedPoint(artifactInfo)) } + @AuditEntry( + actionId = NODE_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = NODE_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.DATE_TEMPLATE, value = "#nodeRestoreOption?.deletedId") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_RESTORE_CONTENT + ) @ApiOperation("恢复被删除节点") @Permission(type = ResourceType.NODE, action = PermissionAction.WRITE) @PostMapping("/restore/$DEFAULT_MAPPING_URI") @@ -406,6 +611,7 @@ class UserNodeController( artifactInfo: ArtifactInfo, nodeRestoreOption: NodeRestoreOption, ): Response { + ActionAuditContext.current().setInstance(nodeRestoreOption) return ResponseBuilder.success(nodeService.restoreNode(artifactInfo, nodeRestoreOption)) } diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserProjectController.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserProjectController.kt index 5bc1c43138..bf4d2e06a8 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserProjectController.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserProjectController.kt @@ -27,11 +27,20 @@ package com.tencent.bkrepo.repository.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.annotations.AuditRequestBody +import com.tencent.bk.audit.context.ActionAuditContext +import com.tencent.bkrepo.common.artifact.audit.PROJECT_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.PROJECT_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.PROJECT_RESOURCE import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.common.api.pojo.Page import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.metadata.permission.PermissionManager import com.tencent.bkrepo.common.metadata.service.project.ProjectService +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent import com.tencent.bkrepo.common.security.permission.Principal import com.tencent.bkrepo.common.security.permission.PrincipalType import com.tencent.bkrepo.common.service.util.ResponseBuilder @@ -62,11 +71,25 @@ class UserProjectController( private val permissionManager: PermissionManager, private val projectService: ProjectService ) { + @AuditEntry( + actionId = PROJECT_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = PROJECT_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = PROJECT_RESOURCE, + instanceIds = "#userProjectRequest?.name", + instanceNames = "#userProjectRequest?.displayName" + ), + scopeId = "#userProjectRequest?.name", + content = ActionAuditContent.PROJECT_CREATE_CONTENT + ) @ApiOperation("创建项目") @Principal(PrincipalType.GENERAL) @PostMapping("/create") fun createProject( @RequestAttribute userId: String, + @AuditRequestBody @RequestBody userProjectRequest: UserProjectCreateRequest ): Response { val createRequest = with(userProjectRequest) { @@ -79,6 +102,7 @@ class UserProjectController( metadata = metadata ) } + ActionAuditContext.current().setInstance(createRequest) projectService.createProject(createRequest) return ResponseBuilder.success() } @@ -106,14 +130,30 @@ class UserProjectController( return ResponseBuilder.success(projectService.checkProjectExist(name, displayName)) } + + @AuditEntry( + actionId = PROJECT_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = PROJECT_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = PROJECT_RESOURCE, + instanceIds = "#name", + instanceNames = "#name" + ), + scopeId = "#name", + content = ActionAuditContent.PROJECT_EDIT_CONTENT + ) @ApiOperation("编辑项目") @PutMapping("/{name}") fun updateProject( @RequestAttribute userId: String, @ApiParam(value = "项目ID", required = true) @PathVariable name: String, + @AuditRequestBody @RequestBody projectUpdateRequest: ProjectUpdateRequest ): Response { + ActionAuditContext.current().setInstance(projectUpdateRequest) permissionManager.checkProjectPermission(PermissionAction.UPDATE, name) return ResponseBuilder.success(projectService.updateProject(name, projectUpdateRequest)) } @@ -134,6 +174,19 @@ class UserProjectController( return ResponseBuilder.success(projectService.listPermissionProject(userId, option)) } + @AuditEntry( + actionId = PROJECT_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = PROJECT_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = PROJECT_RESOURCE, + instanceIds = "#userProjectRequest?.name", + instanceNames = "#userProjectRequest?.displayName" + ), + scopeId = "#userProjectRequest?.name", + content = ActionAuditContent.PROJECT_CREATE_CONTENT + ) @Deprecated("waiting kb-ci", replaceWith = ReplaceWith("createProject")) @ApiOperation("创建项目") @Principal(PrincipalType.PLATFORM) diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserRepositoryController.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserRepositoryController.kt index 897d992623..95599a3c17 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserRepositoryController.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserRepositoryController.kt @@ -27,11 +27,25 @@ package com.tencent.bkrepo.repository.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.annotations.AuditRequestBody +import com.tencent.bk.audit.context.ActionAuditContext +import com.tencent.bkrepo.common.artifact.audit.PROJECT_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.PROJECT_VIEW_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.REPO_VIEW_ACTION import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Page import com.tencent.bkrepo.common.api.pojo.Response import com.tencent.bkrepo.common.metadata.permission.PermissionManager +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent import com.tencent.bkrepo.common.metadata.service.node.NodeService import com.tencent.bkrepo.common.metadata.service.repo.QuotaService import com.tencent.bkrepo.common.metadata.service.repo.RepositoryService @@ -70,6 +84,22 @@ class UserRepositoryController( private val nodeService: NodeService ) { + @AuditEntry( + actionId = REPO_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = REPO_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_VIEW_CONTENT + ) @ApiOperation("根据名称类型查询仓库") @Permission(type = ResourceType.REPO, action = PermissionAction.READ) @GetMapping("/info/{projectId}/{repoName}", "/info/{projectId}/{repoName}/{type}") @@ -100,10 +130,30 @@ class UserRepositoryController( return ResponseBuilder.success(repositoryService.checkExist(projectId, repoName)) } + @AuditEntry( + actionId = REPO_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = REPO_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#userRepoCreateRequest?.name", + instanceNames = "#userRepoCreateRequest?.name" + ), + attributes = [ + AuditAttribute( + name = ActionAuditContent.PROJECT_CODE_TEMPLATE, + value = "#userRepoCreateRequest?.projectId" + ), + ], + scopeId = "#userRepoCreateRequest?.projectId", + content = ActionAuditContent.REPO_CREATE_CONTENT + ) @ApiOperation("创建仓库") @PostMapping("/create") fun createRepo( @RequestAttribute userId: String, + @AuditRequestBody @RequestBody userRepoCreateRequest: UserRepoCreateRequest, ): Response { val createRequest = with(userRepoCreateRequest) { @@ -126,9 +176,26 @@ class UserRepositoryController( display = display, ) } + ActionAuditContext.current().setInstance(createRequest) return ResponseBuilder.success(repositoryService.createRepo(createRequest)) } + @AuditEntry( + actionId = REPO_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = REPO_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoListOption?.name", + instanceNames = "#repoListOption?.name", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_LIST_CONTENT + ) @ApiOperation("查询有权限的仓库列表") @GetMapping("/list/{projectId}") fun listUserRepo( @@ -141,6 +208,22 @@ class UserRepositoryController( return ResponseBuilder.success(repositoryService.listPermissionRepo(userId, projectId, repoListOption)) } + @AuditEntry( + actionId = PROJECT_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = PROJECT_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = PROJECT_RESOURCE, + instanceIds = "#projectId", + instanceNames = "#projectId", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_LIST_CONTENT + ) @ApiOperation("分页查询有权限的仓库列表") @GetMapping("/page/{projectId}/{pageNumber}/{pageSize}") fun listUserRepoPage( @@ -160,6 +243,22 @@ class UserRepositoryController( return ResponseBuilder.success(page) } + @AuditEntry( + actionId = REPO_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = REPO_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_QUOTE_VIEW_CONTENT + ) @ApiOperation("查询仓库配额") @Permission(type = ResourceType.REPO, action = PermissionAction.READ) @GetMapping("/quota/{projectId}/{repoName}") @@ -174,6 +273,23 @@ class UserRepositoryController( return ResponseBuilder.success(quotaService.getRepoQuotaInfo(projectId, repoName)) } + + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_QUOTE_EDIT_CONTENT + ) @ApiOperation("修改仓库配额") @Permission(type = ResourceType.REPO, action = PermissionAction.MANAGE) @PostMapping("/quota/{projectId}/{repoName}") @@ -195,10 +311,27 @@ class UserRepositoryController( quota = quota, operator = userId, ) + ActionAuditContext.current().setInstance(repoUpdateRequest) repositoryService.updateRepo(repoUpdateRequest) return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = REPO_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_DELETE_CONTENT + ) @ApiOperation("删除仓库") @Permission(type = ResourceType.REPO, action = PermissionAction.DELETE) @DeleteMapping("/delete/{projectId}/{repoName}") @@ -218,6 +351,22 @@ class UserRepositoryController( return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#repoName", + instanceNames = "#repoName", + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#projectId"), + ], + scopeId = "#projectId", + content = ActionAuditContent.REPO_EDIT_CONTENT + ) @ApiOperation("更新仓库") @Permission(type = ResourceType.REPO, action = PermissionAction.MANAGE) @PostMapping("/update/{projectId}/{repoName}") @@ -240,10 +389,29 @@ class UserRepositoryController( operator = userId, display = request.display ) + ActionAuditContext.current().setInstance(repoUpdateRequest) repositoryService.updateRepo(repoUpdateRequest) return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = REPO_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#userRepoCreateRequest?.name", + instanceNames = "#userRepoCreateRequest?.name" + ), + attributes = [ + AuditAttribute( + name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#userRepoCreateRequest?.projectId" + ), + ], + scopeId = "#userRepoCreateRequest?.projectId", + content = ActionAuditContent.REPO_CREATE_CONTENT + ) @Deprecated("waiting kb-ci and bk", replaceWith = ReplaceWith("createRepo")) @ApiOperation("创建仓库") @PostMapping diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserShareController.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserShareController.kt index 95830c762a..6c7a04552a 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserShareController.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/controller/user/UserShareController.kt @@ -31,6 +31,14 @@ package com.tencent.bkrepo.repository.controller.user +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_VIEW_ACTION import com.tencent.bkrepo.auth.pojo.enums.PermissionAction import com.tencent.bkrepo.auth.pojo.enums.ResourceType import com.tencent.bkrepo.common.api.pojo.Response @@ -40,6 +48,7 @@ import com.tencent.bkrepo.common.artifact.api.DefaultArtifactInfo import com.tencent.bkrepo.common.artifact.api.DefaultArtifactInfo.Companion.DEFAULT_MAPPING_URI import com.tencent.bkrepo.common.artifact.path.PathUtils import com.tencent.bkrepo.common.metadata.permission.PermissionManager +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent import com.tencent.bkrepo.common.security.permission.Permission import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.repository.pojo.share.BatchShareRecordCreateRequest @@ -67,6 +76,23 @@ class UserShareController( private val shareService: ShareService ) { + @AuditEntry( + actionId = NODE_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = NODE_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_SHARE_CREATE_CONTENT + ) @ApiOperation("创建分享链接") @Permission(type = ResourceType.NODE, action = PermissionAction.WRITE) @PostMapping(DEFAULT_MAPPING_URI) @@ -75,9 +101,33 @@ class UserShareController( @ArtifactPathVariable artifactInfo: ArtifactInfo, @RequestBody shareRecordCreateRequest: ShareRecordCreateRequest ): Response { + ActionAuditContext.current().setInstance(shareRecordCreateRequest) return ResponseBuilder.success(shareService.create(userId, artifactInfo, shareRecordCreateRequest)) } + @AuditEntry( + actionId = NODE_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = NODE_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#batchShareRecordCreateRequest?.fullPathList", + instanceNames = "#batchShareRecordCreateRequest?.fullPathList", + ), + attributes = [ + AuditAttribute( + name = ActionAuditContent.PROJECT_CODE_TEMPLATE, + value = "#batchShareRecordCreateRequest?.projectId" + ), + AuditAttribute( + name = ActionAuditContent.REPO_NAME_TEMPLATE, + value = "#batchShareRecordCreateRequest?.repoName" + ) + ], + scopeId = "#batchShareRecordCreateRequest?.projectId", + content = ActionAuditContent.NODE_SHARE_CREATE_CONTENT + ) @ApiOperation("批量创建分享链接") @PostMapping("/batch") fun batchShare( @@ -85,6 +135,7 @@ class UserShareController( @RequestBody batchShareRecordCreateRequest: BatchShareRecordCreateRequest ): Response> { with(batchShareRecordCreateRequest) { + ActionAuditContext.current().setInstance(batchShareRecordCreateRequest) val shareRecordCreateRequest = ShareRecordCreateRequest(authorizedUserList, authorizedIpList, expireSeconds) val recordInfoList = fullPathList.map { val fullPath = PathUtils.normalizeFullPath(it) @@ -96,6 +147,33 @@ class UserShareController( } } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()", + ), + attributes = [ + AuditAttribute( + name = ActionAuditContent.PROJECT_CODE_TEMPLATE, + value = "#artifactInfo?.projectId" + ), + AuditAttribute( + name = ActionAuditContent.REPO_NAME_TEMPLATE, + value = "#artifactInfo?.repoName" + ), + AuditAttribute( + name = ActionAuditContent.TOKEN_TEMPLATE, + value = "#token" + ) + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_SHARE_DOWNLOAD_CONTENT + ) @ApiOperation("下载分享文件") @GetMapping(DEFAULT_MAPPING_URI) fun download( @@ -105,6 +183,7 @@ class UserShareController( @ArtifactPathVariable artifactInfo: ArtifactInfo ) { val downloadUser = downloadUserId ?: userId + ActionAuditContext.current().addExtendData("downloadUser", downloadUser) shareService.download(downloadUser, token, artifactInfo) } } diff --git a/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceController.kt b/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceController.kt index 61d04c4cc3..e1b8b981b5 100644 --- a/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceController.kt +++ b/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceController.kt @@ -31,8 +31,20 @@ package com.tencent.bkrepo.rpm.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.artifact.api.ArtifactFile import com.tencent.bkrepo.common.artifact.api.ArtifactPathVariable +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_DELETE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.rpm.api.RpmResource import com.tencent.bkrepo.rpm.artifact.RpmArtifactInfo import com.tencent.bkrepo.rpm.servcie.RpmService @@ -43,22 +55,108 @@ import org.springframework.web.bind.annotation.RestController class RpmResourceController( private val rpmService: RpmService ) : RpmResource { + + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#rpmArtifactInfo?.getArtifactFullPath()", + instanceNames = "#rpmArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#rpmArtifactInfo?.repoName") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) override fun deploy(rpmArtifactInfo: RpmArtifactInfo, artifactFile: ArtifactFile) { rpmService.deploy(rpmArtifactInfo, artifactFile) } + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#rpmArtifactInfo?.getArtifactFullPath()", + instanceNames = "#rpmArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#rpmArtifactInfo?.repoName") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) override fun install(rpmArtifactInfo: RpmArtifactInfo) { rpmService.install(rpmArtifactInfo) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#rpmArtifactInfo?.repoName", + instanceNames = "#rpmArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.REPO_EDIT_CONTENT + ) override fun addGroups(rpmArtifactInfo: RpmArtifactInfo, groups: MutableSet) { + ActionAuditContext.current().setInstance(groups) rpmService.addGroups(rpmArtifactInfo, groups) } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#rpmArtifactInfo?.repoName", + instanceNames = "#rpmArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.REPO_EDIT_CONTENT + ) override fun deleteGroups(rpmArtifactInfo: RpmArtifactInfo, groups: MutableSet) { + ActionAuditContext.current().setInstance(groups) rpmService.deleteGroups(rpmArtifactInfo, groups) } + @AuditEntry( + actionId = NODE_DELETE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DELETE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#rpmArtifactInfo?.getArtifactFullPath()", + instanceNames = "#rpmArtifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#rpmArtifactInfo?.repoName") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.NODE_DELETE_CONTENT + ) @DeleteMapping(RpmArtifactInfo.RPM) fun delete(@ArtifactPathVariable rpmArtifactInfo: RpmArtifactInfo) { rpmService.delete(rpmArtifactInfo) diff --git a/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceWebController.kt b/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceWebController.kt index f455e6d7ac..0e49f8e4cf 100644 --- a/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceWebController.kt +++ b/src/backend/rpm/biz-rpm/src/main/kotlin/com/tencent/bkrepo/rpm/controller/RpmResourceWebController.kt @@ -31,8 +31,15 @@ package com.tencent.bkrepo.rpm.controller +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord import com.tencent.bkrepo.common.api.pojo.Page import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.REPO_EDIT_ACTION +import com.tencent.bkrepo.common.artifact.audit.REPO_RESOURCE import com.tencent.bkrepo.common.service.util.ResponseBuilder import com.tencent.bkrepo.rpm.api.RpmWebResource import com.tencent.bkrepo.rpm.artifact.RpmArtifactInfo @@ -46,11 +53,48 @@ import org.springframework.web.bind.annotation.RestController class RpmResourceWebController( private val rpmWebService: RpmWebService ) : RpmWebResource { + + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#rpmArtifactInfo?.repoName", + instanceNames = "#rpmArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey") + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_DELETE_CONTENT + ) override fun deletePackage(rpmArtifactInfo: RpmArtifactInfo, packageKey: String): Response { rpmWebService.deletePackage(rpmArtifactInfo, packageKey) return ResponseBuilder.success() } + @AuditEntry( + actionId = REPO_EDIT_ACTION + ) + @ActionAuditRecord( + actionId = REPO_EDIT_ACTION, + instance = AuditInstanceRecord( + resourceType = REPO_RESOURCE, + instanceIds = "#rpmArtifactInfo?.repoName", + instanceNames = "#rpmArtifactInfo?.repoName" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#rpmArtifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#packageKey"), + AuditAttribute(name = ActionAuditContent.VERSION_TEMPLATE, value = "#version") + + ], + scopeId = "#rpmArtifactInfo?.projectId", + content = ActionAuditContent.REPO_PACKAGE_VERSION_DELETE_CONTENT + ) override fun deleteVersion(rpmArtifactInfo: RpmArtifactInfo, packageKey: String, version: String?): Response { rpmWebService.delete(rpmArtifactInfo, packageKey, version) return ResponseBuilder.success() diff --git a/src/backend/s3/biz-s3/src/main/kotlin/com/tencent/bkrepo/s3/service/S3ObjectService.kt b/src/backend/s3/biz-s3/src/main/kotlin/com/tencent/bkrepo/s3/service/S3ObjectService.kt index 2b9a4f9b0c..dd150e898d 100644 --- a/src/backend/s3/biz-s3/src/main/kotlin/com/tencent/bkrepo/s3/service/S3ObjectService.kt +++ b/src/backend/s3/biz-s3/src/main/kotlin/com/tencent/bkrepo/s3/service/S3ObjectService.kt @@ -31,6 +31,11 @@ package com.tencent.bkrepo.s3.service +import com.tencent.bk.audit.annotations.ActionAuditRecord +import com.tencent.bk.audit.annotations.AuditAttribute +import com.tencent.bk.audit.annotations.AuditEntry +import com.tencent.bk.audit.annotations.AuditInstanceRecord +import com.tencent.bk.audit.context.ActionAuditContext import com.tencent.bkrepo.common.api.constant.HttpStatus import com.tencent.bkrepo.common.api.constant.StringPool import com.tencent.bkrepo.common.api.constant.StringPool.SLASH @@ -42,6 +47,12 @@ import com.tencent.bkrepo.common.artifact.repository.context.ArtifactContextHold import com.tencent.bkrepo.common.artifact.repository.context.ArtifactDownloadContext import com.tencent.bkrepo.common.artifact.repository.context.ArtifactUploadContext import com.tencent.bkrepo.common.artifact.repository.core.ArtifactService +import com.tencent.bkrepo.common.artifact.audit.ActionAuditContent +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_DOWNLOAD_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_RESOURCE +import com.tencent.bkrepo.common.artifact.audit.NODE_VIEW_ACTION +import com.tencent.bkrepo.common.artifact.audit.NODE_CREATE_ACTION import com.tencent.bkrepo.common.generic.configuration.AutoIndexRepositorySettings import com.tencent.bkrepo.common.metadata.service.metadata.MetadataService import com.tencent.bkrepo.common.metadata.service.node.NodeSearchService @@ -80,6 +91,23 @@ class S3ObjectService( private val metadataService: MetadataService ) : ArtifactService() { + @AuditEntry( + actionId = NODE_DOWNLOAD_ACTION + ) + @ActionAuditRecord( + actionId = NODE_DOWNLOAD_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_DOWNLOAD_CONTENT + ) fun getObject(artifactInfo: S3ArtifactInfo) { val node = ArtifactContextHolder.getNodeDetail(artifactInfo) ?: throw S3NotFoundException( @@ -103,11 +131,46 @@ class S3ObjectService( repository.download(context) } + + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_UPLOAD_CONTENT + ) fun putObject(artifactInfo: S3ArtifactInfo, file: ArtifactFile) { val context = ArtifactUploadContext(file) repository.upload(context) } + @AuditEntry( + actionId = NODE_VIEW_ACTION + ) + @ActionAuditRecord( + actionId = NODE_VIEW_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#prefix", + instanceNames = "#prefix" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_VIEW_CONTENT + ) fun listObjects( artifactInfo: S3ArtifactInfo, marker: Int, @@ -162,6 +225,24 @@ class S3ObjectService( return ListBucketResult(repoName, data, maxKeys, prefix, folders, delimiter, currentNode) } + @AuditEntry( + actionId = NODE_CREATE_ACTION + ) + @ActionAuditRecord( + actionId = NODE_CREATE_ACTION, + instance = AuditInstanceRecord( + resourceType = NODE_RESOURCE, + instanceIds = "#artifactInfo?.getArtifactFullPath()", + instanceNames = "#artifactInfo?.getArtifactFullPath()" + ), + attributes = [ + AuditAttribute(name = ActionAuditContent.PROJECT_CODE_TEMPLATE, value = "#artifactInfo?.projectId"), + AuditAttribute(name = ActionAuditContent.REPO_NAME_TEMPLATE, value = "#artifactInfo?.repoName"), + AuditAttribute(name = ActionAuditContent.NAME_TEMPLATE, value = "#artifactInfo?.getArtifactFullPath()") + ], + scopeId = "#artifactInfo?.projectId", + content = ActionAuditContent.NODE_COPY_CONTENT + ) fun copyObject(artifactInfo: S3ArtifactInfo): CopyObjectResult { val source = HeaderUtils.getHeader(X_AMZ_COPY_SOURCE) ?: throw IllegalArgumentException(X_AMZ_COPY_SOURCE) val delimiterIndex = source.indexOf(SLASH) @@ -177,6 +258,7 @@ class S3ObjectService( overwrite = true, operator = SecurityUtils.getUserId() ) + ActionAuditContext.current().setInstance(copyRequest) var dstNode = nodeService.copyNode(copyRequest) dstNode = replaceMetadata(dstNode) return CopyObjectResult(