diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..79d29358 --- /dev/null +++ b/.clang-format @@ -0,0 +1,16 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -8 +BreakBeforeBraces: Allman +BreakConstructorInitializers: AfterColon +ColumnLimit: 80 +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +DerivePointerAlignment: true +IndentWidth: 4 +SortIncludes: Never +SpaceAfterTemplateKeyword: false +SpaceBeforeCtorInitializerColon: false +SpaceBeforeParens: Never +UseTab: Never diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1fa4b7f7..0ec135e0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,7 +9,7 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: "Golang CodeQL" on: push: @@ -37,8 +37,6 @@ jobs: strategy: fail-fast: false - matrix: - language: [ 'cpp', 'go' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed @@ -55,7 +53,7 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: - languages: ${{ matrix.language }} + languages: go # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. diff --git a/.github/workflows/dummy_c-ci.yaml b/.github/workflows/dummy_c-ci.yaml new file mode 100644 index 00000000..40bd5d64 --- /dev/null +++ b/.github/workflows/dummy_c-ci.yaml @@ -0,0 +1,56 @@ +name: Build dummy_c plugin +on: + pull_request: + branches: [ master ] + paths: + - 'plugins/dummy_c/**' + push: + branches: [ master ] + paths: + - 'plugins/dummy_c/**' + workflow_dispatch: + +# Checks if any concurrent jobs under the same pull request or branch are being executed +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + name: build + runs-on: ubuntu-22.04 + steps: + - name: Checkout ⤵️ + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Install deps ⛓️ + run: | + sudo apt update -y + sudo apt install -y --no-install-recommends build-essential + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: cpp + + - name: Build dummy_c plugin 🏗️ + run: | + cd plugins/dummy_c + make libdummy_c.so + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + + formatting-check: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Run clang-format style check + uses: jidicula/clang-format-action@f62da5e3d3a2d88ff364771d9d938773a618ab5e #v4.11.0 + with: + clang-format-version: '14' + check-path: plugins/dummy_c diff --git a/plugins/dummy_c/dummy.cpp b/plugins/dummy_c/dummy.cpp index 3a687b30..c1dda748 100644 --- a/plugins/dummy_c/dummy.cpp +++ b/plugins/dummy_c/dummy.cpp @@ -6,7 +6,7 @@ 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 + 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, @@ -31,196 +31,209 @@ limitations under the License. class dummy_source { -public: - virtual ~dummy_source() = default; - - dummy_source(uint64_t max_evts, uint64_t start, uint64_t jitter) : m_event_count(0), - m_max_evts(max_evts), - m_sample_value(start), - m_jitter(jitter), - m_enc() - { - } - - falcosecurity::result_code next_event(falcosecurity::event_writer &evt) - { - if (m_event_count >= m_max_evts) - { - return falcosecurity::result_code::SS_PLUGIN_EOF; - } - m_event_count++; - - // Increment sample by 1, also add a jitter of [0:jitter] - m_sample_value += 1 + (random() % (m_jitter + 1)); - - // we will memcpy the content of `m_sample_value` inside `m_enc.encode`. - m_enc.set_data((void *)&m_sample_value, sizeof(uint64_t)); - m_enc.encode(evt); - return falcosecurity::result_code::SS_PLUGIN_SUCCESS; - } - -private: - uint64_t m_event_count; - uint64_t m_max_evts; - uint64_t m_sample_value; - uint64_t m_jitter; - falcosecurity::events::pluginevent_e_encoder m_enc; + public: + virtual ~dummy_source() = default; + + dummy_source(uint64_t max_evts, uint64_t start, uint64_t jitter): + m_event_count(0), m_max_evts(max_evts), m_sample_value(start), + m_jitter(jitter), m_enc() + { + } + + falcosecurity::result_code next_event(falcosecurity::event_writer &evt) + { + if(m_event_count >= m_max_evts) + { + return falcosecurity::result_code::SS_PLUGIN_EOF; + } + m_event_count++; + + // Increment sample by 1, also add a jitter of [0:jitter] + m_sample_value += 1 + (random() % (m_jitter + 1)); + + // we will memcpy the content of `m_sample_value` inside `m_enc.encode`. + m_enc.set_data((void *)&m_sample_value, sizeof(uint64_t)); + m_enc.encode(evt); + return falcosecurity::result_code::SS_PLUGIN_SUCCESS; + } + + private: + uint64_t m_event_count; + uint64_t m_max_evts; + uint64_t m_sample_value; + uint64_t m_jitter; + falcosecurity::events::pluginevent_e_encoder m_enc; }; class dummy { -public: - virtual ~dummy() = default; - - std::string get_name() { return PLUGIN_NAME; } - - std::string get_version() { return PLUGIN_VERSION; } - - std::string get_description() { return PLUGIN_DESCRIPTION; } - - std::string get_contact() { return PLUGIN_CONTACT; } - - uint32_t get_id() { return PLUGIN_ID; }; - - std::string get_event_source() { return PLUGIN_SOURCE_NAME; } - - std::string get_last_error() { return m_lasterr; } - - bool init(falcosecurity::init_input &in) - { - // Config is optional. In this case, defaults are used. - if (in.get_config().empty()) - { - return true; - } - - try - { - auto cfg = nlohmann::json::parse(in.get_config()); - auto it = cfg.find("jitter"); - if (it != cfg.end()) - { - m_jitter = *it; - } - } - catch (std::exception e) - { - m_lasterr = "unable to parse the json config"; - log_error(m_lasterr); - return false; - } - - return true; - } - - std::vector get_extract_event_sources() { return {PLUGIN_SOURCE_NAME}; } - - std::vector get_fields() - { - // We need to compile at least with c++11 to use an ordinary initializer list. - auto divisibile_arg = falcosecurity::field_arg(); - divisibile_arg.required = true; - divisibile_arg.index = true; - - using ft = falcosecurity::field_value_type; - return { - {ft::FTYPE_UINT64, "dummy.divisible", "Return 1 if the value is divisible by the provided divisor, 0 otherwise", "Return 1 if the value is divisible by the provided divisor, 0 otherwise", divisibile_arg}, - {ft::FTYPE_UINT64, "dummy.value", "The sample value in the event", "The sample value in the event"}, - {ft::FTYPE_STRING, "dummy.strvalue", "The sample value in the event, as a string", "The sample value in the event, as a string"}, - }; - } - - void log_error(std::string err_mess) - { - printf("%s %s\n", PLUGIN_LOG_PREFIX, err_mess.c_str()); - } - - bool extract(const falcosecurity::extract_fields_input &in) - { - auto &req = in.get_extract_request(); - falcosecurity::events::pluginevent_e_decoder dec(in.get_event_reader()); - uint32_t len = 0; - auto sample = *((uint64_t *)(dec.get_data(len))); - if (len != sizeof(uint64_t)) - { - log_error("invalid event payload"); - } - - switch (req.get_field_id()) - { - case 0: // dummy.divisible - { - if (!req.is_arg_present()) - { - log_error("'dummy.divisible' requires an argument but no argument is provided"); - return false; - } - - uint64_t res = 0; - auto divisor = req.get_arg_index(); - if ((sample % divisor) == 0) - { - res = 1; - } - req.set_value(res, true); - return true; - } - case 1: // dummy.value - { - req.set_value(sample, true); - return true; - } - case 2: // dummy.strvalue - { - // The event payload is simply the sample, as a string - req.set_value(std::to_string(sample), true); - return true; - } - default: - m_lasterr = "no known field: " + std::to_string(req.get_field_id()); - log_error(m_lasterr); - return false; - } - - return false; - } - - std::unique_ptr open(const std::string ¶ms) - { - // Config is optional. In this case, defaults are used. - uint64_t max_events = DEFAULT_MAX_EVENTS; - uint64_t start = DEFAULT_START_VALUE; - - if (!params.empty()) - { - try - { - auto open_params = nlohmann::json::parse(params); - auto it = open_params.find("start"); - if (it != open_params.end()) - { - start = *it; - } - - it = open_params.find("maxEvents"); - if (it != open_params.end()) - { - max_events = *it; - } - } - catch (std::exception e) - { - m_lasterr = "wrong open params format"; - log_error(m_lasterr); - return nullptr; - } - } - - return std::unique_ptr(new dummy_source(max_events, start, m_jitter)); - } - - std::string m_lasterr = ""; - uint64_t m_jitter = DEFAULT_JITTER; + public: + virtual ~dummy() = default; + + std::string get_name() { return PLUGIN_NAME; } + + std::string get_version() { return PLUGIN_VERSION; } + + std::string get_description() { return PLUGIN_DESCRIPTION; } + + std::string get_contact() { return PLUGIN_CONTACT; } + + uint32_t get_id() { return PLUGIN_ID; }; + + std::string get_event_source() { return PLUGIN_SOURCE_NAME; } + + std::string get_last_error() { return m_lasterr; } + + bool init(falcosecurity::init_input &in) + { + // Config is optional. In this case, defaults are used. + if(in.get_config().empty()) + { + return true; + } + + try + { + auto cfg = nlohmann::json::parse(in.get_config()); + auto it = cfg.find("jitter"); + if(it != cfg.end()) + { + m_jitter = *it; + } + } + catch(std::exception e) + { + m_lasterr = "unable to parse the json config"; + log_error(m_lasterr); + return false; + } + + return true; + } + + std::vector get_extract_event_sources() + { + return {PLUGIN_SOURCE_NAME}; + } + + std::vector get_fields() + { + // We need to compile at least with c++11 to use an ordinary initializer + // list. + auto divisibile_arg = falcosecurity::field_arg(); + divisibile_arg.required = true; + divisibile_arg.index = true; + + using ft = falcosecurity::field_value_type; + return { + {ft::FTYPE_UINT64, "dummy.divisible", + "Return 1 if the value is divisible by the provided divisor, " + "0 otherwise", + "Return 1 if the value is divisible by the provided divisor, " + "0 otherwise", + divisibile_arg}, + {ft::FTYPE_UINT64, "dummy.value", + "The sample value in the event", + "The sample value in the event"}, + {ft::FTYPE_STRING, "dummy.strvalue", + "The sample value in the event, as a string", + "The sample value in the event, as a string"}, + }; + } + + void log_error(std::string err_mess) + { + printf("%s %s\n", PLUGIN_LOG_PREFIX, err_mess.c_str()); + } + + bool extract(const falcosecurity::extract_fields_input &in) + { + auto &req = in.get_extract_request(); + falcosecurity::events::pluginevent_e_decoder dec(in.get_event_reader()); + uint32_t len = 0; + auto sample = *((uint64_t *)(dec.get_data(len))); + if(len != sizeof(uint64_t)) + { + log_error("invalid event payload"); + } + + switch(req.get_field_id()) + { + case 0: // dummy.divisible + { + if(!req.is_arg_present()) + { + log_error("'dummy.divisible' requires an argument but no " + "argument is provided"); + return false; + } + + uint64_t res = 0; + auto divisor = req.get_arg_index(); + if((sample % divisor) == 0) + { + res = 1; + } + req.set_value(res, true); + return true; + } + case 1: // dummy.value + { + req.set_value(sample, true); + return true; + } + case 2: // dummy.strvalue + { + // The event payload is simply the sample, as a string + req.set_value(std::to_string(sample), true); + return true; + } + default: + m_lasterr = "no known field: " + std::to_string(req.get_field_id()); + log_error(m_lasterr); + return false; + } + + return false; + } + + std::unique_ptr open(const std::string ¶ms) + { + // Config is optional. In this case, defaults are used. + uint64_t max_events = DEFAULT_MAX_EVENTS; + uint64_t start = DEFAULT_START_VALUE; + + if(!params.empty()) + { + try + { + auto open_params = nlohmann::json::parse(params); + auto it = open_params.find("start"); + if(it != open_params.end()) + { + start = *it; + } + + it = open_params.find("maxEvents"); + if(it != open_params.end()) + { + max_events = *it; + } + } + catch(std::exception e) + { + m_lasterr = "wrong open params format"; + log_error(m_lasterr); + return nullptr; + } + } + + return std::unique_ptr( + new dummy_source(max_events, start, m_jitter)); + } + + std::string m_lasterr = ""; + uint64_t m_jitter = DEFAULT_JITTER; }; FALCOSECURITY_PLUGIN(dummy);