补充API 与脱敏
This commit is contained in:
parent
c394dfe825
commit
fc0efc490e
@ -3,4 +3,6 @@ package apps
|
|||||||
import (
|
import (
|
||||||
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/resource/api"
|
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/resource/api"
|
||||||
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/resource/impl"
|
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/resource/impl"
|
||||||
|
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/secret/api"
|
||||||
|
_ "gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/secret/impl"
|
||||||
)
|
)
|
||||||
|
88
devcloud-mini/cmdb/apps/secret/api/api.go
Normal file
88
devcloud-mini/cmdb/apps/secret/api/api.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||||
|
"github.com/emicklei/go-restful/v3"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/infraboard/mcube/v2/exception"
|
||||||
|
"github.com/infraboard/mcube/v2/http/restful/response"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc/config/gorestful"
|
||||||
|
"gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/secret"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ioc.Api().Registry(&SecretApiHandler{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecretApiHandler struct {
|
||||||
|
ioc.ObjectImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SecretApiHandler) Name() string {
|
||||||
|
return secret.AppName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SecretApiHandler) Init() error {
|
||||||
|
// WebService ws
|
||||||
|
// api/v1/resource
|
||||||
|
ws := gorestful.ObjectRouter(r)
|
||||||
|
|
||||||
|
tags := []string{"凭证管理"}
|
||||||
|
|
||||||
|
ws.Route(ws.GET("").To(r.QuerySecret).Doc("凭证列表").
|
||||||
|
Param(ws.QueryParameter("page_size", "分页大小").DataType("intger")).
|
||||||
|
Param(ws.QueryParameter("page_number", "页码").DataType("intger")).
|
||||||
|
Param(ws.QueryParameter("keywords", "关键字过滤").DataType("string")).
|
||||||
|
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||||
|
Writes(SecretSet{}).
|
||||||
|
Returns(200, "OK", SecretSet{}).
|
||||||
|
Returns(404, "Not Found", exception.NewNotFound("")))
|
||||||
|
|
||||||
|
// :id -> {id}
|
||||||
|
ws.Route(ws.GET("/{id}").To(r.DescribeSecret).Doc("凭证详情").
|
||||||
|
Param(ws.PathParameter("id", "凭证Id").DataType("string")).
|
||||||
|
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||||
|
Writes(secret.Secret{}).
|
||||||
|
Returns(200, "OK", secret.Secret{}).
|
||||||
|
Returns(404, "Not Found", exception.NewNotFound("")))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecretSet struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Items []*secret.Secret `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SecretApiHandler) QuerySecret(req *restful.Request, resp *restful.Response) {
|
||||||
|
sr := secret.NewQuerySecretRequest()
|
||||||
|
|
||||||
|
// 获取参数, bind
|
||||||
|
err := binding.Query.Bind(req.Request, sr)
|
||||||
|
if err != nil {
|
||||||
|
response.Failed(resp, exception.NewBadRequest(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 业务逻辑
|
||||||
|
set, err := secret.GetService().QuerySecret(req.Request.Context(), sr)
|
||||||
|
if err != nil {
|
||||||
|
response.Failed(resp, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(resp, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SecretApiHandler) DescribeSecret(req *restful.Request, resp *restful.Response) {
|
||||||
|
sr := secret.NewDescribeSecretRequeset(req.PathParameter("id"))
|
||||||
|
|
||||||
|
// 业务逻辑
|
||||||
|
ins, err := secret.GetService().DescribeSecret(req.Request.Context(), sr)
|
||||||
|
if err != nil {
|
||||||
|
response.Failed(resp, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(resp, ins)
|
||||||
|
}
|
17
devcloud-mini/cmdb/apps/secret/impl/impl_test.go
Normal file
17
devcloud-mini/cmdb/apps/secret/impl/impl_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package impl_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/secret"
|
||||||
|
"gitlab.com/go-course-project/go17/devcloud-mini/cmdb/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctx = context.Background()
|
||||||
|
svc = secret.GetService()
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
test.SetUp()
|
||||||
|
}
|
40
devcloud-mini/cmdb/apps/secret/impl/secret_test.go
Normal file
40
devcloud-mini/cmdb/apps/secret/impl/secret_test.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package impl_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/resource"
|
||||||
|
"gitlab.com/go-course-project/go17/devcloud-mini/cmdb/apps/secret"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateSecret(t *testing.T) {
|
||||||
|
req := secret.NewCreateSecretRequest()
|
||||||
|
req.Name = "腾讯云只读账号"
|
||||||
|
req.Vendor = resource.VENDOR_TENCENT
|
||||||
|
req.ApiKey = "xxx"
|
||||||
|
req.ApiSecret = "xx"
|
||||||
|
req.Regions = []string{"ap-shanghai", "ap-guangzhou"}
|
||||||
|
ins, err := svc.CreateSecret(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(ins)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQuerySecret(t *testing.T) {
|
||||||
|
req := secret.NewQuerySecretRequest()
|
||||||
|
set, err := svc.QuerySecret(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDescribeSecret(t *testing.T) {
|
||||||
|
req := secret.NewDescribeSecretRequeset("0f6836e0-a894-3f87-b031-216478a8093b")
|
||||||
|
set, err := svc.DescribeSecret(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(set)
|
||||||
|
}
|
@ -23,14 +23,14 @@ func NewSecret(in *CreateSecretRequest) *Secret {
|
|||||||
return &Secret{
|
return &Secret{
|
||||||
Id: uid,
|
Id: uid,
|
||||||
UpdateAt: time.Now().Unix(),
|
UpdateAt: time.Now().Unix(),
|
||||||
CreateSecretRequest: in,
|
CreateSecretRequest: *in,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
Id string `json:"id" bson:"_id"`
|
Id string `json:"id" bson:"_id"`
|
||||||
UpdateAt int64 `json:"update_at" bson:"update_at"`
|
UpdateAt int64 `json:"update_at" bson:"update_at"`
|
||||||
*CreateSecretRequest `bson:"inline"`
|
CreateSecretRequest `bson:"inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Secret) String() string {
|
func (s *Secret) String() string {
|
||||||
@ -50,10 +50,11 @@ type CreateSecretRequest struct {
|
|||||||
Vendor resource.VENDOR `json:"vendor"`
|
Vendor resource.VENDOR `json:"vendor"`
|
||||||
// Vmware
|
// Vmware
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
//
|
// 需要被脱敏
|
||||||
|
// Musk
|
||||||
ApiKey string `json:"api_key"`
|
ApiKey string `json:"api_key"`
|
||||||
//
|
//
|
||||||
ApiSecret string `json:"api_secret"`
|
ApiSecret string `json:"api_secret" mask:",5,4"`
|
||||||
//
|
//
|
||||||
isEncrypted bool
|
isEncrypted bool
|
||||||
|
|
||||||
@ -73,7 +74,12 @@ func (r *CreateSecretRequest) EncryptedApiSecret() error {
|
|||||||
// 对称加密 AES(cbc)
|
// 对称加密 AES(cbc)
|
||||||
// @v1,xxxx@xxxxx
|
// @v1,xxxx@xxxxx
|
||||||
|
|
||||||
cipherText, err := cbc.MustNewAESCBCCihper([]byte(SECRET_KEY)).Encrypt([]byte(r.ApiSecret))
|
key, err := base64.StdEncoding.DecodeString(SECRET_KEY)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherText, err := cbc.MustNewAESCBCCihper(key).Encrypt([]byte(r.ApiSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -90,7 +96,12 @@ func (r *CreateSecretRequest) DecryptedApiSecret() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
plainText, err := cbc.MustNewAESCBCCihper([]byte(SECRET_KEY)).Decrypt([]byte(cipherdText))
|
key, err := base64.StdEncoding.DecodeString(SECRET_KEY)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
plainText, err := cbc.MustNewAESCBCCihper(key).Decrypt([]byte(cipherdText))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,25 +32,34 @@
|
|||||||
<mxGeometry x="10" y="230" width="110" height="90" as="geometry"/>
|
<mxGeometry x="10" y="230" width="110" height="90" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="11" value="Controller" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="11" value="Controller" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
<mxGeometry x="70" y="660" width="350" height="60" as="geometry"/>
|
<mxGeometry x="70" y="710" width="350" height="60" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="12" value="<span style="color: rgb(0, 0, 0);">&nbsp;Secret: ApiSecret</span>" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
<mxCell id="12" value="<span style="color: rgb(0, 0, 0);">&nbsp;Secret: ApiSecret</span>" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
||||||
<mxGeometry x="170" y="760" width="150" height="80" as="geometry"/>
|
<mxGeometry x="170" y="810" width="150" height="80" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="13" value="加密" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
<mxCell id="13" value="密文" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||||
<mxGeometry x="70" y="785" width="60" height="30" as="geometry"/>
|
<mxGeometry x="70" y="835" width="60" height="30" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="15" value="secret" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="15" value="secret" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
<mxGeometry x="280" y="675" width="60" height="30" as="geometry"/>
|
<mxGeometry x="280" y="725" width="60" height="30" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="17" style="edgeStyle=none;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="16" target="15">
|
<mxCell id="17" style="edgeStyle=none;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="16" target="15">
|
||||||
<mxGeometry relative="1" as="geometry"/>
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="16" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="16" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
<mxGeometry x="354" y="675" width="60" height="30" as="geometry"/>
|
<mxGeometry x="354" y="725" width="60" height="30" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="18" value="Text" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
<mxCell id="18" value="secet controller 提供明文" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||||
<mxGeometry x="470" y="675" width="60" height="30" as="geometry"/>
|
<mxGeometry x="445" y="725" width="220" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="19" value="Api" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="70" y="605" width="350" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="20" value="UI (不能拿到明文)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="70" y="520" width="350" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="21" value="脱名: 明文" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="445" y="620" width="60" height="30" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
</root>
|
</root>
|
||||||
</mxGraphModel>
|
</mxGraphModel>
|
||||||
|
2
go.mod
2
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-playground/validator/v10 v10.20.0
|
github.com/go-playground/validator/v10 v10.20.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/infraboard/mcube/v2 v2.0.49
|
github.com/infraboard/mcube/v2 v2.0.51
|
||||||
github.com/rs/zerolog v1.32.0
|
github.com/rs/zerolog v1.32.0
|
||||||
go.mongodb.org/mongo-driver v1.14.0
|
go.mongodb.org/mongo-driver v1.14.0
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.31.0
|
||||||
|
4
go.sum
4
go.sum
@ -98,8 +98,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF
|
|||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/infraboard/mcube/v2 v2.0.49 h1:V8Q8j5vOiYSnQmcVBeVGPlyJxNVsyniJgoKCGvGwy8c=
|
github.com/infraboard/mcube/v2 v2.0.51 h1:QWgC6yo6qfx5xvU25MPdoQhkPuzjwrn8YfrQxOonL/8=
|
||||||
github.com/infraboard/mcube/v2 v2.0.49/go.mod h1:gnr0xPPDPHvCS6JAzvdjqJ62J2+vUZTkobomjTXKsx0=
|
github.com/infraboard/mcube/v2 v2.0.51/go.mod h1:gnr0xPPDPHvCS6JAzvdjqJ62J2+vUZTkobomjTXKsx0=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user