mirror of
https://github.com/nicksherron/bashhub-server.git
synced 2025-09-05 03:44:30 +08:00
test/server_test: first tests
This commit is contained in:
parent
1af500af14
commit
ce4313b18e
8 changed files with 338 additions and 7 deletions
2
Makefile
2
Makefile
|
@ -61,5 +61,5 @@ clean:
|
|||
@test ! -e bin/${BIN_NAME} || rm bin/${BIN_NAME}
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
go test -v ./...
|
||||
|
||||
|
|
|
@ -119,6 +119,6 @@ func checkBhEnv() {
|
|||
WARNING: BH_URL is set to https://bashhub.com on this machine
|
||||
If you will be running bashhub-client locally be sure to add
|
||||
export BH_URL=%v to your .bashrc or .zshrc`, internal.Addr)
|
||||
fmt.Println(msg, "\n")
|
||||
fmt.Println(msg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,7 @@ func sysRegister(mac string, site string, user string, pass string) string {
|
|||
"hostname": host,
|
||||
"mac": mac,
|
||||
}
|
||||
|
||||
payloadBytes, err := json.Marshal(sys)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
3
go.mod
3
go.mod
|
@ -2,15 +2,18 @@ module github.com/nicksherron/bashhub-server
|
|||
|
||||
require (
|
||||
github.com/appleboy/gin-jwt/v2 v2.6.3
|
||||
github.com/appleboy/gofight/v2 v2.1.2
|
||||
github.com/cheggaaa/pb/v3 v3.0.4
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/gin-gonic/gin v1.5.0
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jinzhu/gorm v1.9.12
|
||||
github.com/lib/pq v1.3.0
|
||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd
|
||||
)
|
||||
|
||||
|
|
2
go.sum
2
go.sum
|
@ -37,6 +37,8 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
|||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
|
||||
|
|
|
@ -222,7 +222,7 @@ func (cmd Command) commandInsert() int64 {
|
|||
|
||||
res, err := db.Exec(`
|
||||
INSERT INTO commands("process_id","process_start_time","exit_status","uuid","command", "created", "path", "user_id", "system_name")
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) ON CONFLICT do nothing`,
|
||||
cmd.ProcessId, cmd.ProcessStartTime, cmd.ExitStatus, cmd.Uuid, cmd.Command, cmd.Created, cmd.Path, cmd.User.ID, cmd.SystemName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -129,8 +129,8 @@ func loggerWithFormatterWriter(f gin.LogFormatter) gin.HandlerFunc {
|
|||
})
|
||||
}
|
||||
|
||||
// Run starts server
|
||||
func Run() {
|
||||
// configure routes and middleware
|
||||
func SetupRouter() *gin.Engine {
|
||||
// Initialize backend
|
||||
dbInit()
|
||||
|
||||
|
@ -197,7 +197,7 @@ func Run() {
|
|||
return &User{
|
||||
Username: user.Username,
|
||||
SystemName: user.userGetSystemName(),
|
||||
ID: user.userGetID(),
|
||||
ID: user.userGetID(),
|
||||
}, nil
|
||||
}
|
||||
fmt.Println("failed")
|
||||
|
@ -457,8 +457,15 @@ func Run() {
|
|||
c.AbortWithStatus(http.StatusOK)
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// Run starts server
|
||||
func Run() {
|
||||
r := SetupRouter()
|
||||
|
||||
Addr = strings.ReplaceAll(Addr, "http://", "")
|
||||
err = r.Run(Addr)
|
||||
err := r.Run(Addr)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error: \t", err)
|
||||
|
|
318
test/server_test.go
Normal file
318
test/server_test.go
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
*
|
||||
* Copyright © 2020 nicksherron <nsherron90@gmail.com>
|
||||
*
|
||||
* 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 test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/nicksherron/bashhub-server/internal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
router *gin.Engine
|
||||
sysRegistered bool
|
||||
jwtToken string
|
||||
user = "tester"
|
||||
pass = "tester"
|
||||
mac = "888888888888888"
|
||||
)
|
||||
|
||||
func createUser(t *testing.T) {
|
||||
auth := map[string]interface{}{
|
||||
"Username": user,
|
||||
"password": pass,
|
||||
"email": "test@email.com",
|
||||
}
|
||||
|
||||
payloadBytes, err := json.Marshal(auth)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body := bytes.NewReader(payloadBytes)
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/user", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
}
|
||||
|
||||
func getToken(t *testing.T) string {
|
||||
|
||||
auth := map[string]interface{}{
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"mac": mac,
|
||||
}
|
||||
|
||||
payloadBytes, err := json.Marshal(auth)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body := bytes.NewReader(payloadBytes)
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/login", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
|
||||
buf, err := ioutil.ReadAll(w.Body)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
j := make(map[string]interface{})
|
||||
|
||||
json.Unmarshal(buf, &j)
|
||||
|
||||
if len(j) == 0 {
|
||||
t.Fatal("login failed for getToken")
|
||||
|
||||
}
|
||||
token := fmt.Sprintf("Bearer %v", j["accessToken"])
|
||||
|
||||
if !sysRegistered {
|
||||
// register system
|
||||
return sysRegister(t, token)
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func sysRegister(t *testing.T, token string) string {
|
||||
|
||||
host, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sys := map[string]interface{}{
|
||||
"clientVersion": "1.2.0",
|
||||
"name": "test-system",
|
||||
"hostname": host,
|
||||
"mac": mac,
|
||||
}
|
||||
payloadBytes, err := json.Marshal(sys)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body := bytes.NewReader(payloadBytes)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/system", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", token)
|
||||
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 201, w.Code)
|
||||
|
||||
sysRegistered = true
|
||||
|
||||
return getToken(t)
|
||||
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
err := os.RemoveAll("testdata")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
dir, err = os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = os.Mkdir("testdata", 0700)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
internal.DbPath = filepath.Join(dir, "test.db")
|
||||
|
||||
router = internal.SetupRouter()
|
||||
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/ping", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.Equal(t, "{\"message\":\"pong\"}\n", w.Body.String())
|
||||
createUser(t)
|
||||
sysRegistered = false
|
||||
jwtToken = getToken(t)
|
||||
|
||||
}
|
||||
|
||||
var commandTests = []internal.Command{
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "cat foo.txt"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "ls"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "pwd"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "whoami"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "which cat"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "head foo.txt"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "sed 's/fooobaar/foobar/g' somefile.txt"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "curl google.com"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "file /dev/null"},
|
||||
{ProcessId: 90226, ExitStatus: 0, Command: "df -h"},
|
||||
{ProcessId: 90226, ExitStatus: 127, Command: "catt"},
|
||||
{ProcessId: 90226, ExitStatus: 127, Command: "cay"},
|
||||
}
|
||||
|
||||
func TestCommand(t *testing.T) {
|
||||
hourAgo := time.Now().UnixNano() - (1 * time.Hour).Nanoseconds()
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
for _, tc := range commandTests {
|
||||
uid, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tc.Path = dir
|
||||
tc.Created = time.Now().Unix()
|
||||
tc.ProcessStartTime = hourAgo
|
||||
tc.Uuid = uid.String()
|
||||
payloadBytes, err := json.Marshal(&tc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body := bytes.NewReader(payloadBytes)
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/command", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
}
|
||||
}
|
||||
func() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/command/search?unique=true", nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var data []internal.Command
|
||||
err = json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 10, len(data))
|
||||
}()
|
||||
func() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/command/search?", nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var data []internal.Command
|
||||
err = json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 50, len(data))
|
||||
}()
|
||||
func() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/command/search?query=%5Ecurl&unique=true", nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var data []internal.Command
|
||||
err = json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 1, len(data))
|
||||
}()
|
||||
func() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/command/search?unique=true&systemName=test-system", nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var data []internal.Command
|
||||
err = json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 10, len(data))
|
||||
}()
|
||||
func() {
|
||||
w := httptest.NewRecorder()
|
||||
v := url.Values{}
|
||||
v.Add("unique", "true")
|
||||
v.Add("path", dir)
|
||||
u := fmt.Sprintf("/api/v1/command/search?%v", v.Encode())
|
||||
req, _ := http.NewRequest("GET", u, nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Authorization", jwtToken)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var data []internal.Command
|
||||
err = json.Unmarshal(b, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 10, len(data))
|
||||
}()
|
||||
}
|
Loading…
Add table
Reference in a new issue