diff --git a/proposals/20190826-grpc-outputs.md b/proposals/20190826-grpc-outputs.md index 3a6308ec9b9..0e2a6c4abbd 100644 --- a/proposals/20190826-grpc-outputs.md +++ b/proposals/20190826-grpc-outputs.md @@ -1,4 +1,4 @@ -# gRPC Falco Output +# Falco gRPC Outputs @@ -25,7 +25,7 @@ An alert is an "output" when it goes over a transport, and it is emitted by Falc At the current moment, however, Falco can deliver alerts in a very basic way, for example by dumping them to standard output. -For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://sysdig.slack.com) if we can find a more consumable way to implement Falco outputs in an extensible way. +For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://slack.k8s.io) if we can find a more consumable way to implement Falco outputs in an extensible way. The motivation behind this proposal is to design a new output implementation that can meet our user's needs. @@ -39,7 +39,10 @@ The motivation behind this proposal is to design a new output implementation tha - To continue supporting the old output formats by implementing their same interface - To be secure by default (**mutual TLS** authentication) - To be **asynchronous** and **non-blocking** -- To implement a Go SDK +- To provide a connection over unix socket (no authentication) +- To implement a Go client +- To implement a Rust client +- To implement a Python client ### Non-Goals @@ -77,26 +80,25 @@ syntax = "proto3"; import "google/protobuf/timestamp.proto"; import "schema.proto"; -package falco.output; +package falco.outputs; -option go_package = "github.com/falcosecurity/client-go/pkg/api/output"; +option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs"; -// The `subscribe` service defines the RPC call -// to perform an output `request` which will lead to obtain an output `response`. +// This service defines the RPC methods +// to `request` a stream of output `response`s. service service { - rpc subscribe(request) returns (stream response); + // Subscribe to a stream of Falco outputs by sending a stream of requests. + rpc sub(stream request) returns (stream response); + // Get all the Falco outputs present in the system up to this call. + rpc get(request) returns (stream response); } // The `request` message is the logical representation of the request model. -// It is the input of the `subscribe` service. -// It is used to configure the kind of subscription to the gRPC streaming server. +// It is the input of the `output.service` service. message request { - bool keepalive = 1; - // string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference. - // repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference. } -// The `response` message is the logical representation of the output model. +// The `response` message is the representation of the output model. // It contains all the elements that Falco emits in an output along with the // definitions for priorities and source. message response { @@ -106,7 +108,7 @@ message response { string rule = 4; string output = 5; map output_fields = 6; - // repeated string tags = 7; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference + string hostname = 7; } ``` diff --git a/userspace/falco/CMakeLists.txt b/userspace/falco/CMakeLists.txt index afe3a339efd..e45f1e43e47 100644 --- a/userspace/falco/CMakeLists.txt +++ b/userspace/falco/CMakeLists.txt @@ -19,23 +19,24 @@ add_custom_command( ${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h ${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/version.pb.h - ${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc - ${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.h - ${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc - ${CMAKE_CURRENT_BINARY_DIR}/output.pb.h + ${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h + ${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h ${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h - COMMENT "Generate gRPC version API" + COMMENT "Generate gRPC API" + # Falco gRPC Version API DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} ${CMAKE_CURRENT_SOURCE_DIR}/version.proto - COMMENT "Generate gRPC outputs API" - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/output.proto - COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/output.proto + # Falco gRPC Outputs API + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto + COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto ${CMAKE_CURRENT_SOURCE_DIR}/schema.proto COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} - ${CMAKE_CURRENT_SOURCE_DIR}/output.proto + ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_executable( @@ -54,8 +55,8 @@ add_executable( grpc_server.cpp ${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc - ${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc - ${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc) add_dependencies(falco civetweb string-view-lite) diff --git a/userspace/falco/falco_outputs.cpp b/userspace/falco/falco_outputs.cpp index 36bbb27dc1b..450d0c9e45c 100644 --- a/userspace/falco/falco_outputs.cpp +++ b/userspace/falco/falco_outputs.cpp @@ -22,11 +22,10 @@ limitations under the License. #include "formats.h" #include "logger.h" -#include "falco_output_queue.h" +#include "falco_outputs_queue.h" #include "banned.h" // This raises a compilation error when certain functions are used using namespace std; -using namespace falco::output; const static struct luaL_reg ll_falco_outputs [] = { @@ -316,7 +315,7 @@ int falco_outputs::handle_grpc(lua_State *ls) lua_error(ls); } - response grpc_res = response(); + falco::outputs::response grpc_res; // time gen_event *evt = (gen_event *)lua_topointer(ls, 1); @@ -366,7 +365,7 @@ int falco_outputs::handle_grpc(lua_State *ls) auto host = grpc_res.mutable_hostname(); *host = (char *)lua_tostring(ls, 7); - falco::output::queue::get().push(grpc_res); + falco::outputs::queue::get().push(grpc_res); return 1; } diff --git a/userspace/falco/falco_output_queue.h b/userspace/falco/falco_outputs_queue.h similarity index 96% rename from userspace/falco/falco_output_queue.h rename to userspace/falco/falco_outputs_queue.h index 2e57001aa44..26c1e041e8d 100644 --- a/userspace/falco/falco_output_queue.h +++ b/userspace/falco/falco_outputs_queue.h @@ -16,12 +16,12 @@ limitations under the License. #pragma once -#include "output.pb.h" +#include "outputs.pb.h" #include "tbb/concurrent_queue.h" namespace falco { -namespace output +namespace outputs { typedef tbb::concurrent_queue response_cq; diff --git a/userspace/falco/grpc_context.h b/userspace/falco/grpc_context.h index 2278479046b..1320d41d430 100644 --- a/userspace/falco/grpc_context.h +++ b/userspace/falco/grpc_context.h @@ -36,7 +36,7 @@ class context { public: context(::grpc::ServerContext* ctx); - ~context() = default; + virtual ~context() = default; void get_metadata(std::string key, std::string& val); @@ -50,7 +50,7 @@ class stream_context : public context public: stream_context(::grpc::ServerContext* ctx): context(ctx){}; - ~stream_context() = default; + virtual ~stream_context() = default; enum : char { @@ -61,6 +61,15 @@ class stream_context : public context mutable void* m_stream = nullptr; // todo(fntlnz, leodido) > useful in the future mutable bool m_has_more = false; + mutable bool m_is_running = true; +}; + +class bidi_context : public stream_context +{ +public: + bidi_context(::grpc::ServerContext* ctx): + stream_context(ctx){}; + virtual ~bidi_context() = default; }; } // namespace grpc diff --git a/userspace/falco/grpc_request_context.cpp b/userspace/falco/grpc_request_context.cpp index 50970345e32..194fb442975 100644 --- a/userspace/falco/grpc_request_context.cpp +++ b/userspace/falco/grpc_request_context.cpp @@ -24,12 +24,12 @@ namespace grpc { template<> -void request_stream_context::start(server* srv) +void request_stream_context::start(server* srv) { m_state = request_context_base::REQUEST; m_srv_ctx.reset(new ::grpc::ServerContext); auto srvctx = m_srv_ctx.get(); - m_res_writer.reset(new ::grpc::ServerAsyncWriter(srvctx)); + m_res_writer.reset(new ::grpc::ServerAsyncWriter(srvctx)); m_stream_ctx.reset(); m_req.Clear(); auto cq = srv->m_completion_queue.get(); @@ -38,7 +38,7 @@ void request_stream_context -void request_stream_context::process(server* srv) +void request_stream_context::process(server* srv) { // When it is the 1st process call if(m_state == request_context_base::REQUEST) @@ -48,40 +48,46 @@ void request_stream_context*m_process_func)(*m_stream_ctx, m_req, res); // subscribe() + outputs::response res; + (srv->*m_process_func)(*m_stream_ctx, m_req, res); // get() + + if(!m_stream_ctx->m_is_running) + { + m_state = request_context_base::FINISH; + m_res_writer->Finish(::grpc::Status::OK, this); + return; + } // When there are still more responses to stream if(m_stream_ctx->m_has_more) { // todo(leodido) > log "write: tag=this, state=m_state" m_res_writer->Write(res, this); + return; } + // No more responses to stream - else - { - // Communicate to the gRPC runtime that we have finished. - // The memory address of "this" instance uniquely identifies the event. - m_state = request_context_base::FINISH; - // todo(leodido) > log "finish: tag=this, state=m_state" - m_res_writer->Finish(::grpc::Status::OK, this); - } + // Communicate to the gRPC runtime that we have finished. + // The memory address of "this" instance uniquely identifies the event. + m_state = request_context_base::FINISH; + // todo(leodido) > log "finish: tag=this, state=m_state" + m_res_writer->Finish(::grpc::Status::OK, this); } template<> -void request_stream_context::end(server* srv, bool errored) +void request_stream_context::end(server* srv, bool error) { if(m_stream_ctx) { - if(errored) + if(error) { // todo(leodido) > log error "error streaming: tag=this, state=m_state, stream=m_stream_ctx->m_stream" } - m_stream_ctx->m_status = errored ? stream_context::ERROR : stream_context::SUCCESS; + m_stream_ctx->m_status = error ? stream_context::ERROR : stream_context::SUCCESS; // Complete the processing - output::response res; - (srv->*m_process_func)(*m_stream_ctx, m_req, res); // subscribe() + outputs::response res; + (srv->*m_process_func)(*m_stream_ctx, m_req, res); // get() } else { @@ -98,7 +104,7 @@ void request_stream_context -void falco::grpc::request_context::start(server* srv) +void request_context::start(server* srv) { m_state = request_context_base::REQUEST; m_srv_ctx.reset(new ::grpc::ServerContext); @@ -113,7 +119,7 @@ void falco::grpc::request_context -void falco::grpc::request_context::process(server* srv) +void request_context::process(server* srv) { version::response res; (srv->*m_process_func)(m_srv_ctx.get(), m_req, res); @@ -125,13 +131,85 @@ void falco::grpc::request_context -void falco::grpc::request_context::end(server* srv, bool errored) +void request_context::end(server* srv, bool error) { // todo(leodido) > handle processing errors here - + // Ask to start processing requests start(srv); } +template<> +void request_bidi_context::start(server* srv) +{ + m_state = request_context_base::REQUEST; + m_srv_ctx.reset(new ::grpc::ServerContext); + auto srvctx = m_srv_ctx.get(); + m_reader_writer.reset(new ::grpc::ServerAsyncReaderWriter(srvctx)); + m_req.Clear(); + auto cq = srv->m_completion_queue.get(); + // Request to start processing given requests. + // Using "this" - ie., the memory address of this context - as the tag that uniquely identifies the request. + // In this way, different contexts can serve different requests concurrently. + (srv->m_output_svc.*m_request_func)(srvctx, m_reader_writer.get(), cq, cq, this); +}; + +template<> +void request_bidi_context::process(server* srv) +{ + switch(m_state) + { + case request_context_base::REQUEST: + m_bidi_ctx.reset(new bidi_context(m_srv_ctx.get())); + m_bidi_ctx->m_status = bidi_context::STREAMING; + m_state = request_context_base::WRITE; + m_reader_writer->Read(&m_req, this); + return; + case request_context_base::WRITE: + // Processing + { + outputs::response res; + (srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub() + + if(!m_bidi_ctx->m_is_running) + { + m_state = request_context_base::FINISH; + m_reader_writer->Finish(::grpc::Status::OK, this); + return; + } + + if(m_bidi_ctx->m_has_more) + { + m_state = request_context_base::WRITE; + m_reader_writer->Write(res, this); + return; + } + + m_state = request_context_base::WRITE; + m_reader_writer->Read(&m_req, this); + } + + return; + default: + return; + } +}; + +template<> +void request_bidi_context::end(server* srv, bool error) +{ + if(m_bidi_ctx) + { + m_bidi_ctx->m_status = error ? bidi_context::ERROR : bidi_context::SUCCESS; + + // Complete the processing + outputs::response res; + (srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub() + } + + // Ask to start processing requests + start(srv); +}; + } // namespace grpc -} // namespace falco \ No newline at end of file +} // namespace falco diff --git a/userspace/falco/grpc_request_context.h b/userspace/falco/grpc_request_context.h index 8a0174e4d14..1b4878ecd09 100644 --- a/userspace/falco/grpc_request_context.h +++ b/userspace/falco/grpc_request_context.h @@ -29,7 +29,8 @@ class request_context_base { public: request_context_base() = default; - ~request_context_base() = default; + // virtual to guarantee that the derived classes are destructed properly + virtual ~request_context_base() = default; std::unique_ptr<::grpc::ServerContext> m_srv_ctx; enum : char @@ -39,6 +40,7 @@ class request_context_base WRITE, FINISH } m_state = UNKNOWN; + virtual void start(server* srv) = 0; virtual void process(server* srv) = 0; virtual void end(server* srv, bool isError) = 0; @@ -63,7 +65,7 @@ class request_stream_context : public request_context_base void start(server* srv); void process(server* srv); - void end(server* srv, bool isError); + void end(server* srv, bool error); private: std::unique_ptr<::grpc::ServerAsyncWriter> m_res_writer; @@ -90,11 +92,37 @@ class request_context : public request_context_base void start(server* srv); void process(server* srv); - void end(server* srv, bool isError); + void end(server* srv, bool error); private: std::unique_ptr<::grpc::ServerAsyncResponseWriter> m_res_writer; Request m_req; }; + +template +class request_bidi_context : public request_context_base +{ +public: + request_bidi_context(): + m_process_func(nullptr), + m_request_func(nullptr){}; + ~request_bidi_context() = default; + + // Pointer to function that does actual processing + void (server::*m_process_func)(const bidi_context&, const Request&, Response&); + + // Pointer to function that requests the system to start processing given requests + void (Service::AsyncService::*m_request_func)(::grpc::ServerContext*, ::grpc::ServerAsyncReaderWriter*, ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*); + + void start(server* srv); + void process(server* srv); + void end(server* srv, bool error); + +private: + std::unique_ptr<::grpc::ServerAsyncReaderWriter> m_reader_writer; + std::unique_ptr m_bidi_ctx; + Request m_req; +}; + } // namespace grpc -} // namespace falco \ No newline at end of file +} // namespace falco diff --git a/userspace/falco/grpc_server.cpp b/userspace/falco/grpc_server.cpp index b337f1f7831..920c5920c52 100644 --- a/userspace/falco/grpc_server.cpp +++ b/userspace/falco/grpc_server.cpp @@ -44,6 +44,15 @@ limitations under the License. c.start(this); \ } +#define REGISTER_BIDI(req, res, svc, rpc, impl, num) \ + std::vector> rpc##_contexts(num); \ + for(request_bidi_context & c : rpc##_contexts) \ + { \ + c.m_process_func = &server::impl; \ + c.m_request_func = &svc::AsyncService::Request##rpc; \ + c.start(this); \ + } + static void gpr_log_dispatcher_func(gpr_log_func_args* args) { int priority; @@ -60,7 +69,10 @@ static void gpr_log_dispatcher_func(gpr_log_func_args* args) break; } - falco_logger::log(priority, args->message); + string copy = "grpc: "; + copy.append(args->message); + copy.push_back('\n'); + falco_logger::log(priority, copy); } void falco::grpc::server::thread_process(int thread_index) @@ -199,7 +211,8 @@ void falco::grpc::server::run() // todo(leodido) > take a look at thread_stress_test.cc into grpc repository REGISTER_UNARY(version::request, version::response, version::service, version, version, context_num) - REGISTER_STREAM(output::request, output::response, output::service, subscribe, subscribe, context_num) + REGISTER_STREAM(outputs::request, outputs::response, outputs::service, get, get, context_num) + REGISTER_BIDI(outputs::request, outputs::response, outputs::service, sub, sub, context_num) m_threads.resize(m_threadiness); int thread_idx = 0; @@ -211,7 +224,7 @@ void falco::grpc::server::run() while(server_impl::is_running()) { - sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // todo(leodido) > log "stopping gRPC server" stop(); diff --git a/userspace/falco/grpc_server.h b/userspace/falco/grpc_server.h index 9f24b65170a..ced4020f097 100644 --- a/userspace/falco/grpc_server.h +++ b/userspace/falco/grpc_server.h @@ -44,7 +44,7 @@ class server : public server_impl void run(); void stop(); - output::service::AsyncService m_output_svc; + outputs::service::AsyncService m_output_svc; version::service::AsyncService m_version_svc; std::unique_ptr<::grpc::ServerCompletionQueue> m_completion_queue; diff --git a/userspace/falco/grpc_server_impl.cpp b/userspace/falco/grpc_server_impl.cpp index cf027bd72cf..bda1656a0b1 100644 --- a/userspace/falco/grpc_server_impl.cpp +++ b/userspace/falco/grpc_server_impl.cpp @@ -16,7 +16,8 @@ limitations under the License. #include "config_falco.h" #include "grpc_server_impl.h" -#include "falco_output_queue.h" +#include "falco_outputs_queue.h" +#include "logger.h" #include "banned.h" // This raises a compilation error when certain functions are used bool falco::grpc::server_impl::is_running() @@ -28,29 +29,39 @@ bool falco::grpc::server_impl::is_running() return true; } -void falco::grpc::server_impl::subscribe(const stream_context& ctx, const output::request& req, output::response& res) +void falco::grpc::server_impl::get(const stream_context& ctx, const outputs::request& req, outputs::response& res) { if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR) { // todo(leodido) > log "status=ctx->m_status, stream=ctx->m_stream" ctx.m_stream = nullptr; + return; } - else + + ctx.m_is_running = is_running(); + + // Start or continue streaming + // m_status == stream_context::STREAMING? + // todo(leodido) > set m_stream + + ctx.m_has_more = outputs::queue::get().try_pop(res); +} + +void falco::grpc::server_impl::sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res) +{ + if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR) { - // Start or continue streaming - // todo(leodido) > check for m_status == stream_context::STREAMING? - // todo(leodido) > set m_stream - if(output::queue::get().try_pop(res) && !req.keepalive()) - { - ctx.m_has_more = true; - return; - } - while(is_running() && !output::queue::get().try_pop(res) && req.keepalive()) - { - } - - ctx.m_has_more = !is_running() ? false : req.keepalive(); + ctx.m_stream = nullptr; + return; } + + ctx.m_is_running = is_running(); + + // Start or continue streaming + // m_status == stream_context::STREAMING? + // todo(leodido) > set m_stream + + ctx.m_has_more = outputs::queue::get().try_pop(res); } void falco::grpc::server_impl::version(const context& ctx, const version::request&, version::response& res) diff --git a/userspace/falco/grpc_server_impl.h b/userspace/falco/grpc_server_impl.h index c6b93a88e1b..f6ac1dcee6a 100644 --- a/userspace/falco/grpc_server_impl.h +++ b/userspace/falco/grpc_server_impl.h @@ -17,7 +17,7 @@ limitations under the License. #pragma once #include -#include "output.grpc.pb.h" +#include "outputs.grpc.pb.h" #include "version.grpc.pb.h" #include "grpc_context.h" @@ -36,8 +36,11 @@ class server_impl protected: bool is_running(); - void subscribe(const stream_context& ctx, const output::request& req, output::response& res); + // Outputs + void get(const stream_context& ctx, const outputs::request& req, outputs::response& res); + void sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res); + // Version void version(const context& ctx, const version::request& req, version::response& res); private: diff --git a/userspace/falco/output.proto b/userspace/falco/output.proto deleted file mode 100644 index d4058c7c7ff..00000000000 --- a/userspace/falco/output.proto +++ /dev/null @@ -1,40 +0,0 @@ -syntax = "proto3"; - -import "google/protobuf/timestamp.proto"; -import "schema.proto"; - -package falco.output; - -option go_package = "github.com/falcosecurity/client-go/pkg/api/output"; - -// The `subscribe` service defines the RPC call -// to perform an output `request` which will lead to obtain an output `response`. -service service { - rpc subscribe(request) returns (stream response); -} - -// The `request` message is the logical representation of the request model. -// It is the input of the `subscribe` service. -// It is used to configure the kind of subscription to the gRPC streaming server. -// -// By default the request asks to the server to only receive the accumulated events. -// In case you want to wait indefinitely for new events to come set the keepalive option to true. -message request { - bool keepalive = 1; - // string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference. - // repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference. -} - -// The `response` message is the logical representation of the output model. -// It contains all the elements that Falco emits in an output along with the -// definitions for priorities and source. -message response { - google.protobuf.Timestamp time = 1; - falco.schema.priority priority = 2; - falco.schema.source source = 3; - string rule = 4; - string output = 5; - map output_fields = 6; - string hostname = 7; - // repeated string tags = 8; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference -} diff --git a/userspace/falco/outputs.proto b/userspace/falco/outputs.proto new file mode 100644 index 00000000000..43d16ef213e --- /dev/null +++ b/userspace/falco/outputs.proto @@ -0,0 +1,55 @@ +/* +Copyright (C) 2020 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; +import "schema.proto"; + +package falco.outputs; + +option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs"; + +// This service defines the RPC methods +// to `request` a stream of output `response`s. +service service { + // Subscribe to a stream of Falco outputs by sending a stream of requests. + rpc sub(stream request) returns (stream response); + // Get all the Falco outputs present in the system up to this call. + rpc get(request) returns (stream response); +} + +// The `request` message is the logical representation of the request model. +// It is the input of the `output.service` service. +message request { + // TODO(leodido,fntlnz): tags not supported yet, keeping it for reference. + // repeated string tags = 1; +} + +// The `response` message is the representation of the output model. +// It contains all the elements that Falco emits in an output along with the +// definitions for priorities and source. +message response { + google.protobuf.Timestamp time = 1; + falco.schema.priority priority = 2; + falco.schema.source source = 3; + string rule = 4; + string output = 5; + map output_fields = 6; + string hostname = 7; + // TODO(leodido,fntlnz): tags not supported yet, keeping it for reference. + // repeated string tags = 8; +} \ No newline at end of file diff --git a/userspace/falco/schema.proto b/userspace/falco/schema.proto index bcd90f514c7..b57ebff867e 100644 --- a/userspace/falco/schema.proto +++ b/userspace/falco/schema.proto @@ -1,3 +1,19 @@ +/* +Copyright (C) 2020 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + syntax = "proto3"; package falco.schema; diff --git a/userspace/falco/version.proto b/userspace/falco/version.proto index 3f0d99ec2ca..97896543c25 100644 --- a/userspace/falco/version.proto +++ b/userspace/falco/version.proto @@ -1,3 +1,19 @@ +/* +Copyright (C) 2020 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + syntax = "proto3"; package falco.version;