use encrypt page in listVuln api
Signed-off-by: liangchenye <liangchenye@huawei.com>
This commit is contained in:
parent
a541e964e0
commit
48ffb2687a
@ -213,7 +213,7 @@ The GET route for the Vulnerabilities resource displays the vulnerabilities data
|
|||||||
###### Example Request
|
###### Example Request
|
||||||
|
|
||||||
```json
|
```json
|
||||||
GET http://localhost:6060/v1/namespaces/debian%3A8/vulnerabilities?page=0&limit=2 HTTP/1.1
|
GET http://localhost:6060/v1/namespaces/debian%3A8/vulnerabilities?limit=2 HTTP/1.1
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Example Response
|
###### Example Response
|
||||||
@ -247,7 +247,8 @@ Server: clair
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"NextPage":"gAAAAABW1ABiOlm6KMDKYFE022bEy_IFJdm4ExxTNuJZMN0Eycn0Sut2tOH9bDB4EWGy5s6xwATUHiG-6JXXaU5U32sBs6_DmA=="
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
@ -276,6 +277,7 @@ type NamespaceEnvelope struct {
|
|||||||
type VulnerabilityEnvelope struct {
|
type VulnerabilityEnvelope struct {
|
||||||
Vulnerability *Vulnerability `json:"Vulnerability,omitempty"`
|
Vulnerability *Vulnerability `json:"Vulnerability,omitempty"`
|
||||||
Vulnerabilities *[]Vulnerability `json:"Vulnerabilities,omitempty"`
|
Vulnerabilities *[]Vulnerability `json:"Vulnerabilities,omitempty"`
|
||||||
|
NextPage *string `json:"NextPage,omitempty"`
|
||||||
Error *Error `json:"Error,omitempty"`
|
Error *Error `json:"Error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,3 +319,24 @@ func pageNumberToToken(page database.VulnerabilityNotificationPageNumber, key st
|
|||||||
|
|
||||||
return string(tokenBytes)
|
return string(tokenBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tokenToNumber(token, key string) (int, error) {
|
||||||
|
k, _ := fernet.DecodeKey(key)
|
||||||
|
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
|
||||||
|
if msg == nil {
|
||||||
|
return -1, errors.New("invalid or expired pagination token")
|
||||||
|
}
|
||||||
|
|
||||||
|
page, err := strconv.Atoi(string(msg))
|
||||||
|
return page, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberToToken(page int, key string) string {
|
||||||
|
k, _ := fernet.DecodeKey(key)
|
||||||
|
tokenBytes, err := fernet.EncryptAndSign([]byte(strconv.Itoa(page)), k)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("failed to encrypt number")
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(tokenBytes)
|
||||||
|
}
|
||||||
|
@ -202,21 +202,17 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
|
|||||||
return getVulnerabilitiesRoute, http.StatusBadRequest
|
return getVulnerabilitiesRoute, http.StatusBadRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page := 0
|
||||||
pageStrs, pageExists := query["page"]
|
pageStrs, pageExists := query["page"]
|
||||||
if !pageExists {
|
if pageExists {
|
||||||
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"must provide page query parameter"}})
|
page, err = tokenToNumber(pageStrs[0], ctx.Config.PaginationKey)
|
||||||
return getVulnerabilitiesRoute, http.StatusBadRequest
|
if err != nil {
|
||||||
}
|
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
|
||||||
page, err := strconv.Atoi(pageStrs[0])
|
return getNotificationRoute, http.StatusBadRequest
|
||||||
if err != nil {
|
}
|
||||||
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
|
|
||||||
return getVulnerabilitiesRoute, http.StatusBadRequest
|
|
||||||
} else if page < 0 {
|
|
||||||
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"page value should not be less than zero"}})
|
|
||||||
return getVulnerabilitiesRoute, http.StatusBadRequest
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbVulns, err := ctx.Store.ListVulnerabilities(p.ByName("namespaceName"), limit, page)
|
dbVulns, nextPage, err := ctx.Store.ListVulnerabilities(p.ByName("namespaceName"), limit, page)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeResponse(w, r, http.StatusInternalServerError, VulnerabilityEnvelope{Error: &Error{err.Error()}})
|
writeResponse(w, r, http.StatusInternalServerError, VulnerabilityEnvelope{Error: &Error{err.Error()}})
|
||||||
return getVulnerabilitiesRoute, http.StatusInternalServerError
|
return getVulnerabilitiesRoute, http.StatusInternalServerError
|
||||||
@ -228,7 +224,12 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
|
|||||||
vulns = append(vulns, vuln)
|
vulns = append(vulns, vuln)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeResponse(w, r, http.StatusOK, VulnerabilityEnvelope{Vulnerabilities: &vulns})
|
var nextPageStr string
|
||||||
|
if nextPage != -1 {
|
||||||
|
nextPageStr = numberToToken(nextPage, ctx.Config.PaginationKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeResponse(w, r, http.StatusOK, VulnerabilityEnvelope{Vulnerabilities: &vulns, NextPage: &nextPageStr})
|
||||||
return getVulnerabilitiesRoute, http.StatusOK
|
return getVulnerabilitiesRoute, http.StatusOK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,9 @@ type Datastore interface {
|
|||||||
// # Vulnerability
|
// # Vulnerability
|
||||||
// ListVulnerabilities returns the list of vulnerabilies of a certain Namespace.
|
// ListVulnerabilities returns the list of vulnerabilies of a certain Namespace.
|
||||||
// The Limit and page parameters are used to paginate the return list.
|
// The Limit and page parameters are used to paginate the return list.
|
||||||
ListVulnerabilities(namespaceName string, limit int, page int) ([]Vulnerability, error)
|
// The first given page should be 0. The function will then return the next available page.
|
||||||
|
// If there is no more page, -1 has to be returned.
|
||||||
|
ListVulnerabilities(namespaceName string, limit int, page int) ([]Vulnerability, int, error)
|
||||||
|
|
||||||
// InsertVulnerabilities stores the given Vulnerabilities in the database, updating them if
|
// InsertVulnerabilities stores the given Vulnerabilities in the database, updating them if
|
||||||
// necessary. A vulnerability is uniquely identified by its Namespace and its Name.
|
// necessary. A vulnerability is uniquely identified by its Namespace and its Name.
|
||||||
|
@ -145,8 +145,9 @@ const (
|
|||||||
searchVulnerabilityByNamespaceAndName = ` WHERE n.name = $1 AND v.name = $2 AND v.deleted_at IS NULL`
|
searchVulnerabilityByNamespaceAndName = ` WHERE n.name = $1 AND v.name = $2 AND v.deleted_at IS NULL`
|
||||||
searchVulnerabilityByID = ` WHERE v.id = $1`
|
searchVulnerabilityByID = ` WHERE v.id = $1`
|
||||||
searchVulnerabilityByNamespace = ` WHERE n.name = $1 AND v.deleted_at IS NULL
|
searchVulnerabilityByNamespace = ` WHERE n.name = $1 AND v.deleted_at IS NULL
|
||||||
ORDER BY v.name
|
AND v.id >= $2
|
||||||
LIMIT $2 offset $3`
|
ORDER BY v.id
|
||||||
|
LIMIT $3`
|
||||||
|
|
||||||
searchVulnerabilityFixedIn = `
|
searchVulnerabilityFixedIn = `
|
||||||
SELECT vfif.version, f.id, f.Name
|
SELECT vfif.version, f.id, f.Name
|
||||||
|
@ -28,22 +28,20 @@ import (
|
|||||||
"github.com/guregu/null/zero"
|
"github.com/guregu/null/zero"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (pgSQL *pgSQL) ListVulnerabilities(namespaceName string, limit int, page int) ([]database.Vulnerability, error) {
|
func (pgSQL *pgSQL) ListVulnerabilities(namespaceName string, limit int, startID int) ([]database.Vulnerability, int, error) {
|
||||||
return listVulnerabilities(pgSQL, namespaceName, limit, page)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listVulnerabilities(queryer Queryer, namespaceName string, limit int, page int) ([]database.Vulnerability, error) {
|
|
||||||
defer observeQueryTime("listVulnerabilities", "all", time.Now())
|
defer observeQueryTime("listVulnerabilities", "all", time.Now())
|
||||||
|
|
||||||
// Query.
|
// Query.
|
||||||
query := searchVulnerabilityBase + searchVulnerabilityByNamespace
|
query := searchVulnerabilityBase + searchVulnerabilityByNamespace
|
||||||
rows, err := queryer.Query(query, namespaceName, limit, page*limit)
|
rows, err := pgSQL.Query(query, namespaceName, startID, limit+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError("searchVulnerabilityByNamespace", err)
|
return nil, -1, handleError("searchVulnerabilityByNamespace", err)
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var vulns []database.Vulnerability
|
var vulns []database.Vulnerability
|
||||||
|
nextID := -1
|
||||||
|
size := 0
|
||||||
// Scan query.
|
// Scan query.
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var vulnerability database.Vulnerability
|
var vulnerability database.Vulnerability
|
||||||
@ -59,17 +57,22 @@ func listVulnerabilities(queryer Queryer, namespaceName string, limit int, page
|
|||||||
&vulnerability.Metadata,
|
&vulnerability.Metadata,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleError("searchVulnerabilityByNamespace.Scan()", err)
|
return nil, -1, handleError("searchVulnerabilityByNamespace.Scan()", err)
|
||||||
|
}
|
||||||
|
size++
|
||||||
|
if size > limit {
|
||||||
|
nextID = vulnerability.ID
|
||||||
} else {
|
} else {
|
||||||
vulns = append(vulns, vulnerability)
|
vulns = append(vulns, vulnerability)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
if err := rows.Err(); err != nil {
|
||||||
return nil, handleError("searchVulnerabilityByNamespace.Rows()", err)
|
return nil, -1, handleError("searchVulnerabilityByNamespace.Rows()", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return vulns, nil
|
fmt.Println(nextID)
|
||||||
|
return vulns, nextID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pgSQL *pgSQL) FindVulnerability(namespaceName, name string) (database.Vulnerability, error) {
|
func (pgSQL *pgSQL) FindVulnerability(namespaceName, name string) (database.Vulnerability, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user