Exemplo n.º 1
0
// Verify if the method that choose the domains that needs to be verified is correct
func domainsNotification(domainDAO dao.DomainDAO) {
	numberOfItemsToBeVerified := 1000
	numberOfItemsToDontBeVerified := 1000
	nameserverErrorAlertDays := 7
	nameserverTimeoutAlertDays := 30
	dsErrorAlertDays := 1
	dsTimeoutAlertDays := 7
	maxExpirationAlertDays := 5

	data := []struct {
		name                      string
		numberOfItems             int
		nameserverTimeoutLastOKAt time.Time
		nameserverErrorLastOKAt   time.Time
		dsTimeoutLastOkAt         time.Time
		dsErrorLastOkAt           time.Time
		dsExpiresAt               time.Time
	}{
		{
			name:                      "shouldbenotified",
			numberOfItems:             numberOfItemsToBeVerified,
			nameserverTimeoutLastOKAt: time.Now().Add(time.Duration(-nameserverTimeoutAlertDays*24) * time.Hour),
			nameserverErrorLastOKAt:   time.Now().Add(time.Duration(-nameserverErrorAlertDays*24) * time.Hour),
			dsTimeoutLastOkAt:         time.Now().Add(time.Duration(-dsTimeoutAlertDays*24) * time.Hour),
			dsErrorLastOkAt:           time.Now().Add(time.Duration(-dsErrorAlertDays*24) * time.Hour),
			dsExpiresAt:               time.Now().Add(time.Duration((maxExpirationAlertDays)*24) * time.Hour),
		},
		{
			name:                      "shouldnotbenotified",
			numberOfItems:             numberOfItemsToDontBeVerified,
			nameserverTimeoutLastOKAt: time.Now().Add(time.Duration((-nameserverTimeoutAlertDays+1)*24) * time.Hour),
			nameserverErrorLastOKAt:   time.Now().Add(time.Duration((-nameserverErrorAlertDays+1)*24) * time.Hour),
			dsTimeoutLastOkAt:         time.Now().Add(time.Duration((-dsTimeoutAlertDays+1)*24) * time.Hour),
			dsErrorLastOkAt:           time.Now().Add(time.Duration((-dsErrorAlertDays+1)*24) * time.Hour),
			dsExpiresAt:               time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour),
		},
	}

	for _, item := range data {
		for i := 0; i < item.numberOfItems/5; i++ {
			domain := model.Domain{
				FQDN: fmt.Sprintf("%s%d.com.br", item.name, i),
				Nameservers: []model.Nameserver{
					{
						LastStatus: model.NameserverStatusTimeout,
						LastOKAt:   item.nameserverTimeoutLastOKAt,
					},
				},
			}

			if err := domainDAO.Save(&domain); err != nil {
				utils.Fatalln("Error saving domain in database", err)
			}
		}

		for i := item.numberOfItems / 5; i < item.numberOfItems/5*2; i++ {
			domain := model.Domain{
				FQDN: fmt.Sprintf("%s%d.com.br", item.name, i),
				Nameservers: []model.Nameserver{
					{
						LastStatus: model.NameserverStatusNoAuthority,
						LastOKAt:   item.nameserverErrorLastOKAt,
					},
				},
			}

			if err := domainDAO.Save(&domain); err != nil {
				utils.Fatalln("Error saving domain in database", err)
			}
		}

		for i := item.numberOfItems / 5 * 2; i < item.numberOfItems/5*3; i++ {
			domain := model.Domain{
				FQDN: fmt.Sprintf("%s%d.com.br", item.name, i),
				DSSet: []model.DS{
					{
						LastStatus: model.DSStatusTimeout,
						LastOKAt:   item.dsTimeoutLastOkAt,
						ExpiresAt:  time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour),
					},
				},
			}

			if err := domainDAO.Save(&domain); err != nil {
				utils.Fatalln("Error saving domain in database", err)
			}
		}

		for i := item.numberOfItems / 5 * 3; i < item.numberOfItems/5*4; i++ {
			domain := model.Domain{
				FQDN: fmt.Sprintf("%s%d.com.br", item.name, i),
				DSSet: []model.DS{
					{
						LastStatus: model.DSStatusExpiredSignature,
						LastOKAt:   item.dsErrorLastOkAt,
						ExpiresAt:  time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour),
					},
				},
			}

			if err := domainDAO.Save(&domain); err != nil {
				utils.Fatalln("Error saving domain in database", err)
			}
		}

		for i := item.numberOfItems / 5 * 4; i < item.numberOfItems; i++ {
			domain := model.Domain{
				FQDN: fmt.Sprintf("%s%d.com.br", item.name, i),
				DSSet: []model.DS{
					{
						LastStatus: model.DSStatusOK,
						LastOKAt:   time.Now(),
						ExpiresAt:  item.dsExpiresAt,
					},
				},
			}

			if err := domainDAO.Save(&domain); err != nil {
				utils.Fatalln("Error saving domain in database", err)
			}
		}
	}

	domainChannel, err := domainDAO.FindAllAsyncToBeNotified(
		nameserverErrorAlertDays,
		nameserverTimeoutAlertDays,
		dsErrorAlertDays,
		dsTimeoutAlertDays,
		maxExpirationAlertDays,
	)

	if err != nil {
		utils.Fatalln("Error retrieving domains to be notified", err)
	}

	var domains []*model.Domain
	for {
		domainResult := <-domainChannel

		if domainResult.Error != nil {
			utils.Fatalln("Error retrieving domain to be notified", domainResult.Error)
		}

		if domainResult.Error != nil || domainResult.Domain == nil {
			break
		}

		domains = append(domains, domainResult.Domain)
	}

	if len(domains) != numberOfItemsToBeVerified {
		utils.Fatalln(fmt.Sprintf("Did not select all the domains ready for notification. "+
			"Expected %d and got %d", numberOfItemsToBeVerified, len(domains)), nil)
	}

	for _, item := range data {
		for i := 0; i < item.numberOfItems; i++ {
			fqdn := fmt.Sprintf("%s%d.com.br", item.name, i)
			if err := domainDAO.RemoveByFQDN(fqdn); err != nil {
				utils.Fatalln("Error removing domain from database", err)
			}
		}
	}
}
Exemplo n.º 2
0
// Notify is responsable for selecting the domains that should be notified in the system.
// It will send alert e-mails for each owner of a domain
func Notify() {
	defer func() {
		// Something went really wrong while notifying the owners. Log the error stacktrace
		// and move out
		if r := recover(); r != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			log.Printf("Panic detected while notifying the owners. Details: %v\n%s", r, buf)
		}
	}()

	log.Info("Start notification job")
	defer func() {
		log.Info("End notification job")
	}()

	log.Debugf("Initializing database with the parameters: URIS - %v | Name - %s | Auth - %t | Username - %s",
		config.ShelterConfig.Database.URIs,
		config.ShelterConfig.Database.Name,
		config.ShelterConfig.Database.Auth.Enabled,
		config.ShelterConfig.Database.Auth.Username,
	)

	database, databaseSession, err := mongodb.Open(
		config.ShelterConfig.Database.URIs,
		config.ShelterConfig.Database.Name,
		config.ShelterConfig.Database.Auth.Enabled,
		config.ShelterConfig.Database.Auth.Username,
		config.ShelterConfig.Database.Auth.Password,
	)

	if err != nil {
		log.Println("Error while initializing database. Details:", err)
		return
	}
	defer databaseSession.Close()

	domainDAO := dao.DomainDAO{
		Database: database,
	}

	domainChannel, err := domainDAO.FindAllAsyncToBeNotified(
		config.ShelterConfig.Notification.NameserverErrorAlertDays,
		config.ShelterConfig.Notification.NameserverTimeoutAlertDays,
		config.ShelterConfig.Notification.DSErrorAlertDays,
		config.ShelterConfig.Notification.DSTimeoutAlertDays,

		// TODO: Should we move this configuration parameter to a place were both modules can
		// access it. This sounds better for configuration deployment
		config.ShelterConfig.Scan.VerificationIntervals.MaxExpirationAlertDays,
	)

	if err != nil {
		log.Println("Error retrieving domains to notify. Details:", err)
		return
	}

	// Dispatch the asynchronous part of the method
	for {
		// Get domain from the database (one-by-one)
		domainResult := <-domainChannel

		// Detect errors while retrieving a specific domain. We are not going to stop all the
		// process when only one domain got an error
		if domainResult.Error != nil {
			log.Println("Error retrieving domain to notify. Details:", domainResult.Error)
			continue
		}

		// Problem detected while retrieving a domain or we don't have domains anymore
		if domainResult.Error != nil || domainResult.Domain == nil {
			break
		}

		if err := notifyDomain(domainResult.Domain); err != nil {
			log.Println("Error notifying a domain. Details:", err)
		}
	}
}