File: //lib/google-cloud-sdk/lib/googlecloudsdk/api_lib/container/images/container_analysis_data_util.py
# -*- coding: utf-8 -*- #
# Copyright 2016 Google LLC. All Rights Reserved.
#
# 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.
"""Utilities for the container analysis data model."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import collections
from googlecloudsdk.api_lib.container.images import container_data_util
from googlecloudsdk.api_lib.util import apis
_INDENT = ' '
_NULL_SEVERITY = 'UNKNOWN'
class SummaryResolver(object):
"""SummaryResolver is a base class for occurrence summary objects."""
def resolve(self):
"""resolve is called after all records are added to the summary.
In this function, aggregate data can be calculated for display.
"""
pass
class PackageVulnerabilitiesSummary(SummaryResolver):
"""PackageVulnerabilitiesSummary has information about vulnerabilities."""
def __init__(self):
self.__messages = apis.GetMessagesModule('containeranalysis', 'v1alpha1')
self.vulnerabilities = collections.defaultdict(list)
def add_record(self, occ):
sev = str(occ.vulnerabilityDetails.severity)
self.vulnerabilities[sev].append(occ)
def resolve(self):
self.total_vulnerability_found = 0
self.not_fixed_vulnerability_count = 0
for occs in self.vulnerabilities.values():
for occ in occs:
for package_issue in occ.vulnerabilityDetails.packageIssue:
self.total_vulnerability_found += 1
if (package_issue.fixedLocation.version.kind ==
self.__messages.Version.KindValueValuesEnum.MAXIMUM):
self.not_fixed_vulnerability_count += 1
# The gcloud encoder gets confused unless we turn this back into a dict.
self.vulnerabilities = dict(self.vulnerabilities)
class ImageBasesSummary(SummaryResolver):
"""PackageVulnerabilitiesSummary has information about image basis."""
def __init__(self):
self.base_images = []
def add_record(self, occ):
self.base_images.append(occ)
class BuildsSummary(SummaryResolver):
"""BuildsSummary has information about builds."""
def __init__(self):
self.build_details = []
def add_record(self, occ):
self.build_details.append(occ)
class DeploymentsSummary(SummaryResolver):
"""DeploymentsSummary has information about deployments."""
def __init__(self):
self.deployments = []
def add_record(self, occ):
self.deployments.append(occ)
class DiscoverySummary(SummaryResolver):
"""DiscoveryResolver has information about vulnerability discovery."""
def __init__(self):
self.discovery = []
def add_record(self, occ):
self.discovery.append(occ)
class ContainerAndAnalysisData(container_data_util.ContainerData):
"""Class defining container and analysis data.
ContainerAndAnalysisData subclasses ContainerData because we want it to
contain a superset of the attributes, particularly when `--format=json`,
`format=value(digest)`, etc. is used with `container images describe`.
"""
def __init__(self, name):
super(ContainerAndAnalysisData, self).__init__(
registry=name.registry, repository=name.repository, digest=name.digest)
self.package_vulnerability_summary = PackageVulnerabilitiesSummary()
self.image_basis_summary = ImageBasesSummary()
self.build_details_summary = BuildsSummary()
self.deployment_summary = DeploymentsSummary()
self.discovery_summary = DiscoverySummary()
def add_record(self, occurrence):
messages = apis.GetMessagesModule('containeranalysis', 'v1alpha1')
if (occurrence.kind ==
messages.Occurrence.KindValueValuesEnum.PACKAGE_VULNERABILITY):
self.package_vulnerability_summary.add_record(occurrence)
elif occurrence.kind == messages.Occurrence.KindValueValuesEnum.IMAGE_BASIS:
self.image_basis_summary.add_record(occurrence)
elif (occurrence.kind ==
messages.Occurrence.KindValueValuesEnum.BUILD_DETAILS):
self.build_details_summary.add_record(occurrence)
elif (occurrence.kind ==
messages.Occurrence.KindValueValuesEnum.DEPLOYABLE):
self.deployment_summary.add_record(occurrence)
elif (occurrence.kind ==
messages.Occurrence.KindValueValuesEnum.DISCOVERY):
self.discovery_summary.add_record(occurrence)
def resolveSummaries(self):
self.package_vulnerability_summary.resolve()
self.image_basis_summary.resolve()
self.build_details_summary.resolve()
self.deployment_summary.resolve()
self.discovery_summary.resolve()