Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): add /v1experimental/importfindings/{source} API endpoint for linter findings #2987

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 40 additions & 33 deletions gcp/api/osv_service_v1_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions gcp/api/osv_service_v1_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import google.protobuf.descriptor
import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import osv.importfinding_pb2
import osv.vulnerability_pb2
import sys
import typing
Expand Down Expand Up @@ -203,6 +204,23 @@ class DetermineVersionParameters(google.protobuf.message.Message):

global___DetermineVersionParameters = DetermineVersionParameters

@typing.final
class ImportFindingsParameters(google.protobuf.message.Message):
"""Parameters for ImportFindings."""

DESCRIPTOR: google.protobuf.descriptor.Descriptor

SOURCE_FIELD_NUMBER: builtins.int
source: builtins.str
def __init__(
self,
*,
source: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["source", b"source"]) -> None: ...

global___ImportFindingsParameters = ImportFindingsParameters

@typing.final
class VersionQuery(google.protobuf.message.Message):
"""The version query."""
Expand Down Expand Up @@ -280,6 +298,24 @@ class VersionMatchList(google.protobuf.message.Message):

global___VersionMatchList = VersionMatchList

@typing.final
class ImportFindingList(google.protobuf.message.Message):
"""Result of ImportFindings."""

DESCRIPTOR: google.protobuf.descriptor.Descriptor

INVALID_RECORDS_FIELD_NUMBER: builtins.int
@property
def invalid_records(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[osv.importfinding_pb2.ImportFinding]: ...
def __init__(
self,
*,
invalid_records: collections.abc.Iterable[osv.importfinding_pb2.ImportFinding] | None = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["invalid_records", b"invalid_records"]) -> None: ...

global___ImportFindingList = ImportFindingList

@typing.final
class VersionMatch(google.protobuf.message.Message):
"""Match information for the provided VersionQuery."""
Expand Down
44 changes: 44 additions & 0 deletions gcp/api/osv_service_v1_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def __init__(self, channel):
request_serializer=osv__service__v1__pb2.DetermineVersionParameters.SerializeToString,
response_deserializer=osv__service__v1__pb2.VersionMatchList.FromString,
_registered_method=True)
self.ImportFindings = channel.unary_unary(
'/osv.v1.OSV/ImportFindings',
request_serializer=osv__service__v1__pb2.ImportFindingsParameters.SerializeToString,
response_deserializer=osv__service__v1__pb2.ImportFindingList.FromString,
_registered_method=True)


class OSVServicer(object):
Expand Down Expand Up @@ -98,6 +103,13 @@ def DetermineVersion(self, request, context):
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def ImportFindings(self, request, context):
"""Get import findings per source.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')


def add_OSVServicer_to_server(servicer, server):
rpc_method_handlers = {
Expand All @@ -121,6 +133,11 @@ def add_OSVServicer_to_server(servicer, server):
request_deserializer=osv__service__v1__pb2.DetermineVersionParameters.FromString,
response_serializer=osv__service__v1__pb2.VersionMatchList.SerializeToString,
),
'ImportFindings': grpc.unary_unary_rpc_method_handler(
servicer.ImportFindings,
request_deserializer=osv__service__v1__pb2.ImportFindingsParameters.FromString,
response_serializer=osv__service__v1__pb2.ImportFindingList.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'osv.v1.OSV', rpc_method_handlers)
Expand Down Expand Up @@ -240,3 +257,30 @@ def DetermineVersion(request,
timeout,
metadata,
_registered_method=True)

@staticmethod
def ImportFindings(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/osv.v1.OSV/ImportFindings',
osv__service__v1__pb2.ImportFindingsParameters.SerializeToString,
osv__service__v1__pb2.ImportFindingList.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
27 changes: 27 additions & 0 deletions gcp/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from osv import semver_index
from osv import purl_helpers
from osv import vulnerability_pb2
from osv import importfinding_pb2
from osv.logs import setup_gcp_logging
from gcp.api import osv_service_v1_pb2
from gcp.api import osv_service_v1_pb2_grpc
Expand Down Expand Up @@ -345,6 +346,32 @@ def DetermineVersion(self, request, context: grpc.ServicerContext):
res = determine_version(request.query, context).result()
return res

@ndb_context
@trace_filter.log_trace
def ImportFindings(self, request, context: grpc.ServicerContext):
"""Return a list of `ImportFinding` for a given source."""
source = request.source
# TODO(gongh@): add source check
hogo6002 marked this conversation as resolved.
Show resolved Hide resolved
if not source:
context.abort(grpc.StatusCode.INVALID_ARGUMENT, 'Source is required.')
if get_gcp_project() == _TEST_INSTANCE:
logging.info('Checking import finding for %s\n', source)

query = osv.ImportFinding.query(osv.ImportFinding.source == source)
import_findings: list[osv.ImportFinding] = query.fetch()
invalid_records = []
for finding in import_findings:
invalid_records.append(
importfinding_pb2.ImportFinding(
hogo6002 marked this conversation as resolved.
Show resolved Hide resolved
bug_id=finding.bug_id,
source=finding.source,
findings=finding.findings, # type: ignore
first_seen=finding.first_seen.timestamp_pb(), #type: ignore
last_attempt=finding.last_attempt.timestamp_pb(), #type: ignore
))

return osv_service_v1_pb2.ImportFindingList(invalid_records=invalid_records)

@ndb_context
def Check(self, request, context: grpc.ServicerContext):
"""Health check per the gRPC health check protocol."""
Expand Down
Binary file modified gcp/api/v1/api_descriptor.pb
Binary file not shown.
18 changes: 18 additions & 0 deletions gcp/api/v1/osv_service_v1.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ syntax = "proto3";
package osv.v1;

import "osv/vulnerability.proto";
import "osv/importfinding.proto";
import "google/api/annotations.proto";

// A list of Vulnerability entries.
Expand Down Expand Up @@ -72,6 +73,11 @@ message DetermineVersionParameters {
VersionQuery query = 1;
}

// Parameters for ImportFindings.
message ImportFindingsParameters {
string source = 1;
}

// The version query.
message VersionQuery {
// The name of the dependency. Can be empty.
Expand All @@ -97,6 +103,11 @@ message VersionMatchList {
repeated VersionMatch matches = 1;
}

// Result of ImportFindings.
message ImportFindingList {
repeated osv.ImportFinding invalid_records = 1;
}

// Match information for the provided VersionQuery.
message VersionMatch {
// Score in the interval (0.0, 1.0] with 1.0 being a perfect match.
Expand Down Expand Up @@ -166,4 +177,11 @@ service OSV {
body: "query"
};
}

// Get import findings per source.
rpc ImportFindings(ImportFindingsParameters) returns (ImportFindingList) {
option (google.api.http) = {
get: "/v1/importfindings/{source}"
hogo6002 marked this conversation as resolved.
Show resolved Hide resolved
};
}
}
2 changes: 1 addition & 1 deletion osv/build_protos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@


cd ../
python -m grpc_tools.protoc --python_out=. --mypy_out=. --proto_path=. osv/vulnerability.proto
python -m grpc_tools.protoc --python_out=. --mypy_out=. --proto_path=. osv/*.proto
42 changes: 42 additions & 0 deletions osv/importfinding.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2024 Google LLC
//
// 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.

syntax = "proto3";

package osv;

import "google/protobuf/timestamp.proto";

enum ImportFindingType {
IMPORT_FINDING_TYPE_NONE = 0;
IMPORT_FINDING_TYPE_DELETED = 1;
IMPORT_FINDING_TYPE_INVALID_JSON = 2;
IMPORT_FINDING_TYPE_INVALID_PACKAGE = 3;
IMPORT_FINDING_TYPE_INVALID_PURL = 4;
IMPORT_FINDING_TYPE_INVALID_VERSION = 5;
IMPORT_FINDING_TYPE_INVALID_COMMIT = 6;
IMPORT_FINDING_TYPE_INVALID_RANGE = 7;
IMPORT_FINDING_TYPE_BAD_ALIASED_CVE = 8;
}

// An importfinding entry.
// The protobuf representation is *NOT* stable and only used for implementing
// the JSON based API.
message ImportFinding {
string bug_id = 1;
string source = 2;
repeated ImportFindingType findings = 3;
google.protobuf.Timestamp first_seen = 4;
google.protobuf.Timestamp last_attempt = 5;
}
Loading
Loading