// AtomicUpdateHandler will accept multiple TUF files and ensure that the storage // backend is atomically updated with all the new records. func AtomicUpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) error { defer r.Body.Close() s := ctx.Value("metaStore") store, ok := s.(storage.MetaStore) if !ok { return errors.ErrNoStorage.WithDetail(nil) } vars := mux.Vars(r) gun := vars["imageName"] reader, err := r.MultipartReader() if err != nil { return errors.ErrMalformedUpload.WithDetail(nil) } var updates []storage.MetaUpdate for { part, err := reader.NextPart() if err == io.EOF { break } role := strings.TrimSuffix(part.FileName(), ".json") if role == "" { return errors.ErrNoFilename.WithDetail(nil) } else if !data.ValidRole(role) { return errors.ErrInvalidRole.WithDetail(role) } meta := &data.SignedMeta{} var input []byte inBuf := bytes.NewBuffer(input) dec := json.NewDecoder(io.TeeReader(part, inBuf)) err = dec.Decode(meta) if err != nil { return errors.ErrMalformedJSON.WithDetail(nil) } version := meta.Signed.Version updates = append(updates, storage.MetaUpdate{ Role: role, Version: version, Data: inBuf.Bytes(), }) } if err = validateUpdate(gun, updates, store); err != nil { return errors.ErrMalformedUpload.WithDetail(err) } err = store.UpdateMany(gun, updates) if err != nil { return errors.ErrUpdating.WithDetail(err) } return nil }
func (db *KeyDB) AddRole(r *data.Role) error { if !data.ValidRole(r.Name) { return ErrInvalidRole } if r.Threshold < 1 { return ErrInvalidThreshold } // validate all key ids are in the keys maps for _, id := range r.KeyIDs { if _, ok := db.keys[id]; !ok { return ErrInvalidKeyID } } db.roles[r.Name] = r return nil }
// AtomicUpdateHandler will accept multiple TUF files and ensure that the storage // backend is atomically updated with all the new records. func AtomicUpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError { defer r.Body.Close() s := ctx.Value("metaStore") if s == nil { return &errors.HTTPError{ HTTPStatus: http.StatusInternalServerError, Code: 9999, Err: fmt.Errorf("Version store is nil"), } } store, ok := s.(storage.MetaStore) if !ok { return &errors.HTTPError{ HTTPStatus: http.StatusInternalServerError, Code: 9999, Err: fmt.Errorf("Version store not configured"), } } vars := mux.Vars(r) gun := vars["imageName"] reader, err := r.MultipartReader() if err != nil { return &errors.HTTPError{ HTTPStatus: http.StatusBadRequest, Code: 9999, Err: err, } } var updates []storage.MetaUpdate for { part, err := reader.NextPart() if err == io.EOF { break } role := strings.TrimSuffix(part.FileName(), ".json") if role == "" { return &errors.HTTPError{ HTTPStatus: http.StatusBadRequest, Code: 9999, Err: fmt.Errorf("Empty filename provided. No updates performed"), } } else if !data.ValidRole(role) { return &errors.HTTPError{ HTTPStatus: http.StatusBadRequest, Code: 9999, Err: fmt.Errorf("Invalid role: %s. No updates performed", role), } } meta := &data.SignedTargets{} var input []byte inBuf := bytes.NewBuffer(input) dec := json.NewDecoder(io.TeeReader(part, inBuf)) err = dec.Decode(meta) if err != nil { return &errors.HTTPError{ HTTPStatus: http.StatusBadRequest, Code: 9999, Err: err, } } version := meta.Signed.Version updates = append(updates, storage.MetaUpdate{ Role: role, Version: version, Data: inBuf.Bytes(), }) } err = store.UpdateMany(gun, updates) if err != nil { return &errors.HTTPError{ HTTPStatus: http.StatusInternalServerError, Code: 9999, Err: err, } } return nil }