def test_poll_discovery_occurrence(self):
        # create discovery occurrence
        note_id = 'discovery-note-{}'.format(uuid.uuid4())
        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        note = {'discovery': {'analysis_kind': NoteKind.DISCOVERY}}
        grafeas_client.\
            create_note(parent=f"projects/{PROJECT_ID}", note_id=note_id, note=note)
        occurrence = {
            'note_name': f"projects/{PROJECT_ID}/notes/{note_id}",
            'resource_uri': self.image_url,
            'discovery': {
                'analysis_status':
                DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS
            }
        }
        created = grafeas_client.\
            create_occurrence(parent=f"projects/{PROJECT_ID}",
                              occurrence=occurrence)

        disc = samples.poll_discovery_finished(self.image_url, 10, PROJECT_ID)
        status = disc.discovery.analysis_status
        assert disc is not None
        assert status == DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS

        # clean up
        samples.delete_occurrence(basename(created.name), PROJECT_ID)
        samples.delete_note(note_id, PROJECT_ID)
def create_occurrence(resource_url, note_id, occurrence_project, note_project):
    """ Creates and returns a new occurrence of a previously
    created vulnerability note."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # note_id = 'my-note'
    # occurrence_project = 'my-gcp-project'
    # note_project = 'my-gcp-project'

    from grafeas.grafeas_v1.gapic.enums import Version
    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    formatted_note = grafeas_client.note_path(note_project, note_id)
    formatted_project = grafeas_client.project_path(occurrence_project)

    occurrence = {
        'note_name': formatted_note,
        'resource_uri': resource_url,
        'vulnerability': {
            'package_issue': [{
                'affected_cpe_uri': 'your-uri-here',
                'affected_package': 'your-package-here',
                'min_affected_version': {
                    'kind': Version.VersionKind.MINIMUM
                },
                'fixed_version': {
                    'kind': Version.VersionKind.MAXIMUM
                }
            }]
        }
    }

    return grafeas_client.create_occurrence(formatted_project, occurrence)
def create_note(note_id, project_id):
    """Creates and returns a new vulnerability note."""
    # note_id = 'my-note'
    # project_id = 'my-gcp-project'

    from grafeas.grafeas_v1.gapic.enums import Version
    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)
    note = {
        'vulnerability': {
            'details': [{
                'affected_cpe_uri': 'your-uri-here',
                'affected_package': 'your-package-here',
                'min_affected_version': {
                    'kind': Version.VersionKind.MINIMUM
                },
                'fixed_version': {
                    'kind': Version.VersionKind.MAXIMUM
                }
            }]
        }
    }
    response = grafeas_client.create_note(project_name, note_id, note)
    return response
    def test_set_iam_policy(self):
        # Setup Expected Response
        version = 351608024
        etag = b"21"
        expected_response = {"version": version, "etag": etag}
        expected_response = policy_pb2.Policy(**expected_response)

        # Mock the API response
        channel = ChannelStub(responses=[expected_response])
        patch = mock.patch("google.api_core.grpc_helpers.create_channel")
        with patch as create_channel:
            create_channel.return_value = channel
            client = containeranalysis_v1.ContainerAnalysisClient()

        # Setup Request
        resource = client.note_path("[PROJECT]", "[NOTE]")
        policy = {}

        response = client.set_iam_policy(resource, policy)
        assert expected_response == response

        assert len(channel.requests) == 1
        expected_request = iam_policy_pb2.SetIamPolicyRequest(
            resource=resource, policy=policy
        )
        actual_request = channel.requests[0][1]
        assert expected_request == actual_request
    def test_test_iam_permissions(self):
        # Setup Expected Response
        expected_response = {}
        expected_response = iam_policy_pb2.TestIamPermissionsResponse(
            **expected_response
        )

        # Mock the API response
        channel = ChannelStub(responses=[expected_response])
        patch = mock.patch("google.api_core.grpc_helpers.create_channel")
        with patch as create_channel:
            create_channel.return_value = channel
            client = containeranalysis_v1.ContainerAnalysisClient()

        # Setup Request
        resource = client.note_path("[PROJECT]", "[NOTE]")
        permissions = []

        response = client.test_iam_permissions(resource, permissions)
        assert expected_response == response

        assert len(channel.requests) == 1
        expected_request = iam_policy_pb2.TestIamPermissionsRequest(
            resource=resource, permissions=permissions
        )
        actual_request = channel.requests[0][1]
        assert expected_request == actual_request
    def test_find_high_severity_vulnerabilities(self):
        occ_list = samples.find_high_severity_vulnerabilities_for_image(
            self.image_url, PROJECT_ID)
        assert len(occ_list) == 0

        # create new high severity vulnerability
        note_id = 'discovery-note-{}'.format(int(time()))
        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        note = {
            'vulnerability': {
                'severity':
                Severity.CRITICAL,
                'details': [{
                    'affected_cpe_uri': 'your-uri-here',
                    'affected_package': 'your-package-here',
                    'min_affected_version': {
                        'kind': Version.VersionKind.MINIMUM
                    },
                    'fixed_version': {
                        'kind': Version.VersionKind.MAXIMUM
                    }
                }]
            }
        }
        grafeas_client.\
            create_note(grafeas_client.project_path(PROJECT_ID), note_id, note)
        occurrence = {
            'note_name': client.note_path(PROJECT_ID, note_id),
            'resource_uri': self.image_url,
            'vulnerability': {
                'package_issue': [{
                    'affected_cpe_uri': 'your-uri-here',
                    'affected_package': 'your-package-here',
                    'min_affected_version': {
                        'kind': Version.VersionKind.MINIMUM
                    },
                    'fixed_version': {
                        'kind': Version.VersionKind.MAXIMUM
                    }
                }]
            }
        }
        created = grafeas_client.\
            create_occurrence(grafeas_client.project_path(PROJECT_ID),
                              occurrence)
        # query again
        tries = 0
        count = 0
        while count != 1 and tries < TRY_LIMIT:
            tries += 1
            occ_list = samples.find_vulnerabilities_for_image(
                self.image_url, PROJECT_ID)
            count = len(occ_list)
            sleep(SLEEP_TIME)
        assert len(occ_list) == 1
        # clean up
        samples.delete_occurrence(basename(created.name), PROJECT_ID)
        samples.delete_note(note_id, PROJECT_ID)
def get_occurrence(occurrence_id, project_id):
    """retrieves and prints a specified occurrence from the server."""
    # occurrence_id = basename(occurrence.name)
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    parent = grafeas_client.occurrence_path(project_id, occurrence_id)
    return grafeas_client.get_occurrence(parent)
def delete_occurrence(occurrence_id, project_id):
    """Removes an existing occurrence from the server."""
    # occurrence_id = basename(occurrence.name)
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    parent = grafeas_client.occurrence_path(project_id, occurrence_id)
    grafeas_client.delete_occurrence(parent)
def get_note(note_id, project_id):
    """Retrieves and prints a specified note from the server."""
    # note_id = 'my-note'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    note_name = grafeas_client.note_path(project_id, note_id)
    response = grafeas_client.get_note(note_name)
    return response
def delete_note(note_id, project_id):
    """Removes an existing note from the server."""
    # note_id = 'my-note'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    note_name = grafeas_client.note_path(project_id, note_id)

    grafeas_client.delete_note(note_name)
    def test_get_iam_policy_exception(self):
        # Mock the API response
        channel = ChannelStub(responses=[CustomException()])
        patch = mock.patch("google.api_core.grpc_helpers.create_channel")
        with patch as create_channel:
            create_channel.return_value = channel
            client = containeranalysis_v1.ContainerAnalysisClient()

        # Setup request
        resource = client.note_path("[PROJECT]", "[NOTE]")

        with pytest.raises(CustomException):
            client.get_iam_policy(resource)
Beispiel #12
0
    def test_set_iam_policy_exception(self):
        # Mock the API response
        channel = ChannelStub(responses=[CustomException()])
        patch = mock.patch("google.api_core.grpc_helpers.create_channel")
        with patch as create_channel:
            create_channel.return_value = channel
            client = containeranalysis_v1.ContainerAnalysisClient()

        # Setup request
        resource = "resource-341064690"
        policy = {}

        with pytest.raises(CustomException):
            client.set_iam_policy(resource, policy)
def find_vulnerabilities_for_image(resource_url, project_id):
    """"Retrieves all vulnerability occurrences associated with a resource."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    filter_str = 'kind="VULNERABILITY" AND resourceUrl="{}"'\
        .format(resource_url)
    return list(grafeas_client.list_occurrences(project_name, filter_str))
def image_vuln_pubsub_handler(event, context):
    #get the Pub/Sub message containing the vulnerability occurrence id
    data = json.loads(base64.b64decode(event['data']).decode('utf-8'))

    #load in environment variables for GCS bucket.  
    bucket_name = os.environ.get("BUCKET_NAME", "Bucket name not set")

    #get the occurrence via the grafeas client
    occurrence_name = (data['name'])
    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    o = grafeas_client.get_occurrence(name=occurrence_name)

    #write to storage
    write_vuln_to_bucket(bucket_name, str(o), str(o.name))
def poll_discovery_finished(resource_url, timeout_seconds, project_id):
    """Returns the discovery occurrence for a resource once it reaches a
    terminal state."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # timeout_seconds = 20
    # project_id = 'my-gcp-project'

    import time
    from grafeas.grafeas_v1 import DiscoveryOccurrence
    from google.cloud.devtools import containeranalysis_v1

    deadline = time.time() + timeout_seconds

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = f"projects/{project_id}"

    discovery_occurrence = None
    while discovery_occurrence is None:
        time.sleep(1)
        filter_str = 'resourceUrl="{}" \
                      AND noteProjectId="goog-analysis" \
                      AND noteId="PACKAGE_VULNERABILITY"'.format(resource_url)
        # [END containeranalysis_poll_discovery_occurrence_finished]
        # The above filter isn't testable, since it looks for occurrences in a
        # locked down project fall back to a more permissive filter for testing
        filter_str = 'kind="DISCOVERY" AND resourceUrl="{}"'\
            .format(resource_url)
        # [START containeranalysis_poll_discovery_occurrence_finished]
        result = grafeas_client.list_occurrences(parent=project_name,
                                                 filter=filter_str)
        # only one occurrence should ever be returned by ListOccurrences
        # and the given filter
        for item in result:
            discovery_occurrence = item
        if time.time() > deadline:
            raise RuntimeError('timeout while retrieving discovery occurrence')

    status = DiscoveryOccurrence.AnalysisStatus.PENDING
    while status != DiscoveryOccurrence.AnalysisStatus.FINISHED_UNSUPPORTED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_FAILED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS:
        time.sleep(1)
        updated = grafeas_client.get_occurrence(name=discovery_occurrence.name)
        status = updated.discovery.analysis_status
        if time.time() > deadline:
            raise RuntimeError('timeout while waiting for terminal state')
    return discovery_occurrence
def get_discovery_info(resource_url, project_id):
    """Retrieves and prints the discovery occurrence created for a specified
    image. The discovery occurrence contains information about the initial
    scan on the image."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    filter_str = 'kind="DISCOVERY" AND resourceUrl="{}"'.format(resource_url)
    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)
    response = grafeas_client.list_occurrences(project_name,
                                               filter_=filter_str)
    for occ in response:
        print(occ)
Beispiel #17
0
def poll_discovery_finished(resource_url, timeout_seconds, project_id):
    """Returns the discovery occurrence for a resource once it reaches a
    terminal state."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # timeout_seconds = 20
    # project_id = 'my-gcp-project'

    import time
    from google.cloud.devtools import containeranalysis_v1

    deadline = time.time() + timeout_seconds

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    discovery_occurrence = None
    while discovery_occurrence is None:
        time.sleep(1)
        sys.stdout.write(".")
        resource_url = get_resource_url(resource_url)
        filter_str = 'resourceUrl="{}" \
                      AND noteProjectId="goog-analysis" \
                      AND noteId="PACKAGE_VULNERABILITY"'.format(resource_url)
        result = grafeas_client.list_occurrences(project_name, filter_str)
        # only one occurrence should ever be returned by ListOccurrences
        # and the given filter
        for item in result:
            discovery_occurrence = item
        if time.time() > deadline:
            raise RuntimeError('timeout while retrieving discovery occurrence')

    status = DiscoveryOccurrence.AnalysisStatus.PENDING
    while status != DiscoveryOccurrence.AnalysisStatus.FINISHED_UNSUPPORTED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_FAILED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS:
        time.sleep(1)
        sys.stdout.write(".")
        updated = grafeas_client.get_occurrence(discovery_occurrence.name)
        status = updated.discovery.analysis_status
        if time.time() > deadline:
            raise RuntimeError('timeout while waiting for terminal state')
    print("")
    return discovery_occurrence
def get_occurrences_for_note(note_id, project_id):
    """Retrieves all the occurrences associated with a specified Note.
    Here, all occurrences are printed and counted."""
    # note_id = 'my-note'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    note_name = grafeas_client.note_path(project_id, note_id)

    response = grafeas_client.list_note_occurrences(note_name)
    count = 0
    for o in response:
        # do something with the retrieved occurrence
        # in this sample, we will simply count each one
        count += 1
    return count
Beispiel #19
0
    def test_poll_discovery_occurrence(self):
        # try with no discovery occurrence
        try:
            samples.poll_discovery_finished(self.image_url, 5, PROJECT_ID)
        except RuntimeError:
            pass
        else:
            # we expect timeout error
            assert False

        # create discovery occurrence
        note_id = 'discovery-note-{}'.format(uuid.uuid4())
        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        note = {
            'discovery': {
                'analysis_kind': NoteKind.DISCOVERY
            }
        }
        grafeas_client.\
            create_note(grafeas_client.project_path(PROJECT_ID), note_id, note)
        occurrence = {
            'note_name': grafeas_client.note_path(PROJECT_ID, note_id),
            'resource_uri': self.image_url,
            'discovery': {
                'analysis_status': DiscoveryOccurrence.AnalysisStatus
                                                      .FINISHED_SUCCESS
            }
        }
        created = grafeas_client.\
            create_occurrence(grafeas_client.project_path(PROJECT_ID),
                              occurrence)

        # poll again
        disc = samples.poll_discovery_finished(self.image_url, 10, PROJECT_ID)
        status = disc.discovery.analysis_status
        assert disc is not None
        assert status == DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS

        # clean up
        samples.delete_occurrence(basename(created.name), PROJECT_ID)
        samples.delete_note(note_id, PROJECT_ID)
def get_occurrences_for_image(resource_url, project_id):
    """Retrieves all the occurrences associated with a specified image.
    Here, all occurrences are simply printed and counted."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    filter_str = 'resourceUrl="{}"'.format(resource_url)
    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    response = grafeas_client.list_occurrences(project_name,
                                               filter_=filter_str)
    count = 0
    for o in response:
        # do something with the retrieved occurrence
        # in this sample, we will simply count each one
        count += 1
    return count
def find_high_severity_vulnerabilities_for_image(resource_url, project_id):
    """Retrieves a list of only high vulnerability occurrences associated
    with a resource."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from grafeas.grafeas_v1.gapic.enums import Severity
    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    filter_str = 'kind="VULNERABILITY" AND resourceUrl="{}"'\
        .format(resource_url)
    vulnerabilities = grafeas_client.list_occurrences(project_name, filter_str)
    filtered_list = []
    for v in vulnerabilities:
        if v.severity == Severity.HIGH or v.severity == Severity.CRITICAL:
            filtered_list.append(v)
    return filtered_list
Beispiel #22
0
def cve_trigger(event, context):
    """Triggered from a message on a Cloud Pub/Sub topic.
    Args:
         event (dict): Event payload.
         context (google.cloud.functions.Context): Metadata for the event.
    """
    pubsub_message = json.loads(base64.b64decode(event['data']).decode('utf-8'))
    print(pubsub_message)
    
    if "VULNERABILITY" in pubsub_message['kind']:
        occurrence_id = os.path.basename(pubsub_message['name'])

        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        parent = grafeas_client.occurrence_path(project_id, occurrence_id)
        occurrence = grafeas_client.get_occurrence(parent)
        if registry in occurrence.resource_uri:
            for i in occurrence.vulnerability.package_issue:
                if i.fixed_package is not None:
                    print("Fix found.  Triggering build.")
                    buildsomething = cloudbuild_v1.CloudBuildClient()
                    buildsomething.run_build_trigger(project_id, trigger_id, {})