Example #1
0
File: clair.go Project: dwdm/clair
// Boot starts Clair. By exporting this function, anyone can import their own
// custom fetchers/updaters into their own package and then call clair.Boot.
func Boot(config *config.Config) {
	rand.Seed(time.Now().UnixNano())
	st := utils.NewStopper()

	// Open database
	err := database.Open(config.Database)
	if err != nil {
		log.Fatal(err)
	}
	defer database.Close()

	// Start notifier
	st.Begin()
	go notifier.Run(config.Notifier, st)

	// Start API
	st.Begin()
	go api.Run(config.API, st)
	st.Begin()
	go api.RunHealth(config.API, st)

	// Start updater
	st.Begin()
	go updater.Run(config.Updater, st)

	// Wait for interruption and shutdown gracefully.
	waitForSignals(os.Interrupt)
	log.Info("Received interruption, gracefully stopping ...")
	st.Stop()
}
Example #2
0
func ClairServiceInit() error {
	// Load database setting
	if setting.ClairDBPath != "" {
		clairConf.DBPath = setting.ClairDBPath
	} else {
		clairConf.DBPath = DefaultClairDBPath
	}

	clairConf.KeepDB = setting.ClairKeepDB
	clairConf.LogLevel = setting.ClairLogLevel
	clairConf.Duration = setting.ClairUpdateDuration
	clairConf.VulnPriority = setting.ClairVulnPriority

	// Set database
	if err := database.Open("bolt", clairConf.DBPath); err != nil {
		logrus.Debug(err)
		return err
	}

	// Set logLevel of clair lib
	logLevel, err := capnslog.ParseLevel(strings.ToUpper(clairConf.LogLevel))
	if err != nil {
		logLevel, _ = capnslog.ParseLevel(strings.ToUpper(DefaultClairLogLevel))
	}
	capnslog.SetGlobalLogLevel(logLevel)
	capnslog.SetFormatter(capnslog.NewPrettyFormatter(os.Stdout, false))

	// Set minumum priority parameter.
	if types.Priority(clairConf.VulnPriority).IsValid() {
		logrus.Debugf("Vuln priority is invalid :%v.", clairConf.VulnPriority)
		clairConf.VulnPriority = DefaultClairVulnPriority
	}

	// Set 'duration' and Update the CVE database
	if clairConf.Duration == "" {
		logrus.Debugf("No duration set, so only update at the beginning.")
		go updater.Update()
		clairStopper = nil
	} else {
		st := utils.NewStopper()
		st.Begin()
		d, err := time.ParseDuration(clairConf.Duration)
		if err != nil {
			logrus.Warnf("Wrong duration format, use the default duration: %v.", DefaultClairUpdateDuration)
			clairConf.Duration = DefaultClairUpdateDuration
			d, err = time.ParseDuration(clairConf.Duration)
			if err != nil {
				logrus.Debugf("Cannot pare du %v", err)
			}
		}

		go updater.Run(d, st)
		clairStopper = st
		st.Begin()
	}
	return nil
}
Example #3
0
func TestDistUpgrade(t *testing.T) {
	database.Open(&config.DatabaseConfig{Type: "memstore"})
	defer database.Close()

	_, f, _, _ := runtime.Caller(0)
	path := path.Join(path.Dir(f)) + "/testdata/DistUpgrade/"

	// blank.tar: MAINTAINER Quentin MACHU <quentin.machu.fr>
	// wheezy.tar: FROM debian:wheezy
	// jessie.tar: RUN sed -i "s/precise/trusty/" /etc/apt/sources.list && apt-get update && apt-get -y dist-upgrade
	assert.Nil(t, Process("blank", "", path+"blank.tar.gz", "Docker"))
	assert.Nil(t, Process("wheezy", "blank", path+"wheezy.tar.gz", "Docker"))
	assert.Nil(t, Process("jessie", "wheezy", path+"jessie.tar.gz", "Docker"))

	err := Process("blank", "", path+"blank.tar.gz", "")
	assert.Error(t, err, "could not process a layer which does not have a specified format")

	err = Process("blank", "", path+"blank.tar.gz", "invalid")
	assert.Error(t, err, "could not process a layer which does not have a supported format")

	wheezy, err := database.FindOneLayerByID("wheezy", database.FieldLayerAll)
	if assert.Nil(t, err) {
		assert.Equal(t, "debian:7", wheezy.OS)
		assert.Len(t, wheezy.InstalledPackagesNodes, 52)
		assert.Len(t, wheezy.RemovedPackagesNodes, 0)

		jessie, err := database.FindOneLayerByID("jessie", database.FieldLayerAll)
		if assert.Nil(t, err) {
			assert.Equal(t, "debian:8", jessie.OS)
			assert.Len(t, jessie.InstalledPackagesNodes, 66)
			assert.Len(t, jessie.RemovedPackagesNodes, 44)

			packageNodes, err := jessie.AllPackages()
			if assert.Nil(t, err) {
				// These packages haven't been upgraded
				nonUpgradedPackages := []database.Package{
					database.Package{Name: "libtext-wrapi18n-perl", Version: types.NewVersionUnsafe("0.06-7")},
					database.Package{Name: "libtext-charwidth-perl", Version: types.NewVersionUnsafe("0.04-7")},
					database.Package{Name: "libtext-iconv-perl", Version: types.NewVersionUnsafe("1.7-5")},
					database.Package{Name: "mawk", Version: types.NewVersionUnsafe("1.3.3-17")},
					database.Package{Name: "insserv", Version: types.NewVersionUnsafe("1.14.0-5")},
					database.Package{Name: "db", Version: types.NewVersionUnsafe("5.1.29-5")},
					database.Package{Name: "ustr", Version: types.NewVersionUnsafe("1.0.4-3")},
					database.Package{Name: "xz-utils", Version: types.NewVersionUnsafe("5.1.1alpha+20120614-2")},
				}
				for _, p := range nonUpgradedPackages {
					p.OS = "debian:7"
					assert.Contains(t, packageNodes, p.GetNode(), "Jessie layer doesn't have %s but it should.", p)
				}
				for _, p := range nonUpgradedPackages {
					p.OS = "debian:8"
					assert.NotContains(t, packageNodes, p.GetNode(), "Jessie layer has %s but it shouldn't.", p)
				}
			}
		}
	}
}
Example #4
0
File: main.go Project: ruo91/clair
func main() {
	rand.Seed(time.Now().UTC().UnixNano())

	var err error
	st := utils.NewStopper()

	// Parse command-line arguments
	kingpin.Parse()
	if *cfgDbType != "memstore" && *cfgDbPath == "" {
		kingpin.Errorf("required flag --db-path not provided, try --help")
		os.Exit(1)
	}
	if *cfgNotifierType == "http" && *cfgNotifierHTTPURL == "" {
		kingpin.Errorf("required flag --notifier-http-url not provided, try --help")
		os.Exit(1)
	}

	// Initialize error/logging system
	logLevel, err := capnslog.ParseLevel(strings.ToUpper(*cfgLogLevel))
	capnslog.SetGlobalLogLevel(logLevel)
	capnslog.SetFormatter(capnslog.NewPrettyFormatter(os.Stdout, false))

	// Enable CPU Profiling if specified
	if *cfgCPUProfilePath != "" {
		f, err := os.Create(*cfgCPUProfilePath)
		if err != nil {
			log.Fatalf("failed to create profile file: %s", err)
		}
		defer f.Close()

		pprof.StartCPUProfile(f)
		log.Info("started profiling")

		defer func() {
			pprof.StopCPUProfile()
			log.Info("stopped profiling")
		}()
	}

	// Open database
	err = database.Open(*cfgDbType, *cfgDbPath)
	if err != nil {
		log.Fatal(err)
	}
	defer database.Close()

	// Start notifier
	var notifierService notifier.Notifier
	switch *cfgNotifierType {
	case "http":
		notifierService, err = notifier.NewHTTPNotifier(*cfgNotifierHTTPURL)
		if err != nil {
			log.Fatalf("could not initialize HTTP notifier: %s", err)
		}
	}
	if notifierService != nil {
		st.Begin()
		go notifierService.Run(st)
	}

	// Start Main API and Health API
	st.Begin()
	go api.RunMain(&api.Config{
		Port:     *cfgAPIPort,
		TimeOut:  *cfgAPITimeout,
		CertFile: *cfgAPICertFile,
		KeyFile:  *cfgAPIKeyFile,
		CAFile:   *cfgAPICAFile,
	}, st)
	st.Begin()
	go api.RunHealth(*cfgAPIPort+1, st)

	// Start updater
	st.Begin()
	go updater.Run(*cfgUpdateInterval, st)

	// This blocks the main goroutine which is required to keep all the other goroutines running
	interrupts := make(chan os.Signal, 1)
	signal.Notify(interrupts, os.Interrupt)
	<-interrupts
	log.Info("Received interruption, gracefully stopping ...")
	st.Stop()
}