func processUpdateResponse(response *http.Response) (interface{}, error) { log.Debug("Received response:", response.Status) respBody, err := ioutil.ReadAll(response.Body) if err != nil { return nil, err } switch response.StatusCode { case http.StatusOK: log.Debug("Have update available") var data UpdateResponse if err := json.Unmarshal(respBody, &data); err != nil { return nil, errors.Wrapf(err, "failed to parse response") } if err := validateGetUpdate(data); err != nil { return nil, err } return data, nil case http.StatusNoContent: log.Debug("No update available") return nil, nil case http.StatusUnauthorized: log.Warn("Client not authorized to get update schedule.") return nil, ErrNotAuthorized default: return nil, errors.New("Invalid response received from server") } }
func (m *mender) Authorize() menderError { if m.authMgr.IsAuthorized() { log.Info("authorization data present and valid, skipping authorization attempt") return m.loadAuth() } m.authToken = noAuthToken rsp, err := m.authReq.Request(m.api, m.config.ServerURL, m.authMgr) if err != nil { if err == client.AuthErrorUnauthorized { // make sure to remove auth token once device is rejected if remErr := m.authMgr.RemoveAuthToken(); remErr != nil { log.Warn("can not remove rejected authentication token") } } return NewTransientError(errors.Wrap(err, "authorization request failed")) } err = m.authMgr.RecvAuthResponse(rsp) if err != nil { return NewTransientError(errors.Wrap(err, "failed to parse authorization response")) } log.Info("successfuly received new authorization data") return m.loadAuth() }
func loadClientCert(conf Config) (*tls.Certificate, error) { if conf.CertFile == "" || conf.CertKey == "" { // TODO: this is for pre-production version only to simplify tests. // Make sure to remove in production version. log.Warn("No client key and certificate provided. Using system default.") return nil, nil } clientCert, err := tls.LoadX509KeyPair(conf.CertFile, conf.CertKey) if err != nil { return nil, errorLoadingClientCertificate } return &clientCert, nil }
func loadServerTrust(conf Config) (*x509.CertPool, error) { if conf.ServerCert == "" { // TODO: this is for pre-production version only to simplify tests. // Make sure to remove in production version. log.Warn("Server certificate not provided. Trusting all servers.") return nil, nil } certs := x509.NewCertPool() // Read certificate file. cacert, err := ioutil.ReadFile(conf.ServerCert) if err != nil { return nil, err } certs.AppendCertsFromPEM(cacert) if len(certs.Subjects()) == 0 { return nil, errorAddingServerCertificateToPool } return certs, nil }
// Check if new update is available. In case of errors, returns nil and error // that occurred. If no update is available *UpdateResponse is nil, otherwise it // contains update information. func (m *mender) CheckUpdate() (*client.UpdateResponse, menderError) { currentImageID := m.GetCurrentImageID() //TODO: if currentImageID == "" { // return errors.New("") // } haveUpdate, err := m.updater.GetScheduledUpdate(m.api.Request(m.authToken), m.config.ServerURL) if err != nil { // remove authentication token if device is not authorized if err == client.ErrNotAuthorized { if remErr := m.authMgr.RemoveAuthToken(); remErr != nil { log.Warn("can not remove rejected authentication token") } } log.Error("Error receiving scheduled update data: ", err) return nil, NewTransientError(err) } if haveUpdate == nil { log.Debug("no updates available") return nil, nil } update, ok := haveUpdate.(client.UpdateResponse) if !ok { return nil, NewTransientError(errors.Errorf("not an update response?")) } log.Debugf("received update response: %v", update) if update.Image.YoctoID == currentImageID { log.Info("Attempting to upgrade to currently installed image ID, not performing upgrade.") return &update, NewTransientError(os.ErrExist) } return &update, nil }