vulndb/snooze.go (154 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package vulndb import ( "context" "database/sql" "encoding/csv" "io" "time" "github.com/pkg/errors" "github.com/facebookincubator/flog" "github.com/facebookincubator/nvdtools/vulndb/debug" "github.com/facebookincubator/nvdtools/vulndb/sqlutil" ) // SnoozeRecord represents a database record of the `snooze` table. type SnoozeRecord struct { Owner string `sql:"owner"` Collector string `sql:"collector"` Provider string `sql:"provider"` CVE string `sql:"cve_id"` Deadline sqlutil.NullTime `sql:"deadline"` Metadata []byte `sql:"metadata"` } // SnoozeCreator is a helper for creating snoozes. type SnoozeCreator struct { DB *sql.DB Owner string Collector string Provider string Deadline time.Time Metadata []byte } // Create creates a snooze. func (s SnoozeCreator) Create(ctx context.Context, cve ...string) error { records := make([]SnoozeRecord, len(cve)) for i := 0; i < len(records); i++ { records[i] = SnoozeRecord{ Owner: s.Owner, Collector: s.Collector, Provider: s.Provider, CVE: cve[i], Deadline: sqlutil.NullTime{ Valid: !s.Deadline.IsZero(), Time: s.Deadline, }, Metadata: s.Metadata, } } r := sqlutil.NewRecords(records) q := sqlutil.Replace(). Into("snooze"). Fields(r.Fields()...). Values(r...) query, args := q.String(), q.QueryArgs() if debug.V(1) { flog.Infof("running: %q / %#v", query, args) } _, err := s.DB.ExecContext(ctx, query, args...) if err != nil { return errors.Wrap(err, "cannot create snooze") } return nil } // SnoozeGetter gets data from the database. type SnoozeGetter struct { DB *sql.DB Collector string Provider string FilterCVEs []string } // CSV writes snooze records to w. func (s SnoozeGetter) CSV(ctx context.Context, w io.Writer, header bool) error { r := sqlutil.NewRecordType(SnoozeRecord{}) q := sqlutil.Select( r.Fields()..., ).From( "snooze", ) var cond *sqlutil.QueryConditionSet if s.Collector != "" { cond = sqlutil.Cond().Equal("collector", s.Collector) } if s.Provider != "" { if cond == nil { cond = sqlutil.Cond() } else { cond = cond.And() } cond = cond.Equal("provider", s.Provider) } if len(s.FilterCVEs) > 0 { if cond == nil { cond = sqlutil.Cond() } else { cond = cond.And() } cond = cond.In("cve_id", s.FilterCVEs) } if cond != nil { q = q.Where(cond) } query, args := q.String(), q.QueryArgs() if debug.V(1) { flog.Infof("running: %q / %#v", query, args) } rows, err := s.DB.QueryContext(ctx, query, args...) if err != nil { return errors.Wrap(err, "cannot query snooze") } defer rows.Close() cw := csv.NewWriter(w) defer cw.Flush() if header { cw.Write(r.Fields()) } for rows.Next() { var sr SnoozeRecord err = rows.Scan(sqlutil.NewRecordType(&sr).Values()...) if err != nil { return errors.Wrap(err, "cannot scan snooze data") } var deadline string if sr.Deadline.Valid { deadline = sr.Deadline.Time.Format(TimeLayout) } cw.Write([]string{ sr.Owner, sr.Collector, sr.Provider, sr.CVE, deadline, string(sr.Metadata), }) } return nil } // SnoozeDeleter deletes snoozes from the database. type SnoozeDeleter struct { DB *sql.DB Collector string Provider string FilterCVEs []string } // Delete deletes snooze data from the database. func (s SnoozeDeleter) Delete(ctx context.Context) error { cond := sqlutil.Cond(). Equal("collector", s.Provider). And(). Equal("provider", s.Provider) if len(s.FilterCVEs) > 0 { cond = cond.And().In("cve_id", s.FilterCVEs) } q := sqlutil.Delete().From("snooze").Where(cond) query, args := q.String(), q.QueryArgs() if debug.V(1) { flog.Infof("running: %q / %#v", query, args) } _, err := s.DB.ExecContext(ctx, query, args...) if err != nil { return errors.Wrap(err, "cannot delete snooze data") } return nil }