Skip to content

Commit

Permalink
feat: 新增文件读取接口
Browse files Browse the repository at this point in the history
  • Loading branch information
link-duan authored and kl7sn committed Aug 3, 2020
1 parent 86218e3 commit e055104
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 1 deletion.
4 changes: 4 additions & 0 deletions config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@
[jupiter.server.http]
host = "0.0.0.0"
port = 50010

[api]
# 密钥长度需要为32位
secret = "12341234123412341234123412341234"
25 changes: 24 additions & 1 deletion pkg/core/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
package core

import (
"strconv"

"github.com/douyu/juno-agent/pkg/file"
"github.com/douyu/juno-agent/pkg/model"
"github.com/douyu/juno-agent/pkg/pmt"
"github.com/douyu/juno-agent/pkg/structs"
"github.com/douyu/juno-agent/util"
"github.com/douyu/jupiter/pkg/server/xecho"
"github.com/douyu/jupiter/pkg/server/xgrpc"
"github.com/labstack/echo/v4"
pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
"google.golang.org/grpc/examples/helloworld/helloworld"
"strconv"
)

func (eng *Engine) serveHTTP() error {
Expand All @@ -34,6 +37,7 @@ func (eng *Engine) serveHTTP() error {
group.GET("/agent/reload", eng.agentReload) // restart confd monitoring
group.GET("/agent/process/status", eng.processStatus) // real time process status
group.POST("/agent/process/shell", eng.pmtShell)
group.GET("/agent/file", eng.readFile) // 文件读取

v1Group := s.Group("/api/v1")
v1Group.GET("/agent/:target", eng.getAppConfig) // get app config
Expand Down Expand Up @@ -196,6 +200,25 @@ func (eng *Engine) pmtShell(ctx echo.Context) error {
return reply200(ctx, reply)
}

func (eng *Engine) readFile(c echo.Context) error {
var param model.GetFileReq
err := c.Bind(&param)
if err != nil {
return reply400(c, err.Error())
}

content, err := file.ReadFile(param.FileName)
if err != nil {
return reply400(c, err.Error())
}

content = util.EncryptAPIResp(content)

return reply200(c, map[string]interface{}{
"content": content,
})
}

func reply200(ctx echo.Context, data interface{}) error {
return ctx.JSON(200, map[string]interface{}{
"code": 200,
Expand Down
27 changes: 27 additions & 0 deletions pkg/file/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package file

import (
"fmt"
"io/ioutil"
"os"
)

func ReadFile(path string) (content string, err error) {
stat, err := os.Stat(path)
if err != nil {
return
}

if stat.IsDir() {
return "", fmt.Errorf(path + " is directory, not file")
}

fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return
}

content = string(fileBytes)

return
}
19 changes: 19 additions & 0 deletions pkg/model/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2020 Douyu
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package model

type GetFileReq struct {
FileName string `query:"file_name"`
}
81 changes: 81 additions & 0 deletions util/encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2020 Douyu
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package util

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"

"github.com/douyu/jupiter/pkg/conf"
)

//EncryptAPIResp 加密API响应内容
func EncryptAPIResp(plainText string) string {
cipherText, _ := AESCBCEncrypt(plainText, conf.GetString("api.secret"))
return cipherText
}

func AESCBCEncrypt(orig string, key string) (string, error) {
// 转成字节数组
origData := []byte(orig)
k := []byte(key)
if len(k) != 32 {
return "", fmt.Errorf("密钥长度需要为32")
}

// NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, _ := aes.NewCipher(k)
blockSize := block.BlockSize()
origData = PKCS7Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
cryted := make([]byte, len(origData))
blockMode.CryptBlocks(cryted, origData)
return base64.StdEncoding.EncodeToString(cryted), nil
}

func AESCBCDecrypt(cryted string, key string) (string, error) {
// 转成字节数组
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
k := []byte(key)
if len(k) != 32 {
return "", fmt.Errorf("密钥长度需要为32")
}

block, _ := aes.NewCipher(k)
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
orig := make([]byte, len(crytedByte))
blockMode.CryptBlocks(orig, crytedByte)
orig = PKCS7UnPadding(orig)
return string(orig), nil
}

//补码, len = 128||192||256
//AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}

//去码
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
30 changes: 30 additions & 0 deletions util/encrypt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package util

import "testing"

func TestAesEncrypt(t *testing.T) {
type args struct {
orig string
key string
}
tests := []struct {
name string
args args
}{
{
name: "1",
args: args{
orig: "123", key: "12341234123412341234123412341234",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, _ := AESCBCEncrypt(tt.args.orig, tt.args.key)
dec, _ := AESCBCDecrypt(got, tt.args.key)
if tt.args.orig != dec {
t.Errorf("AESCBCEncrypt() = %v, AESCBCDecrypt() = %v", got, dec)
}
})
}
}

0 comments on commit e055104

Please sign in to comment.