Esempio n. 1
0
func NatTunnel(url, ngrokPath, ngrokLogPath, ngrokConfPath, ip string) {
	if !isNodeNated(ip) {
		return
	}

	if !utils.FileExist(ngrokPath) {
		Logger.Println("Cannot find ngrok binary at", ngrokPath)
		DownloadNgrok(NgrokBinaryURL, ngrokPath)
	} else {
		Logger.Println("Found ngrok binary at", ngrokPath)
	}

	updateNgrokHost(url)
	createNgrokConfFile(ngrokConfPath)

	var cmd *exec.Cmd
	if *FlagNgrokToken != "" {
		cmd = exec.Command(ngrokPath,
			"-log", "stdout",
			"-authtoken", *FlagNgrokToken,
			"-proto", "tcp",
			DockerHostPort)
	} else {
		if !utils.FileExist(ngrokConfPath) {
			SendError(errors.New("Cannot find ngrok conf"), "Cannot find ngrok conf file", nil)
			Logger.Println("Cannot find NAT tunnel configuration")
			return
		}
		cmd = exec.Command(ngrokPath,
			"-config", ngrokConfPath,
			"-log", "stdout",
			"-proto", "tcp",
			DockerHostPort)
	}

	os.RemoveAll(ngrokLogPath)
	logFile, err := os.OpenFile(ngrokLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		SendError(err, "Failed to open ngrok log file", nil)
		Logger.Println(err)
	} else {
		defer logFile.Close()
		cmd.Stdout = logFile
	}

	go monitorTunnels(url, ngrokLogPath)
	Logger.Println("Starting NAT tunnel:", cmd.Args)

	for {
		runGronk(cmd)
		time.Sleep(10 * time.Second)
		Logger.Println("Restarting NAT tunnel:", cmd.Args)
	}
}
Esempio n. 2
0
func DownloadDocker(url, dockerBinPath string) {
	if !utils.FileExist(dockerBinPath) {
		Logger.Println("Downloading docker binary...")
		downloadFile(url, dockerBinPath, "docker")
	}
	createDockerSymlink(dockerBinPath, DockerSymbolicLink)
}
Esempio n. 3
0
func getDockerStartOpt(dockerBinPath, keyFilePath, certFilePath, caFilePath string) []string {
	ver := getDockerClientVersion(dockerBinPath)
	v, err := semver.Make(ver)
	if err != nil {
		Logger.Println("Cannot get semantic version of", ver)
	}
	v1_7, err := semver.Make("1.7.0")
	v1_8, err := semver.Make("1.8.0")

	daemonOpt := "daemon"
	if v.LT(v1_8) {
		daemonOpt = "-d"
	}

	userlandProxyOpt := ""
	if v.GTE(v1_7) {
		userlandProxyOpt = " --userland-proxy=false"
	}

	debugOpt := ""
	if *FlagDebugMode {
		debugOpt = " -D"
	}

	bindOpt := fmt.Sprintf(" -H %s -H %s", DockerDefaultHost, Conf.DockerHost)

	var certOpt string
	if *FlagStandalone && !utils.FileExist(caFilePath) {
		certOpt = fmt.Sprintf(" --tlscert %s --tlskey %s --tls", certFilePath, keyFilePath)
		fmt.Fprintln(os.Stderr, "WARNING: standalone mode activated but no CA certificate found - client authentication disabled")
	} else {
		certOpt = fmt.Sprintf(" --tlscert %s --tlskey %s --tlscacert %s --tlsverify", certFilePath, keyFilePath, caFilePath)
	}

	extraOpt := ""
	if Conf.DockerOpts != "" {
		extraOpt = " " + Conf.DockerOpts
	}

	optStr := fmt.Sprintf("%s%s%s%s%s%s", daemonOpt, debugOpt, bindOpt, userlandProxyOpt, certOpt, extraOpt)

	optSlice, err := shlex.Split(optStr)
	if err != nil {
		optSlice = strings.Split(optStr, " ")
	}
	return optSlice
}
Esempio n. 4
0
func UpdateDocker(dockerBinPath, dockerNewBinPath, dockerNewBinSigPath, keyFilePath, certFilePath, caFilePath string) {
	if utils.FileExist(dockerNewBinPath) {
		Logger.Printf("New Docker binary (%s) found", dockerNewBinPath)
		Logger.Println("Updating docker...")
		if verifyDockerSig(dockerNewBinPath, dockerNewBinSigPath) {
			Logger.Println("Stopping docker daemon")
			ScheduleToTerminateDocker = true
			StopDocker()
			Logger.Println("Removing old docker binary")
			if err := os.RemoveAll(dockerBinPath); err != nil {
				SendError(err, "Failed to remove the old docker binary", nil)
				Logger.Println("Cannot remove old docker binary:", err)
			}
			Logger.Println("Renaming new docker binary")
			if err := os.Rename(dockerNewBinPath, dockerBinPath); err != nil {
				SendError(err, "Failed to rename the docker binary", nil)
				Logger.Println("Cannot rename docker binary:", err)
			}
			Logger.Println("Removing the signature file", dockerNewBinSigPath)
			if err := os.RemoveAll(dockerNewBinSigPath); err != nil {
				SendError(err, "Failed to remove the docker sig file", nil)
				Logger.Println(err)
			}
			createDockerSymlink(dockerBinPath, DockerSymbolicLink)
			ScheduleToTerminateDocker = false
			StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath)
			Logger.Println("Docker binary updated successfully")
		} else {
			Logger.Println("Cannot verify signature. Rejecting update")
			Logger.Println("Removing the invalid docker binary", dockerNewBinPath)
			if err := os.RemoveAll(dockerNewBinPath); err != nil {
				SendError(err, "Failed to remove the invalid docker binary", nil)
				Logger.Println(err)
			}
			Logger.Println("Removing the invalid signature file", dockerNewBinSigPath)
			if err := os.RemoveAll(dockerNewBinSigPath); err != nil {
				SendError(err, "Failed to remove the invalid docker sig file", nil)
				Logger.Println(err)
			}
			Logger.Println("Failed to update docker binary")
		}
	}
}
Esempio n. 5
0
func PrepareFiles(configFilePath, dockerBinPath, keyFilePath, certFilePath string) {
	Logger.Println("Checking if config file exists...")
	if !utils.FileExist(configFilePath) {
		LoadDefaultConf()
		if err := SaveConf(configFilePath, Conf); err != nil {
			SendError(err, "Failed to save config to the conf file", nil)
			Logger.Fatalln(err)
		}
	}

	Logger.Println("Loading Configuration file...")
	conf, err := LoadConf(configFilePath)
	if err != nil {
		SendError(err, "Failed to load configuration file", nil)
		Logger.Fatalln("Failed to load configuration file:", err)
	} else {
		Conf = *conf
	}

	if *FlagDockerHost != "" {
		Logger.Printf("Override 'DockerHost' from command line flag: %s\n", *FlagDockerHost)
		Conf.DockerHost = *FlagDockerHost
	}
	if *FlagTutumHost != "" {
		Logger.Printf("Override 'TutumHost' from command line flag: %s\n", *FlagTutumHost)
		Conf.TutumHost = *FlagTutumHost
	}
	if *FlagTutumToken != "" {
		Logger.Printf("Override 'TutumToken' from command line flag: %s\n", *FlagTutumToken)
		Conf.TutumToken = *FlagTutumToken
	}
	if *FlagTutumUUID != "" {
		Logger.Printf("Override 'TutumUUID' from command line flag: %s\n", *FlagTutumUUID)
		Conf.TutumUUID = *FlagTutumUUID
	}
	if *FlagDockerOpts != "" {
		Logger.Printf("Override 'DockerOpts' from command line flag: %s\n", *FlagDockerOpts)
		Conf.DockerOpts = *FlagDockerOpts
	}
}
Esempio n. 6
0
func StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath string) {
	var command *exec.Cmd
	var cmdstring string

	if *FlagDebugMode {
		cmdstring = fmt.Sprintf("-d -D -H %s -H %s --tlscert %s --tlskey %s --tlscacert %s --tlsverify",
			Conf.DockerHost, DockerDefaultHost, certFilePath, keyFilePath, caFilePath)
	} else {
		cmdstring = fmt.Sprintf("-d -H %s -H %s --tlscert %s --tlskey %s --tlscacert %s --tlsverify",
			Conf.DockerHost, DockerDefaultHost, certFilePath, keyFilePath, caFilePath)
	}
	if *FlagStandalone && !utils.FileExist(caFilePath) {
		if *FlagDebugMode {
			cmdstring = fmt.Sprintf("-d -D -H %s -H %s --tlscert %s --tlskey %s --tls",
				Conf.DockerHost, DockerDefaultHost, certFilePath, keyFilePath)
		} else {
			cmdstring = fmt.Sprintf("-d -H %s -H %s --tlscert %s --tlskey %s --tls",
				Conf.DockerHost, DockerDefaultHost, certFilePath, keyFilePath)
		}

		fmt.Fprintln(os.Stderr, "WARNING: standalone mode activated but no CA certificate found - client authentication disabled")
	}

	if *FlagDockerOpts != "" {
		cmdstring = cmdstring + " " + *FlagDockerOpts
	}

	cmdslice, err := shlex.Split(cmdstring)
	if err != nil {
		cmdslice = strings.Split(cmdstring, " ")
	}

	command = exec.Command(dockerBinPath, cmdslice...)

	go runDocker(command)
}
Esempio n. 7
0
func NatTunnel(url, ngrokPath, ngrokLogPath, ngrokConfPath, uuid string) {
	if isNodeReachable(url, uuid) {
		Logger.Printf("Node %s is publicly reachable", Conf.CertCommonName)
		return
	} else {
		Logger.Printf("Node %s is NOT publicly reachable", Conf.CertCommonName)
	}

	if !utils.FileExist(ngrokPath) {
		Logger.Println("Cannot find ngrok binary at", ngrokPath)
		DownloadNgrok(NgrokBinaryURL, ngrokPath)
	}

	updateNgrokHost(url)
	createNgrokConfFile(ngrokConfPath)

	var cmd *exec.Cmd
	if *FlagNgrokToken != "" {
		cmd = exec.Command(ngrokPath,
			"-log", "stdout",
			"-authtoken", *FlagNgrokToken,
			"-proto", "tcp",
			DockerHostPort)
	} else {
		if !utils.FileExist(ngrokConfPath) {
			SendError(errors.New("Cannot find ngrok conf"), "Cannot find ngrok conf file", nil)
			Logger.Println("Cannot find NAT tunnel configuration")
			return
		}
		cmd = exec.Command(ngrokPath,
			"-config", ngrokConfPath,
			"-log", "stdout",
			"-proto", "tcp",
			DockerHostPort)
	}

	os.RemoveAll(ngrokLogPath)
	logFile, err := os.OpenFile(ngrokLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		SendError(err, "Failed to open ngrok log file", nil)
		Logger.Println(err)
	} else {
		defer logFile.Close()
		cmd.Stdout = logFile
	}

	go monitorTunnels(url, ngrokLogPath)
	Logger.Println("Starting NAT tunnel")

	runNgrok(cmd)

	for {
		if ScheduledShutdown {
			Logger.Println("Scheduling for shutting down, do not restart the tunnel")
			break
		} else {
			Logger.Println("Restarting NAT tunnel in 10 seconds")
			time.Sleep(10 * time.Second)
			runNgrok(cmd)
		}
	}
}
Esempio n. 8
0
func DownloadNgrok(url, ngrokBinPath string) {
	if !utils.FileExist(ngrokBinPath) {
		Logger.Println("Downloading NAT tunnel binary ...")
		downloadFile(url, ngrokBinPath, "ngrok")
	}
}
Esempio n. 9
0
func isCertificateExist(keyFilePath, certFilePath string) (isExist bool) {
	if utils.FileExist(keyFilePath) && utils.FileExist(certFilePath) {
		return true
	}
	return false
}
Esempio n. 10
0
func main() {
	dockerBinPath := path.Join(DockerDir, DockerBinaryName)
	dockerNewBinPath := path.Join(DockerDir, DockerNewBinaryName)
	dockerNewBinSigPath := path.Join(DockerDir, DockerNewBinarySigName)
	configFilePath := path.Join(TutumHome, ConfigFileName)
	keyFilePath := path.Join(TutumHome, KeyFileName)
	certFilePath := path.Join(TutumHome, CertFileName)
	caFilePath := path.Join(TutumHome, CAFileName)
	ngrokPath := path.Join(DockerDir, NgrokBinaryName)
	ngrokLogPath := path.Join(LogDir, NgrokLogName)
	ngrokConfPath := path.Join(TutumHome, NgrokConfName)

	_ = os.MkdirAll(TutumHome, 0755)
	_ = os.MkdirAll(DockerDir, 0755)
	_ = os.MkdirAll(LogDir, 0755)

	ParseFlag()

	if *FlagVersion {
		fmt.Println(VERSION)
		return
	}
	SetLogger(path.Join(LogDir, TutumLogFileName))
	Logger.Print("Running tutum-agent: version ", VERSION)
	CreatePidFile(TutumPidFile)

	PrepareFiles(configFilePath, dockerBinPath, keyFilePath, certFilePath)
	SetConfigFile(configFilePath)

	regUrl := utils.JoinURL(Conf.TutumHost, RegEndpoint)
	if Conf.TutumUUID == "" {
		os.RemoveAll(keyFilePath)
		os.RemoveAll(certFilePath)
		os.RemoveAll(caFilePath)

		if !*FlagStandalone {
			Logger.Printf("Registering in Tutum via POST: %s", regUrl)
			PostToTutum(regUrl, caFilePath, configFilePath)
		}
	}

	if *FlagStandalone {
		commonName := Conf.CertCommonName
		if commonName == "" {
			commonName = "*"
		}
		CreateCerts(keyFilePath, certFilePath, commonName)
	} else {
		CreateCerts(keyFilePath, certFilePath, Conf.CertCommonName)
	}

	if utils.FileExist(dockerBinPath) {
		DockerClientVersion = GetDockerClientVersion(dockerBinPath)
	}

	if !*FlagStandalone {
		Logger.Printf("Registering in Tutum via PATCH: %s",
			regUrl+Conf.TutumUUID)
		err := PatchToTutum(regUrl, caFilePath, certFilePath, configFilePath)
		if err != nil {
			Logger.Printf("PATCH error %s :either TutumUUID (%s) or TutumToken is invalid", err.Error(), Conf.TutumUUID)
			Conf.TutumUUID = ""
			SaveConf(configFilePath, Conf)

			os.RemoveAll(keyFilePath)
			os.RemoveAll(certFilePath)
			os.RemoveAll(caFilePath)

			Logger.Printf("Registering in Tutum via POST: %s", regUrl)
			PostToTutum(regUrl, caFilePath, configFilePath)

			CreateCerts(keyFilePath, certFilePath, Conf.CertCommonName)
			DownloadDocker(DockerBinaryURL, dockerBinPath)

			Logger.Printf("Registering in Tutum via PATCH: %s",
				regUrl+Conf.TutumUUID)
			if err = PatchToTutum(regUrl, caFilePath, certFilePath, configFilePath); err != nil {
				SendError(err, "Registion HTTP error", nil)
			}
		}
	}

	if err := SaveConf(configFilePath, Conf); err != nil {
		SendError(err, "Failed to save config to the conf file", nil)
		Logger.Fatalln(err)
	}

	DownloadDocker(DockerBinaryURL, dockerBinPath)
	CreateDockerSymlink(dockerBinPath, DockerSymbolicLink)
	HandleSig()
	syscall.Setpriority(syscall.PRIO_PROCESS, os.Getpid(), RenicePriority)

	Logger.Println("Initializing docker daemon")
	StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath)

	if !*FlagStandalone {
		if *FlagSkipNatTunnel {
			Logger.Println("Skip NAT tunnel")
		} else {
			Logger.Println("Loading NAT tunnel module")
			go NatTunnel(regUrl, ngrokPath, ngrokLogPath, ngrokConfPath, Conf.TutumUUID)
		}
	}

	if !*FlagStandalone {
		Logger.Println("Verifying the registration with Tutum")
		go VerifyRegistration(regUrl)
	}

	Logger.Println("Docker server started. Entering maintenance loop")
	for {
		time.Sleep(HeartBeatInterval * time.Second)
		UpdateDocker(dockerBinPath, dockerNewBinPath, dockerNewBinSigPath, keyFilePath, certFilePath, caFilePath)

		// try to restart docker daemon if it dies somehow
		if DockerProcess == nil {
			time.Sleep(HeartBeatInterval * time.Second)
			if DockerProcess == nil && ScheduleToTerminateDocker == false {
				Logger.Println("Respawning docker daemon")
				StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath)
			}
		}
	}
}
Esempio n. 11
0
func DownloadDocker(url, dockerBinPath string) {
	if !utils.FileExist(dockerBinPath) {
		Logger.Println("Downloading docker binary...")
		downloadFile(url, dockerBinPath, "docker")
	}
}