Beispiel #1
0
func GetSuggestion(w rest.ResponseWriter, r *rest.Request) {
	ID := r.PathParam("id")
	form, ok := client.GetSuggestion(ID)
	if !ok {
		apiutils.WriteRestError(w, apierrors.NewNotFound("suggestion", ID))
		return
	}
	w.WriteJson(form)
}
Beispiel #2
0
// Prepared returns true if no othesamples are expected to be added
func (s Suggestion) Prepared() (bool, error) {
	s, ok := GetSuggestion(s.ID)
	if !ok {
		return false, apierrors.NewNotFound("suggestion", s.ID)
	}
	if s.Token == "" {
		return false, apierrors.NewConflict("suggestion", "", errors.New("No session token associated with suggestion"))
	}
	return s.prepared, nil
}
Beispiel #3
0
func DeleteConnection(w rest.ResponseWriter, r *rest.Request) {
	ID := r.PathParam("id")

	err := clientconfig.Update(func(conf *clientconfig.Config) error {

		all := conf.Settings.Connections
		var result []shared.Connection

		// validate that the id exists
		found := false
		nEnabled := 0
		for _, v := range all {
			if v.ID == ID {
				found = true
				if v.Protected {
					apiutils.WriteRestError(w, apierrors.NewForbidden("connection", ID, nil))
					return nil
				}
			} else {
				if !v.Disabled {
					nEnabled += 1
				}
				result = append(result, v)
			}
		}
		if !found {
			apiutils.WriteRestError(w, apierrors.NewNotFound("connection", ID))
			return nil
		}
		if nEnabled < 1 {
			apiutils.WriteRestError(w,
				apierrors.NewForbidden("connection", ID, errors.New("one connection must be enabled")))
			return nil
		}
		service.UpdateConnections(result)
		conf.Settings.Connections = result
		return nil
	})
	if err != nil {
		lg.Errorln(err)
	}
	clientconfig.Write()
	w.WriteJson(true)

}
Beispiel #4
0
func ToggleConnection(w rest.ResponseWriter, r *rest.Request) {
	ID := r.PathParam("id")

	err := clientconfig.Update(func(conf *clientconfig.Config) error {
		// validate that the id exists, if supplied
		all := conf.Settings.Connections
		foundIdx := 0
		found := false
		nEnabled := 0
		for k, v := range all {
			if !v.Disabled {
				nEnabled += 1
			}
			if v.ID == ID {
				found = true
				foundIdx = k
			}

		}

		if !found {
			apiutils.WriteRestError(w, apierrors.NewNotFound("connection", ID))
			return nil
		}
		if nEnabled < 2 && !conf.Settings.Connections[foundIdx].Disabled {
			apiutils.WriteRestError(w,
				apierrors.NewForbidden("connection", ID, errors.New("one connection must be enabled")))
			return nil
		}
		conf.Settings.Connections[foundIdx].Disabled = !conf.Settings.Connections[foundIdx].Disabled
		service.UpdateConnections(conf.Settings.Connections)

		return nil
	})
	if err != nil {
		lg.Errorln(err)
	}
	clientconfig.Write()
	w.WriteJson(true)

}
Beispiel #5
0
// AddSample adds a sample to the local cache ready to be sent to central using SendSamples.
func (sugg *Suggestion) SendSamples(client *Client) (int, error) {
	s, ok := GetSuggestion(sugg.ID)
	if !ok {
		return 0, apierrors.NewNotFound("suggestion", sugg.ID)
	}
	if s.Token == "" {
		return 0, apierrors.NewConflict("suggestion", "", errors.New("No session token associated with suggestion"))
	}

	n := 0
	var rerr error

	for _, v := range s.samples {
		r, err := client.CreateSample(shared.StoreSampleRequest{
			Sample: &shared.Sample{
				Token:      s.Token,
				SampleType: v.sampleType,
				Data:       v.data,
				URL:        s.URL,
			},
			ClientAddr: shared.GetPublicIPAddr().String(),
		})
		if err != nil {
			rerr = errors.New("error sending sample: " + err.Error())
			continue
		}

		if !r.Ok {
			rerr = errors.New("error sending sample, not accepted")
			continue

		}
		n++
		modifySuggestion <- removeSample(s, v)
	}

	return n, rerr
}
Beispiel #6
0
// SubmitSuggestion initiates the comminication with Central for a Submission
// session.
func SubmitSuggestion(w rest.ResponseWriter, r *rest.Request) {

	// // TODO This is the response that must be forwarded from central/api and parsed by client and passed on to the browser.
	// apiutils.WriteRestError(w,
	// 	apierrors.NewInvalid("object", "suggestion",
	// 		fielderrors.ValidationErrorList{
	// 			fielderrors.NewFieldValueNotSupported("URL", "...", []string{})}))
	// return

	ID := r.PathParam("id")
	suggestion, ok := client.GetSuggestion(ID)
	if !ok {
		apiutils.WriteRestError(w, apierrors.NewNotFound("suggestion", ID))
		return
	}
	wanip := shared.GetPublicIPAddr()
	if wanip == nil {
		lg.Warning("could not resolve public ip addr")
	}

	conf := clientconfig.Get()
	restclient, err := NewRestClient()
	if err != nil {
		apiutils.WriteRestError(w, apierrors.NewInternalError(err))
		return
	}

	tokenResp, err := suggestion.RequestToken(
		restclient, wanip, conf.Settings.Local.CountryCode)
	if err != nil {
		if apiutils.IsNetError(err) {
			apiutils.WriteRestError(w, apierrors.NewServerTimeout("alkasir-central", "request-submission-token", 0))
		} else {
			apiutils.WriteRestError(w, apierrors.NewInternalError(err))
		}
		return
	}
	n, err := suggestion.SendSamples(restclient)
	if err != nil {
		lg.Warningln("error sending samples", err.Error())
	}
	lg.V(5).Infof("sent %d samples", n)

	// continue sending samples if future measuremetns are expected to come
	prepared, err := suggestion.Prepared()
	if err != nil {
		lg.Errorln(err)
	} else if !prepared {
		lg.V(5).Infof("all samples not collected, will try to send the rest when they are done")
		go func(s client.Suggestion) {
			start := time.Now()
			t := time.NewTicker(30 * time.Second)
			defer t.Stop()

		submitSamples:
			for range t.C {
				if time.Now().After(start.Add(15 * time.Minute)) {
					lg.Errorln("Stopping trying to send additional samples")
					return
				}

				prepared, err := suggestion.Prepared()
				if err != nil {
					lg.Errorln(err)
					return
				}
				if prepared {
					restclient, err := NewRestClient()
					if err != nil {
						continue submitSamples
					}
					n, err := suggestion.SendSamples(restclient)
					lg.V(5).Infof("sent %d samples", n)
					if err != nil {
						lg.Warningln("error sending samples", err.Error())
						continue submitSamples
					}
					return
				}
			}
		}(suggestion)
	}

	u, err := url.Parse(suggestion.URL)
	if err != nil {
		lg.Errorln(err)
	} else {
		err := clientconfig.Update(func(conf *clientconfig.Config) error {
			conf.BlockedHosts.Add(u.Host)
			lastBlocklistChange = time.Now()

			pac.UpdateBlockedList(conf.BlockedHostsCentral.Hosts,
				conf.BlockedHosts.Hosts)
			return nil
		})
		if err != nil {
			lg.Errorln(err)
		}
	}
	w.WriteJson(tokenResp)
}
Beispiel #7
0
// SubmitSuggestion initiates the comminication with Central for a Submission
// session.
func SubmitSuggestion(w rest.ResponseWriter, r *rest.Request) {

	// // TODO This is the response that must be forwarded from central/api and parsed by client and passed on to the browser.
	// apiutils.WriteRestError(w,
	// 	apierrors.NewInvalid("object", "suggestion",
	// 		fielderrors.ValidationErrorList{
	// 			fielderrors.NewFieldValueNotSupported("URL", "...", []string{})}))
	// return

	ID := r.PathParam("id")
	suggestion, ok := client.GetSuggestion(ID)
	if !ok {
		apiutils.WriteRestError(w, apierrors.NewNotFound("suggestion", ID))
		return
	}
	wanip := shared.GetPublicIPAddr()
	if wanip == nil {
		lg.Warning("could not resolve public ip addr")
	}

	conf := clientconfig.Get()
	restclient, err := NewRestClient()
	if err != nil {
		apiutils.WriteRestError(w, apierrors.NewInternalError(err))
		return
	}

	tokenResp, err := suggestion.RequestToken(
		restclient, wanip, conf.Settings.Local.CountryCode)
	if err != nil {
		if apiutils.IsNetError(err) {
			apiutils.WriteRestError(w, apierrors.NewServerTimeout("alkasir-central", "request-submission-token", 0))
		} else {
			apiutils.WriteRestError(w, apierrors.NewInternalError(err))
		}
		return
	}
	n, err := suggestion.SendSamples(restclient)
	if err != nil {
		lg.Warningln("error sending samples", err.Error())
	}

	lg.V(5).Infoln("sent ", n)
	// FIXME PRESENTATION: just add the url locally
	u, err := url.Parse(suggestion.URL)
	if err != nil {
		lg.Errorln(err)
	} else {
		err := clientconfig.Update(func(conf *clientconfig.Config) error {
			conf.BlockedHosts.Add(u.Host)
			lastBlocklistChange = time.Now()

			pac.UpdateBlockedList(conf.BlockedHostsCentral.Hosts,
				conf.BlockedHosts.Hosts)
			return nil
		})
		if err != nil {
			lg.Errorln(err)
		}
	}
	w.WriteJson(tokenResp)
}
Beispiel #8
0
// Update list of blocked hosts for an IP address.
func GetUpgrade(dbclients db.Clients) func(w rest.ResponseWriter, r *rest.Request) {
	return func(w rest.ResponseWriter, r *rest.Request) {
		req := shared.BinaryUpgradeRequest{}
		err := r.DecodeJsonPayload(&req)
		// TODO: proper validation response
		if err != nil {
			apiError(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if req.FromVersion == "" {
			apiError(w, "fromversion required", http.StatusInternalServerError)
			return
		}
		v, err := version.NewVersion(req.FromVersion)
		if err != nil {
			lg.Warningln(err)
			apiError(w, fmt.Sprintf("invalid fromVersion %s", req.FromVersion), http.StatusInternalServerError)
			return
		}

		if req.Artifact == "" {
			apiError(w, "artifact required", http.StatusInternalServerError)
			return

		}
		res, found, err := dbclients.DB.GetUpgrade(
			db.GetUpgradeQuery{
				Artifact: req.Artifact,
			})
		if err != nil {
			apiError(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if !found {
			apiutils.WriteRestError(w,
				apierrors.NewNotFound(
					"upgrade", fmt.Sprintf("%s-%s", req.Artifact, req.FromVersion)))
			return
		}

		serverVersion, err := version.NewVersion(res.Version)
		if err != nil {
			apiError(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if serverVersion.LessThan(v) || serverVersion.Equal(v) {
			apiutils.WriteRestError(w,
				apierrors.NewNotFound(
					"upgrade", fmt.Sprintf("%s-%s", req.Artifact, req.FromVersion)))
			return

		}
		w.WriteJson(shared.BinaryUpgradeResponse{
			Artifact:         res.Artifact,
			Version:          res.Version,
			CreatedAt:        res.CreatedAt,
			SHA256Sum:        res.SHA256Sum,
			ED25519Signature: res.ED25519Signature,
		})

	}
}