Example #1
0
// Prompts for input and creates a new loader entry through the API
func loaderCreator(cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("loaderCreator() -> %v", e)
		}
	}()
	var newle mig.LoaderEntry
	fmt.Println("Entering loader creation mode.\nPlease provide the name" +
		" of the new entry")
	newle.Name, err = readline.String("name> ")
	if err != nil {
		panic(err)
	}
	if len(newle.Name) < 3 {
		panic("input name too short")
	}
	fmt.Printf("Name: '%s'\n", newle.Name)
	fmt.Println("Please provide loader key for entry.")
	newle.Key, err = readline.String("key> ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Key: '%s'\n", newle.Key)
	// Validate the new loader entry before sending it to the API
	err = newle.Validate()
	if err != nil {
		panic(err)
	}
	jsonle, err := json.MarshalIndent(newle, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", jsonle)
	input, err := readline.String("create loader entry? (y/n)> ")
	if err != nil {
		panic(err)
	}
	if input != "y" {
		fmt.Println("abort")
		return
	}
	err = cli.PostNewLoader(newle)
	if err != nil {
		panic(err)
	}
	fmt.Println("New entry successfully created but is disabled")
	return
}
Example #2
0
File: main.go Project: rread/rsi
func replCLI(env *Env) {
	defer fmt.Println("\nbye!")
	counter := readline.HistorySize()
	for {
		buf := bytes.Buffer{}
		prompt := fmt.Sprintf("[%d]-> ", counter)
		for {
			l, err := readline.String(prompt)
			if err == io.EOF {
				return
			}
			buf.WriteString(l)
			if validSexp(buf.String()) {
				break
			}
			buf.WriteString("\n")
			prompt = ": "
		}
		result, err := repl(buf.String(), env)
		if err != nil && err != ErrorEOF {
			fmt.Println("Error:", err)
		} else {
			fmt.Println(result)
		}
		readline.AddHistory(buf.String())
		counter++

	}
}
Example #3
0
func main() {
	env := evaluator.BuildEnvironment()

	for {
		l, err := readline.String("> ")
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			break
		}

		f, err := parser.Parse(strings.NewReader(l))
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			readline.AddHistory(l)
		}

		r, err := evaluator.Eval(env, f)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		} else {
			fmt.Println(r)
		}
		readline.AddHistory(l)
	}
}
Example #4
0
func ExampleCleanup() {
	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, syscall.SIGINT)

	readline.CatchSigint = false

	var line string
	var err error

	done := make(chan struct{})

	go func() {
		line, err = readline.String("> ")
		close(done)
	}()

	select {
	case <-sigint:
		fmt.Println("\nInterrupted")

		// Restore terminal attributes
		readline.Cleanup()
		// Note that we still have a goroutine reading from Stdin that
		// will terminate when we exit.
		os.Exit(1)
	case <-done:
		fmt.Printf("Read line %s, error %v\n", line, err)
	}
}
Example #5
0
File: main.go Project: taysom/va
/*
func main() {
	flag.Parse()
	go sigHandler()

	rl, err := readline.New("> ")
	if err != nil {
		panic(err)
	}
	defer rl.Close()

	for {
		line, err := rl.Readline()
		if err != nil {
			break
		}
		args := strings.Fields(line)
		if len(args) == 0 {
			continue
		}
		f, ok := cmd[args[0]]
		if ok {
			err := f(args[1:])
			if err != nil {
				log.Println(line, err)
			}
		} else {
			log.Println("Not found:", line)
		}
		stop = false
	}
	fmt.Println("Exiting")
}
*/
func main() {
	flag.Parse()
	go sigHandler()

	for {
		line, err := readline.String("% ")
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Println("error:", err)
			break
		}
		args := strings.Fields(line)
		if len(args) == 0 {
			continue
		}
		f, ok := cmd[args[0]]
		if ok {
			err := f(args[1:])
			if err != nil {
				log.Println(line, err)
			}
		} else {
			log.Println("Not found:", line)
		}
		stop = false
		readline.AddHistory(line)
	}
	fmt.Println("Exiting")
}
Example #6
0
func uiLoop() {
	for {
		line := readline.String("> ")
		rc := uiParseHistory(line)
		if !rc {
			break
		}
	}
}
Example #7
0
// Starts the controller.
func (c *Controller) Start() int {
	c.welcome()
	c.ChangeWorkingDir("/")

	readline.Completer = c.filenameCompleter
	buffer := bytes.NewBufferString("")
	prompt := ""

	for {
		if buffer.Len() == 0 {
			prompt = c.ps1()
		} else {
			prompt = c.ps2()
		}

		line, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		line = strings.TrimSpace(line)
		if strings.ToLower(line) == "q" || strings.ToLower(line) == "exit" {
			return 0
		}
		if strings.HasSuffix(line, "\\") {
			buffer.WriteString(strings.TrimSuffix(line, "\\") + "\n")
		} else {
			if buffer.Len() > 0 {
				buffer.WriteString(line)
				line = buffer.String()
				buffer.Reset()
			}

			parts, err := shlex.Split(line)
			if err != nil {
				panic(err)
			}
			readline.AddHistory(line)

			in := NewInput(parts[0])
			if len(parts) > 1 {
				in.Args = parts[1:]
			}
			c.handleInput(in)
		}
	}

	return 0
}
Example #8
0
// Gets additional suppression patterns, etc. from the user.
func interact(done chan<- string) {
	const prompt = "prolix> "
L:
	for {
		cmd, _ := readline.String(prompt)
		if cmd == "" {
			break L
		}
		readline.AddHistory(cmd)
		unary := unaryRe.FindStringSubmatch(cmd)
		if unary == nil {
			trimmed := strings.TrimSpace(cmd)
			switch trimmed {
			case "quit":
				done <- "quit"
				return
			case "pats":
				printPats()
			case "help":
				printInteractiveHelp()
			default:
				fmt.Println("Unknown command. Try 'help'.")
			}
		} else {
			switch strings.Replace(unary[1], "_", "-", -1) {
			case "ignore-re":
				if importIgnoreRE(unary[2:3]) {
					ignoreRe = append(ignoreRe, unary[2])
				}
			case "ignore-line":
				ignoreLine = append(ignoreLine, unary[2])
			case "ignore-substring":
				ignoreSubstring = append(ignoreSubstring, unary[2])
			case "snippet":
				if importSnippet(unary[2:3]) {
					snippet = append(snippet, unary[2])
				}
			default:
				fmt.Println("Unknown unary command. Try 'help'.")
			}
		}
	}
	done <- ""
}
Example #9
0
func CommandParser() <-chan Command {
	commands := make(chan Command, 1)

	go func() {
		for {
			in, err := readline.String("")
			if err == io.EOF { // Ctrl+D
				commands <- Exit
				break
			} else if err != nil {
				log.Fatal(err)
			}

			commands <- NormalizeCommand(in)
			readline.AddHistory(in)
		}
	}()

	return commands
}
Example #10
0
File: spur.go Project: jdrivas/spur
func doPrompt(s *KinesisStream) {

	moreToRead := true
	for moreToRead {
		line, err := readline.String("Send to Kinesis, <crtl-d> to end: ")
		if err == io.EOF {
			moreToRead = false
		} else if err != nil {
			log.Fatal(err)
		} else {
			resp, err := s.PutLogLine(strings.TrimRight(line, "\n"))
			if err != nil {
				log.Fatal(err)
			}
			if verbose {
				fmt.Println("Response:", awsutil.StringValue(resp))
			}
			readline.AddHistory(line)
		}
	}
}
Example #11
0
func promptLoop(prompt string, process func(string) error) (err error) {

	errStr := "Error - %s.\n"
	for moreCommands := true; moreCommands; {
		line, err := readline.String(prompt)
		if err == io.EOF {
			moreCommands = false
		} else if err != nil {
			fmt.Printf(errStr, err)
		} else {
			readline.AddHistory(line)
			err = process(line)
			if err == io.EOF {
				moreCommands = false
			} else if err != nil {
				fmt.Printf(errStr, err)
			}
		}
	}
	return nil
}
Example #12
0
// actionLauncher prepares an action for launch, either by starting with an empty
// template, or by loading an existing action from the api or the local disk
func actionLauncher(tpl mig.Action, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("actionLauncher() -> %v", e)
		}
	}()
	var a mig.Action
	if tpl.ID == 0 {
		fmt.Println("Entering action launcher with empty template")
		a.SyntaxVersion = mig.ActionVersion
	} else {
		// reinit the fields that we don't reuse
		a.Name = tpl.Name
		a.Target = tpl.Target
		a.Description = tpl.Description
		a.Threat = tpl.Threat
		a.Operations = tpl.Operations
		a.SyntaxVersion = tpl.SyntaxVersion
		fmt.Printf("Entering action launcher using template '%s'\n", a.Name)
	}
	hasTimes := false
	hasSignatures := false

	fmt.Println("Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	prompt := "\x1b[33;1mlauncher>\x1b[0m "
	for {
		// completion
		var symbols = []string{"addoperation", "deloperation", "exit", "help", "init",
			"json", "launch", "load", "details", "filechecker", "netstat",
			"setname", "settarget", "settimes", "sign", "times"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "addoperation":
			if len(orders) != 2 {
				fmt.Println("Wrong arguments. Expects 'addoperation <module_name>'")
				fmt.Println("example: addoperation filechecker")
				break
			}
			// attempt to call ParamsCreator from the requested module
			// ParamsCreator takes care of retrieving using input
			var operation mig.Operation
			operation.Module = orders[1]
			if _, ok := mig.AvailableModules[operation.Module]; ok {
				// instanciate and call module parameters creation function
				modRunner := mig.AvailableModules[operation.Module]()
				if _, ok := modRunner.(mig.HasParamsCreator); !ok {
					fmt.Println(operation.Module, "module does not provide a parameters creator.")
					fmt.Println("You can write your action by hand and import it using 'load <file>'")
					break
				}
				operation.Parameters, err = modRunner.(mig.HasParamsCreator).ParamsCreator()
				if err != nil {
					fmt.Printf("Parameters creation failed with error: %v\n", err)
					break
				}
				a.Operations = append(a.Operations, operation)
				opjson, err := json.MarshalIndent(operation, "", "  ")
				if err != nil {
					panic(err)
				}
				fmt.Printf("Inserting %s operation with parameters:\n%s\n", operation.Module, opjson)
			} else {
				fmt.Println("Module", operation.Module, "is not available in this console...")
				fmt.Println("You can write your action by hand and import it using 'load <file>'")
			}
		case "deloperation":
			if len(orders) != 2 {
				fmt.Println("Wrong arguments. Expects 'deloperation <opnum>'")
				fmt.Println("example: deloperation 0")
				break
			}
			opnum, err := strconv.Atoi(orders[1])
			if err != nil || opnum < 0 || opnum > len(a.Operations)-1 {
				fmt.Println("error: <opnum> must be a positive integer between 0 and", len(a.Operations)-1)
				break
			}
			a.Operations = append(a.Operations[:opnum], a.Operations[opnum+1:]...)
		case "details":
			fmt.Printf("ID       %.0f\nName     %s\nTarget   %s\nAuthor   %s <%s>\n"+
				"Revision %.0f\nURL      %s\nThreat Type %s, Level %s, Family %s, Reference %s\n",
				a.ID, a.Name, a.Target, a.Description.Author, a.Description.Email,
				a.Description.Revision, a.Description.URL,
				a.Threat.Type, a.Threat.Level, a.Threat.Family, a.Threat.Ref)
			fmt.Printf("%d operations: ", len(a.Operations))
			for i, op := range a.Operations {
				fmt.Printf("%d=%s; ", i, op.Module)
			}
			fmt.Printf("\n")
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
addoperation <module>	append a new operation of type <module> to the action operations
deloperation <opnum>	remove operation numbered <opnum> from operations array, count starts at zero
details			display the action details
exit			exit this mode
help			show this help
json <pretty>		show the json of the action
launch <nofollow>	launch the action. to return before completion, add "nofollow"
load <path>		load an action from a file at <path>
setname <name>		set the name of the action
settarget <target>	set the target
settimes <start> <stop>	set the validity and expiration dates
sign			PGP sign the action
times			show the various timestamps of the action
`)
		case "json":
			ajson, err := json.MarshalIndent(a, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", ajson)
		case "launch":
			follow := true
			if len(orders) > 1 {
				if orders[1] == "nofollow" {
					follow = false
				} else {
					fmt.Printf("Unknown option '%s'\n", orders[1])
				}
			}
			if a.Name == "" {
				fmt.Println("Action has no name. Define one using 'setname <name>'")
				break
			}
			if a.Target == "" {
				fmt.Println("Action has no target. Define one using 'settarget <target>'")
				break
			}
			if !hasTimes {
				fmt.Printf("Times are not defined. Setting validity from now until +%s\n", defaultExpiration)
				// for immediate execution, set validity one minute in the past
				a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
				period, err := time.ParseDuration(defaultExpiration)
				if err != nil {
					panic(err)
				}
				a.ExpireAfter = a.ValidFrom.Add(period)
				a.ExpireAfter = a.ExpireAfter.Add(60 * time.Second).UTC()
				hasTimes = true
			}
			if !hasSignatures {
				pgpsig, err := computeSignature(a, ctx)
				if err != nil {
					panic(err)
				}
				a.PGPSignatures = append(a.PGPSignatures, pgpsig)
				hasSignatures = true
			}
			a, err = postAction(a, follow, ctx)
			if err != nil {
				panic(err)
			}
			fmt.Println("")
			_ = actionReader(fmt.Sprintf("action %.0f", a.ID), ctx)
			goto exit
		case "load":
			if len(orders) != 2 {
				fmt.Println("Wrong arguments. Expects 'load <path_to_file>'")
				break
			}
			a, err = mig.ActionFromFile(orders[1])
			if err != nil {
				panic(err)
			}
			fmt.Printf("Loaded action '%s' from %s\n", a.Name, orders[1])
		case "sign":
			if !hasTimes {
				fmt.Println("Times must be set prior to signing")
				break
			}
			pgpsig, err := computeSignature(a, ctx)
			if err != nil {
				panic(err)
			}
			a.PGPSignatures = append(a.PGPSignatures, pgpsig)
			hasSignatures = true
		case "setname":
			if len(orders) < 2 {
				fmt.Println("Wrong arguments. Must be 'setname <some_name>'")
				break
			}
			a.Name = strings.Join(orders[1:], " ")
		case "settarget":
			if len(orders) < 2 {
				fmt.Println("Wrong arguments. Must be 'settarget <some_target_string>'")
				break
			}
			a.Target = strings.Join(orders[1:], " ")
		case "settimes":
			// set the dates
			if len(orders) != 3 {
				fmt.Println(`Invalid times. Expects settimes <start> <stop.)
examples:
settimes 2014-06-30T12:00:00.0Z 2014-06-30T14:00:00.0Z
settimes now +60m
`)
				break
			}
			if orders[1] == "now" {
				// for immediate execution, set validity one minute in the past
				a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
				period, err := time.ParseDuration(orders[2])
				if err != nil {
					fmt.Println("Failed to parse duration '%s': %v", orders[2], err)
					break
				}
				a.ExpireAfter = a.ValidFrom.Add(period)
				a.ExpireAfter = a.ExpireAfter.Add(60 * time.Second).UTC()
			} else {
				a.ValidFrom, err = time.Parse("2014-01-01T00:00:00.0Z", orders[1])
				if err != nil {
					fmt.Println("Failed to parse time '%s': %v", orders[1], err)
					break
				}
				a.ExpireAfter, err = time.Parse("2014-01-01T00:00:00.0Z", orders[2])
				if err != nil {
					fmt.Println("Failed to parse time '%s': %v", orders[2], err)
					break
				}
			}
			hasTimes = true
		case "times":
			fmt.Printf("Valid from   '%s' until '%s'\nStarted on   '%s'\n"+
				"Last updated '%s'\nFinished on  '%s'\n",
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime)
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in action launcher mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #13
0
func main() {
	var err error
	fmt.Println("\x1b[32;1m" + `
## ##                                     _.---._     .---.
# # # /-\ ---||  |    /\         __...---' .---. '---'-.   '.
#   #|   | / ||  |   /--\    .-''__.--' _.'( | )'.  '.  '._ :
#   # \_/ ---| \_ \_/    \ .'__-'_ .--'' ._'---'_.-.  '.   '-'.
     ###                         ~ -._ -._''---. -.    '-._   '.
      # |\ |\    /---------|          ~ -.._ _ _ _ ..-_ '.  '-._''--.._
      # | \| \  / |- |__ | |                       -~ -._  '-.  -. '-._''--.._.--''.
     ###|  \  \/  ---__| | |                            ~ ~-.__     -._  '-.__   '. '.
          #####                                               ~~ ~---...__ _    ._ .' '.
          #      /\  --- /-\ |--|----                                    ~  ~--.....--~
          # ### /--\  | |   ||-\  //
          #####/    \ |  \_/ |  \//__
` + "\x1b[0m")

	ctx.Homedir = findHomedir()
	// command line options
	var config = flag.String("c", ctx.Homedir+"/.migconsole", "Load configuration from file")
	var api = flag.String("a", "undef", "API base url (ex: http://localhost:1664/api/v1/)")
	var shortnames = flag.Bool("s", false, "Shorten all agent names to first and last 5 characters)")
	flag.Parse()
	// append a space after completion
	readline.CompletionAppendChar = 0x20

	if *shortnames {
		useShortNames = true
	}
	if *api != "undef" {
		ctx.API.URL = *api
	} else {
		err := gcfg.ReadFileInto(&ctx, *config)
		if err != nil {
			panic(err)
		}
	}
	ctx.GPG.Home, err = findGPGHome(ctx)
	if err != nil {
		panic(err)
	}

	err = printStatus(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("\nConnected to %s. Exit with \x1b[32;1mctrl+d\x1b[0m. Type \x1b[32;1mhelp\x1b[0m for help.\n", ctx.API.URL)
	for {
		// completion
		var symbols = []string{"action", "agent", "command", "help", "exit", "showcfg", "status",
			"search", "where", "and"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String("\x1b[32;1mmig>\x1b[0m ")
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "action":
			if len(orders) == 2 {
				if orders[1] == "new" {
					var a mig.Action
					err = actionLauncher(a, ctx)
				} else {
					err = actionReader(input, ctx)
				}
				if err != nil {
					log.Println(err)
				}
			} else {
				fmt.Println("error: 'action' order takes one argument; " +
					"either 'new' to enter launcher mode, or an action ID to enter reader mode.")
			}
		case "agent":
			err = agentReader(input, ctx)
			if err != nil {
				log.Println(err)
			}
		case "command":
			err = commandReader(input, ctx)
			if err != nil {
				log.Println(err)
			}
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
action <id|new>	enter action mode. if <id> is given, go to reader mode. if "new" is given, enter launcher mode.
command <id>	enter command reader mode for command <id>
help		show this help
exit		leave
search		perform a search. see "search help" for more information.
showcfg		display running configuration
status		display platform status: connected agents and latest actions
`)
		case "search":
			err = search(input, ctx)
			if err != nil {
				log.Println(err)
			}
		case "showcfg":
			fmt.Printf("homedir = %s\n[api]\n    url = %s\n[gpg]\n    home = %s\n    keyid = %s\n",
				ctx.API.URL, ctx.Homedir, ctx.GPG.Home, ctx.GPG.KeyID)
		case "status":
			err = printStatus(ctx)
			if err != nil {
				log.Println(err)
			}
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf(`
            .-._   _ _ _ _ _ _ _ _
 .-''-.__.-'Oo  '-' ' ' ' ' ' ' ' '-.
'.___ '    .   .--_'-' '-' '-' _'-' '._
 V: V 'vv-'   '_   '.       .'  _..' '.'.
   '=.____.=_.--'   :_.__.__:_   '.   : :
           (((____.-'        '-.  /   : :
                             (((-'\ .' /
                           _____..'  .'
                          '-._____.-'
              Gators are going back underwater.
`)
}
Example #14
0
func REPL(c Context) (Context, error) {
	tokens := []string{}
	leftCount := 0
	rightCount := 0

	for {
		prompt := mainPrompt
		if len(tokens) > 0 {
			prompt = incompletePrompt
		}

		line, err := readline.String(prompt)
		if err != nil {
			return nil, err
		}

		if line != "" {
			line = strings.TrimRight(line, "\r\n ")
			readline.AddHistory(line)

			if line == "quit" {
				return c, nil
			}

			temp := Tokenize(line)
			for _, t := range temp {
				if t == "(" || t == "'(" {
					leftCount += 1
				} else if t == ")" {
					rightCount += 1
				}
			}

			tokens = append(tokens, temp...)

			if leftCount == rightCount {
				nodes, err := Parse(tokens)
				if err != nil {
					fmt.Println("error: ", err)
				} else {
					for _, n := range nodes {
						r := n.Eval(c)

						if r.Type() == "error" {
							fmt.Println("error:", r.Value().(string))
							break
						}

						if r != NIL {
							fmt.Println(r)
						}
					}
				}

				leftCount = 0
				rightCount = 0
				tokens = []string{}
			}
		}
	}
}
Example #15
0
// commandReader retrieves an command from the API using its numerical ID
// and enters prompt mode to analyze it
func commandReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("commandReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'command <commandid>'")
	}
	cmdid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	cmd, err := cli.GetCommand(cmdid)
	if err != nil {
		panic(err)
	}

	fmt.Println("Entering command reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Command %.0f ran on agent '%s' based on action '%s'\n",
		cmd.ID, cmd.Agent.Name, cmd.Action.Name)
	prompt := fmt.Sprintf("\x1b[36;1mcommand %d>\x1b[0m ", uint64(cmdid)%1000)
	for {
		// completion
		var symbols = []string{"exit", "help", "json", "found", "pretty", "r", "results"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
exit		exit this mode
help		show this help
json		show the json of the command
r		refresh the command (get latest version from upstream)
results <found>	print the results. if "found" is set, only print results that have at least one found
`)
		case "json":
			var cjson []byte
			cjson, err = json.MarshalIndent(cmd, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", cjson)
		case "r":
			cmd, err = cli.GetCommand(cmdid)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "results":
			found := false
			if len(orders) > 1 {
				if orders[1] == "found" {
					found = true
				} else {
					fmt.Printf("Unknown option '%s'\n", orders[1])
				}
			}
			err = client.PrintCommandResults(cmd, found, false)
			if err != nil {
				panic(err)
			}
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in command reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #16
0
// actionReader retrieves an action from the API using its numerical ID
// and enters prompt mode to analyze it
func actionReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("actionReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'action <actionid>'")
	}
	aid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	a, _, err := cli.GetAction(aid)
	if err != nil {
		panic(err)
	}
	investigators := investigatorsStringFromAction(a.Investigators, 80)

	fmt.Println("Entering action reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Action: '%s'.\nLaunched by '%s' on '%s'.\nStatus '%s'.\n",
		a.Name, investigators, a.StartTime, a.Status)
	a.PrintCounters()
	prompt := fmt.Sprintf("\x1b[31;1maction %d>\x1b[0m ", uint64(aid)%1000)
	for {
		// completion
		var symbols = []string{"command", "copy", "counters", "details", "exit", "grep", "help", "investigators",
			"json", "list", "all", "found", "notfound", "pretty", "r", "results", "times"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "command":
			err = commandReader(input, cli)
			if err != nil {
				panic(err)
			}
		case "copy":
			err = actionLauncher(a, cli)
			if err != nil {
				panic(err)
			}
			goto exit
		case "counters":
			a, _, err = cli.GetAction(aid)
			if err != nil {
				panic(err)
			}
			a.PrintCounters()
		case "details":
			actionPrintDetails(a)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
command <id>	jump to command reader mode for command <id>

copy		enter action launcher mode using current action as template

counters	display the counters of the action

details		display the details of the action, including status & times

exit		exit this mode (also works with ctrl+d)

help		show this help

investigators   print the list of investigators that signed the action

json         	show the json of the action

list <show>	returns the list of commands with their status
		<show>: * set to "all" to get all results (default)
			* set to "found" to only display positive results
			* set to "notfound" for negative results
		list can be followed by a 'filter' pipe:
		ex: ls | grep server1.(dom1|dom2) | grep -v example.net

r		refresh the action (get latest version from upstream)

results <show> <render>	display results of all commands
			<show>: * set to "all" to get all results (default)
				* set to "found" to only display positive results
				* set to "notfound" for negative results
			<render>: * set to "text" to print results in console (default)
				  * set to "map" to generate an open a google map

times		show the various timestamps of the action
`)
		case "investigators":
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- Key ID:", i.PGPFingerprint)
			}
		case "json":
			var ajson []byte
			ajson, err = json.MarshalIndent(a, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", ajson)
		case "list":
			err = actionPrintList(aid, orders, cli)
			if err != nil {
				panic(err)
			}
		case "r":
			a, _, err = cli.GetAction(aid)
			if err != nil {
				panic(err)
			}
			fmt.Println("reloaded")
		case "results":
			show := "all"
			if len(orders) > 1 {
				switch orders[1] {
				case "all", "found", "notfound":
					show = orders[1]
				default:
					panic("invalid show '" + orders[2] + "'")
				}
			}
			render := "text"
			if len(orders) > 2 {
				switch orders[2] {
				case "map", "text":
					render = orders[2]
				default:
					panic("invalid rendering '" + orders[2] + "'")
				}
			}
			err = cli.PrintActionResults(a, show, render)
			if err != nil {
				panic(err)
			}
		case "times":
			fmt.Printf("Valid from   '%s' until '%s'\nStarted on   '%s'\n"+
				"Last updated '%s'\nFinished on  '%s'\n",
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime)
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in action reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #17
0
func main() {
	var err error
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "FATAL: %v\n", e)
		}
	}()
	homedir := client.FindHomedir()
	// command line options
	var config = flag.String("c", homedir+"/.migrc", "Load configuration from file")
	var quiet = flag.Bool("q", false, "don't display banners and prompts")
	var showversion = flag.Bool("V", false, "show build version and exit")
	flag.Parse()

	if *showversion {
		fmt.Println(version)
		os.Exit(0)
	}

	// silence extra output
	out := os.Stdout
	if *quiet {
		out.Close()
		out, err = os.Open(os.DevNull)
		if err != nil {
			panic(err)
		}
	}
	defer out.Close()

	fmt.Fprintf(out, "\x1b[32;1m"+banner+"\x1b[0m")

	// append a space after completion
	readline.CompletionAppendChar = 0x20
	// load history
	historyfile := homedir + "/.mig_history"
	fi, err := os.Stat(historyfile)
	if err == nil && fi.Size() > 0 {
		err = readline.LoadHistory(historyfile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "failed to load history from %s\n", historyfile)
		}
	}
	// instanciate an API client
	conf, err := client.ReadConfiguration(*config)
	if err != nil {
		panic(err)
	}
	cli, err := client.NewClient(conf, "console-"+version)
	if err != nil {
		panic(err)
	}
	// print platform status
	err = printStatus(cli)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Fprintf(out, "\nConnected to %s. Exit with \x1b[32;1mctrl+d\x1b[0m. Type \x1b[32;1mhelp\x1b[0m for help.\n", cli.Conf.API.URL)
	for {
		// completion
		var symbols = []string{"action", "agent", "create", "command", "help", "history",
			"exit", "showcfg", "status", "investigator", "search", "where", "and"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String("\x1b[32;1mmig>\x1b[0m ")
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "action":
			if len(orders) == 2 {
				err = actionReader(input, cli)
				if err != nil {
					log.Println(err)
				}
			} else {
				fmt.Println("error: missing action id in 'action <id>'")
			}
		case "agent":
			err = agentReader(input, cli)
			if err != nil {
				log.Println(err)
			}
		case "create":
			if len(orders) == 2 {
				switch orders[1] {
				case "action":
					var a mig.Action
					err = actionLauncher(a, cli)
				case "investigator":
					err = investigatorCreator(cli)
				default:
					fmt.Printf("unknown order 'create %s'\n", orders[1])
				}
				if err != nil {
					log.Println(err)
				}
			} else {
				fmt.Println("error: missing order, must be 'create <action|investigator>'")
			}
		case "command":
			err = commandReader(input, cli)
			if err != nil {
				log.Println(err)
			}
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
action <id>		enter interactive action reader mode for action <id>
agent <id>		enter interactive agent reader mode for agent <id>
create action		create a new action
create investigator	create a new investigator, will prompt for name and public key
command <id>		enter command reader mode for command <id>
exit			leave
help			show this help
history <count>		print last <count> entries in history. count=10 by default.
investigator <id>	enter interactive investigator management mode for investigator <id>
search			perform a search. see "search help" for more information.
showcfg			display running configuration
status			display platform status: connected agents, latest actions, ...
`)
		case "history":
			var count int64 = 10
			if len(orders) > 1 {
				count, err = strconv.ParseInt(orders[1], 10, 64)
				if err != nil {
					log.Println(err)
					break
				}
			}
			for i := readline.HistorySize(); i > 0 && count > 0; i, count = i-1, count-1 {
				fmt.Println(readline.GetHistory(i - 1))
			}
		case "investigator":
			err = investigatorReader(input, cli)
			if err != nil {
				log.Println(err)
			}
		case "search":
			err = search(input, cli)
			if err != nil {
				log.Println(err)
			}
		case "showcfg":
			fmt.Printf("homedir = %s\n[api]\n    url = %s\n[gpg]\n    home = %s\n    keyid = %s\n",
				cli.Conf.API.URL, cli.Conf.Homedir, cli.Conf.GPG.Home, cli.Conf.GPG.KeyID)
		case "status":
			err = printStatus(cli)
			if err != nil {
				log.Println(err)
			}
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Fprintf(out, footer)
	err = readline.SaveHistory(historyfile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to save history to %s\n", historyfile)
	}
}
Example #18
0
// manifestReader is used to manipulate API manifests
func manifestReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("manifestReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'manifest <manifestid>'")
	}
	mid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	mr, err := cli.GetManifestRecord(mid)
	if err != nil {
		panic(err)
	}

	fmt.Println("Entering manifest reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Manifest: '%s'.\nStatus '%s'.\n", mr.Name, mr.Status)

	prompt := fmt.Sprintf("\x1b[31;1mmanifest %d>\x1b[0m ", uint64(mid)%1000)
	for {
		var symbols = []string{"disable", "entry", "exit", "help", "json", "r", "reset", "sign"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "disable":
			err = cli.ManifestRecordStatus(mr, "disabled")
			if err != nil {
				panic(err)
			}
			fmt.Println("Manifest record has been disabled")
		case "entry":
			mre, err := mr.ManifestResponse()
			if err != nil {
				panic(err)
			}
			buf, err := json.MarshalIndent(mre, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", buf)
		case "help":
			fmt.Printf(`The following orders are avialable:
disable         disables manifest and prevents future use

entry           show the manifest for this record as would be sent to a loader

help            show this help

exit            exit this mode (also works with ctrl+d)

json            show json of manifest record stored in database

loaders         show known loader entries that will match this manifest

r               refresh the manifest (get latest version from database)

reset           reset manifest status (marks manifest as staged, removes signatures)

sign            add a signature to the manifest record
`)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "json":
			tmpmr := mr
			if len(tmpmr.Content) > 0 {
				tmpmr.Content = "..."
			} else {
				tmpmr.Content = "None"
			}
			jsonmr, err := json.MarshalIndent(tmpmr, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", jsonmr)
		case "loaders":
			ldrs, err := cli.GetManifestLoaders(mid)
			if err != nil {
				panic(err)
			}
			for _, x := range ldrs {
				buf, err := json.Marshal(x)
				if err != nil {
					panic(err)
				}
				fmt.Printf("%v\n", string(buf))
			}
		case "r":
			mr, err = cli.GetManifestRecord(mid)
			if err != nil {
				panic(err)
			}
			fmt.Println("reloaded")
		case "reset":
			err = cli.ManifestRecordStatus(mr, "staged")
			if err != nil {
				panic(err)
			}
			fmt.Println("Manifest record has been reset")
		case "sign":
			sig, err := cli.SignManifest(mr)
			if err != nil {
				panic(err)
			}
			err = cli.PostManifestSignature(mr, sig)
			if err != nil {
				panic(err)
			}
			fmt.Println("Manifest signature has been accepted")
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in manifest reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}

exit:
	fmt.Printf("\n")
	return
}
Example #19
0
// Prompts for input and creates a new manifest record through the API
func manifestCreator(cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("manifestCreator() -> %v", e)
		}
	}()
	var newmr mig.ManifestRecord
	fmt.Println("Entering manifest creation mode.\nPlease provide the name" +
		" of the new manifest")
	newmr.Name, err = readline.String("name> ")
	if err != nil {
		panic(err)
	}
	if len(newmr.Name) < 3 {
		panic("input name too short")
	}
	fmt.Printf("Name: '%s'\n", newmr.Name)
	fmt.Println("Please provide loader targeting string for manifest.")
	newmr.Target, err = readline.String("target> ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Target: '%s'\n", newmr.Target)
	fmt.Println("Please enter path to new manifest archive content.")
	arcpath, err := readline.String("contentpath> ")
	if err != nil {
		panic(err)
	}
	// Load the content into the manifest record from the specified path,
	// we assume the archive is a gzip compressed tar file; if not it will
	// fail during validation later on.
	err = newmr.ContentFromFile(arcpath)
	if err != nil {
		panic(err)
	}
	newmr.Status = "staged"
	// Validate the new manifest record before sending it to the API
	err = newmr.Validate()
	if err != nil {
		panic(err)
	}
	tmpmr := newmr
	if len(tmpmr.Content) > 0 {
		tmpmr.Content = "..."
	} else {
		tmpmr.Content = "None"
	}
	jsonmr, err := json.MarshalIndent(tmpmr, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", jsonmr)
	input, err := readline.String("create manifest? (y/n)> ")
	if err != nil {
		panic(err)
	}
	if input != "y" {
		fmt.Println("abort")
		return
	}
	err = cli.PostNewManifest(newmr)
	if err != nil {
		panic(err)
	}
	fmt.Println("Manifest successfully created")
	return
}
Example #20
0
// actionReader retrieves an action from the API using its numerical ID
// and enters prompt mode to analyze it
func actionReader(input string, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("actionReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'action <actionid>'")
	}
	aid := inputArr[1]
	a, links, err := getAction(aid, ctx)
	if err != nil {
		panic(err)
	}
	investigators := investigatorsStringFromAction(a.Investigators, 80)

	fmt.Println("Entering action reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Action: '%s'.\nLaunched by '%s' on '%s'.\nStatus '%s'.\n",
		a.Name, investigators, a.StartTime, a.Status)
	prompt := "\x1b[31;1maction " + aid[len(aid)-3:len(aid)] + ">\x1b[0m "
	for {
		// completion
		var symbols = []string{"command", "copy", "counters", "details", "exit", "foundsomething", "foundnothing",
			"grep", "help", "investigators", "json", "ls", "found", "pretty", "r", "results", "times"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "command":
			err = commandReader(input, ctx)
			if err != nil {
				panic(err)
			}
		case "copy":
			err = actionLauncher(a, ctx)
			if err != nil {
				panic(err)
			}
			goto exit
		case "counters":
			fmt.Printf("Sent:\t\t%d\nReturned:\t%d\nDone:\t\t%d\n"+
				"Cancelled:\t%d\nFailed:\t\t%d\nTimeout:\t%d\n",
				a.Counters.Sent, a.Counters.Returned, a.Counters.Done,
				a.Counters.Cancelled, a.Counters.Failed, a.Counters.TimeOut)
		case "details":
			actionPrintDetails(a)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "foundsomething":
			err = searchFoundAnything(a, true, ctx)
			if err != nil {
				panic(err)
			}
		case "foundnothing":
			err = searchFoundAnything(a, false, ctx)
			if err != nil {
				panic(err)
			}
		case "help":
			fmt.Printf(`The following orders are available:
command <id>	jump to command reader mode for command <id>
copy		enter action launcher mode using current action as template
counters	display the counters of the action
exit		exit this mode
foundsomething	list commands and agents that have found something
foundnothing	list commands and agents that have found nothing
help		show this help
investigators   print the list of investigators that signed the action
json         	show the json of the action
ls <filter>	returns the list of commands with their status
		'filter' is a pipe separated string of filter:
		ex: ls | grep server1.(dom1|dom2) | grep -v example.net
details		display the details of the action, including status & times
r		refresh the action (get latest version from upstream)
times		show the various timestamps of the action
`)
		case "investigators":
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- Key ID:", i.PGPFingerprint)
			}
		case "json":
			var ajson []byte
			ajson, err = json.MarshalIndent(a, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", ajson)
		case "ls":
			err = actionPrintLinks(links, orders)
			if err != nil {
				panic(err)
			}
		case "r":
			a, links, err = getAction(aid, ctx)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "results":
			err = actionPrintResults(a, links, orders)
			if err != nil {
				panic(err)
			}
		case "times":
			fmt.Printf("Valid from   '%s' until '%s'\nStarted on   '%s'\n"+
				"Last updated '%s'\nFinished on  '%s'\n",
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime)
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in action reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #21
0
func readCommand() {
	// Reset the color on defer.
	defer fmt.Print(colorReset)

	// Read the input line.
	line, err := gnureadline.String(prompt)
	if err == io.EOF {
		// Print a new line.
		fmt.Println("")
		return
	} else if err != nil {
		fmt.Printf("%serror: %v\n", colorError, err)
		return
	}

	// Set to output color.
	fmt.Print(colorOutput)

	// Trim all spaces.
	line = strings.TrimSpace(line)

	// Split the input line.
	args := strings.Fields(line)

	// Skip if empty.
	if len(args) == 0 {
		return
	}

	// Get the command key.
	key := args[0]

	// Remove the first command key from the slice.
	args = args[1:]

	// Try to find the command in the commands map.
	cmd, ok := commands[key]
	if !ok {
		fmt.Printf("%serror: invalid command\n", colorError)
		return
	}

	// Add the command to the history.
	gnureadline.AddHistory(line)

	// Run the command.
	err = cmd.Run(args)
	if err != nil {
		fmt.Printf("%serror: %v\n", colorError, err)

		// Print the usage if this is an invalid usage error.
		if err == errInvalidUsage {
			// Set to output color.
			fmt.Print(colorReset, colorOutput, "\n")

			cmd.PrintUsage()
		}

		return
	}
}
Example #22
0
func main() {
	host := flag.String("host", "http://localhost:8000", "hostname")
	flag.Parse()

	var client wpmutils.JobqueueHTTPClient

	msg, err := client.Open(*host)
	if err != nil {
		fmt.Println("Invalid address " + (*host) + ":" + err.Error())
		os.Exit(-1)
	}
	fmt.Println(msg)

	//autocomplete = wpmutils.ListTaskNames(*taskdir)
	//readline.Completer = readline.FilenameCompleter

	autocomplete = append(client.ListAsList(), getKeywords()...)
	readline.Completer = taskNameCompleter

	// loop until ReadLine returns nil (signalling EOF)
Loop:
	for {
		rl, err := readline.String("> ")
		if err == io.EOF {
			break Loop
		}
		if err != nil {
			fmt.Println("Error: ", err)
			break Loop
		}
		if "" == rl {
			// ignore blank lines
			continue Loop
		}

		// allow user to recall this line
		readline.AddHistory(rl)

		// split the main command from its (optional) parameters
		command, parameters := parseReadline(rl)

		var msg string

		switch command {
		case "quit", "exit":
			fmt.Println()
			break Loop //exit loop
		case "ls", "list":
			msg, err = client.List()
		case "lw", "listworkers":
			msg, err = client.ListWorkers(parameters)
		case "set":
			taskname, p, v := parseParams(parameters)
			msg, err = client.Set(taskname, p, v)
		case "start":
			msg, err = client.Start(parameters)
		case "stop":
			msg, err = client.Stop(parameters)
		case "st", "status":
			msg, err = client.Status(parameters)
		case "connect", "open":
			msg, err = client.Open(parameters)
			if err == nil {
				// refresh auto-complete list
				autocomplete = append(client.ListAsList(), getKeywords()...)
			}
		case "help", "h":
			msg = getHelp()
		default:
			msg = "ERROR: Command not recognised: " + command
		}

		if err != nil {
			msg = "ERROR: " + err.Error()
		}
		fmt.Println(msg)
	}
	fmt.Println("") // newline before exit
}
Example #23
0
func printContext(lines []string, line, contextCount int) {
	line-- // token.Position.Line starts at 1.
	fmt.Println()
	for i := line - contextCount; i <= line+contextCount; i++ {
		prefix := "    "
		if i == line {
			prefix = "--> "
		}
		if i >= 0 && i < len(lines) {
			line := strings.TrimRightFunc(prefix+lines[i], unicode.IsSpace)
			fmt.Println(line)
		}
	}
	fmt.Println()
}

var input = bufio.NewScanner(os.Stdin)

// This gets overridden when running in a browser.
var promptUser = func() (response string, ok bool) {
	l, err := readline.String("(godebug) ")
	if err != nil {
		return "", false
	}
	if l != "" {
		readline.AddHistory(l)
	}
	return l, true
}
Example #24
0
// investigatorCreator prompt the user for a name and the path to an armored
// public key and calls the API to create a new investigator
func investigatorCreator(cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("investigatorCreator() -> %v", e)
		}
	}()
	var (
		name   string
		pubkey []byte
	)
	fmt.Println("Entering investigator creation mode. Please provide the full name\n" +
		"and the public key of the new investigator.")
	name, err = readline.String("name> ")
	if err != nil {
		panic(err)
	}
	if len(name) < 3 {
		panic("input name too short")
	}
	fmt.Printf("Name: '%s'\n", name)
	fmt.Println("Please provide a public key. You can either provide a local path to the\n" +
		"armored public key file, or a full length PGP fingerprint.\n" +
		"example:\npubkey> 0x716CFA6BA8EBB21E860AE231645090E64367737B")
	input, err := readline.String("pubkey> ")
	if err != nil {
		panic(err)
	}
	re := regexp.MustCompile(`^0x[ABCDEF0-9]{8,64}$`)
	if re.MatchString(input) {
		var keyserver string
		if cli.Conf.GPG.Keyserver == "" {
			keyserver = "http://gpg.mozilla.org"
		}
		fmt.Println("retrieving public key from", keyserver)
		pubkey, err = pgp.GetArmoredKeyFromKeyServer(input, keyserver)
		if err != nil {
			panic(err)
		}
	} else {
		fmt.Println("retrieving public key from", input)
		pubkey, err = ioutil.ReadFile(input)
		if err != nil {
			panic(err)
		}
	}
	fmt.Printf("%s\n", pubkey)
	input, err = readline.String("create investigator? (y/n)> ")
	if err != nil {
		panic(err)
	}
	if input != "y" {
		fmt.Println("abort")
		return
	}
	inv, err := cli.PostInvestigator(name, pubkey)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Investigator '%s' successfully created with ID %.0f\n",
		inv.Name, inv.ID)
	return
}
Example #25
0
// investigatorReader retrieves an agent from the api
// and enters prompt mode to analyze it
func investigatorReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("investigatorReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'investigator <investigatorid>'")
	}
	iid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	inv, err := cli.GetInvestigator(iid)
	if err != nil {
		panic(err)
	}

	fmt.Println("Entering investigator mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Investigator %.0f named '%s'\n", inv.ID, inv.Name)
	prompt := fmt.Sprintf("\x1b[35;1minv %.0f>\x1b[0m ", iid)
	for {
		// completion
		var symbols = []string{"details", "exit", "help", "pubkey", "r", "lastactions"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(input, " ")
		switch orders[0] {
		case "details":
			fmt.Printf("Investigator ID %.0f\nname     %s\nstatus   %s\nkey id   %s\ncreated  %s\nmodified %s\n",
				inv.ID, inv.Name, inv.Status, inv.PGPFingerprint, inv.CreatedAt, inv.LastModified)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
details			print the details of the investigator
exit			exit this mode
help			show this help
lastactions <limit>	print the last actions ran by the investigator. limit=10 by default.
pubkey			show the armored public key of the investigator
r			refresh the investigator (get latest version from upstream)
setstatus <status>	changes the status of the investigator to <status> (can be 'active' or 'disabled')
`)
		case "lastactions":
			limit := 10
			if len(orders) > 1 {
				limit, err = strconv.Atoi(orders[1])
				if err != nil {
					panic(err)
				}
			}
			err = printInvestigatorLastActions(iid, limit, cli)
			if err != nil {
				panic(err)
			}
		case "pubkey":
			armoredPubKey, err := pgp.ArmorPubKey(inv.PublicKey)
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", armoredPubKey)
		case "r":
			inv, err = cli.GetInvestigator(iid)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "setstatus":
			if len(orders) != 2 {
				fmt.Println("error: must be 'setstatus <status>'. try 'help'")
				break
			}
			newstatus := orders[1]
			err = cli.PostInvestigatorStatus(iid, newstatus)
			if err != nil {
				panic(err)
			} else {
				fmt.Println("Investigator status set to", newstatus)
			}
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in investigator mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #26
0
// loaderReader is used to manipulate loader entries
func loaderReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("loaderReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) != 2 {
		panic("wrong order format. must be 'loader <loaderid>'")
	}
	lid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	le, err := cli.GetLoaderEntry(lid)
	if err != nil {
		panic(err)
	}

	fmt.Println("Entering loader reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Loader: '%v'.\nStatus '%v'.\n", le.Name, le.Enabled)

	prompt := fmt.Sprintf("\x1b[31;1mloader %v>\x1b[0m ", uint64(lid)%1000)
	for {
		reloadfunc := func() {
			le, err = cli.GetLoaderEntry(lid)
			if err != nil {
				panic(err)
			}
			fmt.Println("reloaded")
		}
		var symbols = []string{"disable", "enable", "exit", "help", "json", "key", "r"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(strings.TrimSpace(input), " ")
		switch orders[0] {
		case "disable":
			err = cli.LoaderEntryStatus(le, false)
			if err != nil {
				panic(err)
			}
			fmt.Println("Loader has been disabled")
			reloadfunc()
		case "enable":
			err = cli.LoaderEntryStatus(le, true)
			if err != nil {
				panic(err)
			}
			fmt.Println("Loader has been enabled")
			reloadfunc()
		case "help":
			fmt.Printf(`The following orders are avialable:
disable         disable loader entry

enable          enable loader entry

help            show this help

exit            exit this mode (also works with ctrl+d)

json            show json of loader entry stored in database

key             change loader key

r               refresh the loader entry (get latest version from database)
`)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "json":
			jsonle, err := json.MarshalIndent(le, "", "  ")
			if err != nil {
				panic(err)
			}
			fmt.Printf("%v\n", string(jsonle))
		case "key":
			fmt.Printf("New key component must be %v alphanumeric characters long, or type 'generate' to generate one\n", mig.LoaderKeyLength)
			lkey, err := readline.String("New key for loader> ")
			if err != nil {
				panic(err)
			}
			if lkey == "" {
				panic("invalid key specified")
			}
			if lkey == "generate" {
				lkey = mig.GenerateLoaderKey()
				fmt.Printf("New key will be set to %v\n", lkey)
			}
			fmt.Printf("New key including prefix to supply to client will be %q\n", le.Prefix+lkey)
			err = cli.LoaderEntryKey(le, lkey)
			if err != nil {
				panic(err)
			}
			fmt.Println("Loader key changed")
		case "r":
			reloadfunc()
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in loader reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}

exit:
	fmt.Printf("\n")
	return
}
Example #27
0
// agentReader retrieves an agent from the api
// and enters prompt mode to analyze it
func agentReader(input string, cli client.Client) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("agentReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'agent <agentid>'")
	}
	agtid, err := strconv.ParseFloat(inputArr[1], 64)
	if err != nil {
		panic(err)
	}
	agt, err := cli.GetAgent(agtid)
	if err != nil {
		panic(err)
	}

	fmt.Println("Entering agent reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Agent %.0f named '%s'\n", agt.ID, agt.Name)
	prompt := fmt.Sprintf("\x1b[34;1magent %d>\x1b[0m ", uint64(agtid)%1000)
	for {
		// completion
		var symbols = []string{"details", "exit", "help", "json", "pretty", "r", "lastactions"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(input, " ")
		switch orders[0] {
		case "details":
			agt, err = cli.GetAgent(agtid)
			if err != nil {
				panic(err)
			}
			jEnv, err := json.MarshalIndent(agt.Env, "", "    ")
			if err != nil {
				panic(err)
			}
			jTags, err := json.MarshalIndent(agt.Tags, "", "    ")
			if err != nil {
				panic(err)
			}
			fmt.Printf(`Agent ID %.0f
name       %s
last seen  %s ago
version    %s
mode       %s
location   %s
platform   %s %s
pid        %d
starttime  %s
status     %s
environment %s
tags %s
`, agt.ID, agt.Name, time.Now().Sub(agt.HeartBeatTS).String(), agt.Version, agt.Mode, agt.QueueLoc,
				agt.Env.OS, agt.Env.Arch, agt.PID, agt.StartTime, agt.Status, jEnv, jTags)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "help":
			fmt.Printf(`The following orders are available:
details			print the details of the agent
exit			exit this mode
help			show this help
json <pretty>		show the json of the agent registration
r			refresh the agent (get latest version from upstream)
lastactions <limit>	print the last actions that ran on the agent. limit=10 by default.
`)
		case "lastactions":
			limit := 10
			if len(orders) > 1 {
				limit, err = strconv.Atoi(orders[1])
				if err != nil {
					panic(err)
				}
			}
			err = printAgentLastCommands(agtid, limit, cli)
			if err != nil {
				panic(err)
			}
		case "json":
			var agtjson []byte
			if len(orders) > 1 {
				if orders[1] == "pretty" {
					agtjson, err = json.MarshalIndent(agt, "", "  ")
				} else {
					fmt.Printf("Unknown option '%s'\n", orders[1])
				}
			} else {
				agtjson, err = json.Marshal(agt)
			}
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", agtjson)
		case "r":
			agt, err = cli.GetAgent(agtid)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in agent reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}
Example #28
0
func getInput(prompt string) (string, error) {
	return readline.String(prompt)
}