Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: api request - access_key_id not match app_code #42

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions src/bkauth/pkg/api/app/handler/access_key.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -45,19 +45,19 @@ import (
func CreateAccessKey(c *gin.Context) {
errorWrapf := errorx.NewLayerFunctionErrorWrapf("Handler", "CreateAccessKey")

// NOTE: 通过API创建, 不支持指定app_secret
// NOTE: 通过 API 创建,不支持指定 app_secret
createdSource := util.GetAccessAppCode(c)

// TODO: 统一考虑,如何避免获取URL参数的代码重复
// 获取URL参数
// TODO: 统一考虑,如何避免获取 URL 参数的代码重复
// 获取 URL 参数
var uriParams common.AppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
return
}
appCode := uriParams.AppCode

// 创建Secret
// 创建 Secret
svc := service.NewAccessKeyService()
accessKey, err := svc.Create(appCode, createdSource)
if err != nil {
Expand All @@ -73,7 +73,7 @@ func CreateAccessKey(c *gin.Context) {
return
}

// 缓存里删除appCode的所有Secret
// 缓存里删除 appCode 的所有 Secret
cacheImpls.DeleteAccessKey(appCode)

util.SuccessJSONResponse(c, "ok", accessKey)
Expand All @@ -96,18 +96,18 @@ func CreateAccessKey(c *gin.Context) {
func DeleteAccessKey(c *gin.Context) {
errorWrapf := errorx.NewLayerFunctionErrorWrapf("Handler", "DeleteAccessKey")

// TODO: 校验secret创建来源与删除来源是否一致,只有创建者才可以删除???目前只有PaaS可以管理,即增删
// TODO: 校验 secret 创建来源与删除来源是否一致,只有创建者才可以删除???目前只有 PaaS 可以管理,即增删
// source := util.GetAccessAppCode(c)

var uriParams accessKeyAndAppSerializer
var uriParams common.AccessKeyAndAppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
return
}
appCode := uriParams.AppCode
accessKeyID := uriParams.AccessKeyID

// 删除Secret
// 删除 Secret
svc := service.NewAccessKeyService()
err := svc.DeleteByID(appCode, accessKeyID)
if err != nil {
Expand All @@ -123,7 +123,7 @@ func DeleteAccessKey(c *gin.Context) {
return
}

// 缓存里删除appCode的所有Secret
// 缓存里删除 appCode 的所有 Secret
cacheImpls.DeleteAccessKey(appCode)

util.SuccessJSONResponse(c, "ok", nil)
Expand All @@ -143,15 +143,15 @@ func DeleteAccessKey(c *gin.Context) {
// @Header 200 {string} X-Request-Id "the request id"
// @Router /api/v1/apps/{bk_app_code}/access-keys [get]
func ListAccessKey(c *gin.Context) {
// 获取URL参数
// 获取 URL 参数
var uriParams common.AppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
return
}
appCode := uriParams.AppCode

// 创建Secret
// 创建 Secret
svc := service.NewAccessKeyService()
accessKeys, err := svc.ListWithCreatedAtByAppCode(appCode)
if err != nil {
Expand All @@ -178,7 +178,7 @@ func ListAccessKey(c *gin.Context) {
// @Header 200 {string} X-Request-Id "the request id"
// @Router /api/v1/apps/{bk_app_code}/access-keys/verify [post]
func VerifyAccessKey(c *gin.Context) {
// 获取URL参数
// 获取 URL 参数
var uriParams common.AppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
Expand All @@ -202,7 +202,7 @@ func VerifyAccessKey(c *gin.Context) {

data := gin.H{"is_match": exists}
if !exists {
// Note: 这里校验不通过,是业务逻辑,并非接口通讯的认证和鉴权,所以不能返回 401或403 状态码
// Note: 这里校验不通过,是业务逻辑,并非接口通讯的认证和鉴权,所以不能返回 401 或 403 状态码
util.SuccessJSONResponse(c, "bk_app_code or bk_app_secret invalid", data)
return
}
Expand All @@ -227,8 +227,8 @@ func VerifyAccessKey(c *gin.Context) {
// @Router /api/v1/apps/{bk_app_code}/access-keys/{access_key_id} [put]
func UpdateAccessKey(c *gin.Context) {
errorWrapf := errorx.NewLayerFunctionErrorWrapf("Handler", "PutAccessKey")
// 获取URL参数
var uriParams accessKeyAndAppSerializer
// 获取 URL 参数
var uriParams common.AccessKeyAndAppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
return
Expand All @@ -243,9 +243,9 @@ func UpdateAccessKey(c *gin.Context) {
return
}

// 更新accessKey
// 更新 accessKey

// 获取更新的updateFiledMap:如果是空则不更新
// 获取更新的 updateFiledMap:如果是空则不更新
var updateFiledMap map[string]interface{}
err := mapstructure.Decode(body, &updateFiledMap)
if err != nil {
Expand All @@ -267,7 +267,7 @@ func UpdateAccessKey(c *gin.Context) {
return
}

// 缓存里删除appCode的所有Secret
// 缓存里删除 appCode 的所有 Secret
_ = cacheImpls.DeleteAccessKey(uriParams.AppCode)

util.SuccessJSONResponse(c, "ok", nil)
Expand Down
11 changes: 1 addition & 10 deletions src/bkauth/pkg/api/app/handler/access_key_slz.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -18,19 +18,10 @@

package handler

import (
"bkauth/pkg/api/common"
)

type appSecretSerializer struct {
AppSecret string `json:"bk_app_secret" binding:"required,max=128" example:"bk_paas"`
}

type accessKeyAndAppSerializer struct {
common.AppCodeSerializer
AccessKeyID int64 `uri:"access_key_id" binding:"required" example:"1"`
}

type accessKeyUpdateSerializer struct {
Enabled *bool `json:"enabled" binding:"required" example:"true" mapstructure:"enabled,omitempty"`
}
15 changes: 10 additions & 5 deletions src/bkauth/pkg/api/app/router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -21,8 +21,8 @@ package app
import (
"github.com/gin-gonic/gin"

handler "bkauth/pkg/api/app/handler"
common "bkauth/pkg/api/common"
"bkauth/pkg/api/app/handler"
"bkauth/pkg/api/common"
)

// Register ...
Expand All @@ -39,8 +39,13 @@ func Register(r *gin.RouterGroup) {
{
// AccessKey CURD for PaaS
accessKeyCURD.POST("", handler.CreateAccessKey)
accessKeyCURD.DELETE("/:access_key_id", handler.DeleteAccessKey)
accessKeyCURD.PUT("/:access_key_id", handler.UpdateAccessKey)
accessKeyUD := accessKeyCURD.Group("/:access_key_id")
accessKeyUD.Use(common.AccessKeyExists())
{
accessKeyUD.DELETE("", handler.DeleteAccessKey)
accessKeyUD.PUT("", handler.UpdateAccessKey)
}

}

// List for PaaS/APIGateway
Expand Down
37 changes: 35 additions & 2 deletions src/bkauth/pkg/api/common/middleware.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -57,6 +57,39 @@ func AppCodeExists() gin.HandlerFunc {
}
}

func AccessKeyExists() gin.HandlerFunc {
return func(c *gin.Context) {
var uriParams AccessKeyAndAppCodeSerializer
if err := c.ShouldBindUri(&uriParams); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
c.Abort()
return
}

appCode := uriParams.AppCode
accessKeyID := uriParams.AccessKeyID

// check access_key exists
exists, err := service.NewAccessKeyService().ExistsByAppCodeAndID(appCode, accessKeyID)
if err != nil {
util.SystemErrorJSONResponse(
c,
fmt.Errorf("query access_key_id(%d) of app(%s) fail, error: %w", accessKeyID, appCode, err),
)
c.Abort()
return
}

if !exists {
util.NotFoundJSONResponse(c, fmt.Sprintf("AccessKeyID(%d) of app(%s) not exists", accessKeyID, appCode))
c.Abort()
return
}

c.Next()
}
}

func NewAPIAllowMiddleware(api string) gin.HandlerFunc {
return func(c *gin.Context) {
accessAppCode := util.GetAccessAppCode(c)
Expand All @@ -79,7 +112,7 @@ func TargetExistsAndClientValid() gin.HandlerFunc {
}
targetID := uriParams.TargetID

// Note: 这里没必要缓存,因为本身Target的注册和变更频率很低
// Note: 这里没必要缓存,因为本身 Target 的注册和变更频率很低
svc := service.NewTargetService()
target, err := svc.Get(targetID)
if err != nil {
Expand Down
13 changes: 9 additions & 4 deletions src/bkauth/pkg/api/common/slz.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -24,7 +24,7 @@ import (
)

var (
// ValidAppCodeRegex 小写字母或数字开头, 可以包含小写字母/数字/下划线/连字符
// ValidAppCodeRegex 小写字母或数字开头可以包含小写字母/数字/下划线/连字符
ValidAppCodeRegex = regexp.MustCompile("^[a-z0-9][a-z0-9_-]{0,31}$")

ErrInvalidAppCode = errors.New("invalid app_code: app_code should begin with a lowercase letter or numbers, " +
Expand All @@ -35,9 +35,14 @@ type AppCodeSerializer struct {
AppCode string `uri:"bk_app_code" json:"bk_app_code" binding:"required,min=1,max=32" example:"bk_paas"`
}

type AccessKeyAndAppCodeSerializer struct {
AppCodeSerializer
AccessKeyID int64 `uri:"access_key_id" binding:"required" example:"1"`
}

func (s *AppCodeSerializer) ValidateAppCode() error {
// app_code的规则是:
// 由小写英文字母、连接符(-)、下划线(_)或数字组成,长度为[1~32]个字符, 并且以字母或数字开头 (^[a-z0-9][a-z0-9_-]{0,31}$)
// app_code 的规则是:
// 由小写英文字母、连接符 (-)、下划线 (_) 或数字组成,长度为 [1~32] 个字符,并且以字母或数字开头 (^[a-z0-9][a-z0-9_-]{0,31}$)
if !ValidAppCodeRegex.MatchString(s.AppCode) {
return ErrInvalidAppCode
}
Expand Down
17 changes: 16 additions & 1 deletion src/bkauth/pkg/database/dao/access_key.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -55,6 +55,7 @@ type AccessKeyManager interface {
Count(appCode string) (int64, error)
ListAccessKeyByAppCode(appCode string) ([]AccessKey, error)
List() ([]AccessKey, error)
ExistsByAppCodeAndID(appCode string, id int64) (bool, error)
}

type accessKeyManager struct {
Expand Down Expand Up @@ -191,3 +192,17 @@ func (m *accessKeyManager) List() (accessKeys []AccessKey, err error) {
}
return
}

func (m *accessKeyManager) ExistsByAppCodeAndID(appCode string, id int64) (bool, error) {
var existingID int64
query := `SELECT id FROM access_key WHERE app_code = ? AND id = ? LIMIT 1`
err := database.SqlxGet(m.DB, &existingID, query, appCode, id)
if errors.Is(err, sql.ErrNoRows) {
return false, nil
}
if err != nil {
return false, err
}

return true, nil
}
19 changes: 17 additions & 2 deletions src/bkauth/pkg/database/dao/access_key_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TencentBlueKing is pleased to support the open source community by making
* 蓝鲸智云 - Auth服务(BlueKing - Auth) available.
* 蓝鲸智云 - Auth 服务 (BlueKing - Auth) available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -22,7 +22,7 @@ import (
"testing"
"time"

sqlmock "github.com/DATA-DOG/go-sqlmock"
"github.com/DATA-DOG/go-sqlmock"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"

Expand Down Expand Up @@ -180,3 +180,18 @@ func Test_ListAccessKeyByAppCode(t *testing.T) {
assert.Len(t, accessKeys, 2)
})
}

func Test_ExistsByAppCodeAndID(t *testing.T) {
database.RunWithMock(t, func(db *sqlx.DB, mock sqlmock.Sqlmock, t *testing.T) {
mockQuery := `^SELECT id FROM access_key WHERE app_code = (.*) AND id = (.*) LIMIT 1$`
mockRows := sqlmock.NewRows([]string{"id"}).AddRow(int64(1))
mock.ExpectQuery(mockQuery).WithArgs("bkauth", int64(1)).WillReturnRows(mockRows)

manager := &accessKeyManager{DB: db}

exists, err := manager.ExistsByAppCodeAndID("bkauth", 1)

assert.NoError(t, err, "query from db fail.")
assert.Equal(t, exists, true)
})
}
18 changes: 16 additions & 2 deletions src/bkauth/pkg/database/dao/mock/access_key.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading