0%

通过go-restful更新Harbor的Trivy数据库

trivy漏洞数据库下载

  • 数据存储以oci方式存储,需要通过专用工具下载。
1
2
3
$ oras pull ghcr.io/aquasecurity/trivy-db:2
$ ls -l
.rw-rw-r-- 47M yang 28 3月 10:57 db.tar.gz

trivy漏洞数据库上传服务

  • 上传数据命令
1
curl -XPUT http://localhost/api/trivy/v1/database -F "db=@bin/db.tar.gz"
  • github.com/emicklei/go-restful-openapi/v2 v2.9.1为API框架注册上传接口
1
2
3
4
5
6
7
webservice.Route(webservice.PUT("/database").
Doc("Update trivy vulnerability database.").
Param(webservice.BodyParameter("db", "trivy vulnerability database.")).
To(h.updateVulnerabilityDatabase).
Consumes("multipart/form-data").
Returns(http.StatusOK, api.StatusOK, nil).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TrivyTag}))
  • 读入form-data,直接解压并返回trivy metedata信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func (h *handler) updateVulnerabilityDatabase(request *restful.Request, response *restful.Response) {
formfile, _, err := request.Request.FormFile("db")
if err != nil {
api.HandleBadRequest(response, request, err)
return
}
defer formfile.Close()

err = utils.Extract(formfile, h.trivyOptions.Cache)
if err != nil {
api.HandleBadRequest(response, request, err)
return
}

// 读数据的元信息并返回,确认一致性
metadata, err := os.ReadFile(filepath.Join(h.trivyOptions.Cache, "metadata.json"))
if err != nil {
api.HandleBadRequest(response, request, err)
return
}
response.Write(metadata)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Implements Extractor.
func Extract(buffer io.Reader, targetDir string) error {
uncompressedStream, err := gzip.NewReader(buffer)
if err != nil {
return err
}

if err := os.MkdirAll(targetDir, 0755); err != nil {
return err
}

tarReader := tar.NewReader(uncompressedStream)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}

path, err := cleanJoin(targetDir, header.Name)
if err != nil {
return err
}

switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(path, 0755); err != nil {
return err
}
case tar.TypeReg:
outFile, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
if _, err := io.Copy(outFile, tarReader); err != nil {
outFile.Close()
return err
}
outFile.Close()
// We don't want to process these extension header files.
case tar.TypeXGlobalHeader, tar.TypeXHeader:
continue
default:
return errors.Errorf("unknown type: %b in %s", header.Typeflag, header.Name)
}
}
return nil
}
  • 服务镜像制作
1
2
3
4
5
6
7
8
FROM alpine:3.16.2

COPY bin/cmd/trivy-apiserver /
COPY trivy-core.yaml /etc/trivy-core/
WORKDIR /

EXPOSE 9090
CMD ["/trivy-apiserver", "-v5"]

API服务与Harbor集成(ingress, pod)

  • 增加traefik middleware以处理URL路径前缀
1
2
3
4
5
6
7
8
9
10
11
12
13
# Middleware
# Strip prefix /trivy
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: strip-trivy
namespace: "default"

spec:
stripPrefix:
forceSlash: false
prefixes:
- /trivy
  • 增加harbor-ingress配置(需要更新部分)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: harbor-ingress
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.middlewares: default-strip-trivy@kubernetescrd
spec:
rules:
- host: harbor.internal.io
http:
paths:
- path: /trivy/
pathType: Prefix
backend:
service:
name: harbor-trivy
port:
name: trivy-api
  • 在已有harbor-trivy内加入trivy-apiserver容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: apps/v1
kind: Deployment
metadata:
name: harbor-trivy
spec:
replicas: 1
template:
spec:
containers:
- name: trivy
image: harbor-adapter-trivy:2.10.0-debian-12-r13
imagePullPolicy: "IfNotPresent"
ports:
- name: api-server
containerPort: 8080
volumeMounts:
- name: data
mountPath: /bitnami/harbor-adapter-trivy/.cache
readOnly: false
- name: apiserver
image: trivy-apiserver:v1.0.2
imagePullPolicy: "IfNotPresent"
ports:
- name: trivy-api
containerPort: 9090
volumeMounts:
- name: data
mountPath: /bitnami/harbor-adapter-trivy/.cache
readOnly: false
volumes:
- name: data
persistentVolumeClaim:
claimName: trivy-data
  • 测试外部接口上传数据
1
2
$ curl -kXPUT https://harbor.internal.io:21000/trivy/api/v1/database -F "db=@bin/db.tar.gz"
{"Version":2,"NextUpdate":"2024-03-28T06:15:32.76330602Z","UpdatedAt":"2024-03-28T00:15:32.763306431Z","DownloadedAt":"0001-01-01T00:00:00Z"}