test/server_test: first tests

This commit is contained in:
nicksherron 2020-02-14 04:21:34 -05:00
parent 1af500af14
commit ce4313b18e
8 changed files with 338 additions and 7 deletions

View file

@ -61,5 +61,5 @@ clean:
@test ! -e bin/${BIN_NAME} || rm bin/${BIN_NAME}
test:
go test ./...
go test -v ./...

View file

@ -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)
}
}

View file

@ -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
View file

@ -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
View file

@ -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=

View file

@ -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)

View file

@ -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
View 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))
}()
}