Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contrib/fvuls) Add commands to obtained CPE information of network devices by executing snmp2cpe and upload to Fvuls server #1721

Merged
merged 42 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b88c905
add: README.md
Aug 8, 2023
ccf6596
add: commands(discover,add-server,add-cpe)
Aug 8, 2023
b46841a
add: implements(discover,add-server,add-cpe)
Aug 8, 2023
813a861
fix: changed os.Exit(1) in main.go to return an error
Aug 8, 2023
8c425fd
fix: lint error
Aug 8, 2023
32bb08e
delete: trivy-to-vuls stdIn
Aug 17, 2023
5a15fc5
fix: Incomprehesible error logs
Aug 17, 2023
c8b1da8
fix: according to review
Sep 6, 2023
40bf88f
add: function converts old config to latest one
Aug 25, 2023
f9ad423
delete: add-server
Sep 11, 2023
53d5f5a
fix: lint error
Sep 13, 2023
670bbfc
fix
Sep 13, 2023
14334a9
fix: remote scan error in Windows
Sep 8, 2023
cc6981f
fix: lint error
Sep 13, 2023
38b39fb
fix
Sep 13, 2023
88522e3
fix: lint error
Sep 13, 2023
3d02e7c
fix: CONFLICT
Sep 13, 2023
ef5520d
fix: lint error
Sep 13, 2023
b2a48cf
fix: lint error
Sep 13, 2023
61fc240
add: scanner/scanner.go test normalizeHomeDirForWindows()
Sep 13, 2023
70f3930
fix
Sep 13, 2023
96e7f7c
fix
Sep 13, 2023
843c6f2
fix
Sep 13, 2023
f070bd0
fix
Sep 13, 2023
a9d6ecb
Merge branch 'master' of https://github.com/wadda0714/vuls into wada/…
Sep 13, 2023
090c0d3
fix
Sep 13, 2023
16efe8e
fix
Sep 13, 2023
f7d5de4
fix
Sep 19, 2023
679364a
fix
Sep 19, 2023
6e1d563
fix: lint error
Sep 19, 2023
0ea9fa2
Merge branch 'master' into master
wadda0714 Sep 19, 2023
efebcdd
Merge branch 'master' of https://github.com/wadda0714/vuls
Sep 19, 2023
39964f5
fix: error log
Sep 19, 2023
37aeed8
fix
Sep 19, 2023
ba10b2e
refactor(fvuls)
sadayuki-matsuno Sep 20, 2023
9bde04f
merge
sadayuki-matsuno Sep 20, 2023
7f08b42
Refactor (#2)
sadayuki-matsuno Sep 21, 2023
dcae998
Refactor (#3)
wadda0714 Sep 21, 2023
34cb069
fix: CONFLICT
Sep 21, 2023
211187a
fix
Sep 21, 2023
f0c2739
fix: lint error
Sep 21, 2023
4e3f45a
fix
Sep 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
*.swp
*.sqlite3*
*.db
*.toml
tags
.gitmodules
coverage.out
issues/
vendor/
log/
results
config.toml
!setup/docker/*
.DS_Store
dist/
Expand All @@ -21,4 +21,4 @@ vuls
future-vuls
trivy-to-vuls
snmp2cpe
!snmp2cpe/
!snmp2cpe/
133 changes: 130 additions & 3 deletions contrib/future-vuls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,77 @@

## Main Features

- upload vuls results json to future-vuls
- `future-vuls upload`
- upload vuls results json to future-vuls

- `future-vuls discover`
- Explore hosts within the CIDR range using the ping command
- Describe the information including CPE on the found hosts in a toml-formatted file.
- Exec snmp2cpe(https://github.com/future-architect/vuls/pull/1625) to active hosts to obtain CPE<br>
Commands running internally  `snmp2cpe v2c {IPAddr} public | snmp2cpe convert`<br>

Structure of toml-formatted file
```
[server.{ip}]
ip = {IpAddr}
server_name = ""
uuid = {UUID}
cpe_uri = []
fvuls_sync = false
```

- `future-vuls add-cpe`
- Create pseudo server to Fvuls to obtain uuid and Upload CPE information on the specified(FvulsSync is true and UUID is obtained) hosts to Fvuls
- Fvuls_Sync must be rewritten to true to designate it as the target of the command<br><br>


1. `future-vuls discover`

2. `future-vuls add-cpe`

These two commands are used to manage the CPE of network devices, and by executing the commands in the order from the top, you can manage the CPE of each device in Fvuls

toml file after command execution
```
["192.168.0.10"]
ip = "192.168.0.10"
server_name = "192.168.0.10"
uuid = "e811e2b1-9463-d682-7c79-a4ab37de28cf"
cpe_uri = ["cpe:2.3:h:fortinet:fortigate-50e:-:*:*:*:*:*:*:*", "cpe:2.3:o:fortinet:fortios:5.4.6:*:*:*:*:*:*:*"]
fvuls_sync = true
```
## Installation

```
git clone https://github.com/future-architect/vuls.git
cd vuls
make build-future-vuls
```

## Command Reference

```
./future-vuls -h
Usage:
future-vuls [command]

Available Commands:
add-cpe Create a pseudo server in Fvuls and register CPE. Default outputFile is ./discover_list.toml
completion Generate the autocompletion script for the specified shell
discover discover hosts with CIDR range. Run snmp2cpe on active host to get CPE. Default outputFile is ./discover_list.toml
help Help about any command
upload Upload to FutureVuls
version Show version

Flags:
-h, --help help for future-vuls

Use "future-vuls [command] --help" for more information about a command.
```
### Subcommands

```
./future-vuls upload -h
Upload to FutureVuls

Usage:
Expand All @@ -29,10 +88,78 @@ Flags:
--uuid string server uuid. ENV: VULS_SERVER_UUID
```

```
./future-vuls discover -h
discover hosts with CIDR range. Run snmp2cpe on active host to get CPE. Default outputFile is ./discover_list.toml

Usage:
future-vuls discover --cidr <CIDR_RANGE> --output <OUTPUT_FILE> [flags]

Examples:
future-vuls discover --cidr 192.168.0.0/24 --output discover_list.toml

Flags:
--cidr string cidr range
-h, --help help for discover
--output string output file
--snmp-version string snmp version v1,v2c and v3. default: v2c
```

```
./future-vuls add-cpe -h
Create a pseudo server in Fvuls and register CPE. Default outputFile is ./discover_list.toml

Usage:
future-vuls add-cpe --token <VULS_TOKEN> --output <OUTPUT_FILE> [flags]

Examples:
future-vuls add-cpe --token <VULS_TOKEN>

Flags:
-h, --help help for add-cpe
--http-proxy string proxy url
--output string output file
-t, --token string future vuls token ENV: VULS_TOKEN
```

## Usage

- update results json
- `future-vuls upload`

```
cat results.json | future-vuls upload --stdin --token xxxx --url https://xxxx --group-id 1 --uuid xxxx
```
```
- `future-vuls discover`
```
./future-vuls discover -h
discover hosts with CIDR range. Run snmp2cpe on active host to get CPE. Default outputFile is ./discover_list.toml

Usage:
future-vuls discover --cidr <CIDR_RANGE> --output <OUTPUT_FILE> [flags]

Examples:
future-vuls discover --cidr 192.168.0.0/24 --output discover_list.toml

Flags:
--cidr string cidr range
-h, --help help for discover
--output string output file
--snmp-version string snmp version v1,v2c and v3. default: v2c
```
- `future-vuls add-cpe`
```
./future-vuls add-cpe -h
Create a pseudo server in Fvuls and register CPE. Default outputFile is ./discover_list.toml

Usage:
future-vuls add-cpe --token <VULS_TOKEN> --output <OUTPUT_FILE> [flags]

Examples:
future-vuls add-cpe --token <VULS_TOKEN>

Flags:
-h, --help help for add-cpe
--http-proxy string proxy url
--output string output file
-t, --token string future vuls token ENV: VULS_TOKEN
```
139 changes: 95 additions & 44 deletions contrib/future-vuls/cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
package main

Check failure on line 1 in contrib/future-vuls/cmd/main.go

View workflow job for this annotation

GitHub Actions / Build

should have a package comment https://revive.run/r#package-comments

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"

c "github.com/3th1nk/cidr"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/saas"
"github.com/future-architect/vuls/contrib/future-vuls/pkg/cpe"
"github.com/future-architect/vuls/contrib/future-vuls/pkg/discover"
"github.com/future-architect/vuls/contrib/future-vuls/pkg/saas"
"github.com/future-architect/vuls/contrib/future-vuls/pkg/schema"

"github.com/spf13/cobra"
)

var (
configFile string
stdIn bool
jsonDir string
serverUUID string
groupID int64
token string
tags []string
url string
configFile string
stdIn bool
jsonDir string
serverUUID string
groupID int64
token string
tags []string
url string
outputFile string
cidr string
snmpVersion string
proxy string
)

func main() {
Expand All @@ -32,15 +39,14 @@
Use: "upload",
Short: "Upload to FutureVuls",
Long: `Upload to FutureVuls`,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if len(serverUUID) == 0 {
serverUUID = os.Getenv("VULS_SERVER_UUID")
}
if groupID == 0 {
envGroupID := os.Getenv("VULS_GROUP_ID")
if groupID, err = strconv.ParseInt(envGroupID, 10, 64); err != nil {
fmt.Printf("Invalid GroupID: %s\n", envGroupID)
return
return fmt.Errorf("invalid GroupID: %s", envGroupID)
}
}
if len(url) == 0 {
Expand All @@ -52,44 +58,22 @@
if len(tags) == 0 {
tags = strings.Split(os.Getenv("VULS_TAGS"), ",")
}

var scanResultJSON []byte
if stdIn {
reader := bufio.NewReader(os.Stdin)
buf := new(bytes.Buffer)
if _, err = buf.ReadFrom(reader); err != nil {
return
if _, err := buf.ReadFrom(reader); err != nil {
return fmt.Errorf("failed to read from stdIn. err: %v", err)
}
scanResultJSON = buf.Bytes()
} else {
fmt.Println("use --stdin option")
os.Exit(1)
return
}

var scanResult models.ScanResult
if err = json.Unmarshal(scanResultJSON, &scanResult); err != nil {
fmt.Println("Failed to parse json", err)
os.Exit(1)
return
}
scanResult.ServerUUID = serverUUID
if 0 < len(tags) {
if scanResult.Optional == nil {
scanResult.Optional = map[string]interface{}{}
}
scanResult.Optional["VULS_TAGS"] = tags
return fmt.Errorf("use --stdin option")
}

config.Conf.Saas.GroupID = groupID
config.Conf.Saas.Token = token
config.Conf.Saas.URL = url
if err = (saas.Writer{}).Write(scanResult); err != nil {
fmt.Println(err)
if err := saas.UploadToFvuls(serverUUID, groupID, url, token, tags, scanResultJSON); err != nil {
fmt.Printf("%v", err)
os.Exit(1)
return
}
return
return nil
},
}
var cmdVersion = &cobra.Command{
Expand All @@ -100,19 +84,86 @@
fmt.Printf("future-vuls-%s-%s\n", config.Version, config.Revision)
},
}

var cmdDiscover = &cobra.Command{
Use: "discover --cidr <CIDR_RANGE> --output <OUTPUT_FILE>",
Short: "discover hosts with CIDR range. Run snmp2cpe on active host to get CPE. Default outputFile is ./discover_list.toml",
Example: "future-vuls discover --cidr 192.168.0.0/24 --output discover_list.toml",
RunE: func(cmd *cobra.Command, args []string) error {
if len(outputFile) == 0 {
outputFile = schema.FileName
}
if len(cidr) == 0 {
return fmt.Errorf("please specify cidr range")
}
if _, err := c.Parse(cidr); err != nil {
return fmt.Errorf("Invalid cidr range")
}
if len(snmpVersion) == 0 {
snmpVersion = schema.SnmpVersion
}
if snmpVersion != "v1" && snmpVersion != "v2c" && snmpVersion != "v3" {
return fmt.Errorf("Invalid snmpVersion")
}
if err := discover.ActiveHosts(cidr, outputFile, snmpVersion); err != nil {
fmt.Printf("%v", err)
os.Exit(1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for exiting without returning err?

}
return nil
},
}

var cmdAddCpe = &cobra.Command{
Use: "add-cpe --token <VULS_TOKEN> --output <OUTPUT_FILE>",
Short: "Create a pseudo server in Fvuls and register CPE. Default outputFile is ./discover_list.toml",
Example: "future-vuls add-cpe --token <VULS_TOKEN>",
RunE: func(cmd *cobra.Command, args []string) error {
if len(token) == 0 {
token = os.Getenv("VULS_TOKEN")
if len(token) == 0 {
return fmt.Errorf("token not specified")
}
}
if len(outputFile) == 0 {
outputFile = schema.FileName
}
url := os.Getenv("VULS_URL")
if len(url) == 0 {
url = schema.RestEndPoint
}
if err := cpe.AddServerToFvuls(token, outputFile, proxy, url); err != nil {
fmt.Printf("%v", err)
os.Exit(1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for exiting without returning err?

}
if err := cpe.AddCpeDataToFvuls(token, outputFile, proxy, url); err != nil {
fmt.Printf("%v", err)
os.Exit(1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for exiting without returning err?

}
return nil
},
}

cmdDiscover.PersistentFlags().StringVar(&cidr, "cidr", "", "cidr range")
cmdDiscover.PersistentFlags().StringVar(&outputFile, "output", "", "output file")
cmdDiscover.PersistentFlags().StringVar(&snmpVersion, "snmp-version", "", "snmp version v1,v2c and v3. default: v2c ")
cmdAddCpe.PersistentFlags().StringVarP(&token, "token", "t", "", "future vuls token ENV: VULS_TOKEN")
cmdAddCpe.PersistentFlags().StringVar(&outputFile, "output", "", "output file")
cmdAddCpe.PersistentFlags().StringVar(&proxy, "http-proxy", "", "proxy url")

cmdFvulsUploader.PersistentFlags().StringVar(&serverUUID, "uuid", "", "server uuid. ENV: VULS_SERVER_UUID")
cmdFvulsUploader.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
cmdFvulsUploader.PersistentFlags().BoolVarP(&stdIn, "stdin", "s", false, "input from stdin. ENV: VULS_STDIN")
// TODO Read JSON file from directory
// cmdFvulsUploader.Flags().StringVarP(&jsonDir, "results-dir", "d", "./", "vuls scan results json dir")
cmdFvulsUploader.PersistentFlags().Int64VarP(&groupID, "group-id", "g", 0, "future vuls group id, ENV: VULS_GROUP_ID")
cmdFvulsUploader.PersistentFlags().StringVarP(&token, "token", "t", "", "future vuls token")
cmdFvulsUploader.PersistentFlags().StringVar(&url, "url", "", "future vuls upload url")

var rootCmd = &cobra.Command{Use: "future-vuls"}
rootCmd.AddCommand(cmdDiscover)
rootCmd.AddCommand(cmdAddCpe)
rootCmd.AddCommand(cmdFvulsUploader)
rootCmd.AddCommand(cmdVersion)
if err = rootCmd.Execute(); err != nil {
fmt.Println("Failed to execute command", err)
fmt.Println("Failed to execute command")
}
}
Loading
Loading