65 lines
1.3 KiB
Go
65 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Run an external program
|
|
func RunProgram(program string, args []string, timeout time.Duration) {
|
|
// Flag if we are starting or stopping a container
|
|
managingContainer := program == "docker"
|
|
|
|
// Create context and command
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
cmd := exec.CommandContext(ctx, program, args...)
|
|
|
|
// Stringify and censor the program's arguments
|
|
strArgs := redactString(strings.Join(args, " "))
|
|
fmt.Printf(" [+] Running %s %s\n", program, strArgs)
|
|
|
|
// Setup pipes
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
stderr, err := cmd.StderrPipe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Start the command
|
|
if err := cmd.Start(); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Stream any messages to the terminal
|
|
for _, r := range []io.Reader{stdout, stderr} {
|
|
// Don't log stdout from the container
|
|
if managingContainer && r == stdout {
|
|
continue
|
|
}
|
|
|
|
scanner := bufio.NewScanner(r)
|
|
scanner.Split(bufio.ScanRunes)
|
|
|
|
for scanner.Scan() {
|
|
fmt.Print(scanner.Text())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Redacts sensitive command line arguments.
|
|
func redactString(raw string) string {
|
|
redactionRegex := regexp.MustCompilePOSIX(`-(user|pass|key) [^ ]+`)
|
|
return redactionRegex.ReplaceAllString(raw, "-$1 REDACTED")
|
|
}
|