From 65778fbeb5aed2a304d8609266bf21819f24db79 Mon Sep 17 00:00:00 2001 From: its-a-feature Date: Thu, 18 Jan 2024 08:52:26 -0600 Subject: [PATCH] v0.0.2.34 --- Mythic_CLI/src/cmd/addDockerCompose.go | 12 +- Mythic_CLI/src/cmd/config/env.go | 16 +-- Mythic_CLI/src/cmd/internal/installservice.go | 9 +- Mythic_CLI/src/cmd/internal/reset.go | 2 +- .../src/cmd/internal/serviceExecution.go | 6 +- .../src/cmd/internal/serviceMetadata.go | 27 ++--- Mythic_CLI/src/cmd/internal/testServices.go | 11 +- Mythic_CLI/src/cmd/internal/utils.go | 2 +- Mythic_CLI/src/cmd/logs.go | 15 ++- .../src/cmd/manager/dockerComposeManager.go | 104 +++++++----------- .../src/cmd/manager/managerInterface.go | 12 +- Mythic_CLI/src/cmd/mythic_sync.go | 3 +- Mythic_CLI/src/cmd/mythic_sync_install.go | 3 +- .../src/cmd/mythic_sync_install_github.go | 2 +- Mythic_CLI/src/cmd/removeDockerCompose.go | 8 +- Mythic_CLI/src/go.mod | 1 + Mythic_CLI/src/go.sum | 2 + nginx-docker/health_check.sh | 8 +- 18 files changed, 122 insertions(+), 121 deletions(-) diff --git a/Mythic_CLI/src/cmd/addDockerCompose.go b/Mythic_CLI/src/cmd/addDockerCompose.go index 990500c1..72c8615d 100644 --- a/Mythic_CLI/src/cmd/addDockerCompose.go +++ b/Mythic_CLI/src/cmd/addDockerCompose.go @@ -1,8 +1,11 @@ package cmd import ( + "github.com/MythicMeta/Mythic_CLI/cmd/config" "github.com/MythicMeta/Mythic_CLI/cmd/internal" + "github.com/MythicMeta/Mythic_CLI/cmd/utils" "github.com/spf13/cobra" + "log" ) // configCmd represents the config command @@ -19,7 +22,12 @@ func init() { } func addDockerCompose(cmd *cobra.Command, args []string) { - if err := internal.Add3rdPartyService(args[0], make(map[string]interface{})); err != nil { - + if utils.StringInSlice(args[0], config.MythicPossibleServices) { + internal.AddMythicService(args[0]) + return + } + err := internal.Add3rdPartyService(args[0], make(map[string]interface{})) + if err != nil { + log.Printf("[-] Failed to add service") } } diff --git a/Mythic_CLI/src/cmd/config/env.go b/Mythic_CLI/src/cmd/config/env.go index 761adb66..3a699585 100644 --- a/Mythic_CLI/src/cmd/config/env.go +++ b/Mythic_CLI/src/cmd/config/env.go @@ -106,17 +106,17 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("nginx_use_ssl", true) mythicEnv.SetDefault("nginx_use_ipv4", true) mythicEnv.SetDefault("nginx_use_ipv6", true) - mythicEnv.SetDefault("nginx_bind_local_mount", true) + mythicEnv.SetDefault("nginx_bind_use_volume", false) // mythic react UI configuration mythicEnv.SetDefault("mythic_react_host", "mythic_react") mythicEnv.SetDefault("mythic_react_port", 3000) mythicEnv.SetDefault("mythic_react_bind_localhost_only", true) - mythicEnv.SetDefault("mythic_react_local_mount", true) + mythicEnv.SetDefault("mythic_react_use_volume", false) // documentation configuration mythicEnv.SetDefault("documentation_host", "mythic_documentation") mythicEnv.SetDefault("documentation_port", 8090) mythicEnv.SetDefault("documentation_bind_localhost_only", true) - mythicEnv.SetDefault("documentation_bind_local_mount", true) + mythicEnv.SetDefault("documentation_bind_use_volume", false) // mythic server configuration mythicEnv.SetDefault("mythic_debug_agent_message", false) mythicEnv.SetDefault("mythic_server_port", 17443) @@ -127,7 +127,7 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("mythic_server_mem_limit", "") mythicEnv.SetDefault("mythic_server_dynamic_ports", "7000-7010") mythicEnv.SetDefault("mythic_server_dynamic_ports_bind_localhost_only", false) - mythicEnv.SetDefault("mythic_server_bind_local_mount", true) + mythicEnv.SetDefault("mythic_server_bind_use_volume", false) mythicEnv.SetDefault("mythic_server_command", "") mythicEnv.SetDefault("mythic_sync_cpus", "2") mythicEnv.SetDefault("mythic_sync_mem_limit", "") @@ -140,7 +140,7 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("postgres_password", utils.GenerateRandomPassword(30)) mythicEnv.SetDefault("postgres_cpus", "2") mythicEnv.SetDefault("postgres_mem_limit", "") - mythicEnv.SetDefault("postgres_bind_local_mount", true) + mythicEnv.SetDefault("postgres_bind_use_volume", false) // rabbitmq configuration mythicEnv.SetDefault("rabbitmq_host", "mythic_rabbitmq") mythicEnv.SetDefault("rabbitmq_port", 5672) @@ -150,7 +150,7 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("rabbitmq_vhost", "mythic_vhost") mythicEnv.SetDefault("rabbitmq_cpus", "2") mythicEnv.SetDefault("rabbitmq_mem_limit", "") - mythicEnv.SetDefault("rabbitmq_bind_local_mount", true) + mythicEnv.SetDefault("rabbitmq_bind_use_volume", false) // jwt configuration mythicEnv.SetDefault("jwt_secret", utils.GenerateRandomPassword(30)) // hasura configuration @@ -160,7 +160,7 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("hasura_secret", utils.GenerateRandomPassword(30)) mythicEnv.SetDefault("hasura_cpus", "2") mythicEnv.SetDefault("hasura_mem_limit", "2gb") - mythicEnv.SetDefault("hasura_bind_local_mount", true) + mythicEnv.SetDefault("hasura_bind_use_volume", false) // docker-compose configuration mythicEnv.SetDefault("COMPOSE_PROJECT_NAME", "mythic") mythicEnv.SetDefault("REBUILD_ON_START", true) @@ -178,7 +178,7 @@ func setMythicConfigDefaultValues() { mythicEnv.SetDefault("jupyter_cpus", "2") mythicEnv.SetDefault("jupyter_mem_limit", "") mythicEnv.SetDefault("jupyter_bind_localhost_only", true) - mythicEnv.SetDefault("jupyter_bind_local_mount", true) + mythicEnv.SetDefault("jupyter_bind_use_volume", false) // debugging help mythicEnv.SetDefault("postgres_debug", false) mythicEnv.SetDefault("mythic_react_debug", false) diff --git a/Mythic_CLI/src/cmd/internal/installservice.go b/Mythic_CLI/src/cmd/internal/installservice.go index f9121cf1..50d1490b 100644 --- a/Mythic_CLI/src/cmd/internal/installservice.go +++ b/Mythic_CLI/src/cmd/internal/installservice.go @@ -156,7 +156,7 @@ func InstallFolder(installPath string, overWrite bool) error { for _, f := range files { if f.IsDir() { log.Printf("[*] Processing Documentation for %s\n", f.Name()) - if config.GetMythicEnv().GetBool("documentation_bind_local_mount") { + if !config.GetMythicEnv().GetBool("documentation_bind_use_volume") { if utils.DirExists(filepath.Join(workingPath, "documentation-docker", "content", "Agents", f.Name())) { if overWrite || config.AskConfirm("[*] "+f.Name()+" documentation already exists. Replace current version? ") { log.Printf("[*] Removing current version\n") @@ -206,7 +206,7 @@ func InstallFolder(installPath string, overWrite bool) error { for _, f := range files { if f.IsDir() { log.Printf("[*] Processing Documentation for %s\n", f.Name()) - if config.GetMythicEnv().GetBool("document_bind_local_mount") { + if !config.GetMythicEnv().GetBool("document_bind_use_volume") { if utils.DirExists(filepath.Join(workingPath, "documentation-docker", "content", "C2 Profiles", f.Name())) { if overWrite || config.AskConfirm("[*] "+f.Name()+" documentation already exists. Replace current version? ") { log.Printf("[*] Removing current version\n") @@ -459,6 +459,7 @@ func InstallMythicSyncFolder(installPath string) error { AddMythicService(service) log.Printf("[+] Successfully installed mythic_sync!\n") if manager.GetManager().IsServiceRunning("mythic_server") { + log.Printf("[*] Starting mythic_sync") err = ServiceStart([]string{strings.ToLower(service)}) if err != nil { log.Printf("[-] Failed to start mythic_sync: %v\n", err) @@ -483,10 +484,10 @@ func InstallMythicSync(url string, branch string) error { } if branch == "" { log.Printf("[*] Cloning %s\n", url) - err = runGitClone([]string{"-c", "http.sslVerify=false", "clone", "--recurse-submodules", "--single-branch", url, filepath.Join(workingPath, "tmp")}) + err = runGitClone([]string{"-c", "http.sslVerify=false", "clone", "--depth 1", "--recurse-submodules", "--single-branch", url, filepath.Join(workingPath, "tmp")}) } else { log.Printf("[*] Cloning branch \"%s\" from %s\n", branch, url) - err = runGitClone([]string{"-c", "http.sslVerify=false", "clone", "--recurse-submodules", "--single-branch", "--branch", branch, url, filepath.Join(workingPath, "tmp")}) + err = runGitClone([]string{"-c", "http.sslVerify=false", "clone", "--depth 1", "--recurse-submodules", "--single-branch", "--branch", branch, url, filepath.Join(workingPath, "tmp")}) } if err != nil { log.Printf("[-] Failed to clone down repository: %v\n", err) diff --git a/Mythic_CLI/src/cmd/internal/reset.go b/Mythic_CLI/src/cmd/internal/reset.go index c15cc9a4..2b86a515 100644 --- a/Mythic_CLI/src/cmd/internal/reset.go +++ b/Mythic_CLI/src/cmd/internal/reset.go @@ -13,7 +13,7 @@ func DatabaseReset() { if confirm { log.Printf("[*] Stopping Mythic\n") manager.GetManager().StopServices([]string{}, config.GetMythicEnv().GetBool("REBUILD_ON_START")) - manager.GetManager().ResetDatabase(config.GetMythicEnv().GetBool("postgres_bind_local_mount")) + manager.GetManager().ResetDatabase(config.GetMythicEnv().GetBool("postgres_bind_use_volume")) log.Printf("[*] Removing database files\n") } } diff --git a/Mythic_CLI/src/cmd/internal/serviceExecution.go b/Mythic_CLI/src/cmd/internal/serviceExecution.go index dc929941..42a0bc97 100644 --- a/Mythic_CLI/src/cmd/internal/serviceExecution.go +++ b/Mythic_CLI/src/cmd/internal/serviceExecution.go @@ -19,7 +19,7 @@ func ServiceStart(containers []string) error { if err != nil { return err } - dockerComposeContainers, err := manager.GetManager().GetAllExistingNonMythicServiceNames() + dockerComposeContainers, err := manager.GetManager().GetAllInstalled3rdPartyServiceNames() if err != nil { return err } @@ -72,7 +72,7 @@ func ServiceStart(containers []string) error { AddMythicService(service) } } - manager.GetManager().TestPorts() + manager.GetManager().TestPorts(finalContainers) err = manager.GetManager().StartServices(finalContainers, config.GetMythicEnv().GetBool("REBUILD_ON_START")) err = manager.GetManager().RemoveImages() if err != nil { @@ -134,7 +134,7 @@ func DockerBuildReactUI() error { // Docker Volume commands func VolumesList() { - manager.GetManager().ListVolumes() + manager.GetManager().PrintVolumeInformation() } func DockerRemoveVolume(volumeName string) error { return manager.GetManager().RemoveVolume(volumeName) diff --git a/Mythic_CLI/src/cmd/internal/serviceMetadata.go b/Mythic_CLI/src/cmd/internal/serviceMetadata.go index c2d4a410..814c3ca1 100644 --- a/Mythic_CLI/src/cmd/internal/serviceMetadata.go +++ b/Mythic_CLI/src/cmd/internal/serviceMetadata.go @@ -49,7 +49,7 @@ func AddMythicService(service string) { } else { pStruct["environment"] = environment } - if mythicEnv.GetBool("postgres_bind_local_mount") { + if !mythicEnv.GetBool("postgres_bind_use_volume") { pStruct["volumes"] = []string{ "./postgres-docker/database:/var/lib/postgresql/data", "./postgres-docker/postgres.conf:/etc/postgresql.conf", @@ -83,7 +83,7 @@ func AddMythicService(service string) { pStruct["environment"] = []string{ "DOCUMENTATION_PORT=${DOCUMENTATION_PORT}", } - if mythicEnv.GetBool("documentation_bind_local_mount") { + if !mythicEnv.GetBool("documentation_bind_use_volume") { pStruct["volumes"] = []string{ "./documentation-docker/:/src", } @@ -135,7 +135,7 @@ func AddMythicService(service string) { "${HASURA_PORT}:${HASURA_PORT}", } } - if mythicEnv.GetBool("hasura_bind_local_mount") { + if !mythicEnv.GetBool("hasura_bind_use_volume") { pStruct["volumes"] = []string{ "./hasura-docker/metadata:/metadata", } @@ -202,7 +202,7 @@ func AddMythicService(service string) { "${NGINX_PORT}:${NGINX_PORT}", } } - if mythicEnv.GetBool("nginx_bind_local_mount") { + if !mythicEnv.GetBool("nginx_bind_use_volume") { pStruct["volumes"] = []string{ "./nginx-docker/ssl:/etc/ssl/private", "./nginx-docker/config:/etc/nginx", @@ -260,7 +260,7 @@ func AddMythicService(service string) { } } pStruct["environment"] = finalRabbitEnv - if mythicEnv.GetBool("rabbitmq_bind_local_mount") { + if !mythicEnv.GetBool("rabbitmq_bind_use_volume") { pStruct["volumes"] = []string{ "./rabbitmq-docker/storage:/var/lib/rabbitmq", "./rabbitmq-docker/generate_config.sh:/generate_config.sh", @@ -294,7 +294,7 @@ func AddMythicService(service string) { "context": "./mythic-react-docker", "args": config.GetBuildArguments(), } - if mythicEnv.GetBool("mythic_react_bind_local_mount") { + if !mythicEnv.GetBool("mythic_react_bind_use_volume") { pStruct["volumes"] = []string{ "./mythic-react-docker/config:/etc/nginx", "./mythic-react-docker/mythic/public:/mythic/new", @@ -354,7 +354,7 @@ func AddMythicService(service string) { } */ - if mythicEnv.GetBool("jupyter_bind_local_mount") { + if !mythicEnv.GetBool("jupyter_bind_use_volume") { pStruct["volumes"] = []string{ "./jupyter-docker/jupyter:/projects", } @@ -425,7 +425,7 @@ func AddMythicService(service string) { } else { pStruct["environment"] = environment } - if mythicEnv.GetBool("mythic_server_bind_local_mount") { + if !mythicEnv.GetBool("mythic_server_bind_use_volume") { pStruct["volumes"] = []string{ "./mythic-docker/src:/usr/src/app", } @@ -508,7 +508,7 @@ func Add3rdPartyService(service string, additionalConfigs map[string]interface{} pStruct[key] = element } pStruct["build"] = map[string]interface{}{ - "context": manager.GetManager().GetPathTo3rdPartyServicesOnDisk(), + "context": filepath.Join(manager.GetManager().GetPathTo3rdPartyServicesOnDisk(), service), "args": config.GetBuildArguments(), } pStruct["network_mode"] = "host" @@ -542,7 +542,7 @@ func Add3rdPartyService(service string, additionalConfigs map[string]interface{} // only add in volumes if some aren't already listed if _, ok := pStruct["volumes"]; !ok { pStruct["volumes"] = []string{ - manager.GetManager().GetPathTo3rdPartyServicesOnDisk() + ":/Mythic/", + filepath.Join(manager.GetManager().GetPathTo3rdPartyServicesOnDisk(), service) + ":/Mythic/", } } return manager.GetManager().SetServiceConfiguration(service, pStruct) @@ -552,13 +552,14 @@ func RemoveService(service string) error { } func Initialize() { + if !manager.GetManager().CheckRequiredManagerVersion() { + log.Fatalf("[-] Bad %s version\n", manager.GetManager().GetManagerName()) + } manager.GetManager().GenerateRequiredConfig() // based on .env, find out which mythic services are supposed to be running and add them to docker compose intendedMythicContainers, _ := config.GetIntendedMythicServiceNames() for _, container := range intendedMythicContainers { AddMythicService(container) } - if !manager.GetManager().CheckRequiredManagerVersion() { - log.Fatalf("[-] Bad %s version\n", manager.GetManager().GetManagerName()) - } + } diff --git a/Mythic_CLI/src/cmd/internal/testServices.go b/Mythic_CLI/src/cmd/internal/testServices.go index 9da735ac..117276cc 100644 --- a/Mythic_CLI/src/cmd/internal/testServices.go +++ b/Mythic_CLI/src/cmd/internal/testServices.go @@ -58,7 +58,7 @@ func TestMythicConnection() { log.Printf(" If there is an issue with Mythic server, use 'mythic-cli logs mythic_server' to view potential errors\n") Status(false) log.Printf("[*] Fetching logs from mythic_server now:\n") - GetLogs("mythic_server", "500") + GetLogs("mythic_server", "500", false) os.Exit(1) } func TestMythicRabbitmqConnection() { @@ -102,7 +102,8 @@ func TestMythicRabbitmqConnection() { } } func TestPorts() error { - manager.GetManager().TestPorts() + intendedServices, _ := config.GetIntendedMythicServiceNames() + manager.GetManager().TestPorts(intendedServices) return nil } @@ -131,13 +132,13 @@ func Status(verbose bool) { log.Printf("[*] If you are using a remote PayloadType or C2Profile, they will need certain environment variables to properly connect to Mythic.\n") log.Printf(" Use 'sudo ./mythic-cli config service' for configs for these services.\n") } -func GetLogs(containerName string, numLogs string) { +func GetLogs(containerName string, numLogs string, follow bool) { logCount, err := strconv.Atoi(numLogs) if err != nil { log.Fatalf("[-] Bad log count: %v\n", err) } - manager.GetManager().GetLogs(containerName, logCount) + manager.GetManager().GetLogs(containerName, logCount, follow) } func ListServices() { - manager.GetManager().ListServices() + manager.GetManager().PrintAllServices() } diff --git a/Mythic_CLI/src/cmd/internal/utils.go b/Mythic_CLI/src/cmd/internal/utils.go index 9d87abd6..dea32ddd 100644 --- a/Mythic_CLI/src/cmd/internal/utils.go +++ b/Mythic_CLI/src/cmd/internal/utils.go @@ -110,7 +110,7 @@ func updateNginxBlockLists() { outputString += fmt.Sprintf("allow %s;\n", ip) } outputString += "deny all;" - if config.GetMythicEnv().GetBool("nginx_bind_local_mount") { + if !config.GetMythicEnv().GetBool("nginx_bind_use_volume") { ipFilePath := filepath.Join(utils.GetCwdFromExe(), "nginx-docker", "config", "blockips.conf") if err := os.WriteFile(ipFilePath, []byte(outputString), 0600); err != nil { log.Fatalf("[-] Failed to write out block list file: %v\n", err) diff --git a/Mythic_CLI/src/cmd/logs.go b/Mythic_CLI/src/cmd/logs.go index ff1f2674..32a04a98 100644 --- a/Mythic_CLI/src/cmd/logs.go +++ b/Mythic_CLI/src/cmd/logs.go @@ -16,9 +16,20 @@ var logsCmd = &cobra.Command{ func init() { rootCmd.AddCommand(logsCmd) - logsCmd.Flags().StringP("lines", "l", "500", "Number of lines to display") + logsCmd.Flags().StringP("lines", "l", "200", "Number of lines to display") + logsCmd.Flags().BoolP( + "follow", + "f", + false, + `Follow a constant stream of logs from the specified container.`, + ) } func getLogs(cmd *cobra.Command, args []string) { - internal.GetLogs(args[0], cmd.Flag("lines").Value.String()) + if cmd.Flag("follow").Value.String() == "true" { + internal.GetLogs(args[0], cmd.Flag("lines").Value.String(), true) + } else { + internal.GetLogs(args[0], cmd.Flag("lines").Value.String(), false) + } + } diff --git a/Mythic_CLI/src/cmd/manager/dockerComposeManager.go b/Mythic_CLI/src/cmd/manager/dockerComposeManager.go index 4db2ffbf..6b5bc03b 100644 --- a/Mythic_CLI/src/cmd/manager/dockerComposeManager.go +++ b/Mythic_CLI/src/cmd/manager/dockerComposeManager.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/MythicMeta/Mythic_CLI/cmd/config" "github.com/MythicMeta/Mythic_CLI/cmd/utils" + "github.com/creack/pty" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/volume" "github.com/docker/docker/client" @@ -323,7 +324,7 @@ func (d *DockerComposeManager) GetPathTo3rdPartyServicesOnDisk() string { // StopServices stops certain containers that are running and optionally deletes the backing images func (d *DockerComposeManager) StopServices(services []string, deleteImages bool) error { - dockerComposeContainers, err := d.GetAllExistingNonMythicServiceNames() + dockerComposeContainers, err := d.GetAllInstalled3rdPartyServiceNames() if err != nil { return err } @@ -363,14 +364,12 @@ func (d *DockerComposeManager) RemoveServices(services []string) error { if key == "services" { allServices := allConfigValues["services"].(map[string]interface{}) for _, service := range services { - if !utils.StringInSlice(service, config.MythicPossibleServices) { - if d.IsServiceRunning(service) { - _ = d.StopServices([]string{strings.ToLower(service)}, true) + if d.IsServiceRunning(service) { + _ = d.StopServices([]string{strings.ToLower(service)}, true) - } - delete(allServices, strings.ToLower(service)) - log.Printf("[+] Removed %s from docker-compose\n", strings.ToLower(service)) } + delete(allServices, strings.ToLower(service)) + log.Printf("[+] Removed %s from docker-compose\n", strings.ToLower(service)) } } } @@ -477,7 +476,7 @@ func (d *DockerComposeManager) BuildUI() error { return err } -func (d *DockerComposeManager) GetLogs(service string, logCount int) { +func (d *DockerComposeManager) GetLogs(service string, logCount int, follow bool) { cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { log.Fatalf("Failed to get client in GetLogs: %v", err) @@ -494,6 +493,7 @@ func (d *DockerComposeManager) GetLogs(service string, logCount int) { reader, err := cli.ContainerLogs(context.Background(), container.ID, types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, + Follow: follow, Tail: fmt.Sprintf("%d", logCount), }) if err != nil { @@ -519,7 +519,7 @@ func (d *DockerComposeManager) GetLogs(service string, logCount int) { } } -func (d *DockerComposeManager) TestPorts() { +func (d *DockerComposeManager) TestPorts(services []string) { // go through the different services in mythicEnv and check to make sure their ports aren't already used by trying to open them //MYTHIC_SERVER_HOST:MYTHIC_SERVER_PORT //POSTGRES_HOST:POSTGRES_PORT @@ -565,19 +565,23 @@ func (d *DockerComposeManager) TestPorts() { var removeServices []string mythicEnv := config.GetMythicEnv() for key, val := range portChecks { - if mythicEnv.GetString(key) == val[1] || mythicEnv.GetString(key) == "127.0.0.1" { - addServices = append(addServices, val[1]) - p, err := net.Listen("tcp", ":"+strconv.Itoa(mythicEnv.GetInt(val[0]))) - if err != nil { - log.Fatalf("[-] Port %d, from variable %s, appears to already be in use: %v\n", mythicEnv.GetInt(val[0]), key, err) + // only check ports for services we're about to start + if utils.StringInSlice(val[1], services) { + if mythicEnv.GetString(key) == val[1] || mythicEnv.GetString(key) == "127.0.0.1" { + addServices = append(addServices, val[1]) + p, err := net.Listen("tcp", ":"+strconv.Itoa(mythicEnv.GetInt(val[0]))) + if err != nil { + log.Fatalf("[-] Port %d, from variable %s, appears to already be in use: %v\n", mythicEnv.GetInt(val[0]), key, err) + } + err = p.Close() + if err != nil { + log.Printf("[-] Failed to close connection: %v\n", err) + } + } else { + removeServices = append(removeServices, val[1]) } - err = p.Close() - if err != nil { - log.Printf("[-] Failed to close connection: %v\n", err) - } - } else { - removeServices = append(removeServices, val[1]) } + } } @@ -662,7 +666,7 @@ func (d *DockerComposeManager) Status(verbose bool) { if err != nil { log.Fatalf("[-] Failed to get list of installed services on disk: %v\n", err) } - elementsInCompose, err := d.GetAllExistingNonMythicServiceNames() + elementsInCompose, err := d.GetAllInstalled3rdPartyServiceNames() if err != nil { log.Fatalf("[-] Failed to get list of installed services in docker-compose: %v\n", err) } @@ -710,12 +714,11 @@ func (d *DockerComposeManager) Status(verbose bool) { } else { info += mnt.Name } - found = true } } if !found { - info += "local" + info += "N/A" } info += "\t" info = info + portString @@ -769,7 +772,7 @@ func (d *DockerComposeManager) Status(verbose bool) { w.Flush() } -func (d *DockerComposeManager) ListServices() { +func (d *DockerComposeManager) PrintAllServices() { cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { log.Fatalf("[-] Failed to get client in List Services: %v", err) @@ -790,7 +793,7 @@ func (d *DockerComposeManager) ListServices() { if err != nil { log.Fatalf("[-] Failed to get list of installed services on disk: %v\n", err) } - elementsInCompose, err := d.GetAllExistingNonMythicServiceNames() + elementsInCompose, err := d.GetAllInstalled3rdPartyServiceNames() if err != nil { log.Fatalf("[-] Failed to get list of installed services in docker-compose: %v\n", err) } @@ -829,24 +832,24 @@ func (d *DockerComposeManager) ListServices() { w.Flush() } -func (d *DockerComposeManager) ResetDatabase(localMount bool) { - if localMount { +func (d *DockerComposeManager) ResetDatabase(useVolume bool) { + if !useVolume { workingPath := utils.GetCwdFromExe() err := os.RemoveAll(filepath.Join(workingPath, "postgres-docker", "database")) if err != nil { - log.Printf("[-] Failed to remove database files\n%v\n", err) + log.Fatalf("[-] Failed to remove database files\n%v\n", err) } else { log.Printf("[+] Successfully reset datbase files\n") } } else { - d.RemoveContainers([]string{"mythic_postgres"}) + _ = d.RemoveContainers([]string{"mythic_postgres"}) err := d.RemoveVolume("mythic_postgres_volume") if err != nil { log.Printf("[-] Failed to remove database:\n%v\n", err) } } } -func (d *DockerComposeManager) ListVolumes() { +func (d *DockerComposeManager) PrintVolumeInformation() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { @@ -1094,43 +1097,11 @@ func (d *DockerComposeManager) runDockerCompose(args []string) error { command := exec.Command(lookPath, args...) command.Dir = exePath command.Env = d.getMythicEnvList() - - stdout, err := command.StdoutPipe() + f, err := pty.Start(command) if err != nil { - log.Fatalf("[-] Failed to get stdout pipe for running docker-compose\n") - } - stderr, err := command.StderrPipe() - if err != nil { - log.Fatalf("[-] Failed to get stderr pipe for running docker-compose\n") - } - - stdoutScanner := bufio.NewScanner(stdout) - stderrScanner := bufio.NewScanner(stderr) - wg := sync.WaitGroup{} - wg.Add(2) - go func() { - for stdoutScanner.Scan() { - fmt.Printf("%s\n", stdoutScanner.Text()) - } - wg.Done() - }() - go func() { - for stderrScanner.Scan() { - fmt.Printf("%s\n", stderrScanner.Text()) - } - wg.Done() - }() - err = command.Start() - if err != nil { - log.Fatalf("[-] Error trying to start docker-compose: %v\n", err) - } - wg.Wait() - err = command.Wait() - if err != nil { - log.Printf("[-] Error from docker-compose: %v\n", err) - log.Printf("[*] Docker compose command: %v\n", args) - return err + log.Fatalf("[-] Failed to run docker command: %v\n", err) } + io.Copy(os.Stdout, f) return nil } func (d *DockerComposeManager) setDockerComposeDefaultsAndWrite(curConfig map[string]interface{}) error { @@ -1201,8 +1172,7 @@ func (d *DockerComposeManager) ensureVolume(volumeName string) error { return errors.New(fmt.Sprintf("failed to find container, %s, for volume, %s", containerName, volumeName)) } -// GetAllExistingNonMythicServiceNames from reading in the docker-compose file, not necessarily what's running -func (d *DockerComposeManager) GetAllExistingNonMythicServiceNames() ([]string, error) { +func (d *DockerComposeManager) GetAllInstalled3rdPartyServiceNames() ([]string, error) { // get all services that exist within the loaded config groupNameConfig := viper.New() groupNameConfig.SetConfigName("docker-compose") diff --git a/Mythic_CLI/src/cmd/manager/managerInterface.go b/Mythic_CLI/src/cmd/manager/managerInterface.go index f9577018..121a37eb 100644 --- a/Mythic_CLI/src/cmd/manager/managerInterface.go +++ b/Mythic_CLI/src/cmd/manager/managerInterface.go @@ -44,7 +44,7 @@ type CLIManager interface { // GetInstalled3rdPartyServicesOnDisk returns the names of the installed services on disk GetInstalled3rdPartyServicesOnDisk() ([]string, error) // GetAllExistingNonMythicServiceNames reads current configuration and returns all non-mythic services - GetAllExistingNonMythicServiceNames() ([]string, error) + GetAllInstalled3rdPartyServiceNames() ([]string, error) // GetCurrentMythicServiceNames reads current configuration and returns all mythic services GetCurrentMythicServiceNames() ([]string, error) // GetPathTo3rdPartyServicesOnDisk returns the path where a 3rd party services Dockerfile lives on disk @@ -54,19 +54,19 @@ type CLIManager interface { // BuildUI a new instance of the Mythic React UI and save it in the mythic-react-docker folder BuildUI() error // GetLogs fetches logCount of the most recent logs from the service container - GetLogs(service string, logCount int) + GetLogs(service string, logCount int, follow bool) // TestPorts check to make sure all ports are available for services to use - TestPorts() + TestPorts(services []string) // PrintConnectionInfo lists out connection information for the various services (web endpoints, open ports, etc) PrintConnectionInfo() // Status prints out the current status of all the containers and volumes in use Status(verbose bool) // ListServices prints out all the 3rd party services on disk and currently installed - ListServices() + PrintAllServices() // ResetDatabase deletes the current database or volume - ResetDatabase(localMount bool) + ResetDatabase(useVolume bool) // ListVolumes prints out all of the volumes in use by Mythic - ListVolumes() + PrintVolumeInformation() // RemoveVolume removes the named volume RemoveVolume(volumeName string) error // CopyIntoVolume copies from a source io.Reader to the destination filename on the destination volume diff --git a/Mythic_CLI/src/cmd/mythic_sync.go b/Mythic_CLI/src/cmd/mythic_sync.go index 8a1ae5ab..6b98fda0 100644 --- a/Mythic_CLI/src/cmd/mythic_sync.go +++ b/Mythic_CLI/src/cmd/mythic_sync.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "log" ) // installCmd represents the config command @@ -17,5 +18,5 @@ func init() { } func mythicSync(cmd *cobra.Command, args []string) { - + log.Fatalf("[-] Must specify install/uninstall") } diff --git a/Mythic_CLI/src/cmd/mythic_sync_install.go b/Mythic_CLI/src/cmd/mythic_sync_install.go index 3f8d1a08..fc2ec3c6 100644 --- a/Mythic_CLI/src/cmd/mythic_sync_install.go +++ b/Mythic_CLI/src/cmd/mythic_sync_install.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "log" ) // installCmd represents the config command @@ -18,5 +19,5 @@ func init() { } func installMythicSync(cmd *cobra.Command, args []string) { - + log.Fatalf("[-] Must specify github or folder") } diff --git a/Mythic_CLI/src/cmd/mythic_sync_install_github.go b/Mythic_CLI/src/cmd/mythic_sync_install_github.go index 92a12b98..e4c7089b 100644 --- a/Mythic_CLI/src/cmd/mythic_sync_install_github.go +++ b/Mythic_CLI/src/cmd/mythic_sync_install_github.go @@ -23,7 +23,7 @@ func init() { "force", "f", false, - `Force installing from GitHub and don't prompt to overwrite files if an older version is already installed'`, + `Force installing from GitHub and don't prompt to overwrite files if an older version is already installed`, ) installMythicSyncGitHubCmd.Flags().StringVarP( &branch, diff --git a/Mythic_CLI/src/cmd/removeDockerCompose.go b/Mythic_CLI/src/cmd/removeDockerCompose.go index fa10fb4b..b7016c15 100644 --- a/Mythic_CLI/src/cmd/removeDockerCompose.go +++ b/Mythic_CLI/src/cmd/removeDockerCompose.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/MythicMeta/Mythic_CLI/cmd/internal" "github.com/spf13/cobra" + "log" ) // configCmd represents the config command @@ -19,7 +20,10 @@ func init() { } func removeDockerCompose(cmd *cobra.Command, args []string) { - if err := internal.RemoveService(args[0]); err != nil { - + err := internal.RemoveService(args[0]) + if err != nil { + log.Printf("[-] Failed to remove service") + return } + log.Printf("[+] Successfully removed service") } diff --git a/Mythic_CLI/src/go.mod b/Mythic_CLI/src/go.mod index 3cdcd308..42a712b9 100644 --- a/Mythic_CLI/src/go.mod +++ b/Mythic_CLI/src/go.mod @@ -12,6 +12,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/creack/pty v1.1.21 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect diff --git a/Mythic_CLI/src/go.sum b/Mythic_CLI/src/go.sum index 04c3cdad..01da836b 100644 --- a/Mythic_CLI/src/go.sum +++ b/Mythic_CLI/src/go.sum @@ -51,6 +51,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= +github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= diff --git a/nginx-docker/health_check.sh b/nginx-docker/health_check.sh index a43ad0bd..85c9fe8a 100644 --- a/nginx-docker/health_check.sh +++ b/nginx-docker/health_check.sh @@ -1,8 +1,8 @@ -#!/bin/bash +#!/bin/sh -if [ "$NGINX_USE_SSL" == "ssl" ] +if [ "$NGINX_USE_SSL" = "ssl" ] then - curl -k https://127.0.0.1:${NGINX_PORT:-7443}/new/login + curl -k https://127.0.0.1:"${NGINX_PORT:-7443}"/new/login else - curl -k http://127.0.0.1:${NGINX_PORT:-7443}/new/login + curl -k http://127.0.0.1:"${NGINX_PORT:-7443}"/new/login fi