Esempio n. 1
0
func (r *pcsStepRetry) step(fn pcsStepFunc) (next pcsStepper) {
	ttl, err := fn()
	if err == nil {
		next = &pcsStepNext{aft: ttl}
	} else {
		next = &pcsStepRetry{aft: timeutil.ExpBackoff(r.aft, time.Minute)}
		log.Printf("go-oidc: provider config sync falied, retyring in %v: %v", next.after(), err)
	}
	return
}
Esempio n. 2
0
func (r *pcsStepRetry) step(fn pcsStepFunc) (next pcsStepper) {
	ttl, err := fn()
	if err == nil {
		next = &pcsStepNext{aft: ttl}
		log.Infof("Provider config sync no longer failing")
	} else {
		next = &pcsStepRetry{aft: timeutil.ExpBackoff(r.aft, time.Minute)}
		log.Errorf("Provider config sync still failing, retrying in %v: %v", next.after(), err)
	}
	return
}
Esempio n. 3
0
func handleTask(notification database.Notification, st *utils.Stopper, maxAttempts int) (bool, bool) {
	// Get notification content.
	// TODO(Quentin-M): Split big notifications.
	notificationContent, err := notification.GetContent()
	if err != nil {
		log.Warningf("could not get content of notification '%s': %s", notification.GetName(), err)
		return false, false
	}

	// Create notification.
	payload := &Notification{
		Name:    notification.GetName(),
		Type:    notification.GetType(),
		Content: notificationContent,
	}

	// Send notification.
	for notifierName, notifier := range notifiers {
		var attempts int
		var backOff time.Duration
		for {
			// Max attempts exceeded.
			if attempts >= maxAttempts {
				log.Infof("giving up on sending notification '%s' to notifier '%s': max attempts exceeded (%d)\n", notification.GetName(), notifierName, maxAttempts)
				return false, false
			}

			// Backoff.
			if backOff > 0 {
				log.Infof("waiting %v before retrying to send notification '%s' to notifier '%s' (Attempt %d / %d)\n", backOff, notification.GetName(), notifierName, attempts+1, maxAttempts)
				if !st.Sleep(backOff) {
					return false, true
				}
			}

			// Send using the current notifier.
			if err := notifier.Send(payload); err == nil {
				// Send has been successful. Go to the next one.
				break
			}

			// Send failed; increase attempts/backoff and retry.
			log.Errorf("could not send notification '%s' to notifier '%s': %s", notification.GetName(), notifierName, err)
			backOff = timeutil.ExpBackoff(backOff, maxBackOff)
			attempts++
		}
	}

	log.Infof("successfully sent notification '%s'\n", notification.GetName())
	return true, false
}
Esempio n. 4
0
func waitForProviderConfig(hc phttp.Client, issuerURL string, clock clockwork.Clock) (pcfg ProviderConfig) {
	var sleep time.Duration
	var err error
	for {
		pcfg, err = FetchProviderConfig(hc, issuerURL)
		if err == nil {
			break
		}

		sleep = timeutil.ExpBackoff(sleep, time.Minute)
		fmt.Printf("Failed fetching provider config, trying again in %v: %v\n", sleep, err)
		time.Sleep(sleep)
	}

	return
}
Esempio n. 5
0
func (r *PrivateKeyRotator) Run() chan struct{} {
	attempt := func() {
		k, err := r.generateKey()
		if err != nil {
			log.Errorf("Failed generating signing key: %v", err)
			return
		}

		exp := r.expiresAt()
		if err := rotatePrivateKeys(r.repo, k, r.keep, exp); err != nil {
			log.Errorf("Failed key rotation: %v", err)
			return
		}

		log.Infof("Rotated signing keys: id=%s expiresAt=%s", k.ID(), exp)
	}

	stop := make(chan struct{})
	go func() {
		for {
			var nextRotation time.Duration
			var sleep time.Duration
			var err error
			for {
				if nextRotation, err = r.nextRotation(); err == nil {
					break
				}
				sleep = ptime.ExpBackoff(sleep, time.Minute)
				log.Errorf("error getting nextRotation, retrying in %v: %v", sleep, err)
				time.Sleep(sleep)
			}

			log.Infof("will rotate keys in %v", nextRotation)
			select {
			case <-r.clock.After(nextRotation):
				attempt()
			case <-stop:
				return
			}
		}
	}()

	return stop
}
Esempio n. 6
0
func (r *PrivateKeyRotator) Run() chan struct{} {
	attempt := func() {
		k, err := r.generateKey()
		if err != nil {
			log.Printf("go-oidc: failed generating signing key: %v", err)
			return
		}

		exp := r.expiresAt()
		if err := rotatePrivateKeys(r.repo, k, r.keep, exp); err != nil {
			log.Printf("go-oidc: key rotation failed: %v", err)
			return
		}
	}

	stop := make(chan struct{})
	go func() {
		for {
			var nextRotation time.Duration
			var sleep time.Duration
			var err error
			for {
				if nextRotation, err = r.nextRotation(); err == nil {
					break
				}
				sleep = ptime.ExpBackoff(sleep, time.Minute)
				log.Printf("go-oidc: error getting nextRotation, retrying in %v: %v", sleep, err)
				time.Sleep(sleep)
			}

			select {
			case <-r.clock.After(nextRotation):
				attempt()
			case <-stop:
				return
			}
		}
	}()

	return stop
}
Esempio n. 7
0
func handleTask(notification database.VulnerabilityNotification, st *utils.Stopper, maxAttempts int) (bool, bool) {
	// Send notification.
	for notifierName, notifier := range notifiers {
		var attempts int
		var backOff time.Duration
		for {
			// Max attempts exceeded.
			if attempts >= maxAttempts {
				log.Infof("giving up on sending notification '%s' via notifier '%s': max attempts exceeded (%d)\n", notification.Name, notifierName, maxAttempts)
				return false, false
			}

			// Backoff.
			if backOff > 0 {
				log.Infof("waiting %v before retrying to send notification '%s' via notifier '%s' (Attempt %d / %d)\n", backOff, notification.Name, notifierName, attempts+1, maxAttempts)
				if !st.Sleep(backOff) {
					return false, true
				}
			}

			// Send using the current notifier.
			if err := notifier.Send(notification); err != nil {
				// Send failed; increase attempts/backoff and retry.
				promNotifierBackendErrorsTotal.WithLabelValues(notifierName).Inc()
				log.Errorf("could not send notification '%s' via notifier '%s': %v", notification.Name, notifierName, err)
				backOff = timeutil.ExpBackoff(backOff, maxBackOff)
				attempts++
				continue
			}

			// Send has been successful. Go to the next notifier.
			break
		}
	}

	log.Infof("successfully sent notification '%s'\n", notification.Name)
	return true, false
}
Esempio n. 8
0
func (s *KeySetSyncer) Run() chan struct{} {
	stop := make(chan struct{})
	go func() {
		var failing bool
		var next time.Duration
		for {
			exp, err := sync(s.readable, s.writable, s.clock)
			if err != nil || exp == 0 {
				if !failing {
					failing = true
					next = time.Second
				} else {
					next = timeutil.ExpBackoff(next, time.Minute)
				}
				if exp == 0 {
					log.Errorf("Synced to already expired key set, retrying in %v: %v", next, err)

				} else {
					log.Errorf("Failed syncing key set, retrying in %v: %v", next, err)
				}
			} else {
				failing = false
				next = exp / 2
				log.Infof("Synced key set, checking again in %v", next)
			}

			select {
			case <-s.clock.After(next):
				continue
			case <-stop:
				return
			}
		}
	}()

	return stop
}
Esempio n. 9
0
// Run pops notifications from the database, lock them, send them, mark them as
// send and unlock them
//
// It uses an exponential backoff when POST requests fail
func (notifier *HTTPNotifier) Run(st *utils.Stopper) {
	defer st.End()

	whoAmI := uuid.New()
	log.Infof("HTTP notifier started. URL: %s. Lock Identifier: %s", notifier.url, whoAmI)

	for {
		node, notification, err := database.FindOneNotificationToSend(database.GetDefaultNotificationWrapper())
		if notification == nil || err != nil {
			if err != nil {
				log.Warningf("could not get notification to send: %s.", err)
			}

			if !st.Sleep(checkInterval) {
				break
			}

			continue
		}

		// Try to lock the notification
		hasLock, hasLockUntil := database.Lock(node, lockDuration, whoAmI)
		if !hasLock {
			continue
		}

		for backOff := time.Duration(0); ; backOff = timeutil.ExpBackoff(backOff, maxBackOff) {
			// Backoff, it happens when an error occurs during the communication
			// with the notification endpoint
			if backOff > 0 {
				// Renew lock before going to sleep if necessary
				if time.Now().Add(backOff).After(hasLockUntil.Add(-refreshLockAnticipation)) {
					hasLock, hasLockUntil = database.Lock(node, lockDuration, whoAmI)
					if !hasLock {
						log.Warning("lost lock ownership, aborting")
						break
					}
				}

				// Sleep
				if !st.Sleep(backOff) {
					return
				}
			}

			// Get notification content
			content, err := notification.GetContent()
			if err != nil {
				log.Warningf("could not get content of notification '%s': %s", notification.GetName(), err.Error())
				break
			}

			// Marshal the notification content
			jsonContent, err := json.Marshal(struct {
				Name, Type string
				Content    interface{}
			}{
				Name:    notification.GetName(),
				Type:    notification.GetType(),
				Content: content,
			})
			if err != nil {
				log.Errorf("could not marshal content of notification '%s': %s", notification.GetName(), err.Error())
				break
			}

			// Post notification
			req, _ := http.NewRequest("POST", notifier.url, bytes.NewBuffer(jsonContent))
			req.Header.Set("Content-Type", "application/json")

			client := &http.Client{}
			res, err := client.Do(req)
			if err != nil {
				log.Warningf("could not post notification '%s': %s", notification.GetName(), err.Error())
				continue
			}
			res.Body.Close()

			if res.StatusCode != 200 && res.StatusCode != 201 {
				log.Warningf("could not post notification '%s': got status code %d", notification.GetName(), res.StatusCode)
				continue
			}

			// Mark the notification as sent
			database.MarkNotificationAsSent(node)

			log.Infof("sent notification '%s' successfully", notification.GetName())
			break
		}

		if hasLock {
			database.Unlock(node, whoAmI)
		}
	}

	log.Info("HTTP notifier stopped")
}