From 8904133d4ea66e6305c0e07c09ab799f8a8f2d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20=C5=BDitnik?= <anze.zitnik@xlab.si> Date: Tue, 14 Dec 2021 11:49:08 +0100 Subject: [PATCH] Use AssessEvidence instead of StoreEvidence RPC on Clouditor. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some refactoring. Squashed commit of the following: commit 11ae9a48f6b41c2dc5b3e00de1b808b75cc39013 Author: Anže Žitnik <anze.zitnik@xlab.si> Date: Tue Dec 14 11:40:01 2021 +0100 Change CI script: build and test all branches commit fe84541d50ffc6b25d5fff94b1781345ec2b548d Author: Anže Žitnik <anze.zitnik@xlab.si> Date: Tue Dec 14 11:33:07 2021 +0100 Version up commit b99df078408ea2649ce59cd2d17c247c04c6a992 Author: Anže Žitnik <anze.zitnik@xlab.si> Date: Tue Dec 14 11:25:12 2021 +0100 Update dockerignore: add (v)env folder. commit 20944e6743ce112d558fb0205a9347a46c17da8b Author: Anže Žitnik <anze.zitnik@xlab.si> Date: Tue Dec 14 10:56:41 2021 +0100 Refactoring: move all gRPC-generated files to their own package (grpc_gen). commit f4dce9c9076a1336dc7d0b5e15759b24c4f9bea7 Author: Anže Žitnik <anze.zitnik@xlab.si> Date: Tue Dec 14 10:34:05 2021 +0100 Use AssessEvidence instead of StoreEvidence RPC on Clouditor. Added necessary proto files (removed unneeded) and regenerated python code from them. Also added Google APIs dependencies for grpc code generation. Accordingly updated README. Also updated requirements.txt to include some packages for grpc python code generation and for usage of Google APIs. Note that with the call to AssessEvidence, we need to provide an AssessEvidenceRequest object (instead of simply Evidence as before). Most changes of existing code are because of this. --- .dockerignore | 5 +- MANIFEST | 2 +- README.md | 12 +- evidence/evidence_store_pb2.py | 194 --------- evidence/evidence_store_pb2_grpc.py | 140 ------ evidence/generate_evidence.py | 34 -- forward_evidence/forward_evidence.py | 11 +- forward_evidence/generate_evidence.py | 33 ++ grpc_gen/assessment_pb2.py | 379 +++++++++++++++++ grpc_gen/assessment_pb2_grpc.py | 182 ++++++++ {evidence => grpc_gen}/evidence_pb2.py | 0 {evidence => grpc_gen}/evidence_pb2_grpc.py | 0 grpc_gen/metric_pb2.py | 397 ++++++++++++++++++ grpc_gen/metric_pb2_grpc.py | 4 + proto/assessment.proto | 106 +++++ proto/evidence.proto | 26 +- proto/evidence_store.proto | 51 --- proto/google/api/annotations.proto | 31 ++ proto/google/api/http.proto | 375 +++++++++++++++++ proto/metric.proto | 105 +++++ requirements.txt | 34 +- .../wazuh_evidence_collector.py | 19 +- 22 files changed, 1684 insertions(+), 456 deletions(-) delete mode 100644 evidence/evidence_store_pb2.py delete mode 100644 evidence/evidence_store_pb2_grpc.py delete mode 100644 evidence/generate_evidence.py create mode 100644 forward_evidence/generate_evidence.py create mode 100644 grpc_gen/assessment_pb2.py create mode 100644 grpc_gen/assessment_pb2_grpc.py rename {evidence => grpc_gen}/evidence_pb2.py (100%) rename {evidence => grpc_gen}/evidence_pb2_grpc.py (100%) create mode 100644 grpc_gen/metric_pb2.py create mode 100644 grpc_gen/metric_pb2_grpc.py create mode 100644 proto/assessment.proto delete mode 100644 proto/evidence_store.proto create mode 100644 proto/google/api/annotations.proto create mode 100644 proto/google/api/http.proto create mode 100644 proto/metric.proto diff --git a/.dockerignore b/.dockerignore index 5e6c350..fa3b076 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,4 +7,7 @@ dump.rdb .cache .gitignore .gitlab-ci.yml -test/ \ No newline at end of file +test/ +venv/ +env/ + diff --git a/MANIFEST b/MANIFEST index 972b879..6253e91 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,2 +1,2 @@ -VERSION=v0.0.5 +VERSION=v0.0.6 SERVICE=evidence-collector diff --git a/README.md b/README.md index f06663c..1093fcb 100644 --- a/README.md +++ b/README.md @@ -77,15 +77,19 @@ $ ./entrypoint.sh ### Generate gRPC code from `.proto` files ``` -$ pip3 install grpcio-tools -$ python3 -m grpc_tools.protoc --proto_path=proto evidence.proto --python_out=evidence --grpc_python_out=evidence +pip3 install grpcio-tools # (included in requirements.txt) +python3 -m grpc_tools.protoc --proto_path=proto evidence.proto --python_out=grpc_gen --grpc_python_out=grpc_gen +python3 -m grpc_tools.protoc --proto_path=proto assessment.proto --python_out=grpc_gen --grpc_python_out=grpc_gen +python3 -m grpc_tools.protoc --proto_path=proto metric.proto --python_out=grpc_gen --grpc_python_out=grpc_gen ``` -As we are interacting with Clouditor, .proto files are taken from [there](https://github.com/clouditor/clouditor/tree/main/proto). +As we are interacting with Clouditor, .proto files are taken from [there](https://github.com/clouditor/clouditor/tree/main/proto). +Because of dependencies on Google APIs, .proto files in proto/google are taken from [here](https://github.com/googleapis/googleapis/tree/master/google/api). > Note: > since we are running the code as a package, we have to modify imports in newly generated code: -> `import evidence_pb2 as evidence__pb2` --> `import evidence.evidence_pb2 as evidence__pb2` +> `import evidence_pb2 as evidence__pb2` --> `import grpc_gen.evidence_pb2 as evidence__pb2` +> (check all generated files) ### API User authentication diff --git a/evidence/evidence_store_pb2.py b/evidence/evidence_store_pb2.py deleted file mode 100644 index 69bacf0..0000000 --- a/evidence/evidence_store_pb2.py +++ /dev/null @@ -1,194 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: evidence_store.proto -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -import evidence.evidence_pb2 as evidence__pb2 -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='evidence_store.proto', - package='clouditor', - syntax='proto3', - serialized_options=b'Z\014api/evidence', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x14\x65vidence_store.proto\x12\tclouditor\x1a\x0e\x65vidence.proto\x1a\x1bgoogle/protobuf/empty.proto\"\'\n\x15StoreEvidenceResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\"\x16\n\x14ListEvidencesRequest\"?\n\x15ListEvidencesResponse\x12&\n\tevidences\x18\x01 \x03(\x0b\x32\x13.clouditor.Evidence2\xec\x01\n\rEvidenceStore\x12\x46\n\rStoreEvidence\x12\x13.clouditor.Evidence\x1a .clouditor.StoreEvidenceResponse\x12?\n\x0eStoreEvidences\x12\x13.clouditor.Evidence\x1a\x16.google.protobuf.Empty(\x01\x12R\n\rListEvidences\x12\x1f.clouditor.ListEvidencesRequest\x1a .clouditor.ListEvidencesResponseB\x0eZ\x0c\x61pi/evidenceb\x06proto3' - , - dependencies=[evidence__pb2.DESCRIPTOR,google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,]) - - - - -_STOREEVIDENCERESPONSE = _descriptor.Descriptor( - name='StoreEvidenceResponse', - full_name='clouditor.StoreEvidenceResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='status', full_name='clouditor.StoreEvidenceResponse.status', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=80, - serialized_end=119, -) - - -_LISTEVIDENCESREQUEST = _descriptor.Descriptor( - name='ListEvidencesRequest', - full_name='clouditor.ListEvidencesRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=121, - serialized_end=143, -) - - -_LISTEVIDENCESRESPONSE = _descriptor.Descriptor( - name='ListEvidencesResponse', - full_name='clouditor.ListEvidencesResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='evidences', full_name='clouditor.ListEvidencesResponse.evidences', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=145, - serialized_end=208, -) - -_LISTEVIDENCESRESPONSE.fields_by_name['evidences'].message_type = evidence__pb2._EVIDENCE -DESCRIPTOR.message_types_by_name['StoreEvidenceResponse'] = _STOREEVIDENCERESPONSE -DESCRIPTOR.message_types_by_name['ListEvidencesRequest'] = _LISTEVIDENCESREQUEST -DESCRIPTOR.message_types_by_name['ListEvidencesResponse'] = _LISTEVIDENCESRESPONSE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -StoreEvidenceResponse = _reflection.GeneratedProtocolMessageType('StoreEvidenceResponse', (_message.Message,), { - 'DESCRIPTOR' : _STOREEVIDENCERESPONSE, - '__module__' : 'evidence_store_pb2' - # @@protoc_insertion_point(class_scope:clouditor.StoreEvidenceResponse) - }) -_sym_db.RegisterMessage(StoreEvidenceResponse) - -ListEvidencesRequest = _reflection.GeneratedProtocolMessageType('ListEvidencesRequest', (_message.Message,), { - 'DESCRIPTOR' : _LISTEVIDENCESREQUEST, - '__module__' : 'evidence_store_pb2' - # @@protoc_insertion_point(class_scope:clouditor.ListEvidencesRequest) - }) -_sym_db.RegisterMessage(ListEvidencesRequest) - -ListEvidencesResponse = _reflection.GeneratedProtocolMessageType('ListEvidencesResponse', (_message.Message,), { - 'DESCRIPTOR' : _LISTEVIDENCESRESPONSE, - '__module__' : 'evidence_store_pb2' - # @@protoc_insertion_point(class_scope:clouditor.ListEvidencesResponse) - }) -_sym_db.RegisterMessage(ListEvidencesResponse) - - -DESCRIPTOR._options = None - -_EVIDENCESTORE = _descriptor.ServiceDescriptor( - name='EvidenceStore', - full_name='clouditor.EvidenceStore', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=211, - serialized_end=447, - methods=[ - _descriptor.MethodDescriptor( - name='StoreEvidence', - full_name='clouditor.EvidenceStore.StoreEvidence', - index=0, - containing_service=None, - input_type=evidence__pb2._EVIDENCE, - output_type=_STOREEVIDENCERESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='StoreEvidences', - full_name='clouditor.EvidenceStore.StoreEvidences', - index=1, - containing_service=None, - input_type=evidence__pb2._EVIDENCE, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ListEvidences', - full_name='clouditor.EvidenceStore.ListEvidences', - index=2, - containing_service=None, - input_type=_LISTEVIDENCESREQUEST, - output_type=_LISTEVIDENCESRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) -_sym_db.RegisterServiceDescriptor(_EVIDENCESTORE) - -DESCRIPTOR.services_by_name['EvidenceStore'] = _EVIDENCESTORE - -# @@protoc_insertion_point(module_scope) diff --git a/evidence/evidence_store_pb2_grpc.py b/evidence/evidence_store_pb2_grpc.py deleted file mode 100644 index 3f037d7..0000000 --- a/evidence/evidence_store_pb2_grpc.py +++ /dev/null @@ -1,140 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc - -import evidence.evidence_pb2 as evidence__pb2 -import evidence.evidence_store_pb2 as evidence__store__pb2 -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 - - -class EvidenceStoreStub(object): - """Manages the storage of evidences - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.StoreEvidence = channel.unary_unary( - '/clouditor.EvidenceStore/StoreEvidence', - request_serializer=evidence__pb2.Evidence.SerializeToString, - response_deserializer=evidence__store__pb2.StoreEvidenceResponse.FromString, - ) - self.StoreEvidences = channel.stream_unary( - '/clouditor.EvidenceStore/StoreEvidences', - request_serializer=evidence__pb2.Evidence.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.ListEvidences = channel.unary_unary( - '/clouditor.EvidenceStore/ListEvidences', - request_serializer=evidence__store__pb2.ListEvidencesRequest.SerializeToString, - response_deserializer=evidence__store__pb2.ListEvidencesResponse.FromString, - ) - - -class EvidenceStoreServicer(object): - """Manages the storage of evidences - """ - - def StoreEvidence(self, request, context): - """Stores an evidence to the evidence storage - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def StoreEvidences(self, request_iterator, context): - """Stores a stream of evidences to the evidence storage - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def ListEvidences(self, request, context): - """Returns the evidences lying in the evidence storage - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_EvidenceStoreServicer_to_server(servicer, server): - rpc_method_handlers = { - 'StoreEvidence': grpc.unary_unary_rpc_method_handler( - servicer.StoreEvidence, - request_deserializer=evidence__pb2.Evidence.FromString, - response_serializer=evidence__store__pb2.StoreEvidenceResponse.SerializeToString, - ), - 'StoreEvidences': grpc.stream_unary_rpc_method_handler( - servicer.StoreEvidences, - request_deserializer=evidence__pb2.Evidence.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - 'ListEvidences': grpc.unary_unary_rpc_method_handler( - servicer.ListEvidences, - request_deserializer=evidence__store__pb2.ListEvidencesRequest.FromString, - response_serializer=evidence__store__pb2.ListEvidencesResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'clouditor.EvidenceStore', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) - - - # This class is part of an EXPERIMENTAL API. -class EvidenceStore(object): - """Manages the storage of evidences - """ - - @staticmethod - def StoreEvidence(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, '/clouditor.EvidenceStore/StoreEvidence', - evidence__pb2.Evidence.SerializeToString, - evidence__store__pb2.StoreEvidenceResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) - - @staticmethod - def StoreEvidences(request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.stream_unary(request_iterator, target, '/clouditor.EvidenceStore/StoreEvidences', - evidence__pb2.Evidence.SerializeToString, - google_dot_protobuf_dot_empty__pb2.Empty.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) - - @staticmethod - def ListEvidences(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, '/clouditor.EvidenceStore/ListEvidences', - evidence__store__pb2.ListEvidencesRequest.SerializeToString, - evidence__store__pb2.ListEvidencesResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/evidence/generate_evidence.py b/evidence/generate_evidence.py deleted file mode 100644 index 9e0e53c..0000000 --- a/evidence/generate_evidence.py +++ /dev/null @@ -1,34 +0,0 @@ -import json -from evidence.evidence_pb2 import Evidence - -# Used if user doesn't provide other -_default_resource_type = ["VirtualMachine", "Compute", "Resource"] - -def create_resource(id, name, type, property_list): - resource = { - "id": str(id), - "name": str(name), - "type": type if type is not None else _default_resource_type - } - - if property_list is not None: - resource.update(property_list) - - return resource - -def create_evidence(id, service_id, tool_id, raw, resource): - evidence = Evidence() - - evidence.id = str(id) - evidence.timestamp.GetCurrentTime() - evidence.timestamp.nanos = 0 - evidence.service_id = service_id - evidence.tool_id = tool_id - evidence.raw = json.dumps(raw) - evidence.resource.struct_value.update(resource) - - return evidence - -def print_evidence(logger, evidence): - evidence.raw = evidence.raw[:50] + "..." - logger.debug(evidence) \ No newline at end of file diff --git a/forward_evidence/forward_evidence.py b/forward_evidence/forward_evidence.py index bc2d5f5..59ddc12 100644 --- a/forward_evidence/forward_evidence.py +++ b/forward_evidence/forward_evidence.py @@ -1,21 +1,18 @@ -from evidence.evidence_store_pb2_grpc import EvidenceStoreStub -from evidence.evidence_pb2 import Evidence +from grpc_gen.assessment_pb2_grpc import AssessmentStub import grpc class ForwardEvidence(object): def __init__(self, constants, logger): self.channel = grpc.insecure_channel('{}:{}'.format(constants['clouditor']['host'], constants['clouditor']['port'])) - self.stub = EvidenceStoreStub(self.channel) + self.stub = AssessmentStub(self.channel) self.logger = logger - def send_evidence(self, evidence): + def send_evidence(self, assessevidencerequest): try: - response = self.stub.StoreEvidence(evidence) + response = self.stub.AssessEvidence(assessevidencerequest) self.logger.info('gRPC evidence forwarded: ' + str(response)) except grpc.RpcError as err: self.logger.error(err) self.logger.error(err.details()) self.logger.error('{}, {}'.format(err.code().name, err.code().value)) - - diff --git a/forward_evidence/generate_evidence.py b/forward_evidence/generate_evidence.py new file mode 100644 index 0000000..c8a5a6b --- /dev/null +++ b/forward_evidence/generate_evidence.py @@ -0,0 +1,33 @@ +import json +from grpc_gen.assessment_pb2 import AssessEvidenceRequest + +# Used if user doesn't provide other +_default_resource_type = ["VirtualMachine", "Compute", "Resource"] + +def create_resource(id, name, type, property_list): + resource = { + "id": str(id), + "name": str(name), + "type": type if type is not None else _default_resource_type + } + + if property_list is not None: + resource.update(property_list) + + return resource + +def create_assessevidence_request(id, service_id, tool_id, raw, resource): + aer = AssessEvidenceRequest() + aer.evidence.id = str(id) + aer.evidence.timestamp.GetCurrentTime() + aer.evidence.timestamp.nanos = 0 + aer.evidence.service_id = service_id + aer.evidence.tool_id = tool_id + aer.evidence.raw = json.dumps(raw) + aer.evidence.resource.struct_value.update(resource) + + return aer + +def print_evidence(logger, evidence): + evidence.raw = evidence.raw[:50] + "..." + logger.debug(evidence) diff --git a/grpc_gen/assessment_pb2.py b/grpc_gen/assessment_pb2.py new file mode 100644 index 0000000..82565b5 --- /dev/null +++ b/grpc_gen/assessment_pb2.py @@ -0,0 +1,379 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: assessment.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +import grpc_gen.evidence_pb2 as evidence__pb2 +import grpc_gen.metric_pb2 as metric__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='assessment.proto', + package='clouditor', + syntax='proto3', + serialized_options=b'Z\016api/assessment', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x10\x61ssessment.proto\x12\tclouditor\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x0e\x65vidence.proto\x1a\x0cmetric.proto\".\n\x18TriggerAssessmentRequest\x12\x12\n\nsomeOption\x18\x01 \x01(\t\"\x1e\n\x1cListAssessmentResultsRequest\"C\n\x1dListAssessmentResultsResponse\x12\"\n\x07results\x18\x01 \x03(\x0b\x32\x11.clouditor.Result\">\n\x15\x41ssessEvidenceRequest\x12%\n\x08\x65vidence\x18\x01 \x01(\x0b\x32\x13.clouditor.Evidence\"(\n\x16\x41ssessEvidenceResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\"\xe9\x01\n\x06Result\x12\n\n\x02id\x18\x01 \x01(\t\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tmetric_id\x18\x03 \x01(\t\x12\x33\n\x0bmetric_data\x18\x04 \x01(\x0b\x32\x1e.clouditor.MetricConfiguration\x12\x11\n\tcompliant\x18\x05 \x01(\x08\x12\x13\n\x0b\x65vidence_id\x18\x06 \x01(\t\x12\x13\n\x0bresource_id\x18\x07 \x01(\t\x12\x1f\n\x17non_compliance_comments\x18\x08 \x01(\t2\xae\x03\n\nAssessment\x12R\n\x11TriggerAssessment\x12#.clouditor.TriggerAssessmentRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x8d\x01\n\x15ListAssessmentResults\x12\'.clouditor.ListAssessmentResultsRequest\x1a(.clouditor.ListAssessmentResultsResponse\"!\x82\xd3\xe4\x93\x02\x1b\"\x16/v1/assessment/resultsb\x01*\x12z\n\x0e\x41ssessEvidence\x12 .clouditor.AssessEvidenceRequest\x1a!.clouditor.AssessEvidenceResponse\"#\x82\xd3\xe4\x93\x02\x1d\"\x18/v1/assessment/evidencesb\x01*\x12@\n\x0f\x41ssessEvidences\x12\x13.clouditor.Evidence\x1a\x16.google.protobuf.Empty(\x01\x42\x10Z\x0e\x61pi/assessmentb\x06proto3' + , + dependencies=[google_dot_api_dot_annotations__pb2.DESCRIPTOR,google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,evidence__pb2.DESCRIPTOR,metric__pb2.DESCRIPTOR,]) + + + + +_TRIGGERASSESSMENTREQUEST = _descriptor.Descriptor( + name='TriggerAssessmentRequest', + full_name='clouditor.TriggerAssessmentRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='someOption', full_name='clouditor.TriggerAssessmentRequest.someOption', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=153, + serialized_end=199, +) + + +_LISTASSESSMENTRESULTSREQUEST = _descriptor.Descriptor( + name='ListAssessmentResultsRequest', + full_name='clouditor.ListAssessmentResultsRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=201, + serialized_end=231, +) + + +_LISTASSESSMENTRESULTSRESPONSE = _descriptor.Descriptor( + name='ListAssessmentResultsResponse', + full_name='clouditor.ListAssessmentResultsResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='results', full_name='clouditor.ListAssessmentResultsResponse.results', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=233, + serialized_end=300, +) + + +_ASSESSEVIDENCEREQUEST = _descriptor.Descriptor( + name='AssessEvidenceRequest', + full_name='clouditor.AssessEvidenceRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='evidence', full_name='clouditor.AssessEvidenceRequest.evidence', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=302, + serialized_end=364, +) + + +_ASSESSEVIDENCERESPONSE = _descriptor.Descriptor( + name='AssessEvidenceResponse', + full_name='clouditor.AssessEvidenceResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='status', full_name='clouditor.AssessEvidenceResponse.status', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=366, + serialized_end=406, +) + + +_RESULT = _descriptor.Descriptor( + name='Result', + full_name='clouditor.Result', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='clouditor.Result.id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='timestamp', full_name='clouditor.Result.timestamp', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='metric_id', full_name='clouditor.Result.metric_id', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='metric_data', full_name='clouditor.Result.metric_data', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='compliant', full_name='clouditor.Result.compliant', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='evidence_id', full_name='clouditor.Result.evidence_id', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='resource_id', full_name='clouditor.Result.resource_id', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='non_compliance_comments', full_name='clouditor.Result.non_compliance_comments', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=409, + serialized_end=642, +) + +_LISTASSESSMENTRESULTSRESPONSE.fields_by_name['results'].message_type = _RESULT +_ASSESSEVIDENCEREQUEST.fields_by_name['evidence'].message_type = evidence__pb2._EVIDENCE +_RESULT.fields_by_name['timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_RESULT.fields_by_name['metric_data'].message_type = metric__pb2._METRICCONFIGURATION +DESCRIPTOR.message_types_by_name['TriggerAssessmentRequest'] = _TRIGGERASSESSMENTREQUEST +DESCRIPTOR.message_types_by_name['ListAssessmentResultsRequest'] = _LISTASSESSMENTRESULTSREQUEST +DESCRIPTOR.message_types_by_name['ListAssessmentResultsResponse'] = _LISTASSESSMENTRESULTSRESPONSE +DESCRIPTOR.message_types_by_name['AssessEvidenceRequest'] = _ASSESSEVIDENCEREQUEST +DESCRIPTOR.message_types_by_name['AssessEvidenceResponse'] = _ASSESSEVIDENCERESPONSE +DESCRIPTOR.message_types_by_name['Result'] = _RESULT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TriggerAssessmentRequest = _reflection.GeneratedProtocolMessageType('TriggerAssessmentRequest', (_message.Message,), { + 'DESCRIPTOR' : _TRIGGERASSESSMENTREQUEST, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.TriggerAssessmentRequest) + }) +_sym_db.RegisterMessage(TriggerAssessmentRequest) + +ListAssessmentResultsRequest = _reflection.GeneratedProtocolMessageType('ListAssessmentResultsRequest', (_message.Message,), { + 'DESCRIPTOR' : _LISTASSESSMENTRESULTSREQUEST, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.ListAssessmentResultsRequest) + }) +_sym_db.RegisterMessage(ListAssessmentResultsRequest) + +ListAssessmentResultsResponse = _reflection.GeneratedProtocolMessageType('ListAssessmentResultsResponse', (_message.Message,), { + 'DESCRIPTOR' : _LISTASSESSMENTRESULTSRESPONSE, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.ListAssessmentResultsResponse) + }) +_sym_db.RegisterMessage(ListAssessmentResultsResponse) + +AssessEvidenceRequest = _reflection.GeneratedProtocolMessageType('AssessEvidenceRequest', (_message.Message,), { + 'DESCRIPTOR' : _ASSESSEVIDENCEREQUEST, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.AssessEvidenceRequest) + }) +_sym_db.RegisterMessage(AssessEvidenceRequest) + +AssessEvidenceResponse = _reflection.GeneratedProtocolMessageType('AssessEvidenceResponse', (_message.Message,), { + 'DESCRIPTOR' : _ASSESSEVIDENCERESPONSE, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.AssessEvidenceResponse) + }) +_sym_db.RegisterMessage(AssessEvidenceResponse) + +Result = _reflection.GeneratedProtocolMessageType('Result', (_message.Message,), { + 'DESCRIPTOR' : _RESULT, + '__module__' : 'assessment_pb2' + # @@protoc_insertion_point(class_scope:clouditor.Result) + }) +_sym_db.RegisterMessage(Result) + + +DESCRIPTOR._options = None + +_ASSESSMENT = _descriptor.ServiceDescriptor( + name='Assessment', + full_name='clouditor.Assessment', + file=DESCRIPTOR, + index=0, + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_start=645, + serialized_end=1075, + methods=[ + _descriptor.MethodDescriptor( + name='TriggerAssessment', + full_name='clouditor.Assessment.TriggerAssessment', + index=0, + containing_service=None, + input_type=_TRIGGERASSESSMENTREQUEST, + output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='ListAssessmentResults', + full_name='clouditor.Assessment.ListAssessmentResults', + index=1, + containing_service=None, + input_type=_LISTASSESSMENTRESULTSREQUEST, + output_type=_LISTASSESSMENTRESULTSRESPONSE, + serialized_options=b'\202\323\344\223\002\033\"\026/v1/assessment/resultsb\001*', + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='AssessEvidence', + full_name='clouditor.Assessment.AssessEvidence', + index=2, + containing_service=None, + input_type=_ASSESSEVIDENCEREQUEST, + output_type=_ASSESSEVIDENCERESPONSE, + serialized_options=b'\202\323\344\223\002\035\"\030/v1/assessment/evidencesb\001*', + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='AssessEvidences', + full_name='clouditor.Assessment.AssessEvidences', + index=3, + containing_service=None, + input_type=evidence__pb2._EVIDENCE, + output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), +]) +_sym_db.RegisterServiceDescriptor(_ASSESSMENT) + +DESCRIPTOR.services_by_name['Assessment'] = _ASSESSMENT + +# @@protoc_insertion_point(module_scope) diff --git a/grpc_gen/assessment_pb2_grpc.py b/grpc_gen/assessment_pb2_grpc.py new file mode 100644 index 0000000..11ab55b --- /dev/null +++ b/grpc_gen/assessment_pb2_grpc.py @@ -0,0 +1,182 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import grpc_gen.assessment_pb2 as assessment__pb2 +import grpc_gen.evidence_pb2 as evidence__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 + + +class AssessmentStub(object): + """Representing the link between orchestrator and discovery: Assessing evidences + from discovery and sending results to orchestrator + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.TriggerAssessment = channel.unary_unary( + '/clouditor.Assessment/TriggerAssessment', + request_serializer=assessment__pb2.TriggerAssessmentRequest.SerializeToString, + response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + ) + self.ListAssessmentResults = channel.unary_unary( + '/clouditor.Assessment/ListAssessmentResults', + request_serializer=assessment__pb2.ListAssessmentResultsRequest.SerializeToString, + response_deserializer=assessment__pb2.ListAssessmentResultsResponse.FromString, + ) + self.AssessEvidence = channel.unary_unary( + '/clouditor.Assessment/AssessEvidence', + request_serializer=assessment__pb2.AssessEvidenceRequest.SerializeToString, + response_deserializer=assessment__pb2.AssessEvidenceResponse.FromString, + ) + self.AssessEvidences = channel.stream_unary( + '/clouditor.Assessment/AssessEvidences', + request_serializer=evidence__pb2.Evidence.SerializeToString, + response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + ) + + +class AssessmentServicer(object): + """Representing the link between orchestrator and discovery: Assessing evidences + from discovery and sending results to orchestrator + """ + + def TriggerAssessment(self, request, context): + """Triggers the assessment. Part of the private API, + not exposed as REST. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListAssessmentResults(self, request, context): + """TODO(all): Part of public API because external entities (mainly + discoveries) can use it? List the latest set of assessment results. Part of + the public API, also exposed as REST + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AssessEvidence(self, request, context): + """Assesses the evidence sent by discovery. Part of the public API, + also exposed as REST + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AssessEvidences(self, request_iterator, context): + """Assesses stream of evidences coming from the discovery. Part of the public + API, not exposed as REST + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_AssessmentServicer_to_server(servicer, server): + rpc_method_handlers = { + 'TriggerAssessment': grpc.unary_unary_rpc_method_handler( + servicer.TriggerAssessment, + request_deserializer=assessment__pb2.TriggerAssessmentRequest.FromString, + response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + ), + 'ListAssessmentResults': grpc.unary_unary_rpc_method_handler( + servicer.ListAssessmentResults, + request_deserializer=assessment__pb2.ListAssessmentResultsRequest.FromString, + response_serializer=assessment__pb2.ListAssessmentResultsResponse.SerializeToString, + ), + 'AssessEvidence': grpc.unary_unary_rpc_method_handler( + servicer.AssessEvidence, + request_deserializer=assessment__pb2.AssessEvidenceRequest.FromString, + response_serializer=assessment__pb2.AssessEvidenceResponse.SerializeToString, + ), + 'AssessEvidences': grpc.stream_unary_rpc_method_handler( + servicer.AssessEvidences, + request_deserializer=evidence__pb2.Evidence.FromString, + response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'clouditor.Assessment', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class Assessment(object): + """Representing the link between orchestrator and discovery: Assessing evidences + from discovery and sending results to orchestrator + """ + + @staticmethod + def TriggerAssessment(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, '/clouditor.Assessment/TriggerAssessment', + assessment__pb2.TriggerAssessmentRequest.SerializeToString, + google_dot_protobuf_dot_empty__pb2.Empty.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def ListAssessmentResults(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, '/clouditor.Assessment/ListAssessmentResults', + assessment__pb2.ListAssessmentResultsRequest.SerializeToString, + assessment__pb2.ListAssessmentResultsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def AssessEvidence(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, '/clouditor.Assessment/AssessEvidence', + assessment__pb2.AssessEvidenceRequest.SerializeToString, + assessment__pb2.AssessEvidenceResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def AssessEvidences(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_unary(request_iterator, target, '/clouditor.Assessment/AssessEvidences', + evidence__pb2.Evidence.SerializeToString, + google_dot_protobuf_dot_empty__pb2.Empty.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/evidence/evidence_pb2.py b/grpc_gen/evidence_pb2.py similarity index 100% rename from evidence/evidence_pb2.py rename to grpc_gen/evidence_pb2.py diff --git a/evidence/evidence_pb2_grpc.py b/grpc_gen/evidence_pb2_grpc.py similarity index 100% rename from evidence/evidence_pb2_grpc.py rename to grpc_gen/evidence_pb2_grpc.py diff --git a/grpc_gen/metric_pb2.py b/grpc_gen/metric_pb2.py new file mode 100644 index 0000000..433292d --- /dev/null +++ b/grpc_gen/metric_pb2.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: metric.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='metric.proto', + package='clouditor', + syntax='proto3', + serialized_options=b'Z\016api/assessment', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0cmetric.proto\x12\tclouditor\x1a\x1cgoogle/protobuf/struct.proto\"\xc1\x01\n\x06Metric\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61tegory\x18\x04 \x01(\t\x12&\n\x05scale\x18\x05 \x01(\x0e\x32\x17.clouditor.Metric.Scale\x12\x1f\n\x05range\x18\x06 \x01(\x0b\x32\x10.clouditor.Range\"-\n\x05Scale\x12\x0b\n\x07NOMIMAL\x10\x00\x12\x0b\n\x07ORDINAL\x10\x01\x12\n\n\x06METRIC\x10\x02\"\x8d\x01\n\x05Range\x12\x32\n\x0e\x61llowed_values\x18\x01 \x01(\x0b\x32\x18.clouditor.AllowedValuesH\x00\x12!\n\x05order\x18\x02 \x01(\x0b\x32\x10.clouditor.OrderH\x00\x12$\n\x07min_max\x18\x03 \x01(\x0b\x32\x11.clouditor.MinMaxH\x00\x42\x07\n\x05range\"\"\n\x06MinMax\x12\x0b\n\x03min\x18\x01 \x01(\x03\x12\x0b\n\x03max\x18\x02 \x01(\x03\"7\n\rAllowedValues\x12&\n\x06values\x18\x01 \x03(\x0b\x32\x16.google.protobuf.Value\"/\n\x05Order\x12&\n\x06values\x18\x01 \x03(\x0b\x32\x16.google.protobuf.Value\"i\n\x13MetricConfiguration\x12\x10\n\x08operator\x18\x01 \x01(\t\x12,\n\x0ctarget_value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x12\n\nis_default\x18\x03 \x01(\x08\x42\x10Z\x0e\x61pi/assessmentb\x06proto3' + , + dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,]) + + + +_METRIC_SCALE = _descriptor.EnumDescriptor( + name='Scale', + full_name='clouditor.Metric.Scale', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='NOMIMAL', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ORDINAL', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='METRIC', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=206, + serialized_end=251, +) +_sym_db.RegisterEnumDescriptor(_METRIC_SCALE) + + +_METRIC = _descriptor.Descriptor( + name='Metric', + full_name='clouditor.Metric', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='clouditor.Metric.id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', full_name='clouditor.Metric.name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='description', full_name='clouditor.Metric.description', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='category', full_name='clouditor.Metric.category', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='scale', full_name='clouditor.Metric.scale', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='range', full_name='clouditor.Metric.range', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _METRIC_SCALE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=58, + serialized_end=251, +) + + +_RANGE = _descriptor.Descriptor( + name='Range', + full_name='clouditor.Range', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='allowed_values', full_name='clouditor.Range.allowed_values', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='order', full_name='clouditor.Range.order', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='min_max', full_name='clouditor.Range.min_max', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='range', full_name='clouditor.Range.range', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=254, + serialized_end=395, +) + + +_MINMAX = _descriptor.Descriptor( + name='MinMax', + full_name='clouditor.MinMax', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='min', full_name='clouditor.MinMax.min', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='max', full_name='clouditor.MinMax.max', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=397, + serialized_end=431, +) + + +_ALLOWEDVALUES = _descriptor.Descriptor( + name='AllowedValues', + full_name='clouditor.AllowedValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='values', full_name='clouditor.AllowedValues.values', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=433, + serialized_end=488, +) + + +_ORDER = _descriptor.Descriptor( + name='Order', + full_name='clouditor.Order', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='values', full_name='clouditor.Order.values', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=490, + serialized_end=537, +) + + +_METRICCONFIGURATION = _descriptor.Descriptor( + name='MetricConfiguration', + full_name='clouditor.MetricConfiguration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='operator', full_name='clouditor.MetricConfiguration.operator', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='target_value', full_name='clouditor.MetricConfiguration.target_value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_default', full_name='clouditor.MetricConfiguration.is_default', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=539, + serialized_end=644, +) + +_METRIC.fields_by_name['scale'].enum_type = _METRIC_SCALE +_METRIC.fields_by_name['range'].message_type = _RANGE +_METRIC_SCALE.containing_type = _METRIC +_RANGE.fields_by_name['allowed_values'].message_type = _ALLOWEDVALUES +_RANGE.fields_by_name['order'].message_type = _ORDER +_RANGE.fields_by_name['min_max'].message_type = _MINMAX +_RANGE.oneofs_by_name['range'].fields.append( + _RANGE.fields_by_name['allowed_values']) +_RANGE.fields_by_name['allowed_values'].containing_oneof = _RANGE.oneofs_by_name['range'] +_RANGE.oneofs_by_name['range'].fields.append( + _RANGE.fields_by_name['order']) +_RANGE.fields_by_name['order'].containing_oneof = _RANGE.oneofs_by_name['range'] +_RANGE.oneofs_by_name['range'].fields.append( + _RANGE.fields_by_name['min_max']) +_RANGE.fields_by_name['min_max'].containing_oneof = _RANGE.oneofs_by_name['range'] +_ALLOWEDVALUES.fields_by_name['values'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_ORDER.fields_by_name['values'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_METRICCONFIGURATION.fields_by_name['target_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +DESCRIPTOR.message_types_by_name['Metric'] = _METRIC +DESCRIPTOR.message_types_by_name['Range'] = _RANGE +DESCRIPTOR.message_types_by_name['MinMax'] = _MINMAX +DESCRIPTOR.message_types_by_name['AllowedValues'] = _ALLOWEDVALUES +DESCRIPTOR.message_types_by_name['Order'] = _ORDER +DESCRIPTOR.message_types_by_name['MetricConfiguration'] = _METRICCONFIGURATION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Metric = _reflection.GeneratedProtocolMessageType('Metric', (_message.Message,), { + 'DESCRIPTOR' : _METRIC, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.Metric) + }) +_sym_db.RegisterMessage(Metric) + +Range = _reflection.GeneratedProtocolMessageType('Range', (_message.Message,), { + 'DESCRIPTOR' : _RANGE, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.Range) + }) +_sym_db.RegisterMessage(Range) + +MinMax = _reflection.GeneratedProtocolMessageType('MinMax', (_message.Message,), { + 'DESCRIPTOR' : _MINMAX, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.MinMax) + }) +_sym_db.RegisterMessage(MinMax) + +AllowedValues = _reflection.GeneratedProtocolMessageType('AllowedValues', (_message.Message,), { + 'DESCRIPTOR' : _ALLOWEDVALUES, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.AllowedValues) + }) +_sym_db.RegisterMessage(AllowedValues) + +Order = _reflection.GeneratedProtocolMessageType('Order', (_message.Message,), { + 'DESCRIPTOR' : _ORDER, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.Order) + }) +_sym_db.RegisterMessage(Order) + +MetricConfiguration = _reflection.GeneratedProtocolMessageType('MetricConfiguration', (_message.Message,), { + 'DESCRIPTOR' : _METRICCONFIGURATION, + '__module__' : 'metric_pb2' + # @@protoc_insertion_point(class_scope:clouditor.MetricConfiguration) + }) +_sym_db.RegisterMessage(MetricConfiguration) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/grpc_gen/metric_pb2_grpc.py b/grpc_gen/metric_pb2_grpc.py new file mode 100644 index 0000000..2daafff --- /dev/null +++ b/grpc_gen/metric_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/proto/assessment.proto b/proto/assessment.proto new file mode 100644 index 0000000..c3002ac --- /dev/null +++ b/proto/assessment.proto @@ -0,0 +1,106 @@ +/* + * Copyright 2021 Fraunhofer AISEC + * + * 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. + * + * $$\ $$\ $$\ $$\ + * $$ | $$ |\__| $$ | + * $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\ + * $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\ + * $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__| + * $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ | + * \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ | + * \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__| + * + * This file is part of Clouditor Community Edition. + */ +syntax = "proto3"; + +package clouditor; + +import "google/api/annotations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "evidence.proto"; +import "metric.proto"; + +option go_package = "api/assessment"; + +// Representing the link between orchestrator and discovery: Assessing evidences +// from discovery and sending results to orchestrator +service Assessment { + // Triggers the assessment. Part of the private API, + // not exposed as REST. + rpc TriggerAssessment(TriggerAssessmentRequest) + returns (google.protobuf.Empty) {} + + // TODO(all): Part of public API because external entities (mainly + // discoveries) can use it? List the latest set of assessment results. Part of + // the public API, also exposed as REST + rpc ListAssessmentResults(ListAssessmentResultsRequest) + returns (ListAssessmentResultsResponse) { + option (google.api.http) = { + post : "/v1/assessment/results" + response_body : "*" + }; + } + + // Assesses the evidence sent by discovery. Part of the public API, + // also exposed as REST + rpc AssessEvidence(AssessEvidenceRequest) returns (AssessEvidenceResponse) { + option (google.api.http) = { + post : "/v1/assessment/evidences" + response_body : "*" + }; + } + + // Assesses stream of evidences coming from the discovery. Part of the public + // API, not exposed as REST + rpc AssessEvidences(stream Evidence) returns (google.protobuf.Empty); +}; + +message TriggerAssessmentRequest { string someOption = 1; } + +message ListAssessmentResultsRequest {} +message ListAssessmentResultsResponse { repeated Result results = 1; } + +message AssessEvidenceRequest { Evidence evidence = 1; } +message AssessEvidenceResponse { bool status = 1; } + +// A result resource, representing the result after assessing the cloud resource +// with id resource_id. +message Result { + // Assessment result id + string id = 1; + + // Time of assessment + google.protobuf.Timestamp timestamp = 2; + + // Reference to the metric the assessment was based on + string metric_id = 3; + + // Data corresponding to the metric by the given metric id + MetricConfiguration metric_data = 4; + + // Compliant case: true or false + bool compliant = 5; + + // Reference to the assessed evidence + string evidence_id = 6; + + // Reference to the resource of the assessed evidence + string resource_id = 7; + + // Some comments on the reason for non-compliance + string non_compliance_comments = 8; +} diff --git a/proto/evidence.proto b/proto/evidence.proto index 145d767..f1f2585 100644 --- a/proto/evidence.proto +++ b/proto/evidence.proto @@ -37,11 +37,23 @@ option go_package = "api/evidence"; // An evidence resource message Evidence { - string id = 1; // the ID in a uuid format - // TODO: replace with google/type/date.proto timestamp.proto or date.proto? - google.protobuf.Timestamp timestamp = 2; // time of evidence creation - string service_id = 3; // Reference to a service this evidence was gathered from - string tool_id = 4; // Reference to the tool which provided the evidence - string raw = 5; // evidence in its original form without following a defined schema, e.g. the raw JSON - google.protobuf.Value resource = 6; // semantic representation of the Cloud resource according to our defined ontology + // the ID in a uuid format + string id = 1; + + // time of evidence creation + google.protobuf.Timestamp timestamp = 2; + + // Reference to a service this evidence was gathered from + string service_id = 3; + + // Reference to the tool which provided the evidence + string tool_id = 4; + + // Contains the evidence in its original form without following a defined + // schema, e.g. the raw JSON + string raw = 5; + + // Semantic representation of the Cloud resource according to our defined + // ontology + google.protobuf.Value resource = 6; } \ No newline at end of file diff --git a/proto/evidence_store.proto b/proto/evidence_store.proto deleted file mode 100644 index 8181628..0000000 --- a/proto/evidence_store.proto +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2021 Fraunhofer AISEC - * - * 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. - * - * $$\ $$\ $$\ $$\ - * $$ | $$ |\__| $$ | - * $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\ - * $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\ - * $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__| - * $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ | - * \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ | - * \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__| - * - * This file is part of Clouditor Community Edition. - */ - syntax = "proto3"; - - package clouditor; - - import "evidence.proto"; - import "google/protobuf/empty.proto"; - - option go_package = "api/evidence"; - - // Manages the storage of evidences - service EvidenceStore { - // Stores an evidence to the evidence storage - rpc StoreEvidence(Evidence) returns (StoreEvidenceResponse); - - // Stores a stream of evidences to the evidence storage - rpc StoreEvidences(stream Evidence) returns (google.protobuf.Empty); - - // Returns the evidences lying in the evidence storage - rpc ListEvidences(ListEvidencesRequest) returns (ListEvidencesResponse); - } - - message StoreEvidenceResponse { bool status = 1; } - - message ListEvidencesRequest {} - message ListEvidencesResponse { repeated Evidence evidences = 1; } \ No newline at end of file diff --git a/proto/google/api/annotations.proto b/proto/google/api/annotations.proto new file mode 100644 index 0000000..efdab3d --- /dev/null +++ b/proto/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2015 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 google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/proto/google/api/http.proto b/proto/google/api/http.proto new file mode 100644 index 0000000..113fa93 --- /dev/null +++ b/proto/google/api/http.proto @@ -0,0 +1,375 @@ +// Copyright 2015 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 google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/proto/metric.proto b/proto/metric.proto new file mode 100644 index 0000000..f5f0763 --- /dev/null +++ b/proto/metric.proto @@ -0,0 +1,105 @@ +/* + * Copyright 2021 Fraunhofer AISEC + * + * 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. + * + * $$\ $$\ $$\ $$\ + * $$ | $$ |\__| $$ | + * $$$$$$$\ $$ | $$$$$$\ $$\ $$\ $$$$$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\ + * $$ _____|$$ |$$ __$$\ $$ | $$ |$$ __$$ |$$ |\_$$ _| $$ __$$\ $$ __$$\ + * $$ / $$ |$$ / $$ |$$ | $$ |$$ / $$ |$$ | $$ | $$ / $$ |$$ | \__| + * $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$\ $$ | $$ |$$ | + * \$$$$$$\ $$ |\$$$$$ |\$$$$$ |\$$$$$$ |$$ | \$$$ |\$$$$$ |$$ | + * \_______|\__| \______/ \______/ \_______|\__| \____/ \______/ \__| + * + * This file is part of Clouditor Community Edition. + */ +// ToDo(all): Change name of file to resources.proto or similar? (It is not +// containing evidences only) +syntax = "proto3"; + +package clouditor; + +import "google/protobuf/struct.proto"; + +option go_package = "api/assessment"; + +// A metric resource +message Metric { + // Required. The unique identifier of the metric. + string id = 1; + + // Required. The human readable name of the metric. + string name = 2; + + // The description of the metric + string description = 3; + + // The reference to control catalog category or domain + string category = 4; + + // The scale of this metric, e.g. categories, ranked data or metric values. + Scale scale = 5; + + // The range of this metric. Depending on the scale. + Range range = 6; + + // The values a Scale accepts + enum Scale { + NOMIMAL = 0; + ORDINAL = 1; + METRIC = 2; + } +} + +// A range resource representing the range of values +message Range { + // Required. + oneof range { + // used for nominal scale + AllowedValues allowed_values = 1; + + // used for ordinal scale + Order order = 2; + + // used for metric scale + MinMax min_max = 3; + } +} + +// Defines a range of values through a (inclusive) minimum and a maximum +message MinMax { + // Required. + int64 min = 1; + // Required. + int64 max = 2; +} + +// Defines a range +message AllowedValues { repeated google.protobuf.Value values = 1; } + +// Defines a range of values in a pre-defined order from the lowest to the +// highest. +message Order { repeated google.protobuf.Value values = 1; } + +// Defines the operator and a target value for an individual metric +message MetricConfiguration { + // The operator to compare the metric, such as == or > + string operator = 1; + + // The target value + google.protobuf.Value target_value = 2; + + // Whether this configuration is a default configuration + bool is_default = 3; +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 77f9652..fc5e774 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,30 @@ -grpcio==1.41.1 -rq==1.2.2 +cachetools==4.2.4 +certifi==2021.10.8 +charset-normalizer==2.0.9 +click==7.1.2 +configparser==5.1.0 +croniter==1.0.15 elasticsearch==7.13.4 +elasticsearch-dsl==7.4.0 +google-api-core==2.3.0 +google-api-python-client==2.33.0 +google-auth==2.3.3 +google-auth-httplib2==0.1.0 +googleapis-common-protos==1.54.0 +grpcio==1.42.0 +grpcio-tools==1.42.0 +httplib2==0.20.2 +idna==3.3 +protobuf==3.19.1 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 +pyparsing==3.0.6 +python-dateutil==2.8.2 redis==3.3.11 +requests==2.26.0 +rq==1.2.2 +rq-scheduler==0.11.0 +rsa==4.8 +six==1.16.0 +uritemplate==4.1.1 urllib3==1.25.8 -elasticsearch_dsl==7.4.0 -protobuf==3.19.1 -rq_scheduler==0.11.0 -click==7.1.2 -configparser==5.1.0 \ No newline at end of file diff --git a/wazuh_evidence_collector/wazuh_evidence_collector.py b/wazuh_evidence_collector/wazuh_evidence_collector.py index bc6a87a..a24c5c4 100644 --- a/wazuh_evidence_collector/wazuh_evidence_collector.py +++ b/wazuh_evidence_collector/wazuh_evidence_collector.py @@ -3,10 +3,9 @@ from wazuh_evidence_collector.wazuh_client import WazuhClient from elasticsearch import Elasticsearch from elasticsearch_dsl import Search from forward_evidence.forward_evidence import ForwardEvidence -from evidence.generate_evidence import create_resource, create_evidence, print_evidence +from forward_evidence.generate_evidence import create_resource, create_assessevidence_request, print_evidence import uuid import configparser -import logging import logging.config f = open('constants.json',) @@ -61,7 +60,7 @@ def run_collector(): # Get list of all agent ids (including manager's) def get_agents(wc): body = wc.req('GET', 'agents') - + agent_list = [] for agent in body['data']['affected_items']: agent_list.append([agent['id'], agent['name']]) @@ -70,17 +69,17 @@ def run_collector(): body, agent_list = get_agents(wc) - evidence_list = [] + ae_req_list = [] for agent in agent_list: - evidence_list.append(generate_evidence(wc, es, agent)) + ae_req_list.append(generate_evidence(wc, es, agent)) # TODO: - for evidence in evidence_list: - forwarder.send_evidence(evidence) - print_evidence(LOGGER, evidence) + for ae_req in ae_req_list: + forwarder.send_evidence(ae_req) + print_evidence(LOGGER, ae_req.evidence) - return evidence_list + return ae_req_list # Run checks and generate evidence def generate_evidence(wc, es, agent): @@ -204,7 +203,7 @@ def generate_evidence(wc, es, agent): # TODO: change ID resource = create_resource(agent[0], agent[1], None, malware_protection) - return create_evidence(get_id(), "evidence_collector_service", get_tool_id(), raw_evidence, resource) + return create_assessevidence_request(get_id(), "evidence_collector_service", get_tool_id(), raw_evidence, resource) if __name__ == "__main__": main() \ No newline at end of file -- GitLab