From 6465e9b97bdbf89f1e78b8078fa03612900eabb6 Mon Sep 17 00:00:00 2001 From: Stephen Augustus Date: Tue, 16 Nov 2021 06:31:39 -0500 Subject: [PATCH 1/2] Remove vulndash I'm not a fan of doing this (because it was an intern's work), but vulndash is undeployed and unmaintained. Given the scope of the work, it creates an attack surface for the project in an unmaintained state, so we need to remove it. Signed-off-by: Stephen Augustus --- .github/ISSUE_TEMPLATE/dep-golang.md | 3 - cmd/vulndash/Dockerfile | 51 ------ cmd/vulndash/Makefile | 101 ----------- cmd/vulndash/OWNERS | 6 - cmd/vulndash/cloudbuild.yaml | 54 ------ cmd/vulndash/cmd/root.go | 186 -------------------- cmd/vulndash/dashboard.html | 22 --- cmd/vulndash/dashboard.js | 69 -------- cmd/vulndash/main.go | 23 --- cmd/vulndash/variants.yaml | 6 - dependencies.yaml | 19 -- pkg/vulndash/OWNERS | 6 - pkg/vulndash/adapter/adapter.go | 250 --------------------------- pkg/vulndash/adapter/adapter_test.go | 227 ------------------------ pkg/vulndash/adapter/types.go | 28 --- 15 files changed, 1051 deletions(-) delete mode 100644 cmd/vulndash/Dockerfile delete mode 100644 cmd/vulndash/Makefile delete mode 100644 cmd/vulndash/OWNERS delete mode 100644 cmd/vulndash/cloudbuild.yaml delete mode 100644 cmd/vulndash/cmd/root.go delete mode 100644 cmd/vulndash/dashboard.html delete mode 100644 cmd/vulndash/dashboard.js delete mode 100644 cmd/vulndash/main.go delete mode 100644 cmd/vulndash/variants.yaml delete mode 100644 pkg/vulndash/OWNERS delete mode 100644 pkg/vulndash/adapter/adapter.go delete mode 100644 pkg/vulndash/adapter/adapter_test.go delete mode 100644 pkg/vulndash/adapter/types.go diff --git a/.github/ISSUE_TEMPLATE/dep-golang.md b/.github/ISSUE_TEMPLATE/dep-golang.md index 16f21ba7196..d1fa43e1f2d 100644 --- a/.github/ISSUE_TEMPLATE/dep-golang.md +++ b/.github/ISSUE_TEMPLATE/dep-golang.md @@ -31,9 +31,6 @@ SIG Release Slack thread: - [ ] image promotion: - -- [ ] `vulndash` image update: - - [ ] image promotion: diff --git a/cmd/vulndash/Dockerfile b/cmd/vulndash/Dockerfile deleted file mode 100644 index 0f6e748c7cb..00000000000 --- a/cmd/vulndash/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2020 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Build the manager binary -ARG GO_VERSION -ARG OS_CODENAME -# TODO(codename): Consider parameterizing in Makefile based on codename -ARG DISTROLESS_IMAGE -FROM golang:${GO_VERSION}-${OS_CODENAME} as builder - -WORKDIR /go/src/k8s.io/release - -# Copy the sources -ENV package="./cmd/vulndash" -COPY ../../go.mod ../../go.sum ./ -COPY ../../pkg ./pkg/ -COPY ../../cmd/vulndash ${package}/ - -RUN go mod download - -# Build -ARG ARCH - -ENV CGO_ENABLED=0 -ENV GOOS=linux -ENV GOARCH=${ARCH} - -RUN go build -trimpath -ldflags '-s -w -buildid= -extldflags "-static"' \ - -o vulndash ${package} - -# Production image -FROM gcr.io/distroless/${DISTROLESS_IMAGE}:latest - -LABEL maintainers="Kubernetes Authors" -LABEL description="A vulnerability dashboard for GCR container images" - -WORKDIR / -COPY --from=builder /go/src/k8s.io/release/vulndash . - -ENTRYPOINT ["/vulndash"] diff --git a/cmd/vulndash/Makefile b/cmd/vulndash/Makefile deleted file mode 100644 index 90fc94ec519..00000000000 --- a/cmd/vulndash/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2020 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# include the common image-building Makefiles -#include $(CURDIR)/../../Makefile.common-image - -# set default shell -SHELL=/bin/bash -o pipefail - -REGISTRY ?= gcr.io/k8s-staging-artifact-promoter -IMGNAME = vulndash -IMAGE_VERSION ?= v0.4.3-8 - -IMAGE = $(REGISTRY)/$(IMGNAME) - -TAG ?= $(shell git describe --tags --always --dirty) - -# Build args -GO_VERSION ?= 1.17.3 -OS_CODENAME ?= buster -DISTROLESS_IMAGE ?= static-debian10 - -# Configuration -CONFIG = $(OS_CODENAME) - -PLATFORMS ?= linux/amd64 - -HOST_GOOS ?= $(shell go env GOOS) -HOST_GOARCH ?= $(shell go env GOARCH) -GO_BUILD ?= go build - -BUILD_ARGS = --build-arg=GO_VERSION=$(GO_VERSION) \ - --build-arg=OS_CODENAME=$(OS_CODENAME) \ - --build-arg=DISTROLESS_IMAGE=$(DISTROLESS_IMAGE) - -# Ensure support for 'docker buildx' and 'docker manifest' commands -export DOCKER_CLI_EXPERIMENTAL=enabled - -.PHONY: all build clean - -.PHONY: all -all: build - -.PHONY: build -build: - $(GO_BUILD) - -.PHONY: clean -clean: - rm vulndash - -# build with buildx -# https://github.com/docker/buildx/issues/59 -.PHONY: container -container: init-docker-buildx - echo "Building $(IMGNAME) for the following platforms: $(PLATFORMS)" - @for platform in $(PLATFORMS); do \ - echo "Starting build for $${platform} platform"; \ - docker buildx build \ - --load \ - --progress plain \ - --platform $${platform} \ - --tag $(IMAGE)-$${platform##*/}:$(IMAGE_VERSION) \ - --tag $(IMAGE)-$${platform##*/}:$(TAG) \ - --tag $(IMAGE)-$${platform##*/}:latest \ - $(BUILD_ARGS) \ - -f $(CURDIR)/Dockerfile \ - ../../.; \ - done - -.PHONY: push -push: container - echo "Pushing $(IMGNAME) tags" - @for platform in $(PLATFORMS); do \ - echo "Pushing tags for $${platform} platform"; \ - docker push $(IMAGE)-$${platform##*/}:$(IMAGE_VERSION); \ - docker push $(IMAGE)-$${platform##*/}:$(TAG); \ - docker push $(IMAGE)-$${platform##*/}:latest; \ - done - -.PHONY: manifest -manifest: push - docker manifest create --amend $(IMAGE):$(IMAGE_VERSION) $(IMAGE)-$(subst linux/,,$(firstword $(PLATFORMS))):$(IMAGE_VERSION) - @for platform in $(PLATFORMS); do docker manifest annotate --arch "$${platform##*/}" ${IMAGE}:${IMAGE_VERSION} ${IMAGE}-$${platform##*/}:${IMAGE_VERSION}; done - docker manifest push --purge $(IMAGE):$(IMAGE_VERSION) - -# enable buildx -.PHONY: init-docker-buildx -init-docker-buildx: - ./../../hack/init-buildx.sh diff --git a/cmd/vulndash/OWNERS b/cmd/vulndash/OWNERS deleted file mode 100644 index 5eefcc1d300..00000000000 --- a/cmd/vulndash/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -# See the OWNERS docs at https://go.k8s.io/owners - -approvers: - - promo-tools-approvers -reviewers: - - promo-tools-reviewers diff --git a/cmd/vulndash/cloudbuild.yaml b/cmd/vulndash/cloudbuild.yaml deleted file mode 100644 index c90a8570b7c..00000000000 --- a/cmd/vulndash/cloudbuild.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# See https://github.com/kubernetes/test-infra/blob/master/config/jobs/image-pushing/README.md for more details on image pushing process - -# this must be specified in seconds. If omitted, defaults to 600s (10 mins) -timeout: 1200s - -# this prevents errors if you don't use both _GIT_TAG and _PULL_BASE_REF, -# or any new substitutions added in the future. -options: - substitution_option: ALLOW_LOOSE - machineType: 'N1_HIGHCPU_8' - -steps: - - name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v20210917-12df099d55' - entrypoint: 'bash' - dir: ./cmd/vulndash - env: - - DOCKER_CLI_EXPERIMENTAL=enabled - - REGISTRY=gcr.io/$PROJECT_ID - - HOME=/root - - TAG=$_GIT_TAG - - PULL_BASE_REF=$_PULL_BASE_REF - - IMAGE_VERSION=$_IMAGE_VERSION - - GO_VERSION=$_GO_VERSION - - OS_CODENAME=$_OS_CODENAME - - DISTROLESS_IMAGE=$_DISTROLESS_IMAGE - args: - - '-c' - - | - gcloud auth configure-docker \ - && make manifest - -substitutions: - # _GIT_TAG will be filled with a git-based tag for the image, of the form vYYYYMMDD-hash, and - # can be used as a substitution - _GIT_TAG: '12345' - _PULL_BASE_REF: 'dev' - _IMAGE_VERSION: 'v0.0.0' - _GO_VERSION: '0.0.0' - _OS_CODENAME: 'codename' - _DISTROLESS_IMAGE: 'static-debian00' - -tags: -- 'vulndash' -- ${_GIT_TAG} -- ${_PULL_BASE_REF} -- ${_IMAGE_VERSION} -- ${_GO_VERSION} -- ${_OS_CODENAME} -- ${_DISTROLESS_IMAGE} - -images: - - 'gcr.io/$PROJECT_ID/vulndash-amd64:$_IMAGE_VERSION' - - 'gcr.io/$PROJECT_ID/vulndash-amd64:$_GIT_TAG' - - 'gcr.io/$PROJECT_ID/vulndash-amd64:latest' diff --git a/cmd/vulndash/cmd/root.go b/cmd/vulndash/cmd/root.go deleted file mode 100644 index 03c67d4f3e8..00000000000 --- a/cmd/vulndash/cmd/root.go +++ /dev/null @@ -1,186 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cmd - -import ( - "fmt" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - adapter "k8s.io/release/pkg/vulndash/adapter" - "sigs.k8s.io/release-utils/log" -) - -var validRegistryHostnames = []string{"gcr.io", "us.gcr.io", "asia.gcr.io", "eu.gcr.io"} - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "vulndash --project --bucket --dashboard-file-path ", - Short: "vulndash generates a dashboard of container image vulnerabilities within a GCP project", - Example: "vulndash --project --bucket --dashboard-file-path ", - SilenceUsage: true, - SilenceErrors: true, - PersistentPreRunE: initLogging, - PreRunE: func(cmd *cobra.Command, args []string) error { - return checkRequiredFlags(cmd.Flags()) - }, - RunE: func(*cobra.Command, []string) error { - return run(opts) - }, -} - -type options struct { - project string - bucket string - dashboardFilePath string - registryHostname string - pageSize int32 - logLevel string -} - -var opts = &options{} - -var ( - projectFlag = "project" - bucketFlag = "bucket" - dashboardFilePathFlag = "dashboard-file-path" - registryHostnameFlag = "registry-hostname" - pageSizeFlag = "page-size" - - // requiredFlags only if the config flag is not set - requiredFlags = []string{ - projectFlag, - bucketFlag, - dashboardFilePathFlag, - } -) - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := rootCmd.Execute(); err != nil { - logrus.Fatal(err) - } -} - -func init() { - rootCmd.PersistentFlags().StringVar( - &opts.project, - projectFlag, - "", - "the project which the vulnerability dashboard will display information for", - ) - - rootCmd.PersistentFlags().StringVar( - &opts.bucket, - bucketFlag, - "", - "GCS bucket to upload dashboard files to", - ) - - rootCmd.PersistentFlags().StringVar( - &opts.dashboardFilePath, - dashboardFilePathFlag, - "", - "the path to the local dashboard files", - ) - - rootCmd.PersistentFlags().StringVar( - &opts.logLevel, - "log-level", - "info", - fmt.Sprintf("the logging verbosity, either %s", log.LevelNames()), - ) - - rootCmd.PersistentFlags().StringVar( - &opts.registryHostname, - registryHostnameFlag, - "", - "the registry hostname for where the images are located to use to filter "+ - "when getting the reports, ie. us.gcr.io, asia.gcr.io or eu.gcr.io", - ) - - rootCmd.PersistentFlags().Int32Var( - &opts.pageSize, - pageSizeFlag, - 200, - "the page size when getting the list of vulnerabilities", - ) -} - -func initLogging(*cobra.Command, []string) error { - return log.SetupGlobalLogger(opts.logLevel) -} - -func checkRequiredFlags(flags *pflag.FlagSet) error { - checkRequiredFlags := []string{} - flags.VisitAll(func(flag *pflag.Flag) { - for _, requiredflag := range requiredFlags { - if requiredflag == flag.Name && !flag.Changed { - checkRequiredFlags = append(checkRequiredFlags, requiredflag) - } - } - }) - - if len(checkRequiredFlags) != 0 { - return errors.New("Required flag(s) `" + strings.Join(checkRequiredFlags, ", ") + "` not set") - } - - return nil -} - -func validateFlags(opts *options) error { - if opts.registryHostname != "" { - for _, registry := range validRegistryHostnames { - if registry == opts.registryHostname { - return nil - } - } - - return errors.New("--registry-hostname needs to be one of " + strings.Join(validRegistryHostnames, ", ") + - " and was set " + opts.registryHostname) - } - - return nil -} - -func run(opts *options) error { - if err := validateFlags(opts); err != nil { - return errors.Wrap(err, "validating the flags") - } - - logrus.Info("Updating the vulnerability dashboard...") - - updateErr := adapter.UpdateVulnerabilityDashboard( - opts.dashboardFilePath, - opts.project, - opts.registryHostname, - opts.bucket, - opts.pageSize, - ) - if updateErr != nil { - return errors.Wrap(updateErr, "updating vulnerability dashboard") - } - - logrus.Info("Finished vulnerability dashboard updates") - - return nil -} diff --git a/cmd/vulndash/dashboard.html b/cmd/vulndash/dashboard.html deleted file mode 100644 index 006e208b200..00000000000 --- a/cmd/vulndash/dashboard.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - -

Vulnerability Dashboard

-

This is the Vulnerability Dashboard for the Kubernetes Images.

-

This is in Alpha development.

- - -
-
-
- - - diff --git a/cmd/vulndash/dashboard.js b/cmd/vulndash/dashboard.js deleted file mode 100644 index ad01243f6fa..00000000000 --- a/cmd/vulndash/dashboard.js +++ /dev/null @@ -1,69 +0,0 @@ -const DASHBOARD_JSON = "https://storage.googleapis.com/k8s-artifacts-prod-vuln-dashboard/dashboard.json"; -const VULNERABILITY_URL_PREFIX = "https://cve.mitre.org/cgi-bin/cvename.cgi?name="; -const TABLE = "#table"; - -console.log("Starting up..."); - -$.getJSON(DASHBOARD_JSON, function (data) { - $('#pagination-container').pagination({ - dataSource: function (done) { - var result = []; - for (var resourceURI in data) { - result.push(data[resourceURI]); - } - done(result); - }, - pageSize: 20, - callback: function (data, pagination) { - $(TABLE).empty(); - headers(data); - constructTable(data); - } - }); -}) - -function constructTable(data) { - $.each(data, function (index, item) { - var row = $(''); - var link = $('' + item.ResourceURI + ''); - row.append($('').html(link)); - - var vul = $('
' + item.NumVulnerabilities + '
'); - row.append($('').html(vul)); - - var columnCrit = $('
'); - for (var i = 0; i < item.CriticalVulnerabilities.length; i++) { - $('' + item.CriticalVulnerabilities[i] + '').appendTo(columnCrit); - } - row.append($('
').html(columnCrit)); - - var columnFix = $('
'); - for (var i = 0; i < item.FixableVulnerabilities.length; i++) { - $('' + item.FixableVulnerabilities[i] + '').appendTo(columnFix); - } - row.append($('
').html(columnFix)); - - $(TABLE).append(row); - }); -} - -function headers(item) { - var headers = []; - var header = $(''); - for (var resourceURI in item) { - var row = item[resourceURI]; - for (var k in row) { - if (k == "ResourceURI" || k == "ImageDigest") { - continue; - } - if ($.inArray(k, headers) == -1) { - headers.push(k); - // Creating the header - header.append($('').html(k)); - } - } - } - // Appending the header to the table - $(TABLE).append(header); - return headers; -} diff --git a/cmd/vulndash/main.go b/cmd/vulndash/main.go deleted file mode 100644 index 4710fc017f0..00000000000 --- a/cmd/vulndash/main.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import "k8s.io/release/cmd/vulndash/cmd" - -func main() { - cmd.Execute() -} diff --git a/cmd/vulndash/variants.yaml b/cmd/vulndash/variants.yaml deleted file mode 100644 index 7d06ad2fc2b..00000000000 --- a/cmd/vulndash/variants.yaml +++ /dev/null @@ -1,6 +0,0 @@ -variants: - default: - IMAGE_VERSION: 'v0.4.3-8' - GO_VERSION: '1.17.3' - OS_CODENAME: 'buster' - DISTROLESS_IMAGE: 'static-debian10' diff --git a/dependencies.yaml b/dependencies.yaml index d377b7412c6..25e31d4e1a3 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -66,10 +66,6 @@ dependencies: match: FROM golang:\d+.\d+(alpha|beta|rc)?\.?(\d+)-(bullseye|buster) AS builder - path: Dockerfile-kubepkg-rpm match: FROM golang:\d+.\d+(alpha|beta|rc)?\.?(\d+)-(bullseye|buster) AS builder - - path: cmd/vulndash/Makefile - match: GO_VERSION\ \?=\ \d+.\d+(alpha|beta|rc)?\.?(\d+)? - - path: cmd/vulndash/variants.yaml - match: "GO_VERSION: '\\d+.\\d+(alpha|beta|rc)?\\.?(\\d+)?'" - path: images/build/cross/Makefile match: GO_VERSION\ \?=\ \d+.\d+(alpha|beta|rc)?\.?(\d+)? - path: images/build/cross/variants.yaml @@ -157,14 +153,6 @@ dependencies: - path: images/releng/ci/variants.yaml match: REVISION:\ '\d+' - - name: "k8s.gcr.io/artifact-promoter/vulndash" - version: v0.4.3-8 - refPaths: - - path: cmd/vulndash/Makefile - match: IMAGE_VERSION\ \?=\ v((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)-([0-9]+) - - path: cmd/vulndash/variants.yaml - match: v((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)-([0-9]+) - - name: "k8s.gcr.io/build-image/go-runner" version: v2.3.1-go1.17.3-buster.0 refPaths: @@ -357,11 +345,6 @@ dependencies: - name: "Debian: codename (default)" version: buster refPaths: - # Must match distroless Debian version as well - - path: cmd/vulndash/Makefile - match: OS_CODENAME\ \?=\ (bullseye|buster) - - path: cmd/vulndash/variants.yaml - match: "OS_CODENAME: '(bullseye|buster)'" - path: images/build/cross/Makefile match: OS_CODENAME\ \?=\ (bullseye|buster) - path: images/build/cross/variants.yaml @@ -479,8 +462,6 @@ dependencies: - name: "gcr.io/k8s-staging-test-infra/gcb-docker-gcloud" version: v20210917-12df099d55 refPaths: - - path: cmd/vulndash/cloudbuild.yaml - match: "name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v[0-9]{8}-[a-z0-9]{10}'" - path: images/build/cross/cloudbuild.yaml match: "name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v[0-9]{8}-[a-z0-9]{10}'" - path: images/build/debian-base/cloudbuild.yaml diff --git a/pkg/vulndash/OWNERS b/pkg/vulndash/OWNERS deleted file mode 100644 index 5eefcc1d300..00000000000 --- a/pkg/vulndash/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -# See the OWNERS docs at https://go.k8s.io/owners - -approvers: - - promo-tools-approvers -reviewers: - - promo-tools-reviewers diff --git a/pkg/vulndash/adapter/adapter.go b/pkg/vulndash/adapter/adapter.go deleted file mode 100644 index 45b40b674f0..00000000000 --- a/pkg/vulndash/adapter/adapter.go +++ /dev/null @@ -1,250 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package adapter - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "path" - "strings" - "time" - - containeranalysis "cloud.google.com/go/containeranalysis/apiv1" - "cloud.google.com/go/storage" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/html" - "google.golang.org/api/iterator" - grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1" -) - -// DefaultPageSize to be used in the vulnerabilities list to set how many items -// will be retrieved in each request -const DefaultPageSize = 200 - -func uploadFile(directory, filename, bucket string) error { - const timeout = 60 - ctx := context.Background() - client, err := storage.NewClient(ctx) - if err != nil { - return errors.Errorf("storage.NewClient: %v", err) - } - defer client.Close() - - // Open local file - f, err := os.Open(directory + filename) - if err != nil { - return errors.Errorf("os.Open: %v", err) - } - defer f.Close() - - ctx, cancel := context.WithTimeout(ctx, time.Second*timeout) - defer cancel() - - // Upload the object with storage.Writer - wc := client.Bucket(bucket).Object(filename).NewWriter(ctx) - if _, err = io.Copy(wc, f); err != nil { - return errors.Errorf("io.Copy: %v", err) - } - - if err := wc.Close(); err != nil { - return errors.Errorf("Writer.Close: %v", err) - } - - return nil -} - -// GetAllVulnerabilities gets all of the vulnerability occurrences associated -// with images in a specific project using the Container Analysis Service. -func GetAllVulnerabilities( - projectID, - registryHostname string, - pageSize int32, -) ([]*grafeaspb.Occurrence, error) { - ctx := context.Background() - client, err := containeranalysis.NewClient(ctx) - if err != nil { - return nil, errors.Errorf("NewClient: %v", err) - } - defer client.Close() - - if pageSize <= 0 { - pageSize = DefaultPageSize - } - req := &grafeaspb.ListOccurrencesRequest{ - Parent: fmt.Sprintf("projects/%s", projectID), - Filter: fmt.Sprintf("kind = %q", "VULNERABILITY"), - PageSize: pageSize, - } - - if registryHostname != "" { - resourceURLPrefix := fmt.Sprintf("https://%s/%s/", registryHostname, projectID) - logrus.Infof("checking all vulnerabilities in %s", resourceURLPrefix) - req.Filter = fmt.Sprintf("kind = %q AND has_prefix(resourceUrl, %q)", "VULNERABILITY", resourceURLPrefix) - } - - logrus.Info("listing the vulnerabilities, will take a while...") - var occurrenceList []*grafeaspb.Occurrence - it := client.GetGrafeasClient().ListOccurrences(ctx, req) - logrus.Debug("got a list of occurrences") - for { - var occ *grafeaspb.Occurrence - var err error - occ, err = it.Next() - if err == iterator.Done { - break - } - if err != nil { - return nil, errors.Errorf("occurrence iteration error: %v", err) - } - logrus.Debug("updating the list of occurrences") - occurrenceList = append(occurrenceList, occ) - } - logrus.Infof("done listing the vulnerabilities") - - return occurrenceList, err -} - -func parseImageResourceURL(resourceURL string) (registryImageName, digest string) { - FQIN := path.Base(resourceURL) - splitFQIN := strings.Split(FQIN, "@") - registryImageName, digest = splitFQIN[0], splitFQIN[1] - - return registryImageName, digest -} - -func parseVulnName(noteName string) string { - return path.Base(noteName) -} - -// GenerateVulnerabilityBreakdown parses the a slice of vulnerability -// occurrences into a breakdown that only contains the necessary information -// for each vulnerability. -func GenerateVulnerabilityBreakdown( - productionVulnerabilities []*grafeaspb.Occurrence, -) map[string]ImageVulnBreakdown { - vulnBreakdowns := make(map[string]ImageVulnBreakdown) - - for _, occ := range productionVulnerabilities { - // resourceURI is a url pointing to a specific image - // in the form gcr.io/project/foo@sha256:111 - if _, found := vulnBreakdowns[occ.ResourceUri]; !found { - imageName, imageDigest := parseImageResourceURL(occ.ResourceUri) - vulnBreakdowns[occ.ResourceUri] = ImageVulnBreakdown{ - occ.ResourceUri, - imageName, - imageDigest, - 0, - []string{}, - []string{}, - } - } - - imageVulnBreakdown := vulnBreakdowns[occ.ResourceUri] - imageVulnBreakdown.NumVulnerabilities++ - - vulnName := parseVulnName(occ.NoteName) - vuln := occ.GetVulnerability() - if vuln.GetSeverity() == grafeaspb.Severity_CRITICAL { - imageVulnBreakdown.CriticalVulnerabilities = append( - imageVulnBreakdown.CriticalVulnerabilities, - vulnName, - ) - } - if vuln.GetFixAvailable() { - imageVulnBreakdown.FixableVulnerabilities = append( - imageVulnBreakdown.FixableVulnerabilities, - vulnName, - ) - } - vulnBreakdowns[occ.ResourceUri] = imageVulnBreakdown - } - - return vulnBreakdowns -} - -// UpdateVulnerabilityDashboard updates the vulnerability dashboard by uploading -// the lastest versions of all the vulnerability dashboard's files. -func UpdateVulnerabilityDashboard( - dashboardPath, - vulnProject, - registryHostname, - dashboardBucket string, - pageSize int32, -) error { - dashboardHTML := dashboardPath + "dashboard.html" - logrus.Infof("opening %s", dashboardHTML) - htmlReader, openErr := os.Open(dashboardHTML) - if openErr != nil { - return errors.Wrap(openErr, "opening dashboard file") - } - - logrus.Infof("parsing %s", dashboardHTML) - _, err := html.Parse(htmlReader) - if err != nil { - return errors.Errorf("dashboard.html is not valid HTML: %v", err) - } - - logrus.Infof("uploading %s to gcs", dashboardHTML) - err = uploadFile(dashboardPath, "dashboard.html", dashboardBucket) - if err != nil { - return errors.Errorf("Unable to upload latest version of "+ - "dashboard HTML: %v", err) - } - - logrus.Info("uploading updated dashboard.js to gcs") - err = uploadFile(dashboardPath, "dashboard.js", dashboardBucket) - if err != nil { - return errors.Errorf("Unable to upload latest version of "+ - "dashboard JS: %v", err) - } - - logrus.Infof("checking all vulnerabilities for %s", vulnProject) - productionVulnerabilities, getVulnErr := GetAllVulnerabilities(vulnProject, registryHostname, pageSize) - if getVulnErr != nil { - return errors.Wrap(getVulnErr, "getting all vulnerabilities") - } - - logrus.Infof("parsing the vulnerabilities for %s", vulnProject) - vulnBreakdowns := GenerateVulnerabilityBreakdown(productionVulnerabilities) - jsonFile, err := json.MarshalIndent(vulnBreakdowns, "", " ") - if err != nil { - return errors.Errorf("Unable to generate dashboard json: %v", err) - } - - dashboardJSON := dashboardPath + "dashboard.json" - logrus.Infof("writing the vulnerabilities for %s in the file %s", vulnProject, dashboardJSON) - //nolint:gosec // TODO(gosec): G306: Expect WriteFile permissions to be - // 0600 or less - err = os.WriteFile(dashboardJSON, jsonFile, 0o644) - if err != nil { - return errors.Errorf("Unable to create temporary local"+ - "JSON file for the dashboard: %v", err) - } - - logrus.Infof("uploading updated %s to gcs", dashboardJSON) - err = uploadFile(dashboardPath, "dashboard.json", dashboardBucket) - if err != nil { - return errors.Errorf("Unable to upload latest version of "+ - "dashboard JSON: %v", err) - } - - return nil -} diff --git a/pkg/vulndash/adapter/adapter_test.go b/pkg/vulndash/adapter/adapter_test.go deleted file mode 100644 index 8ad7afa2cbc..00000000000 --- a/pkg/vulndash/adapter/adapter_test.go +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package adapter_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1" - adapter "k8s.io/release/pkg/vulndash/adapter" -) - -func TestGenerateVulnerabilityBreakdown(t *testing.T) { - tests := []struct { - name string - vulnerabilities []*grafeaspb.Occurrence - expected map[string]adapter.ImageVulnBreakdown - }{ - { - "No critical and no fixable vulnerabilities", - []*grafeaspb.Occurrence{ - { - ResourceUri: "foo/bar1@sha256:111", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_HIGH, - FixAvailable: false, - }, - }, - }, - { - ResourceUri: "foo/bar2@sha256:000", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_HIGH, - FixAvailable: false, - }, - }, - }, - }, - map[string]adapter.ImageVulnBreakdown{ - "foo/bar1@sha256:111": { - "foo/bar1@sha256:111", - "bar1", - "sha256:111", - 1, - []string{}, - []string{}, - }, - "foo/bar2@sha256:000": { - "foo/bar2@sha256:000", - "bar2", - "sha256:000", - 1, - []string{}, - []string{}, - }, - }, - }, - { - "No critical and Multiple fixable vulnerabilities", - []*grafeaspb.Occurrence{ - { - ResourceUri: "foo/bar1@sha256:111", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_HIGH, - FixAvailable: true, - }, - }, - }, - { - ResourceUri: "foo/bar2@sha256:000", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_MEDIUM, - FixAvailable: true, - }, - }, - }, - }, - map[string]adapter.ImageVulnBreakdown{ - "foo/bar1@sha256:111": { - "foo/bar1@sha256:111", - "bar1", - "sha256:111", - 1, - []string{}, - []string{ - "CVE-2000", - }, - }, - "foo/bar2@sha256:000": { - "foo/bar2@sha256:000", - "bar2", - "sha256:000", - 1, - []string{}, - []string{ - "CVE-2000", - }, - }, - }, - }, - { - "Multiple critical and no fixable vulnerabilities", - []*grafeaspb.Occurrence{ - { - ResourceUri: "foo/bar1@sha256:111", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_CRITICAL, - FixAvailable: false, - }, - }, - }, - { - ResourceUri: "foo/bar2@sha256:000", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_CRITICAL, - FixAvailable: false, - }, - }, - }, - }, - map[string]adapter.ImageVulnBreakdown{ - "foo/bar1@sha256:111": { - "foo/bar1@sha256:111", - "bar1", - "sha256:111", - 1, - []string{ - "CVE-2000", - }, - []string{}, - }, - "foo/bar2@sha256:000": { - "foo/bar2@sha256:000", - "bar2", - "sha256:000", - 1, - []string{ - "CVE-2000", - }, - []string{}, - }, - }, - }, - { - "Multiple critical and fixable vulnerabilities", - []*grafeaspb.Occurrence{ - { - ResourceUri: "foo/bar1@sha256:111", - NoteName: "vuln/CVE-2000", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_CRITICAL, - FixAvailable: true, - }, - }, - }, - { - ResourceUri: "foo/bar2@sha256:000", - NoteName: "vuln/CVE-2001", - Details: &grafeaspb.Occurrence_Vulnerability{ - Vulnerability: &grafeaspb.VulnerabilityOccurrence{ - Severity: grafeaspb.Severity_CRITICAL, - FixAvailable: true, - }, - }, - }, - }, - map[string]adapter.ImageVulnBreakdown{ - "foo/bar1@sha256:111": { - "foo/bar1@sha256:111", - "bar1", - "sha256:111", - 1, - []string{ - "CVE-2000", - }, - []string{ - "CVE-2000", - }, - }, - "foo/bar2@sha256:000": { - "foo/bar2@sha256:000", - "bar2", - "sha256:000", - 1, - []string{ - "CVE-2001", - }, - []string{ - "CVE-2001", - }, - }, - }, - }, - } - - for _, test := range tests { - testBreakdown := adapter.GenerateVulnerabilityBreakdown(test.vulnerabilities) - require.Equal(t, testBreakdown, test.expected) - } -} diff --git a/pkg/vulndash/adapter/types.go b/pkg/vulndash/adapter/types.go deleted file mode 100644 index 2dd89077186..00000000000 --- a/pkg/vulndash/adapter/types.go +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package adapter - -// ImageVulnBreakdown is used by the adapter in order to store the information -// from image vulnerability occurrences that the dashboard needs. -type ImageVulnBreakdown struct { - ResourceURI string - ImageName string - ImageDigest string - NumVulnerabilities int - CriticalVulnerabilities []string - FixableVulnerabilities []string -} From 2c99ef669ee65f02340a9367ac6bb481d4dfaddd Mon Sep 17 00:00:00 2001 From: Stephen Augustus Date: Tue, 16 Nov 2021 06:55:23 -0500 Subject: [PATCH 2/2] generated: Run `go mod tidy` Signed-off-by: Stephen Augustus --- go.mod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 96c658f1871..5c43470dc07 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module k8s.io/release go 1.17 require ( - cloud.google.com/go/containeranalysis v0.1.0 cloud.google.com/go/storage v1.16.1 github.com/GoogleCloudPlatform/testgrid v0.0.38 github.com/blang/semver v3.5.1+incompatible @@ -27,7 +26,6 @@ require ( github.com/shirou/gopsutil/v3 v3.21.10 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.2.1 - github.com/spf13/pflag v1.0.5 github.com/spiegel-im-spiegel/go-cvss v0.4.0 github.com/stretchr/testify v1.7.0 github.com/yuin/goldmark v1.4.4 @@ -36,7 +34,6 @@ require ( golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 golang.org/x/tools v0.1.7 google.golang.org/api v0.56.0 - google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 gopkg.in/yaml.v2 v2.4.0 sigs.k8s.io/mdtoc v1.1.0 sigs.k8s.io/promo-tools/v3 v3.2.1 @@ -120,6 +117,9 @@ require ( ) require ( + cloud.google.com/go/containeranalysis v0.1.0 // indirect github.com/shibumi/go-pathspec v1.2.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.0.0-20211013075003-97ac67df715c // indirect + google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect )