requests working but query needs fixed

This commit is contained in:
nicksherron 2020-02-11 00:15:11 -05:00
parent 624adf11a6
commit af61b5d388
5 changed files with 274 additions and 5 deletions

240
cmd/migrate.go Normal file
View 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
View file

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

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

View file

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

View file

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