Exemplo n.º 1
0
// NewDockerTransport creates an HTTP transport to the Docker unix/tcp socket.
func NewDockerTransport(proto, addr string) (tr *http.Transport, e error) {
	// check Docker environment variables
	dockerHost := os.Getenv("DOCKER_HOST")
	if os.Getenv("DOCKER_TLS_VERIFY") == "0" {
		DockerTLSVerify = false
	}
	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
	if dockerHost == "" {
		DockerProto = proto
		DockerAddr = addr
	} else {
		blog.Info("$DOCKER_HOST env var = %s", dockerHost)
		switch {
		case strings.HasPrefix(dockerHost, "tcp://"):
			blog.Info("Using protocol tcp")
			DockerProto = "tcp"
			DockerAddr = dockerHost[6:]
		case strings.HasPrefix(dockerHost, "unix://"):
			blog.Info("Using protocol unix")
			DockerProto = "unix"
			DockerAddr = dockerHost[6:]
		default:
			except.Fail("Unexpected value in $DOCKER_HOST:", dockerHost)
		}
	}

	// create transport for unix socket
	if DockerProto != "unix" && DockerProto != "tcp" {
		e = errors.New("Protocol " + DockerProto + " is not yet supported")
		return
	}
	if DockerProto == "unix" {
		tr = &http.Transport{}
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.DialTimeout(DockerProto, DockerAddr, HTTPTIMEOUT)
		}
		return
	}
	if DockerTLSVerify {
		certfile := dockerCertPath + "/cert.pem"
		cafile := dockerCertPath + "/ca.pem"
		keyfile := dockerCertPath + "/key.pem"
		tr, e = NewTLSTransport(DockerAddr, certfile, cafile, keyfile)
		if e != nil {
			except.Fail(e, "NewTLSTransport")
		}
		return
	}

	tr = &http.Transport{}
	return
}
Exemplo n.º 2
0
// CopyDirTree copies all files from srcDir to destDir
func CopyDirTree(srcDir, destDir string) {
	srcs, err := filepath.Glob(srcDir)
	if err != nil {
		except.Fail(err, ": Error in generating matches for", srcDir)
	}
	args := []string{"-rp"}
	dirs := append(args, append(srcs, destDir)...)
	cpCmd := exec.Command("cp", dirs...)
	err = cpCmd.Run()
	if err != nil {
		except.Fail(err, ": Error in copying", srcDir, " to ", destDir)
	}
}
Exemplo n.º 3
0
// GetRegistryURL determines the full URL, with or without HTTP Basic Auth, needed to
// access the registry or Docker Hub.
func GetRegistryURL() (URL string, hubAPI bool, BasicAuth string, XRegistryAuth string) {
	basicAuth, fullRegistry, XRegistryAuth := RegAuth(RegistrySpec)
	if *AuthRegistry == true {
		if basicAuth == "" {
			except.Fail("Registry auth could not be determined from docker config.")
		}
		BasicAuth = basicAuth
	}
	if *HTTPSRegistry == false {
		URL = "http://" + RegistrySpec
	} else {
		// HTTPS is required
		if strings.HasPrefix(fullRegistry, "https://") {
			URL = fullRegistry
		} else {
			URL = "https://" + RegistrySpec
		}
		if *RegistryTokenAuth == true {
			hubAPI = true
		}
		if strings.Contains(URL, "docker.io") || strings.Contains(URL, "gcr.io") {
			hubAPI = true
			if *RegistryTokenAuth == false {
				except.Warn("Forcing --registrytokenauth=true, as required for Docker Hub and Google Container Registry")
				*RegistryTokenAuth = true
			}
		}
	}
	return
}
Exemplo n.º 4
0
func setupLogging() {
	consoleLog := blog.NewConsoleLogWriter()
	consoleLog = consoleLog.SetColor(true)
	blog.AddFilter("stdout", CONSOLELOGLEVEL, consoleLog)
	if *fileLog == true {
		f, e := os.OpenFile(LOGFILENAME, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if e != nil {
			except.Fail(e, ": Error in opening log file: ", LOGFILENAME)
		}
		f.Close()
		flw := blog.NewFileLogWriter(LOGFILENAME, false)
		blog.AddFilter("file", FILELOGLEVEL, flw)
	}
}
Exemplo n.º 5
0
func main() {
	doFlags()

	setupLogging()

	//verifyVolumes()

	copyBanyanData()

	// setup connection to docker daemon's unix/tcp socket
	var e error
	collector.DockerTransport, e = collector.NewDockerTransport(*dockerProto, *dockerAddr)
	if e != nil {
		except.Fail(e, ": Error in connecting to docker remote API socket")
	}

	authToken := RegisterCollector()

	// Set output writers
	SetOutputWriters(authToken)
	SetupBanyanStatus(authToken)

	checkConfigUpdate(true)
	if collector.LocalHost == false && collector.RegistryAPIURL == "" {
		collector.RegistryAPIURL, collector.HubAPI, collector.BasicAuth, collector.XRegistryAuth = collector.GetRegistryURL()
		blog.Info("registry API URL: %s", collector.RegistryAPIURL)
	}

	// Log the docker version
	major, minor, revision, e := collector.DockerVersion()
	if e != nil {
		except.Error(e, ": Could not identify Docker version")
	} else {
		blog.Info("Docker version %d.%d.%d", major, minor, revision)
		config.BanyanUpdate("Docker version", strconv.Itoa(major)+"."+strconv.Itoa(minor)+"."+strconv.Itoa(revision))
	}

	// Images we have processed already
	processedImages := collector.NewImageSet()
	e = getImageList(processedImages)
	if e != nil {
		blog.Info("Fresh start: No previously collected images were found in %s", *imageList)
	}
	_ = getImageManifestHashList(processedImages)
	blog.Debug(processedImages)

	// Main infinite loop.
	InfLoop(authToken, processedImages)
}
Exemplo n.º 6
0
func getScriptsToRun() (scripts []Script) {
	// get default scripts
	defaultScripts, err := getScripts(DefaultScriptsDir)
	if err != nil {
		except.Fail(err, ": Error in getting default scripts")
	}

	// get user-specified scripts
	userScripts, err := getScripts(UserScriptsDir)
	if err != nil {
		except.Warn(err, ": Error in getting user-specified scripts")
	}

	scripts = append(defaultScripts, userScripts...)
	return
}
Exemplo n.º 7
0
// getAuthConfig returns the Base64-encoded JSONified AuthConfig struct needed to authorize
// with the Docker Remote API.
func getAuthConfig(user, password, auth, email, registry string) (authConfig string) {
	ac := AuthConfig{
		Username:      user,
		Password:      password,
		Auth:          auth,
		Email:         email,
		ServerAddress: registry,
	}
	jsonString, err := json.Marshal(ac)
	if err != nil {
		except.Fail("Failed to marshal authconfig")
	}
	dst := make([]byte, base64.URLEncoding.EncodedLen(len(jsonString)))
	base64.URLEncoding.Encode(dst, jsonString)
	authConfig = string(dst)
	return
}
Exemplo n.º 8
0
// doFlags defines the cmdline Usage string and parses flag options.
func doFlags() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "  Usage: %s [OPTIONS] REGISTRY REPO [REPO...]\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\n  REGISTRY:\n")
		fmt.Fprintf(os.Stderr, "\tURL of your Docker registry; use index.docker.io for Docker Hub, use local.host to collect images from local Docker host\n")
		fmt.Fprintf(os.Stderr, "\n  REPO:\n")
		fmt.Fprintf(os.Stderr, "\tOne or more repos to gather info about; if no repo is specified Collector will gather info on *all* repos in the Registry\n")
		fmt.Fprintf(os.Stderr, "\n  Environment variables:\n")
		fmt.Fprintf(os.Stderr, "\tCOLLECTOR_DIR:   (Required) Directory that contains the \"data\" folder with Collector default scripts, e.g., $GOPATH/src/github.com/banyanops/collector\n")
		fmt.Fprintf(os.Stderr, "\tCOLLECTOR_ID:    ID provided by Banyan web interface to register Collector with the Banyan service\n")
		fmt.Fprintf(os.Stderr, "\tBANYAN_HOST_DIR: Host directory mounted into Collector/Target containers where results are stored (default: $HOME/.banyan)\n")
		fmt.Fprintf(os.Stderr, "\tBANYAN_DIR:      (Specify only in Dockerfile) Directory in the Collector container where host directory BANYAN_HOST_DIR is mounted\n")
		fmt.Fprintf(os.Stderr, "\tDOCKER_{HOST,CERT_PATH,TLS_VERIFY}: If set, e.g., by docker-machine, then they take precedence over --dockerProto and --dockerAddr\n")
		printExampleUsage()
		fmt.Fprintf(os.Stderr, "  Options:\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	if config.COLLECTORDIR() == "" {
		flag.Usage()
		os.Exit(except.ErrorExitStatus)
	}
	if len(flag.Args()) < 1 {
		flag.Usage()
		os.Exit(except.ErrorExitStatus)
	}
	if *dockerProto != "unix" && *dockerProto != "tcp" {
		flag.Usage()
		os.Exit(except.ErrorExitStatus)
	}
	requiredDirs := []string{config.BANYANDIR(), filepath.Dir(*imageList), filepath.Dir(*repoList), *config.BanyanOutDir, collector.DefaultScriptsDir, collector.UserScriptsDir, collector.BinDir}
	for _, dir := range requiredDirs {
		blog.Debug("Creating directory: " + dir)
		err := fsutil.CreateDirIfNotExist(dir)
		if err != nil {
			except.Fail(err, ": Error in creating a required directory: ", dir)
		}
	}
	collector.RegistrySpec = flag.Arg(0)
	// EqualFold: case insensitive comparison
	if strings.EqualFold(flag.Arg(0), "local.host") {
		collector.LocalHost = true
	}
	//nextMaxImages = *maxImages
}
Exemplo n.º 9
0
// JWT uses the JWT provider to obtain DockerConfig.
func JWT() credentialprovider.DockerConfig {
	enabled := jprovider.Enabled()
	if !enabled {
		except.Fail("Failed to enable JWT credential provider")
	}
	DockerConfig := jprovider.Provide()
	/*
		for registry, entry := range DockerConfig {
			fmt.Println("Registry", registry)
			fmt.Println("\tUsername:"******"\tPassword:"******"\tEmail:", entry.Email)
			fieldValue := entry.Username + ":" + entry.Password
			fmt.Println("\tAuth:", base64.StdEncoding.EncodeToString([]byte(fieldValue)))
		}
	*/
	return DockerConfig
}
Exemplo n.º 10
0
func init() {
	type elem struct {
		name    regexpPattern
		pattern string
	}
	patternList := []elem{
		elem{name: rel6z, pattern: `release 6\.([\d]+)`},
		elem{name: rel5z, pattern: `release 5\.([\d]+)`},
	}

	for _, p := range patternList {
		r, err := regexp.Compile(p.pattern)
		if err != nil {
			except.Fail(err, p.name, p.pattern)
		}
		distroRegexp[p.name] = r
	}
}
Exemplo n.º 11
0
// RegAuth takes as input the name of a registry, and it parses the contents of
// $HOME/.dockercfg or $HOME/.docker/config.json to return the user authentication info and registry URL.
// TODO: Change this to return authConfig instead of user&password, and then
// use X-Registry-Auth in the HTTP request header.
func RegAuth(registry string) (basicAuth, fullRegistry, authConfig string) {
	if *AuthRegistry == false {
		fullRegistry = registry
		return
	}

	if *GCEMetadata {
		return GCEMetadataRegAuth(registry)
	}
	if *GCEKeyFile > "" {
		return GCEKeyFileRegAuth(registry)
	}

	if len(DockerConfig) == 0 {
		major, minor, revision, err := DockerVersion()
		if err != nil {
			except.Fail("Could not determine Docker version")
		}
		if major < 1 || (major == 1 && minor <= 2) {
			except.Fail("Unsupported docker version %d.%d.%d", major, minor, revision)
		}
		if major == 1 && minor <= 6 {
			DockerConfig = os.Getenv("HOME") + "/.dockercfg"
		} else {
			DockerConfig = os.Getenv("HOME") + "/.docker/config.json"
		}
	}

	useDotDockerDir := strings.Contains(DockerConfig, ".docker/config.json")

	data, err := ioutil.ReadFile(DockerConfig)
	if err != nil {
		if useDotDockerDir == false {
			except.Fail("Could not read %s", DockerConfig)
		}
		// new .docker/config.json didn't work, so try the old .dockercfg
		except.Error("Could not read %s, trying $HOME/.dockercfg", DockerConfig)
		DockerConfig = os.Getenv("HOME") + "/.dockercfg"
		useDotDockerDir = false
		data, err = ioutil.ReadFile(DockerConfig)
		if err != nil {
			except.Fail("Could not read", DockerConfig)
		}
	}

	var dcj DockerConfigJSON
	var das DockerAuthSet
	if useDotDockerDir {
		err = json.Unmarshal(data, &dcj)
		das = dcj.Auths
	} else {
		err = json.Unmarshal(data, &das)
	}
	if err != nil {
		except.Error(err, "Couldn't JSON unmarshal from docker auth data")
		return
	}
	for r, d := range das {
		if r == registry || r == "https://"+registry || r == "https://"+registry+"/v1/" {
			encData, err := base64.StdEncoding.DecodeString(d.Auth)
			if err != nil {
				except.Error(err, ": error")
				return
			}
			up := strings.Split(string(encData), ":")
			if len(up) != 2 {
				except.Error("Invalid auth: %s", string(encData))
				return
			}
			if strings.HasSuffix(registry, "/v1/") {
				registry = registry[0 : len(registry)-4]
			}
			user := up[0]
			password := up[1]
			basicAuth = d.Auth
			fullRegistry = registry
			authConfig = getAuthConfig(user, password, d.Auth, d.Email, r)
			return
		}
	}
	return
}