mirror of
https://github.com/nicksherron/bashhub-server.git
synced 2025-09-15 00:34:51 +08:00
requests working but query needs fixed
This commit is contained in:
parent
624adf11a6
commit
af61b5d388
5 changed files with 274 additions and 5 deletions
240
cmd/migrate.go
Normal file
240
cmd/migrate.go
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
*
|
||||
* 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 cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/nicksherron/bashhub-server/internal"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type cList struct {
|
||||
UUID string `json:"uuid"`
|
||||
Command string `json:"command"`
|
||||
Created int64 `json:"created"`
|
||||
}
|
||||
|
||||
type commandRecord struct {
|
||||
Command string `json:"command"`
|
||||
Path string `json:"path"`
|
||||
Created int64 `json:"created"`
|
||||
UUID string `json:"uuid"`
|
||||
ExitStatus int `json:"exitStatus"`
|
||||
Username string `json:"username"`
|
||||
SystemName string `json:"systemName"`
|
||||
SessionID string `json:"sessionId"`
|
||||
}
|
||||
|
||||
type commandsList []cList
|
||||
|
||||
var (
|
||||
srcUser string
|
||||
dstUser string
|
||||
srcURL string
|
||||
dstURL string
|
||||
srcPass string
|
||||
dstPass string
|
||||
srcToken string
|
||||
dstToken string
|
||||
wg sync.WaitGroup
|
||||
cmdList commandsList
|
||||
migrateCmd = &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "migrate bashhub history ",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmd.Flags().Parse(args)
|
||||
srcToken = getToken(srcURL, srcUser, srcPass)
|
||||
dstToken = getToken(dstURL, dstUser, dstPass)
|
||||
cmdList = getCommandList()
|
||||
counter := 0
|
||||
for _, v := range cmdList {
|
||||
wg.Add(1)
|
||||
counter++
|
||||
go func(c cList) {
|
||||
defer wg.Done()
|
||||
commandLookup(c.UUID)
|
||||
}(v)
|
||||
if counter > 20 {
|
||||
wg.Wait()
|
||||
counter = 0
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
migrateCmd.PersistentFlags().StringVar(&srcURL, "src-url", "https://bashhub.com", "source url")
|
||||
migrateCmd.PersistentFlags().StringVar(&srcUser, "src-user", "", "source username")
|
||||
migrateCmd.PersistentFlags().StringVar(&srcPass, "src-pass", "", "source password")
|
||||
migrateCmd.PersistentFlags().StringVar(&dstURL, "dst-url", "http://localhost:8080", "destination url")
|
||||
migrateCmd.PersistentFlags().StringVar(&dstUser, "dst-user", "", "destination username")
|
||||
migrateCmd.PersistentFlags().StringVar(&dstPass, "dst-pass", "", "destination password")
|
||||
|
||||
}
|
||||
|
||||
func getToken(site string, user string, pass string) string {
|
||||
// function used by bashhub to identify system
|
||||
cmd := exec.Command("python", "-c", "import uuid; print(str(uuid.getnode()))")
|
||||
m, err := cmd.Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mac := strings.ReplaceAll(string(m), "\n", ``)
|
||||
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)
|
||||
|
||||
u := fmt.Sprintf("%v/api/v1/login", site)
|
||||
req, err := http.NewRequest("POST", u, body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
log.Fatal("login failed for ", site)
|
||||
}
|
||||
buf, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
j := make(map[string]interface{})
|
||||
|
||||
json.Unmarshal(buf, &j)
|
||||
if len(j) == 0 {
|
||||
log.Fatal("login failed for ", site)
|
||||
|
||||
}
|
||||
return fmt.Sprintf("Bearer %v", j["accessToken"])
|
||||
}
|
||||
|
||||
func getCommandList() commandsList {
|
||||
u := strings.TrimSpace(srcURL) + "/api/v1/command/search?unique=true&limit=1000000"
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", srcToken)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Error on response.\n[ERRO] -", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
log.Fatalf("failed to get command list from %v, go status code %v", srcURL, resp.StatusCode)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var result commandsList
|
||||
json.Unmarshal(body, &result)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func commandLookup(uuid string) {
|
||||
u := strings.TrimSpace(srcURL) + "/api/v1/command/" + strings.TrimSpace(uuid)
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", srcToken)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Error on response.\n[ERRO] -", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
log.Fatalf("failed command lookup from %v, go status code %v", srcURL, resp.StatusCode)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srcSend(body)
|
||||
var j internal.Query
|
||||
err = json.Unmarshal(body, &j)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
j.Username = dstUser
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srcSend(b)
|
||||
}
|
||||
|
||||
func srcSend(data []byte) {
|
||||
body := bytes.NewReader(data)
|
||||
|
||||
u := dstURL + "/api/v1/import"
|
||||
req, err := http.NewRequest("POST", u, body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
req.Header.Add("Authorization", dstToken)
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Error on response.\n[ERRO] -", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
}
|
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
|||
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/olekukonko/tablewriter v0.0.4
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd
|
||||
|
|
4
go.sum
4
go.sum
|
@ -56,6 +56,8 @@ github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg
|
|||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
|
||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
|
@ -66,6 +68,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
|
|||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||
|
|
|
@ -99,6 +99,8 @@ func dbInit() {
|
|||
gormdb.Model(&System{}).AddIndex("idx_mac", "mac")
|
||||
gormdb.Model(&Command{}).AddIndex("idx_exit_command_created", "exit_status, created, command")
|
||||
gormdb.Model(&Command{}).AddIndex("idx_user_exit_command_created", "user_id, exit_status, created, command")
|
||||
gormdb.Model(&Command{}).AddUniqueIndex("idx_uuid", "uuid")
|
||||
|
||||
// Just need gorm for migration and index creation.
|
||||
gormdb.Close()
|
||||
}
|
||||
|
@ -205,6 +207,7 @@ func (cmd Command) commandInsert() int64 {
|
|||
}
|
||||
return inserted
|
||||
}
|
||||
|
||||
//TODO: make this less complicated. It's the epitome of a cluster fuck.
|
||||
func (cmd Command) commandGet() []Query {
|
||||
var results []Query
|
||||
|
@ -508,3 +511,15 @@ func (sys System) systemGet() System {
|
|||
return row
|
||||
|
||||
}
|
||||
|
||||
func importCommands(q Query) {
|
||||
_, err := db.Exec(`INSERT OR IGNORE INTO commands
|
||||
("command", "path", "created", "uuid", "exit_status",
|
||||
"system_name", "session_id", "user_id" )
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,(select "id" from users where "username" = $8)) ON CONFLICT do nothing`,
|
||||
q.Command, q.Path, q.Created, q.Uuid, q.ExitStatus,
|
||||
q.SystemName, q.SessionID, q.Username)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,15 +42,14 @@ type User struct {
|
|||
}
|
||||
|
||||
type Query struct {
|
||||
Uuid string `json:"uuid"`
|
||||
Command string `json:"command"`
|
||||
Created int64 `json:"created"`
|
||||
Path string `json:"path"`
|
||||
Created int64 `json:"created"`
|
||||
Uuid string `json:"uuid"`
|
||||
ExitStatus int `json:"exitStatus"`
|
||||
Username string `json:"username"`
|
||||
SystemName string `gorm:"-" json:"systemName"`
|
||||
//TODO: implement sessions
|
||||
SessionID string `json:"session_id"`
|
||||
SessionID string `json:"sessionId"`
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
|
@ -67,6 +66,7 @@ type Command struct {
|
|||
Limit int `gorm:"-"`
|
||||
Unique bool `gorm:"-"`
|
||||
Query string `gorm:"-"`
|
||||
SessionID string `json:"sessionId"`
|
||||
}
|
||||
|
||||
type System struct {
|
||||
|
@ -319,9 +319,18 @@ func Run() {
|
|||
|
||||
})
|
||||
|
||||
r.POST("/api/v1/import", func(c *gin.Context) {
|
||||
var query Query
|
||||
if err := c.ShouldBindJSON(&query); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
importCommands(query)
|
||||
})
|
||||
|
||||
Addr = strings.ReplaceAll(Addr, "http://", "")
|
||||
err = r.Run(Addr)
|
||||
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error: \t", err)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue