-
Notifications
You must be signed in to change notification settings - Fork 47
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: Add systemcve cli cmd #177
base: main
Are you sure you want to change the base?
Changes from 9 commits
87efc87
5a742a2
9cfee86
459269b
b3a984a
006df10
d9f1352
55fc0fe
7a97b88
972e6a2
5d8d094
1cecb7f
5c667eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cveallowlist | ||
|
||
import ( | ||
"github.com/goharbor/harbor-cli/pkg/api" | ||
"github.com/goharbor/harbor-cli/pkg/views/systemcve/update" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func AddCveAllowlistCommand() *cobra.Command { | ||
var opts update.UpdateView | ||
|
||
cmd := &cobra.Command{ | ||
Use: "add", | ||
Short: "add cve allowlist", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
var err error | ||
updateView := &update.UpdateView{ | ||
CveId: opts.CveId, | ||
IsExpire: opts.IsExpire, | ||
ExpireDate: opts.ExpireDate, | ||
} | ||
|
||
err = updatecveView(updateView) | ||
if err != nil { | ||
log.Errorf("failed to add cveallowlist: %v", err) | ||
} | ||
}, | ||
} | ||
|
||
flags := cmd.Flags() | ||
flags.BoolVarP(&opts.IsExpire, "isexpire", "i", false, "Systemcve allowlist expire or not") | ||
flags.StringVarP(&opts.CveId, "cveid", "n", "", "CVE ids seperate with commas") | ||
flags.StringVarP(&opts.ExpireDate, "expiredate", "d", "", "If it expire,give Expiry date in the format MM/DD/YYYY") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This text makes little sense without deep context "If it expire,give Expiry date in the format MM/DD/YYYY" |
||
|
||
return cmd | ||
} | ||
|
||
func updatecveView(updateView *update.UpdateView) error { | ||
if updateView == nil { | ||
updateView = &update.UpdateView{} | ||
} | ||
|
||
update.UpdateCveView(updateView) | ||
return api.UpdateSystemCve(*updateView) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package cveallowlist | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func CVEAllowlist() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "cve-allowlist", | ||
Short: "Manage system CVE allowlist", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The description is almost the same, maybe we can have a longer explanation. |
||
Long: `Manage system level allowlist of CVE`, | ||
Example: `harbor cve-allowlist list`, | ||
} | ||
cmd.AddCommand( | ||
ListCveCommand(), | ||
AddCveAllowlistCommand(), | ||
) | ||
|
||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package cveallowlist | ||
|
||
import ( | ||
"github.com/goharbor/harbor-cli/pkg/api" | ||
"github.com/goharbor/harbor-cli/pkg/utils" | ||
"github.com/goharbor/harbor-cli/pkg/views/systemcve/list" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
func ListCveCommand() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "list", | ||
Short: "list system level allowlist of cve", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
cve, err := api.ListSystemCve() | ||
if err != nil { | ||
log.Fatalf("failed to get system cve list: %v", err) | ||
} | ||
FormatFlag := viper.GetString("output-format") | ||
if FormatFlag != "" { | ||
utils.PrintPayloadInJSONFormat(cve) | ||
return | ||
} | ||
|
||
list.ListSystemCve(cve.Payload) | ||
}, | ||
} | ||
|
||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package api | ||
|
||
import ( | ||
"strings" | ||
"time" | ||
|
||
"github.com/goharbor/go-client/pkg/sdk/v2.0/client/system_cve_allowlist" | ||
"github.com/goharbor/go-client/pkg/sdk/v2.0/models" | ||
"github.com/goharbor/harbor-cli/pkg/utils" | ||
"github.com/goharbor/harbor-cli/pkg/views/systemcve/update" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
func ListSystemCve() (system_cve_allowlist.GetSystemCVEAllowlistOK, error) { | ||
ctx, client, err := utils.ContextWithClient() | ||
if err != nil { | ||
return system_cve_allowlist.GetSystemCVEAllowlistOK{}, err | ||
} | ||
|
||
response, err := client.SystemCVEAllowlist.GetSystemCVEAllowlist(ctx, &system_cve_allowlist.GetSystemCVEAllowlistParams{}) | ||
if err != nil { | ||
return system_cve_allowlist.GetSystemCVEAllowlistOK{}, err | ||
} | ||
|
||
return *response, nil | ||
} | ||
|
||
func UpdateSystemCve(opts update.UpdateView) error { | ||
ctx, client, err := utils.ContextWithClient() | ||
if err != nil { | ||
return err | ||
} | ||
var unixTimestamp int64 | ||
if opts.IsExpire { | ||
expiresAt, err := time.Parse("01/02/2006", opts.ExpireDate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use ISO 8601 as default: with
|
||
if err != nil { | ||
return err | ||
} | ||
unixTimestamp = expiresAt.Unix() | ||
} else { | ||
unixTimestamp = 0 | ||
} | ||
|
||
var items []*models.CVEAllowlistItem | ||
cveIds := strings.Split(opts.CveId, ",") | ||
for _, id := range cveIds { | ||
id = strings.TrimSpace(id) | ||
items = append(items, &models.CVEAllowlistItem{CVEID: id}) | ||
} | ||
response, err := client.SystemCVEAllowlist.PutSystemCVEAllowlist(ctx, &system_cve_allowlist.PutSystemCVEAllowlistParams{Allowlist: &models.CVEAllowlist{Items: items, ExpiresAt: &unixTimestamp}}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if response != nil { | ||
log.Info("cveallowlist added successfully") | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package list | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/charmbracelet/bubbles/table" | ||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/goharbor/go-client/pkg/sdk/v2.0/models" | ||
"github.com/goharbor/harbor-cli/pkg/utils" | ||
"github.com/goharbor/harbor-cli/pkg/views/base/tablelist" | ||
) | ||
|
||
var columns = []table.Column{ | ||
{Title: "ID", Width: 6}, | ||
{Title: "CVE Name", Width: 18}, | ||
{Title: "Expires At", Width: 18}, | ||
{Title: "Creation Time", Width: 24}, | ||
} | ||
|
||
func ListSystemCve(systemcve *models.CVEAllowlist) { | ||
var rows []table.Row | ||
var expiresAtStr string | ||
for _, cve := range systemcve.Items { | ||
CveName := cve.CVEID | ||
|
||
if systemcve.ExpiresAt != nil && *systemcve.ExpiresAt != 0 { | ||
expiresAt := time.Unix(int64(*systemcve.ExpiresAt), 0) | ||
expiresAtStr = expiresAt.Format("01/02/2006") | ||
} else { | ||
expiresAtStr = "Never expires" | ||
} | ||
|
||
createdTime, _ := utils.FormatCreatedTime(systemcve.CreationTime.String()) | ||
rows = append(rows, table.Row{ | ||
strconv.FormatInt(systemcve.ID, 10), | ||
CveName, | ||
expiresAtStr, | ||
createdTime, | ||
}) | ||
} | ||
m := tablelist.NewModel(columns, rows, len(rows)) | ||
|
||
if _, err := tea.NewProgram(m).Run(); err != nil { | ||
fmt.Println("Error running program:", err) | ||
os.Exit(1) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package update | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/charmbracelet/huh" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
type UpdateView struct { | ||
CveId string | ||
IsExpire bool | ||
ExpireDate string | ||
} | ||
|
||
func UpdateCveView(updateView *UpdateView) { | ||
theme := huh.ThemeCharm() | ||
err := huh.NewForm( | ||
huh.NewGroup( | ||
huh.NewInput(). | ||
Title("CVE ID"). | ||
Value(&updateView.CveId). | ||
Description("CVE IDs are separator by commas"). | ||
Validate(func(str string) error { | ||
if str == "" { | ||
return errors.New("cve id cannot be empty") | ||
} | ||
return nil | ||
}), | ||
huh.NewConfirm(). | ||
Title("Expires"). | ||
Value(&updateView.IsExpire). | ||
Affirmative("yes"). | ||
Negative("never"), | ||
), | ||
huh.NewGroup( | ||
huh.NewInput(). | ||
Validate(func(str string) error { | ||
if str == "" { | ||
return errors.New("ExpireDate cannot be empty") | ||
} | ||
return nil | ||
}). | ||
Description("Expire Date in the format MM/DD/YYYY"). | ||
Title("Expire Date"). | ||
Value(&updateView.ExpireDate), | ||
).WithHideFunc(func() bool { | ||
return !updateView.IsExpire | ||
}), | ||
).WithTheme(theme).Run() | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This text makes no sense: "Systemcve allowlist expire or not"