From 21a10533ef444a855548121bf46ccce729080c2a Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Wed, 18 Sep 2024 14:46:52 -0600 Subject: [PATCH 1/4] Changed DeleteScannedAssets to work correct and added db tag --- internal/cache/sqlite/sqlite.go | 12 ++++++------ internal/scan.go | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/cache/sqlite/sqlite.go b/internal/cache/sqlite/sqlite.go index 7a04978..a977a56 100644 --- a/internal/cache/sqlite/sqlite.go +++ b/internal/cache/sqlite/sqlite.go @@ -59,8 +59,8 @@ func InsertScannedAssets(path string, assets ...magellan.RemoteAsset) error { return nil } -func DeleteScannedAssets(path string, results ...magellan.RemoteAsset) error { - if results == nil { +func DeleteScannedAssets(path string, assets ...magellan.RemoteAsset) error { + if assets == nil { return fmt.Errorf("no assets found") } db, err := sqlx.Open("sqlite3", path) @@ -68,11 +68,11 @@ func DeleteScannedAssets(path string, results ...magellan.RemoteAsset) error { return fmt.Errorf("failed to open database: %v", err) } tx := db.MustBegin() - for _, state := range results { - sql := fmt.Sprintf(`DELETE FROM %s WHERE host = :host, port = :port;`, TABLE_NAME) - _, err := tx.NamedExec(sql, &state) + for _, asset := range assets { + sql := fmt.Sprintf(`DELETE FROM %s WHERE host=:host AND port=:port;`, TABLE_NAME) + _, err := tx.NamedExec(sql, &asset) if err != nil { - fmt.Printf("failed to execute transaction: %v\n", err) + fmt.Printf("failed to execute DELETE transaction: %v\n", err) } } diff --git a/internal/scan.go b/internal/scan.go index a88116d..1dd99a8 100644 --- a/internal/scan.go +++ b/internal/scan.go @@ -16,11 +16,11 @@ import ( ) type RemoteAsset struct { - Host string `json:"host"` - Port int `json:"port"` - Protocol string `json:"protocol"` - State bool `json:"state"` - Timestamp time.Time `json:"timestamp"` + Host string `db:"host" json:"host"` + Port int `db:"port" json:"port"` + Protocol string `db:"protocol" json:"protocol"` + State bool `db:"state" json:"state"` + Timestamp time.Time `db:"timestamp" json:"timestamp"` } // ScanParams is a collection of commom parameters passed to the CLI From db2b0a73721d6ff89b89b9d068cffd8355233f1f Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Wed, 18 Sep 2024 14:47:20 -0600 Subject: [PATCH 2/4] Added cache command and ability to delete cached assets --- cmd/cache.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 cmd/cache.go diff --git a/cmd/cache.go b/cmd/cache.go new file mode 100644 index 0000000..676581e --- /dev/null +++ b/cmd/cache.go @@ -0,0 +1,69 @@ +package cmd + +import ( + "fmt" + "net/url" + "os" + "strconv" + + magellan "github.com/OpenCHAMI/magellan/internal" + "github.com/OpenCHAMI/magellan/internal/cache/sqlite" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" +) + +var ( + withAllHosts bool + withAllPorts bool +) + +var cacheCmd = &cobra.Command{ + Use: "cache", + Short: "Manage found assets in cache.", + Run: func(cmd *cobra.Command, args []string) { + // show the help for cache and exit + if len(args) <= 0 { + cmd.Help() + os.Exit(0) + } + }, +} + +var cacheRemoveCmd = &cobra.Command{ + Use: "remove", + Short: "Remove a host from a scanned cache list.", + Run: func(cmd *cobra.Command, args []string) { + assets := []magellan.RemoteAsset{} + for _, arg := range args { + var ( + port int + uri *url.URL + err error + ) + uri, err = url.ParseRequestURI(arg) + if err != nil { + log.Error().Err(err).Msg("failed to parse arg") + } + + // convert port to its "proper" type + port, err = strconv.Atoi(uri.Port()) + if err != nil { + log.Error().Err(err).Msg("failed to convert port to integer type") + } + asset := magellan.RemoteAsset{ + Host: fmt.Sprintf("%s://%s", uri.Scheme, uri.Hostname()), + Port: port, + } + fmt.Printf("%s:%d\n", asset.Host, asset.Port) + assets = append(assets, asset) + } + sqlite.DeleteScannedAssets(cachePath, assets...) + }, +} + +func init() { + cacheRemoveCmd.Flags().BoolVar(&withAllHosts, "--all-hosts", false, "Remove all assets with specified hosts") + cacheRemoveCmd.Flags().BoolVar(&withAllPorts, "--all-ports", false, "Remove all assets with specified ports") + cacheCmd.AddCommand(cacheRemoveCmd) + rootCmd.AddCommand(cacheCmd) +} From 4cf854313a350ceec42abbd17457b4c30f38dcc2 Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Wed, 18 Sep 2024 20:18:53 -0600 Subject: [PATCH 3/4] Minor changes --- cmd/cache.go | 20 +++++++++++++++----- internal/cache/sqlite/sqlite.go | 8 +++++++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cmd/cache.go b/cmd/cache.go index 676581e..aefd15b 100644 --- a/cmd/cache.go +++ b/cmd/cache.go @@ -13,8 +13,8 @@ import ( ) var ( - withAllHosts bool - withAllPorts bool + withHosts []string + withPorts []int ) var cacheCmd = &cobra.Command{ @@ -34,6 +34,8 @@ var cacheRemoveCmd = &cobra.Command{ Short: "Remove a host from a scanned cache list.", Run: func(cmd *cobra.Command, args []string) { assets := []magellan.RemoteAsset{} + + // add all assets directly from positional args for _, arg := range args { var ( port int @@ -46,6 +48,9 @@ var cacheRemoveCmd = &cobra.Command{ } // convert port to its "proper" type + if uri.Port() == "" { + uri.Host += ":443" + } port, err = strconv.Atoi(uri.Port()) if err != nil { log.Error().Err(err).Msg("failed to convert port to integer type") @@ -54,16 +59,21 @@ var cacheRemoveCmd = &cobra.Command{ Host: fmt.Sprintf("%s://%s", uri.Scheme, uri.Hostname()), Port: port, } - fmt.Printf("%s:%d\n", asset.Host, asset.Port) assets = append(assets, asset) } + + // add all assets with specified hosts (same host different different ports) + for _, host := range withHosts { + + } + // add all assets with specified ports (same port different hosts) sqlite.DeleteScannedAssets(cachePath, assets...) }, } func init() { - cacheRemoveCmd.Flags().BoolVar(&withAllHosts, "--all-hosts", false, "Remove all assets with specified hosts") - cacheRemoveCmd.Flags().BoolVar(&withAllPorts, "--all-ports", false, "Remove all assets with specified ports") + cacheRemoveCmd.Flags().StringSliceVar(&withHosts, "with-hosts", []string{}, "Remove all assets with specified hosts") + cacheRemoveCmd.Flags().IntSliceVar(&withPorts, "with-ports", []int{}, "Remove all assets with specified ports") cacheCmd.AddCommand(cacheRemoveCmd) rootCmd.AddCommand(cacheCmd) } diff --git a/internal/cache/sqlite/sqlite.go b/internal/cache/sqlite/sqlite.go index a977a56..691b658 100644 --- a/internal/cache/sqlite/sqlite.go +++ b/internal/cache/sqlite/sqlite.go @@ -69,7 +69,13 @@ func DeleteScannedAssets(path string, assets ...magellan.RemoteAsset) error { } tx := db.MustBegin() for _, asset := range assets { - sql := fmt.Sprintf(`DELETE FROM %s WHERE host=:host AND port=:port;`, TABLE_NAME) + if asset.Host == "" && asset.Port <= 0 { + continue + } + sql := fmt.Sprintf(`DELETE FROM %s WHERE port=:port;`, TABLE_NAME) + if asset.Host != "" { + sql += "AND host=:host" + } _, err := tx.NamedExec(sql, &asset) if err != nil { fmt.Printf("failed to execute DELETE transaction: %v\n", err) From 3f12b093f977ea21ea828b581bfa2d6028daaf6a Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Thu, 19 Sep 2024 11:21:08 -0600 Subject: [PATCH 4/4] Fixed removing from cache with --with-* flags --- cmd/cache.go | 23 ++++++++++++++++++++--- internal/cache/sqlite/sqlite.go | 25 ++++++++++++++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/cmd/cache.go b/cmd/cache.go index aefd15b..ef605a9 100644 --- a/cmd/cache.go +++ b/cmd/cache.go @@ -62,11 +62,28 @@ var cacheRemoveCmd = &cobra.Command{ assets = append(assets, asset) } - // add all assets with specified hosts (same host different different ports) + // Add all assets with specified hosts (same host different different ports) + // This should produce the following SQL: + // DELETE FROM magellan_scanned_assets WHERE host=:host for _, host := range withHosts { - + assets = append(assets, magellan.RemoteAsset{ + Host: host, + Port: -1, + }) + } + // Add all assets with specified ports (same port different hosts) + // This should produce the following SQL: + // DELETE FROM magellan_scanned_assets WHERE port=:port + for _, port := range withPorts { + assets = append(assets, magellan.RemoteAsset{ + Host: "", + Port: port, + }) + } + if len(assets) <= 0 { + log.Error().Msg("nothing to do") + os.Exit(1) } - // add all assets with specified ports (same port different hosts) sqlite.DeleteScannedAssets(cachePath, assets...) }, } diff --git a/internal/cache/sqlite/sqlite.go b/internal/cache/sqlite/sqlite.go index 691b658..3e72676 100644 --- a/internal/cache/sqlite/sqlite.go +++ b/internal/cache/sqlite/sqlite.go @@ -2,6 +2,7 @@ package sqlite import ( "fmt" + "strings" magellan "github.com/OpenCHAMI/magellan/internal" "github.com/OpenCHAMI/magellan/internal/util" @@ -60,22 +61,36 @@ func InsertScannedAssets(path string, assets ...magellan.RemoteAsset) error { } func DeleteScannedAssets(path string, assets ...magellan.RemoteAsset) error { + var ( + db *sqlx.DB + tx *sqlx.Tx + err error + ) if assets == nil { return fmt.Errorf("no assets found") } - db, err := sqlx.Open("sqlite3", path) + db, err = sqlx.Open("sqlite3", path) if err != nil { return fmt.Errorf("failed to open database: %v", err) } - tx := db.MustBegin() + tx = db.MustBegin() for _, asset := range assets { + // skip if neither host nor port are specified if asset.Host == "" && asset.Port <= 0 { continue } - sql := fmt.Sprintf(`DELETE FROM %s WHERE port=:port;`, TABLE_NAME) - if asset.Host != "" { - sql += "AND host=:host" + sql := fmt.Sprintf(`DELETE FROM %s`, TABLE_NAME) + where := []string{} + if asset.Port > 0 { + where = append(where, "port=:port") } + if asset.Host != "" { + where = append(where, "host=:host") + } + if len(where) <= 0 { + continue + } + sql += fmt.Sprintf(" WHERE %s;", strings.Join(where, " AND ")) _, err := tx.NamedExec(sql, &asset) if err != nil { fmt.Printf("failed to execute DELETE transaction: %v\n", err)