From 032aa27f84cb212656a96213e3618bf99a6d7963 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Mon, 1 Apr 2024 17:22:19 +0530 Subject: [PATCH 01/36] added trusted github account check --- src/intercept.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/intercept.py b/src/intercept.py index 3f6543e..1b9a627 100644 --- a/src/intercept.py +++ b/src/intercept.py @@ -114,6 +114,7 @@ def __init__(self): self.egress_rules = None self.mode = os.environ.get("BOLT_MODE", "audit") self.default_policy = os.environ.get("BOLT_DEFAULT_POLICY", "block-all") + self.trusted_github_accounts = os.environ.get("BOLT_TRUSTED_GITHUB_ACCOUNTS", None) self.allow_http = os.environ.get("BOLT_ALLOW_HTTP", False) with open("/home/bolt/egress_rules.yaml", "r") as file: yaml = ruamel.yaml.YAML(typ="safe", pure=True) @@ -189,12 +190,12 @@ def wildcard_to_regex(self, wildcard_destination): def tls_clienthello(self, data): default_policy = self.default_policy + destination = data.client_hello.sni matched_rules = [] for rule in self.egress_rules: destination_pattern = self.wildcard_to_regex(rule["destination"]) - destination = data.client_hello.sni if destination_pattern.match(destination) is not None: matched_rules.append(rule) @@ -204,6 +205,9 @@ def tls_clienthello(self, data): if has_paths: return + + if destination == "github.com" or destination == "api.github.com": + return applied_rule = matched_rules[0] if len(matched_rules) > 0 else None @@ -252,6 +256,7 @@ def request(self, flow): default_policy = self.default_policy sni = flow.client_conn.sni + #TODO: check whether host header is spoofed or not host = flow.request.pretty_host destination = sni if sni is not None else host scheme = flow.request.scheme @@ -298,6 +303,21 @@ def request(self, flow): else: applied_rule_name = f"Default Policy - {default_policy}" + normalised_request_path = request_path + if not normalised_request_path.endswith("/"): + normalised_request_path = normalised_request_path + "/" + + trusted_github_account_flag = None + if destination == "github.com" or destination == "api.github.com": + if self.trusted_github_accounts is not None: + for trusted_github_account in self.trusted_github_accounts: + if normalised_request_path.startswith(f"/orgs/{trusted_github_account}/") or \ + normalised_request_path.startswith(f"/repos/{trusted_github_account}/"): + trusted_github_account_flag = True + break + if trusted_github_account_flag is None: + trusted_github_account_flag = False + if block: event = { "action": "block", @@ -315,6 +335,10 @@ def request(self, flow): "rule_name": applied_rule_name, } + if trusted_github_account_flag is not None: + event["trusted_github_account_flag"] = trusted_github_account_flag + event["request_path"] = request_path + self.queue.put(event) From 3bdf3f0bd9ab940a372d6e63171622d37d1f33c8 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:14:42 +0530 Subject: [PATCH 02/36] added trusted account check in interceptor --- src/intercept.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/intercept.py b/src/intercept.py index 1b9a627..737a176 100644 --- a/src/intercept.py +++ b/src/intercept.py @@ -114,7 +114,8 @@ def __init__(self): self.egress_rules = None self.mode = os.environ.get("BOLT_MODE", "audit") self.default_policy = os.environ.get("BOLT_DEFAULT_POLICY", "block-all") - self.trusted_github_accounts = os.environ.get("BOLT_TRUSTED_GITHUB_ACCOUNTS", None) + trusted_github_accounts_string = os.environ.get("BOLT_TRUSTED_GITHUB_ACCOUNTS", "") + self.trusted_github_accounts = trusted_github_accounts_string.split(",") self.allow_http = os.environ.get("BOLT_ALLOW_HTTP", False) with open("/home/bolt/egress_rules.yaml", "r") as file: yaml = ruamel.yaml.YAML(typ="safe", pure=True) @@ -306,13 +307,17 @@ def request(self, flow): normalised_request_path = request_path if not normalised_request_path.endswith("/"): normalised_request_path = normalised_request_path + "/" + + if not normalised_request_path.startswith("/"): + normalised_request_path = "/" + normalised_request_path trusted_github_account_flag = None if destination == "github.com" or destination == "api.github.com": - if self.trusted_github_accounts is not None: + if normalised_request_path.startswith("/orgs/") or \ + normalised_request_path.startswith("/repos/"): for trusted_github_account in self.trusted_github_accounts: if normalised_request_path.startswith(f"/orgs/{trusted_github_account}/") or \ - normalised_request_path.startswith(f"/repos/{trusted_github_account}/"): + normalised_request_path.startswith(f"/repos/{trusted_github_account}/"): trusted_github_account_flag = True break if trusted_github_account_flag is None: @@ -336,7 +341,9 @@ def request(self, flow): } if trusted_github_account_flag is not None: + github_account_name = request_path.split("/")[2] event["trusted_github_account_flag"] = trusted_github_account_flag + event["github_account_name"] = github_account_name event["request_path"] = request_path self.queue.put(event) From ccfd63a43ad4467056f7fb89d55ccfe08337764b Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:15:20 +0530 Subject: [PATCH 03/36] instrumenting bolt service with trusted accounts --- src/bolt_service.js | 2 ++ src/main.js | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/bolt_service.js b/src/bolt_service.js index 4f0aa14..f44a9df 100644 --- a/src/bolt_service.js +++ b/src/bolt_service.js @@ -3,6 +3,7 @@ async function boltService( mode, allowHTTP, defaultPolicy, + trustedGithubAccountsString, logFile, errorLogFile ) { @@ -20,6 +21,7 @@ Restart=always Environment="BOLT_MODE=${mode}" Environment="BOLT_ALLOW_HTTP=${allowHTTP}" Environment="BOLT_DEFAULT_POLICY=${defaultPolicy}" +Environment="BOLT_TRUSTED_GITHUB_ACCOUNTS=${trustedGithubAccountsString}" StandardOutput=file:${logFile} StandardError=file:${errorLogFile} diff --git a/src/main.js b/src/main.js index 5ec0b34..ff224b3 100644 --- a/src/main.js +++ b/src/main.js @@ -26,6 +26,8 @@ async function run() { // Changing boltUser will require changes in bolt.service and intercept.py const boltUser = 'bolt' + const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt + const repoOwner = repoName.split('/')[0]; // e.g. koalalab-inc core.saveState('boltUser', boltUser) core.startGroup('create-bolt-user') @@ -49,7 +51,6 @@ async function run() { // Sample Backup URL :: https://github.com/koalalab-inc/bolt/releases/download/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz let referrer = '' try { - const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt const workflowName = process.env.GITHUB_WORKFLOW.replace(/\//g, "|"); // e.g. CI const jobName = process.env.GITHUB_JOB; // e.g. build referrer = `github.com/${repoName}/${workflowName}/${jobName}` @@ -81,6 +82,8 @@ async function run() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') + const trustedGithubAccounts = core.getInput('trusted_github_accounts') + const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') // Verify that egress_rules_yaml is valid YAML YAML.parse(egressRulesYAML) @@ -126,6 +129,7 @@ async function run() { mode, allowHTTP, defaultPolicy, + trustedGithubAccountsString, logFile, errorLogFile ) @@ -150,6 +154,20 @@ async function run() { benchmark('start-bolt') + core.startGroup('trust-bolt-certificate') + core.info('Install ca-certificates...') + await exec('sudo apt-get update') + await exec('sudo apt-get install -y ca-certificates') + core.info('Install ca-certificates... done') + core.info('Trust bolt certificate...') + await exec( + `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` + ) + await exec('sudo update-ca-certificates') + core.endGroup('trust-bolt-certificate') + + benchmark('trust-bolt-certificate') + core.startGroup('setup-iptables-redirection') await exec('sudo sysctl -w net.ipv4.ip_forward=1') await exec('sudo sysctl -w net.ipv6.conf.all.forwarding=1') From 28cd7c6f0de7f3aab7496a4f8fe75042aa0a333e Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:15:41 +0530 Subject: [PATCH 04/36] updated summary to reflect untrusted github accounts --- src/summary.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/summary.js b/src/summary.js index 21f2bea..b93ac46 100644 --- a/src/summary.js +++ b/src/summary.js @@ -77,6 +77,28 @@ async function summary() { ] ) + const githubAccountCalls = results.filter((result) => { + return result.trusted_github_account_flag !== undefined + }) + + const githubAccounts = githubAccountCalls.reduce((accounts, call) => { + const path = call.destination.request_path + const name = call.github_account_name + const trusted_flag = call.trusted_github_account_flag + accounts[name] = accounts[name] || {} + accounts[name]["name"] = name + accounts[name]["trusted"] = trusted_flag + accounts[name]["paths"] = accounts[name]["paths"] || [] + if (!accounts[name]["paths"].includes(path)) { + accounts[name]["paths"].push(path) + } + return accounts + }, []) + + const untrustedGithubAccounts = Object.values(githubAccounts).filter((account) => { + return account["trusted"] === false + }) + const configMap = { mode, allowHTTP, @@ -114,12 +136,39 @@ async function summary() { core.info(JSON.stringify(results)) core.info('<< 0) { + summary = summary + .addHeading('Untrusted Github Accounts Found', 3) + .addRaw(` + > [!CAUTION] + > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. + `) + + for (const account of untrustedGithubAccounts) { + summary = summary + .addRaw(` +
+ + ${account.name} + +

Paths:

+
    + ${account.paths.map(path => `
  • ${path}
  • `).join('')} +
+
+ `) + } + } + + summary = summary + .addHeading .addHeading('Egress Traffic', 3) .addQuote( 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' @@ -129,7 +178,8 @@ async function summary() { 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' ) - .write() + + summary.write() } module.exports = { summary } From 26ce0a9dacaeab1b29735aa0244817c414d48a4c Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:16:02 +0530 Subject: [PATCH 05/36] added github trusted account input variable --- action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yml b/action.yml index 19e81b4..9cbeeaf 100644 --- a/action.yml +++ b/action.yml @@ -18,6 +18,10 @@ inputs: description: 'Default policy for egress traffic - allow-all or block-all' required: false default: 'block-all' + trusted_github_accounts: + description: 'Trusted Github accounts' + required: false + default: '[]' egress_rules: description: 'Egress rules' required: false From 9ec900fd90d8c98b4dd3b63bbe591acc3b8f91a1 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:18:27 +0530 Subject: [PATCH 06/36] fixed summary and added dist --- badges/coverage.svg | 2 +- dist/index.js | 82 +++++++++++++++++++++++++++++++++++++++++---- src/index.js | 4 +-- src/summary.js | 40 +++++++++++----------- 4 files changed, 97 insertions(+), 31 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index e2966cb..5cc2b10 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 10.92%Coverage10.92% \ No newline at end of file +Coverage: 9.17%Coverage9.17% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 212d4f8..c35c2a9 100644 --- a/dist/index.js +++ b/dist/index.js @@ -25944,6 +25944,7 @@ async function boltService( mode, allowHTTP, defaultPolicy, + trustedGithubAccountsString, logFile, errorLogFile ) { @@ -25961,6 +25962,7 @@ Restart=always Environment="BOLT_MODE=${mode}" Environment="BOLT_ALLOW_HTTP=${allowHTTP}" Environment="BOLT_DEFAULT_POLICY=${defaultPolicy}" +Environment="BOLT_TRUSTED_GITHUB_ACCOUNTS=${trustedGithubAccountsString}" StandardOutput=file:${logFile} StandardError=file:${errorLogFile} @@ -26005,6 +26007,8 @@ async function run() { // Changing boltUser will require changes in bolt.service and intercept.py const boltUser = 'bolt' + const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt + const repoOwner = repoName.split('/')[0]; // e.g. koalalab-inc core.saveState('boltUser', boltUser) core.startGroup('create-bolt-user') @@ -26028,7 +26032,6 @@ async function run() { // Sample Backup URL :: https://github.com/koalalab-inc/bolt/releases/download/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz let referrer = '' try { - const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt const workflowName = process.env.GITHUB_WORKFLOW.replace(/\//g, "|"); // e.g. CI const jobName = process.env.GITHUB_JOB; // e.g. build referrer = `github.com/${repoName}/${workflowName}/${jobName}` @@ -26060,6 +26063,8 @@ async function run() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') + const trustedGithubAccounts = core.getInput('trusted_github_accounts') + const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') // Verify that egress_rules_yaml is valid YAML YAML.parse(egressRulesYAML) @@ -26105,6 +26110,7 @@ async function run() { mode, allowHTTP, defaultPolicy, + trustedGithubAccountsString, logFile, errorLogFile ) @@ -26129,6 +26135,20 @@ async function run() { benchmark('start-bolt') + core.startGroup('trust-bolt-certificate') + core.info('Install ca-certificates...') + await exec('sudo apt-get update') + await exec('sudo apt-get install -y ca-certificates') + core.info('Install ca-certificates... done') + core.info('Trust bolt certificate...') + await exec( + `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` + ) + await exec('sudo update-ca-certificates') + core.endGroup('trust-bolt-certificate') + + benchmark('trust-bolt-certificate') + core.startGroup('setup-iptables-redirection') await exec('sudo sysctl -w net.ipv4.ip_forward=1') await exec('sudo sysctl -w net.ipv6.conf.all.forwarding=1') @@ -26219,7 +26239,7 @@ function getUniqueBy(arr, keys) { return Object.values(uniqueObj) } -async function summary() { +async function generateSummary() { const boltUser = core.getState('boltUser') const mode = core.getInput('mode') const allowHTTP = core.getInput('allow_http') @@ -26243,6 +26263,30 @@ async function summary() { ] ) + const githubAccountCalls = results.filter(result => { + return result.trusted_github_account_flag !== undefined + }) + + const githubAccounts = githubAccountCalls.reduce((accounts, call) => { + const path = call.destination.request_path + const name = call.github_account_name + const trusted_flag = call.trusted_github_account_flag + accounts[name] = accounts[name] || {} + accounts[name]['name'] = name + accounts[name]['trusted'] = trusted_flag + accounts[name]['paths'] = accounts[name]['paths'] || [] + if (!accounts[name]['paths'].includes(path)) { + accounts[name]['paths'].push(path) + } + return accounts + }, []) + + const untrustedGithubAccounts = Object.values(githubAccounts).filter( + account => { + return account['trusted'] === false + } + ) + const configMap = { mode, allowHTTP, @@ -26280,12 +26324,35 @@ async function summary() { core.info(JSON.stringify(results)) core.info('<< 0) { + summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` + > [!CAUTION] + > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. + `) + + for (const account of untrustedGithubAccounts) { + summary = summary.addRaw(` +
+ + ${account.name} + +

Paths:

+
    + ${account.paths.map(path => `
  • ${path}
  • `).join('')} +
+
+ `) + } + } + + summary = summary.addHeading .addHeading('Egress Traffic', 3) .addQuote( 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' @@ -26295,10 +26362,11 @@ async function summary() { 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' ) - .write() + + summary.write() } -module.exports = { summary } +module.exports = { generateSummary } /***/ }), @@ -36658,7 +36726,7 @@ var __webpack_exports__ = {}; * The entrypoint for the action. */ const { run } = __nccwpck_require__(1713) -const { summary } = __nccwpck_require__(7259) +const { generateSummary } = __nccwpck_require__(7259) const core = __nccwpck_require__(2186) const isPost = core.getState('isPost') @@ -36666,7 +36734,7 @@ const flag = isPost === 'true' if (flag) { // Post - summary() + generateSummary() } else { if (!isPost) { core.saveState('isPost', 'true') diff --git a/src/index.js b/src/index.js index 9ee473a..023250d 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,7 @@ * The entrypoint for the action. */ const { run } = require('./main') -const { summary } = require('./summary') +const { generateSummary } = require('./summary') const core = require('@actions/core') const isPost = core.getState('isPost') @@ -10,7 +10,7 @@ const flag = isPost === 'true' if (flag) { // Post - summary() + generateSummary() } else { if (!isPost) { core.saveState('isPost', 'true') diff --git a/src/summary.js b/src/summary.js index b93ac46..ce5855d 100644 --- a/src/summary.js +++ b/src/summary.js @@ -53,7 +53,7 @@ function getUniqueBy(arr, keys) { return Object.values(uniqueObj) } -async function summary() { +async function generateSummary() { const boltUser = core.getState('boltUser') const mode = core.getInput('mode') const allowHTTP = core.getInput('allow_http') @@ -77,7 +77,7 @@ async function summary() { ] ) - const githubAccountCalls = results.filter((result) => { + const githubAccountCalls = results.filter(result => { return result.trusted_github_account_flag !== undefined }) @@ -86,18 +86,20 @@ async function summary() { const name = call.github_account_name const trusted_flag = call.trusted_github_account_flag accounts[name] = accounts[name] || {} - accounts[name]["name"] = name - accounts[name]["trusted"] = trusted_flag - accounts[name]["paths"] = accounts[name]["paths"] || [] - if (!accounts[name]["paths"].includes(path)) { - accounts[name]["paths"].push(path) + accounts[name]['name'] = name + accounts[name]['trusted'] = trusted_flag + accounts[name]['paths'] = accounts[name]['paths'] || [] + if (!accounts[name]['paths'].includes(path)) { + accounts[name]['paths'].push(path) } return accounts }, []) - const untrustedGithubAccounts = Object.values(githubAccounts).filter((account) => { - return account["trusted"] === false - }) + const untrustedGithubAccounts = Object.values(githubAccounts).filter( + account => { + return account['trusted'] === false + } + ) const configMap = { mode, @@ -142,18 +144,15 @@ async function summary() { .addTable(configTable) .addHeading('Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') - + if (untrustedGithubAccounts.length > 0) { - summary = summary - .addHeading('Untrusted Github Accounts Found', 3) - .addRaw(` + summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) - + for (const account of untrustedGithubAccounts) { - summary = summary - .addRaw(` + summary = summary.addRaw(`
${account.name} @@ -166,9 +165,8 @@ async function summary() { `) } } - - summary = summary - .addHeading + + summary = summary.addHeading .addHeading('Egress Traffic', 3) .addQuote( 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' @@ -182,4 +180,4 @@ async function summary() { summary.write() } -module.exports = { summary } +module.exports = { generateSummary } From feb92c6e69e39e79c49dc5028354eb7dd1f92ff3 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 09:58:21 +0530 Subject: [PATCH 07/36] fixed pylint issues --- .flake8 | 2 ++ src/intercept.py | 36 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..79a16af --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 \ No newline at end of file diff --git a/src/intercept.py b/src/intercept.py index 737a176..118327d 100644 --- a/src/intercept.py +++ b/src/intercept.py @@ -101,8 +101,13 @@ """ -# pylint: disable=missing-class-docstring,missing-function-docstring,unspecified-encoding +# pylint: disable=missing-function-docstring,unspecified-encoding class Interceptor: + """ + The Interceptor class is responsible for managing + and controlling the flow of http requests. + """ + # pylint: disable=too-many-instance-attributes def __init__(self): self.outfile = None @@ -114,7 +119,9 @@ def __init__(self): self.egress_rules = None self.mode = os.environ.get("BOLT_MODE", "audit") self.default_policy = os.environ.get("BOLT_DEFAULT_POLICY", "block-all") - trusted_github_accounts_string = os.environ.get("BOLT_TRUSTED_GITHUB_ACCOUNTS", "") + trusted_github_accounts_string = os.environ.get( + "BOLT_TRUSTED_GITHUB_ACCOUNTS", "" + ) self.trusted_github_accounts = trusted_github_accounts_string.split(",") self.allow_http = os.environ.get("BOLT_ALLOW_HTTP", False) with open("/home/bolt/egress_rules.yaml", "r") as file: @@ -206,8 +213,8 @@ def tls_clienthello(self, data): if has_paths: return - - if destination == "github.com" or destination == "api.github.com": + + if destination in ["github.com", "api.github.com"]: return applied_rule = matched_rules[0] if len(matched_rules) > 0 else None @@ -251,13 +258,14 @@ def tls_start_client(self, data): data.ssl_conn = SSL.Connection(SSL.Context(SSL.SSLv23_METHOD)) data.conn.error = "TLS Handshake failed" - # pylint: disable=too-many-branches,too-many-locals + # pylint: disable=too-many-branches,too-many-locals,too-many-statements def request(self, flow): allow_http = self.allow_http default_policy = self.default_policy sni = flow.client_conn.sni - #TODO: check whether host header is spoofed or not + # pylint: disable=fixme + # TODO: check whether host header is spoofed or not host = flow.request.pretty_host destination = sni if sni is not None else host scheme = flow.request.scheme @@ -307,17 +315,21 @@ def request(self, flow): normalised_request_path = request_path if not normalised_request_path.endswith("/"): normalised_request_path = normalised_request_path + "/" - + if not normalised_request_path.startswith("/"): normalised_request_path = "/" + normalised_request_path trusted_github_account_flag = None - if destination == "github.com" or destination == "api.github.com": - if normalised_request_path.startswith("/orgs/") or \ - normalised_request_path.startswith("/repos/"): + if destination in ["github.com", "api.github.com"]: + if normalised_request_path.startswith( + "/orgs/" + ) or normalised_request_path.startswith("/repos/"): for trusted_github_account in self.trusted_github_accounts: - if normalised_request_path.startswith(f"/orgs/{trusted_github_account}/") or \ - normalised_request_path.startswith(f"/repos/{trusted_github_account}/"): + if normalised_request_path.startswith( + f"/orgs/{trusted_github_account}/" + ) or normalised_request_path.startswith( + f"/repos/{trusted_github_account}/" + ): trusted_github_account_flag = True break if trusted_github_account_flag is None: From 81580b24dc072b42c18960f31f7f2fd02a0d796b Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 10:10:16 +0530 Subject: [PATCH 08/36] added pre release flag --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7cd8550..612a7ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,4 +38,4 @@ jobs: name: ${{ env.tag }} generate_release_notes: true token: ${{ secrets.GITHUB_TOKEN }} - + prerelease: ${{ endsWith(env.tag, 'rc') }} From 07eb28d23a45a57534278786bacdaca6008f3257 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 10:21:43 +0530 Subject: [PATCH 09/36] input yaml parsing for trusted github accounts --- badges/coverage.svg | 2 +- dist/index.js | 3 ++- src/main.js | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index 5cc2b10..5440ebe 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 9.17%Coverage9.17% \ No newline at end of file +Coverage: 9.13%Coverage9.13% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index c35c2a9..ead8903 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26063,7 +26063,8 @@ async function run() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') - const trustedGithubAccounts = core.getInput('trusted_github_accounts') + const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') + const trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') // Verify that egress_rules_yaml is valid YAML diff --git a/src/main.js b/src/main.js index ff224b3..7be1757 100644 --- a/src/main.js +++ b/src/main.js @@ -82,7 +82,8 @@ async function run() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') - const trustedGithubAccounts = core.getInput('trusted_github_accounts') + const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') + const trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') // Verify that egress_rules_yaml is valid YAML From 49d4f652c1f50c2de1bdf57a2fffe08afff39aa4 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 10:32:44 +0530 Subject: [PATCH 10/36] fixed issue --- dist/index.js | 2 +- src/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index ead8903..8a0ad33 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26065,7 +26065,7 @@ async function run() { const egressRulesYAML = core.getInput('egress_rules') const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') const trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) - const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') + const trustedGithubAccountsString = [repoOwner, ...trustedGithubAccounts].join(',') // Verify that egress_rules_yaml is valid YAML YAML.parse(egressRulesYAML) diff --git a/src/main.js b/src/main.js index 7be1757..cf4c32d 100644 --- a/src/main.js +++ b/src/main.js @@ -84,7 +84,7 @@ async function run() { const egressRulesYAML = core.getInput('egress_rules') const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') const trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) - const trustedGithubAccountsString = trustedGithubAccounts.push(repoOwner).reverse().join(',') + const trustedGithubAccountsString = [repoOwner, ...trustedGithubAccounts].join(',') // Verify that egress_rules_yaml is valid YAML YAML.parse(egressRulesYAML) From fc6f96fd0e2ecdde8f49106a26bed4fd22016b0f Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 11:03:42 +0530 Subject: [PATCH 11/36] fixed summary issue --- dist/index.js | 2 +- src/summary.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 8a0ad33..2481cbd 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26353,7 +26353,7 @@ async function generateSummary() { } } - summary = summary.addHeading + summary = summary .addHeading('Egress Traffic', 3) .addQuote( 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' diff --git a/src/summary.js b/src/summary.js index ce5855d..edb9b23 100644 --- a/src/summary.js +++ b/src/summary.js @@ -166,7 +166,7 @@ async function generateSummary() { } } - summary = summary.addHeading + summary = summary .addHeading('Egress Traffic', 3) .addQuote( 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' From 58898c7df757dd848443a7a714d089a1144b82ca Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 11:59:06 +0530 Subject: [PATCH 12/36] added release version check --- .github/workflows/release.yml | 9 +++++++ badges/coverage.svg | 2 +- dist/index.js | 44 ++++++++++++++++++++++++++++++++++- src/main.js | 3 ++- src/version.js | 1 + 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/version.js diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 612a7ae..9122552 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,6 +19,15 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Get release version + id: releaseVersion + run: echo "::set-output name=releaseVersion::$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)" + - name: Check if releaseVersion is same as tag + run: | + if [ "${{ env.tag }}" != "${{ steps.releaseVersion.outputs.releaseVersion }}" ]; then + echo "releaseVersion does not match the tag" + exit 1 + fi - name: Fetch MITM-Proxy run: | mkdir -p mitmproxy diff --git a/badges/coverage.svg b/badges/coverage.svg index 5440ebe..ed263b4 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 9.13%Coverage9.13% \ No newline at end of file +Coverage: 9.09%Coverage9.09% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 2481cbd..ffca7e5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -25983,6 +25983,7 @@ const core = __nccwpck_require__(2186) const { exec } = __nccwpck_require__(1514) const { wait } = __nccwpck_require__(1312) const { boltService } = __nccwpck_require__(5147) +const { releaseVersion } = __nccwpck_require__(9554) const YAML = __nccwpck_require__(4083) const fs = __nccwpck_require__(7147) @@ -26026,7 +26027,7 @@ async function run() { // const extractDir = 'home/runner/bolt' // await exec(`mkdir -p ${extractDir}`) core.info('Downloading mitmproxy...') - const releaseVersion = 'v1.1.0' + // const releaseVersion = 'v1.3.0-rc' const filename = `${releaseName}-${releaseVersion}-linux-x86_64.tar.gz` // Sample URL :: https://api-do-blr.koalalab.com/bolt/package/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz // Sample Backup URL :: https://github.com/koalalab-inc/bolt/releases/download/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz @@ -26370,6 +26371,19 @@ async function generateSummary() { module.exports = { generateSummary } +/***/ }), + +/***/ 9554: +/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +__nccwpck_require__.r(__webpack_exports__); +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ "releaseVersion": () => (/* binding */ releaseVersion) +/* harmony export */ }); +const releaseVersion = 'v1.3.0-rc' + + /***/ }), /***/ 1312: @@ -36715,6 +36729,34 @@ exports.visitAsync = visitAsync; /******/ } /******/ /************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __nccwpck_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __nccwpck_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ /******/ /* webpack/runtime/compat */ /******/ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; diff --git a/src/main.js b/src/main.js index cf4c32d..e789b24 100644 --- a/src/main.js +++ b/src/main.js @@ -2,6 +2,7 @@ const core = require('@actions/core') const { exec } = require('@actions/exec') const { wait } = require('./wait') const { boltService } = require('./bolt_service') +const { releaseVersion } = require('./version') const YAML = require('yaml') const fs = require('fs') @@ -45,7 +46,7 @@ async function run() { // const extractDir = 'home/runner/bolt' // await exec(`mkdir -p ${extractDir}`) core.info('Downloading mitmproxy...') - const releaseVersion = 'v1.1.0' + // const releaseVersion = 'v1.3.0-rc' const filename = `${releaseName}-${releaseVersion}-linux-x86_64.tar.gz` // Sample URL :: https://api-do-blr.koalalab.com/bolt/package/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz // Sample Backup URL :: https://github.com/koalalab-inc/bolt/releases/download/v0.7.0/bolt-v0.7.0-linux-x86_64.tar.gz diff --git a/src/version.js b/src/version.js new file mode 100644 index 0000000..ef99e26 --- /dev/null +++ b/src/version.js @@ -0,0 +1 @@ +export const releaseVersion = 'v1.3.0-rc' From da35d1f9e43e359a80dccb91d1e719536939ebcb Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 12:19:10 +0530 Subject: [PATCH 13/36] removed deprecated set-output --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9122552..1d32401 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,10 +21,10 @@ jobs: uses: actions/checkout@v4 - name: Get release version id: releaseVersion - run: echo "::set-output name=releaseVersion::$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)" + run: echo "releaseVersion=$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)" >> $GITHUB_ENV - name: Check if releaseVersion is same as tag run: | - if [ "${{ env.tag }}" != "${{ steps.releaseVersion.outputs.releaseVersion }}" ]; then + if [ "${{ env.tag }}" != "${{ env.releaseVersion }}" ]; then echo "releaseVersion does not match the tag" exit 1 fi From 899b1bbad1c2f1368ecccf9dcb4571a1507937c2 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 12:31:52 +0530 Subject: [PATCH 14/36] summary beautification --- dist/index.js | 26 +++++++++++++------------- src/summary.js | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/dist/index.js b/dist/index.js index ffca7e5..003dff7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26276,9 +26276,9 @@ async function generateSummary() { accounts[name] = accounts[name] || {} accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag - accounts[name]['paths'] = accounts[name]['paths'] || [] + const paths = accounts[name]['paths'] || [] if (!accounts[name]['paths'].includes(path)) { - accounts[name]['paths'].push(path) + accounts[name]['paths'] = [...paths, path] } return accounts }, []) @@ -26335,21 +26335,21 @@ async function generateSummary() { if (untrustedGithubAccounts.length > 0) { summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` - > [!CAUTION] - > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. +> [!CAUTION] +> If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { summary = summary.addRaw(` -
- - ${account.name} - -

Paths:

-
    - ${account.paths.map(path => `
  • ${path}
  • `).join('')} -
-
+
+ + ${account.name} + +

Paths:

+
    + ${account.paths.map(path => `
  • ${path}
  • `).join('')} +
+
`) } } diff --git a/src/summary.js b/src/summary.js index edb9b23..9c56552 100644 --- a/src/summary.js +++ b/src/summary.js @@ -88,9 +88,9 @@ async function generateSummary() { accounts[name] = accounts[name] || {} accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag - accounts[name]['paths'] = accounts[name]['paths'] || [] + const paths = accounts[name]['paths'] || [] if (!accounts[name]['paths'].includes(path)) { - accounts[name]['paths'].push(path) + accounts[name]['paths'] = [...paths, path] } return accounts }, []) @@ -147,21 +147,21 @@ async function generateSummary() { if (untrustedGithubAccounts.length > 0) { summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` - > [!CAUTION] - > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. +> [!CAUTION] +> If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { summary = summary.addRaw(` -
- - ${account.name} - -

Paths:

-
    - ${account.paths.map(path => `
  • ${path}
  • `).join('')} -
-
+
+ + ${account.name} + +

Paths:

+
    + ${account.paths.map(path => `
  • ${path}
  • `).join('')} +
+
`) } } From 9f2d8c9c6eae9552b64177bb400d00cb1b14cc4d Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 12:37:55 +0530 Subject: [PATCH 15/36] summary fixes --- dist/index.js | 2 +- src/summary.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 003dff7..4c5001e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26277,7 +26277,7 @@ async function generateSummary() { accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag const paths = accounts[name]['paths'] || [] - if (!accounts[name]['paths'].includes(path)) { + if (paths.includes(path)) { accounts[name]['paths'] = [...paths, path] } return accounts diff --git a/src/summary.js b/src/summary.js index 9c56552..a08e8a2 100644 --- a/src/summary.js +++ b/src/summary.js @@ -89,7 +89,7 @@ async function generateSummary() { accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag const paths = accounts[name]['paths'] || [] - if (!accounts[name]['paths'].includes(path)) { + if (paths.includes(path)) { accounts[name]['paths'] = [...paths, path] } return accounts From 38db3db73bd924151971848727216ee04d23590f Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 12:45:43 +0530 Subject: [PATCH 16/36] summary fixes --- dist/index.js | 2 +- src/summary.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4c5001e..7e4155d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26277,7 +26277,7 @@ async function generateSummary() { accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag const paths = accounts[name]['paths'] || [] - if (paths.includes(path)) { + if (!paths.includes(path)) { accounts[name]['paths'] = [...paths, path] } return accounts diff --git a/src/summary.js b/src/summary.js index a08e8a2..353c374 100644 --- a/src/summary.js +++ b/src/summary.js @@ -89,7 +89,7 @@ async function generateSummary() { accounts[name]['name'] = name accounts[name]['trusted'] = trusted_flag const paths = accounts[name]['paths'] || [] - if (paths.includes(path)) { + if (!paths.includes(path)) { accounts[name]['paths'] = [...paths, path] } return accounts From dfb2c1b329044ce647b1741349e8eebee57cd498 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 13:03:18 +0530 Subject: [PATCH 17/36] trying collapsible summary tables --- badges/coverage.svg | 2 +- dist/index.js | 29 +++++++++++++++++++---------- src/main.js | 4 ---- src/summary.js | 25 +++++++++++++++++++------ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index ed263b4..5cc2b10 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 9.09%Coverage9.09% \ No newline at end of file +Coverage: 9.17%Coverage9.17% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 7e4155d..110b896 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26138,10 +26138,6 @@ async function run() { benchmark('start-bolt') core.startGroup('trust-bolt-certificate') - core.info('Install ca-certificates...') - await exec('sudo apt-get update') - await exec('sudo apt-get install -y ca-certificates') - core.info('Install ca-certificates... done') core.info('Trust bolt certificate...') await exec( `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` @@ -26270,7 +26266,7 @@ async function generateSummary() { }) const githubAccounts = githubAccountCalls.reduce((accounts, call) => { - const path = call.destination.request_path + const path = call.request_path const name = call.github_account_name const trusted_flag = call.trusted_github_account_flag accounts[name] = accounts[name] || {} @@ -26326,15 +26322,28 @@ async function generateSummary() { core.info(JSON.stringify(results)) core.info('<< + +${configHeaderString} + +${configTableString} +
+ ` + ) + .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` + summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) + .addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) diff --git a/src/main.js b/src/main.js index e789b24..0a7d243 100644 --- a/src/main.js +++ b/src/main.js @@ -157,10 +157,6 @@ async function run() { benchmark('start-bolt') core.startGroup('trust-bolt-certificate') - core.info('Install ca-certificates...') - await exec('sudo apt-get update') - await exec('sudo apt-get install -y ca-certificates') - core.info('Install ca-certificates... done') core.info('Trust bolt certificate...') await exec( `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` diff --git a/src/summary.js b/src/summary.js index 353c374..9210263 100644 --- a/src/summary.js +++ b/src/summary.js @@ -82,7 +82,7 @@ async function generateSummary() { }) const githubAccounts = githubAccountCalls.reduce((accounts, call) => { - const path = call.destination.request_path + const path = call.request_path const name = call.github_account_name const trusted_flag = call.trusted_github_account_flag accounts[name] = accounts[name] || {} @@ -138,15 +138,28 @@ async function generateSummary() { core.info(JSON.stringify(results)) core.info('<< + +${configHeaderString} + +${configTableString} + + ` + ) + .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('Untrusted Github Accounts Found', 3).addRaw(` + summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) + .addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) From 8d93a245e90535da1dfb6745d0ced5d4838f35ec Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 13:12:12 +0530 Subject: [PATCH 18/36] increased wait after bolt start --- dist/index.js | 2 +- src/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 110b896..080aa6c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26129,7 +26129,7 @@ async function run() { core.info('Starting bolt...') await exec('sudo systemctl start bolt') core.info('Waiting for bolt to start...') - const ms = 1000 + const ms = 2000 await wait(ms) await exec('sudo systemctl status bolt') core.info('Starting bolt... done') diff --git a/src/main.js b/src/main.js index 0a7d243..cf47d0e 100644 --- a/src/main.js +++ b/src/main.js @@ -148,7 +148,7 @@ async function run() { core.info('Starting bolt...') await exec('sudo systemctl start bolt') core.info('Waiting for bolt to start...') - const ms = 1000 + const ms = 2000 await wait(ms) await exec('sudo systemctl status bolt') core.info('Starting bolt... done') From ad729b7b69a22495b02c57b63107285cfc7d1114 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 16:06:44 +0530 Subject: [PATCH 19/36] better summary --- badges/coverage.svg | 2 +- dist/index.js | 90 ++++++++++++++++++++++++++++++++++++++++----- src/intercept.py | 14 +++++++ src/summary.js | 90 ++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 175 insertions(+), 21 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index 5cc2b10..2dfab49 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 9.17%Coverage9.17% \ No newline at end of file +Coverage: 8.47%Coverage8.47% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 080aa6c..92da707 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26245,7 +26245,7 @@ async function generateSummary() { const egressRulesYAML = core.getInput('egress_rules') // Verify that egress_rules_yaml is valid YAML try { - YAML.parse(egressRulesYAML) + const egressRules = YAML.parse(egressRulesYAML) } catch (error) { core.info(`Invalid YAML: ${error.message}`) } @@ -26257,7 +26257,8 @@ async function generateSummary() { result.destination, result.scheme, result.rule_name, - actionString(result.action) + actionString(result.action), + result.default ] ) @@ -26297,7 +26298,19 @@ async function generateSummary() { ['Default Policy', defaultPolicy] ] - const table = [ + const knownDestinations = [ + [ + { data: 'Destination', header: true }, + { data: 'Scheme', header: true }, + { data: 'Rule', header: true }, + { data: 'Action', header: true } + ], + ...uniqueResults + .filter(result => result.default || result.action === 'allow') + .map(result => result.slice(0, 4)) + ] + + const unknownDestinations = [ [ { data: 'Destination', header: true }, { data: 'Scheme', header: true }, @@ -26305,13 +26318,16 @@ async function generateSummary() { { data: 'Action', header: true } ], ...uniqueResults + .filter(result => result.default === false && result.action === 'block') + .map(result => result.slice(0, 4)) ] core.info('Koalalab-inc-bolt-config>>>') core.info(JSON.stringify(configMap)) core.info('<<>>') core.info(JSON.stringify(egressRules)) core.info('<< ` ) - .addHeading('πŸ“ Egress rules', 3) - .addCodeBlock(egressRulesYAML, 'yaml') + + if (egressRules.length > 0) { + summary = summary + .addHeading('πŸ“ Egress rules', 3) + .addCodeBlock(egressRulesYAML, 'yaml') + } else { + summary = summary.addRaw(` +> [!NOTE] +> You have not configured egress rules. Only deault policy will be applied. See [documentation]https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. + `) + } if (untrustedGithubAccounts.length > 0) { summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) @@ -26354,7 +26403,6 @@ ${configTableString} ${account.name} -

Paths:

    ${account.paths.map(path => `
  • ${path}
  • `).join('')}
@@ -26365,10 +26413,32 @@ ${configTableString} summary = summary .addHeading('Egress Traffic', 3) - .addQuote( - 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' + .addRaw( + ` +> [!NOTE] +> Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode. + ` + ) + .addRaw( + ` +
+ +${unknownDestinationsHeaderString} + +${unknownDestinationsTableString} +
+ ` + ) + .addRaw( + ` +
+ +${knownDestinationsHeaderString} + +${knownDestinationsTableString} +
+ ` ) - .addTable(table) .addLink( 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' diff --git a/src/intercept.py b/src/intercept.py index 118327d..04f45a8 100644 --- a/src/intercept.py +++ b/src/intercept.py @@ -128,6 +128,8 @@ def __init__(self): yaml = ruamel.yaml.YAML(typ="safe", pure=True) self.egress_rules = yaml.load(file) default_egress_rules = yaml.load(DEFAULT_EGRESS_RULES_YAML) + for rule in default_egress_rules: + rule["default"] = True self.egress_rules = self.egress_rules + default_egress_rules def done(self): @@ -218,6 +220,10 @@ def tls_clienthello(self, data): return applied_rule = matched_rules[0] if len(matched_rules) > 0 else None + if applied_rule is not None: + default_rules_applied = applied_rule.get("default", False) + else: + default_rules_applied = False if applied_rule is not None: applied_rule_name = applied_rule.get("name", "Name not configured") @@ -235,6 +241,7 @@ def tls_clienthello(self, data): "destination": destination, "scheme": "https", "rule_name": applied_rule_name, + "default": default_rules_applied, } data.context.action = "block" if self.mode == "audit": @@ -334,6 +341,11 @@ def request(self, flow): break if trusted_github_account_flag is None: trusted_github_account_flag = False + + if applied_rule is not None: + default_rules_applied = applied_rule.get("default", False) + else: + default_rules_applied = False if block: event = { @@ -341,6 +353,7 @@ def request(self, flow): "destination": destination, "scheme": scheme, "rule_name": applied_rule_name, + "default": default_rules_applied, } if self.mode != "audit": flow.kill() @@ -350,6 +363,7 @@ def request(self, flow): "destination": destination, "scheme": scheme, "rule_name": applied_rule_name, + "default": default_rules_applied, } if trusted_github_account_flag is not None: diff --git a/src/summary.js b/src/summary.js index 9210263..fd8392f 100644 --- a/src/summary.js +++ b/src/summary.js @@ -61,7 +61,7 @@ async function generateSummary() { const egressRulesYAML = core.getInput('egress_rules') // Verify that egress_rules_yaml is valid YAML try { - YAML.parse(egressRulesYAML) + const egressRules = YAML.parse(egressRulesYAML) } catch (error) { core.info(`Invalid YAML: ${error.message}`) } @@ -73,7 +73,8 @@ async function generateSummary() { result.destination, result.scheme, result.rule_name, - actionString(result.action) + actionString(result.action), + result.default ] ) @@ -113,7 +114,7 @@ async function generateSummary() { ['Default Policy', defaultPolicy] ] - const table = [ + const knownDestinations = [ [ { data: 'Destination', header: true }, { data: 'Scheme', header: true }, @@ -121,13 +122,28 @@ async function generateSummary() { { data: 'Action', header: true } ], ...uniqueResults + .filter(result => result.default || result.action === 'allow') + .map(result => result.slice(0, 4)) + ] + + const unknownDestinations = [ + [ + { data: 'Destination', header: true }, + { data: 'Scheme', header: true }, + { data: 'Rule', header: true }, + { data: 'Action', header: true } + ], + ...uniqueResults + .filter(result => result.default === false && result.action === 'block') + .map(result => result.slice(0, 4)) ] core.info('Koalalab-inc-bolt-config>>>') core.info(JSON.stringify(configMap)) core.info('<<>>') core.info(JSON.stringify(egressRules)) core.info('<< ` ) - .addHeading('πŸ“ Egress rules', 3) - .addCodeBlock(egressRulesYAML, 'yaml') + + if (egressRules.length > 0) { + summary = summary + .addHeading('πŸ“ Egress rules', 3) + .addCodeBlock(egressRulesYAML, 'yaml') + } else { + summary = summary.addRaw(` +> [!NOTE] +> You have not configured egress rules. Only deault policy will be applied. See [documentation]https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. + `) + } if (untrustedGithubAccounts.length > 0) { summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) @@ -170,7 +219,6 @@ ${configTableString} ${account.name} -

Paths:

    ${account.paths.map(path => `
  • ${path}
  • `).join('')}
@@ -181,10 +229,32 @@ ${configTableString} summary = summary .addHeading('Egress Traffic', 3) - .addQuote( - 'Note:: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' + .addRaw( + ` +> [!NOTE] +> Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode. + ` + ) + .addRaw( + ` +
+ +${unknownDestinationsHeaderString} + +${unknownDestinationsTableString} +
+ ` + ) + .addRaw( + ` +
+ +${knownDestinationsHeaderString} + +${knownDestinationsTableString} +
+ ` ) - .addTable(table) .addLink( 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' From bd9399fa364e707f8f872012b9cde6db4e9cfc5b Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 16:31:03 +0530 Subject: [PATCH 20/36] known/unknown destinations --- badges/coverage.svg | 2 +- dist/index.js | 53 ++++++++++++++++++++++++--------------------- src/summary.js | 53 ++++++++++++++++++++++++--------------------- 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index 2dfab49..b934318 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 8.47%Coverage8.47% \ No newline at end of file +Coverage: 8.54%Coverage8.54% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 92da707..8e2a05f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26237,6 +26237,15 @@ function getUniqueBy(arr, keys) { return Object.values(uniqueObj) } +function resultToRow(result) { + return [ + result.destination, + result.scheme, + result.rule_name, + actionString(result.action) + ] +} + async function generateSummary() { const boltUser = core.getState('boltUser') const mode = core.getInput('mode') @@ -26252,15 +26261,8 @@ async function generateSummary() { const results = await generateTestResults(boltUser) - const uniqueResults = getUniqueBy(results, ['destination', 'scheme']).map( - result => [ - result.destination, - result.scheme, - result.rule_name, - actionString(result.action), - result.default - ] - ) + const uniqueResults = getUniqueBy(results, ['destination', 'scheme']) + // const uniqueResultRows = uniqueResults.map(resultToRow) const githubAccountCalls = results.filter(result => { return result.trusted_github_account_flag !== undefined @@ -26307,7 +26309,7 @@ async function generateSummary() { ], ...uniqueResults .filter(result => result.default || result.action === 'allow') - .map(result => result.slice(0, 4)) + .map(resultToRow) ] const unknownDestinations = [ @@ -26319,7 +26321,7 @@ async function generateSummary() { ], ...uniqueResults .filter(result => result.default === false && result.action === 'block') - .map(result => result.slice(0, 4)) + .map(resultToRow) ] core.info('Koalalab-inc-bolt-config>>>') @@ -26366,10 +26368,8 @@ async function generateSummary() { .stringify() core.summary.clear() - let summary = core.summary - .addHeading('⚑ Egress Report - powered by Bolt', 2) - .addRaw( - ` + core.summary.addHeading('⚑ Egress Report - powered by Bolt', 2).addRaw( + `
${configHeaderString} @@ -26377,28 +26377,31 @@ ${configHeaderString} ${configTableString}
` - ) + ) if (egressRules.length > 0) { - summary = summary + core.summary .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') } else { - summary = summary.addRaw(` + core.summary + .addRaw( + ` > [!NOTE] -> You have not configured egress rules. Only deault policy will be applied. See [documentation]https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. - `) +> You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. + ` + ) + .addEOL() } if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) - .addRaw(` + core.summary.addHeading('🚨 Untrusted Github Accounts Found', 3).addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { - summary = summary.addRaw(` + core.summary.addRaw(`
${account.name} @@ -26411,7 +26414,7 @@ ${configTableString} } } - summary = summary + core.summary .addHeading('Egress Traffic', 3) .addRaw( ` @@ -26444,7 +26447,7 @@ ${knownDestinationsTableString} 'https://www.koalalab.com' ) - summary.write() + core.summary.write() } module.exports = { generateSummary } diff --git a/src/summary.js b/src/summary.js index fd8392f..dc11a7c 100644 --- a/src/summary.js +++ b/src/summary.js @@ -53,6 +53,15 @@ function getUniqueBy(arr, keys) { return Object.values(uniqueObj) } +function resultToRow(result) { + return [ + result.destination, + result.scheme, + result.rule_name, + actionString(result.action) + ] +} + async function generateSummary() { const boltUser = core.getState('boltUser') const mode = core.getInput('mode') @@ -68,15 +77,8 @@ async function generateSummary() { const results = await generateTestResults(boltUser) - const uniqueResults = getUniqueBy(results, ['destination', 'scheme']).map( - result => [ - result.destination, - result.scheme, - result.rule_name, - actionString(result.action), - result.default - ] - ) + const uniqueResults = getUniqueBy(results, ['destination', 'scheme']) + // const uniqueResultRows = uniqueResults.map(resultToRow) const githubAccountCalls = results.filter(result => { return result.trusted_github_account_flag !== undefined @@ -123,7 +125,7 @@ async function generateSummary() { ], ...uniqueResults .filter(result => result.default || result.action === 'allow') - .map(result => result.slice(0, 4)) + .map(resultToRow) ] const unknownDestinations = [ @@ -135,7 +137,7 @@ async function generateSummary() { ], ...uniqueResults .filter(result => result.default === false && result.action === 'block') - .map(result => result.slice(0, 4)) + .map(resultToRow) ] core.info('Koalalab-inc-bolt-config>>>') @@ -182,10 +184,8 @@ async function generateSummary() { .stringify() core.summary.clear() - let summary = core.summary - .addHeading('⚑ Egress Report - powered by Bolt', 2) - .addRaw( - ` + core.summary.addHeading('⚑ Egress Report - powered by Bolt', 2).addRaw( + `
${configHeaderString} @@ -193,28 +193,31 @@ ${configHeaderString} ${configTableString}
` - ) + ) if (egressRules.length > 0) { - summary = summary + core.summary .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') } else { - summary = summary.addRaw(` + core.summary + .addRaw( + ` > [!NOTE] -> You have not configured egress rules. Only deault policy will be applied. See [documentation]https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. - `) +> You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. + ` + ) + .addEOL() } if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) - .addRaw(` + core.summary.addHeading('🚨 Untrusted Github Accounts Found', 3).addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { - summary = summary.addRaw(` + core.summary.addRaw(`
${account.name} @@ -227,7 +230,7 @@ ${configTableString} } } - summary = summary + core.summary .addHeading('Egress Traffic', 3) .addRaw( ` @@ -260,7 +263,7 @@ ${knownDestinationsTableString} 'https://www.koalalab.com' ) - summary.write() + core.summary.write() } module.exports = { generateSummary } From 2e44e6e503cf1dfb990d7f129329c313076e5cf2 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 16:54:44 +0530 Subject: [PATCH 21/36] summary duplicate fix --- dist/index.js | 35 +++++++++++++++++++---------------- src/summary.js | 35 +++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/dist/index.js b/dist/index.js index 8e2a05f..cf7dd57 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26341,35 +26341,37 @@ async function generateSummary() { core.info('<< ${configHeaderString} @@ -26377,14 +26379,14 @@ ${configHeaderString} ${configTableString}
` - ) + ) if (egressRules.length > 0) { - core.summary + summary = summary .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') } else { - core.summary + summary = summary .addRaw( ` > [!NOTE] @@ -26395,13 +26397,14 @@ ${configTableString} } if (untrustedGithubAccounts.length > 0) { - core.summary.addHeading('🚨 Untrusted Github Accounts Found', 3).addRaw(` + summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) + .addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { - core.summary.addRaw(` + summary = summary.addRaw(`
${account.name} @@ -26414,7 +26417,7 @@ ${configTableString} } } - core.summary + summary = summary .addHeading('Egress Traffic', 3) .addRaw( ` @@ -26434,7 +26437,7 @@ ${unknownDestinationsTableString} ) .addRaw( ` -
+
${knownDestinationsHeaderString} @@ -26447,7 +26450,7 @@ ${knownDestinationsTableString} 'https://www.koalalab.com' ) - core.summary.write() + summary.write() } module.exports = { generateSummary } diff --git a/src/summary.js b/src/summary.js index dc11a7c..12e25df 100644 --- a/src/summary.js +++ b/src/summary.js @@ -157,35 +157,37 @@ async function generateSummary() { core.info('<< ${configHeaderString} @@ -193,14 +195,14 @@ ${configHeaderString} ${configTableString}
` - ) + ) if (egressRules.length > 0) { - core.summary + summary = summary .addHeading('πŸ“ Egress rules', 3) .addCodeBlock(egressRulesYAML, 'yaml') } else { - core.summary + summary = summary .addRaw( ` > [!NOTE] @@ -211,13 +213,14 @@ ${configTableString} } if (untrustedGithubAccounts.length > 0) { - core.summary.addHeading('🚨 Untrusted Github Accounts Found', 3).addRaw(` + summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) + .addRaw(` > [!CAUTION] > If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. `) for (const account of untrustedGithubAccounts) { - core.summary.addRaw(` + summary = summary.addRaw(`
${account.name} @@ -230,7 +233,7 @@ ${configTableString} } } - core.summary + summary = summary .addHeading('Egress Traffic', 3) .addRaw( ` @@ -250,7 +253,7 @@ ${unknownDestinationsTableString} ) .addRaw( ` -
+
${knownDestinationsHeaderString} @@ -263,7 +266,7 @@ ${knownDestinationsTableString} 'https://www.koalalab.com' ) - core.summary.write() + summary.write() } module.exports = { generateSummary } From 83e967e4405106e667f231851351d1726a4097f1 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 17:50:01 +0530 Subject: [PATCH 22/36] updated README --- .github/workflows/release.yml | 2 +- README.md | 3 +++ dist/index.js | 26 ++++++++++---------------- src/intercept.py | 3 ++- src/summary.js | 26 ++++++++++---------------- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d32401..7d025bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Get release version id: releaseVersion - run: echo "releaseVersion=$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)" >> $GITHUB_ENV + run: echo "releaseVersion=\"$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)\"" >> $GITHUB_ENV - name: Check if releaseVersion is same as tag run: | if [ "${{ env.tag }}" != "${{ env.releaseVersion }}" ]; then diff --git a/README.md b/README.md index bf81867..4d7231e 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ You can configuree the Bolt action using inputs. Here is an example of how to co mode: 'audit' default_policy: 'block-all' allow_http: 'false' + trusted_github_accounts: | + - 'akto-api-security' egress_rules: | - name: 'Allow GitHub subs' destination: '*.github.com' @@ -52,6 +54,7 @@ You can configuree the Bolt action using inputs. Here is an example of how to co | `mode` | Configure the mode of operation for the Bolt gateway. It can be `audit` or `active`. Default: `audit` | | `default_policy` | It can be either `block-all` or `allow-all`. Default: `block-all` | | `allow_http` | Whether to allow non-secure HTTP requests or not. Default: `false` +| `trusted_github_accounts` | A list of trusted GitHub accounts. Default: `[]`. The account in which workflow is running will always be trusted. | `egress_rules` | A list of custom egress rules to be applied. Default: `[]`. ## Custom Egress Policy diff --git a/dist/index.js b/dist/index.js index cf7dd57..294625b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26387,11 +26387,8 @@ ${configTableString} .addCodeBlock(egressRulesYAML, 'yaml') } else { summary = summary - .addRaw( - ` -> [!NOTE] -> You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. - ` + .addQuote( + 'NOTE: You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information.' ) .addEOL() } @@ -26400,7 +26397,7 @@ ${configTableString} summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) .addRaw(` > [!CAUTION] -> If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. +> If you do not recognize these Github Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. `) for (const account of untrustedGithubAccounts) { @@ -26419,11 +26416,8 @@ ${configTableString} summary = summary .addHeading('Egress Traffic', 3) - .addRaw( - ` -> [!NOTE] -> Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode. - ` + .addQuote( + 'NOTE: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' ) .addRaw( ` @@ -26444,11 +26438,11 @@ ${knownDestinationsHeaderString} ${knownDestinationsTableString}
` - ) - .addLink( - 'View detailed analysis of this run on Koalalab!', - 'https://www.koalalab.com' - ) + ).addRaw(` + + View detailed analysis of this run on Koalalab! + + `) summary.write() } diff --git a/src/intercept.py b/src/intercept.py index 04f45a8..bcca36d 100644 --- a/src/intercept.py +++ b/src/intercept.py @@ -198,6 +198,7 @@ def wildcard_to_regex(self, wildcard_destination): regex_pattern = "^" + regex_pattern + "$" return re.compile(regex_pattern) + # pylint: disable=too-many-branches def tls_clienthello(self, data): default_policy = self.default_policy destination = data.client_hello.sni @@ -341,7 +342,7 @@ def request(self, flow): break if trusted_github_account_flag is None: trusted_github_account_flag = False - + if applied_rule is not None: default_rules_applied = applied_rule.get("default", False) else: diff --git a/src/summary.js b/src/summary.js index 12e25df..62f1503 100644 --- a/src/summary.js +++ b/src/summary.js @@ -203,11 +203,8 @@ ${configTableString} .addCodeBlock(egressRulesYAML, 'yaml') } else { summary = summary - .addRaw( - ` -> [!NOTE] -> You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information. - ` + .addQuote( + 'NOTE: You have not configured egress rules. Only deault policy will be applied. See [documentation](https://github.com/koalalab-inc/bolt/blob/main/README.md#custom-egress-policy) for more information.' ) .addEOL() } @@ -216,7 +213,7 @@ ${configTableString} summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) .addRaw(` > [!CAUTION] -> If you are not expecting these accounts to be making requests, you may want to investigate further. To avoid getting reports about these accounts, you can add them to the trusted_github_accounts. +> If you do not recognize these Github Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. `) for (const account of untrustedGithubAccounts) { @@ -235,11 +232,8 @@ ${configTableString} summary = summary .addHeading('Egress Traffic', 3) - .addRaw( - ` -> [!NOTE] -> Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode. - ` + .addQuote( + 'NOTE: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.' ) .addRaw( ` @@ -260,11 +254,11 @@ ${knownDestinationsHeaderString} ${knownDestinationsTableString}
` - ) - .addLink( - 'View detailed analysis of this run on Koalalab!', - 'https://www.koalalab.com' - ) + ).addRaw(` + + View detailed analysis of this run on Koalalab! + + `) summary.write() } From 17a158e981b94781bd85f18e7b7c1ef0692019bf Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 18:23:28 +0530 Subject: [PATCH 23/36] fixed Koala Link --- dist/index.js | 4 +--- src/summary.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 294625b..84b22a2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26439,9 +26439,7 @@ ${knownDestinationsTableString}
` ).addRaw(` - - View detailed analysis of this run on Koalalab! - +[View detailed analysis of this run on Koalalab!](https://www.koalalab.com){:target="_blank", :rel="noreferrer"} `) summary.write() diff --git a/src/summary.js b/src/summary.js index 62f1503..babc817 100644 --- a/src/summary.js +++ b/src/summary.js @@ -255,9 +255,7 @@ ${knownDestinationsTableString}
` ).addRaw(` - - View detailed analysis of this run on Koalalab! - +[View detailed analysis of this run on Koalalab!](https://www.koalalab.com){:target="_blank", :rel="noreferrer"} `) summary.write() From 9a4a264fd3dc1facb2997d79d7575bcabdea4393 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 18:57:59 +0530 Subject: [PATCH 24/36] trusted github accounts config in summary --- badges/coverage.svg | 2 +- dist/index.js | 70 ++++++++++++++++++++++++++++++++++++--------- src/main.js | 21 ++++++++++---- src/summary.js | 49 +++++++++++++++++++++++++------ 4 files changed, 113 insertions(+), 29 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index b934318..8373463 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 8.54%Coverage8.54% \ No newline at end of file +Coverage: 8.06%Coverage8.06% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 84b22a2..65a6c6b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26129,8 +26129,6 @@ async function run() { core.info('Starting bolt...') await exec('sudo systemctl start bolt') core.info('Waiting for bolt to start...') - const ms = 2000 - await wait(ms) await exec('sudo systemctl status bolt') core.info('Starting bolt... done') core.endGroup('run-bolt') @@ -26139,10 +26137,21 @@ async function run() { core.startGroup('trust-bolt-certificate') core.info('Trust bolt certificate...') - await exec( - `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` - ) - await exec('sudo update-ca-certificates') + const ms = 500 + for (let i = 1; i <= 10; i++) { + try { + await wait(ms) + await exec( + `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` + ) + await exec('sudo update-ca-certificates') + break + } + catch (error) { + core.info(`waiting for bolt to start, retrying in ${ms}ms...`) + } + } + core.info('Trust bolt certificate... done') core.endGroup('trust-bolt-certificate') benchmark('trust-bolt-certificate') @@ -26252,9 +26261,13 @@ async function generateSummary() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') + const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') // Verify that egress_rules_yaml is valid YAML + let egressRules + let trustedGithubAccounts try { - const egressRules = YAML.parse(egressRulesYAML) + egressRules = YAML.parse(egressRulesYAML) + trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) } catch (error) { core.info(`Invalid YAML: ${error.message}`) } @@ -26324,12 +26337,14 @@ async function generateSummary() { .map(resultToRow) ] + const trustedGithubAccountsData = [ + [{ data: 'Github Account', header: true }, ...trustedGithubAccounts] + ] + core.info('Koalalab-inc-bolt-config>>>') core.info(JSON.stringify(configMap)) core.info('<<>>') core.info(JSON.stringify(egressRules)) core.info('<< 0) { + summary = summary + .addRaw( + ` +
+ + ${trustedGithubAccountsHeaderString} + + ${trustedGithubAccountsTableString} +
+ ` + ) + .addQuote('NOTE: The account in which workflow runs is always trusted.') + } + if (egressRules.length > 0) { summary = summary .addHeading('πŸ“ Egress rules', 3) @@ -26438,9 +26478,11 @@ ${knownDestinationsHeaderString} ${knownDestinationsTableString}
` - ).addRaw(` -[View detailed analysis of this run on Koalalab!](https://www.koalalab.com){:target="_blank", :rel="noreferrer"} - `) + ) + .addLink( + 'View detailed analysis of this run on Koalalab!', + 'https://www.koalalab.com' + ) summary.write() } diff --git a/src/main.js b/src/main.js index cf47d0e..f40a536 100644 --- a/src/main.js +++ b/src/main.js @@ -148,8 +148,6 @@ async function run() { core.info('Starting bolt...') await exec('sudo systemctl start bolt') core.info('Waiting for bolt to start...') - const ms = 2000 - await wait(ms) await exec('sudo systemctl status bolt') core.info('Starting bolt... done') core.endGroup('run-bolt') @@ -158,10 +156,21 @@ async function run() { core.startGroup('trust-bolt-certificate') core.info('Trust bolt certificate...') - await exec( - `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` - ) - await exec('sudo update-ca-certificates') + const ms = 500 + for (let i = 1; i <= 10; i++) { + try { + await wait(ms) + await exec( + `sudo cp /home/${boltUser}/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/bolt.crt` + ) + await exec('sudo update-ca-certificates') + break + } + catch (error) { + core.info(`waiting for bolt to start, retrying in ${ms}ms...`) + } + } + core.info('Trust bolt certificate... done') core.endGroup('trust-bolt-certificate') benchmark('trust-bolt-certificate') diff --git a/src/summary.js b/src/summary.js index babc817..3137794 100644 --- a/src/summary.js +++ b/src/summary.js @@ -68,9 +68,13 @@ async function generateSummary() { const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') + const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') // Verify that egress_rules_yaml is valid YAML + let egressRules + let trustedGithubAccounts try { - const egressRules = YAML.parse(egressRulesYAML) + egressRules = YAML.parse(egressRulesYAML) + trustedGithubAccounts = YAML.parse(trustedGithubAccountsYAML) } catch (error) { core.info(`Invalid YAML: ${error.message}`) } @@ -140,12 +144,14 @@ async function generateSummary() { .map(resultToRow) ] + const trustedGithubAccountsData = [ + [{ data: 'Github Account', header: true }, ...trustedGithubAccounts] + ] + core.info('Koalalab-inc-bolt-config>>>') core.info(JSON.stringify(configMap)) core.info('<<>>') core.info(JSON.stringify(egressRules)) core.info('<< 0) { + summary = summary + .addRaw( + ` +
+ + ${trustedGithubAccountsHeaderString} + + ${trustedGithubAccountsTableString} +
+ ` + ) + .addQuote('NOTE: The account in which workflow runs is always trusted.') + } + if (egressRules.length > 0) { summary = summary .addHeading('πŸ“ Egress rules', 3) @@ -254,9 +285,11 @@ ${knownDestinationsHeaderString} ${knownDestinationsTableString}
` - ).addRaw(` -[View detailed analysis of this run on Koalalab!](https://www.koalalab.com){:target="_blank", :rel="noreferrer"} - `) + ) + .addLink( + 'View detailed analysis of this run on Koalalab!', + 'https://www.koalalab.com' + ) summary.write() } From cc7ed4bfe6db20a7050ba98b7375178a0ba803fc Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 19:20:56 +0530 Subject: [PATCH 25/36] separators in summary --- dist/index.js | 14 ++++++++++---- src/summary.js | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/dist/index.js b/dist/index.js index 65a6c6b..8f0e293 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26338,7 +26338,8 @@ async function generateSummary() { ] const trustedGithubAccountsData = [ - [{ data: 'Github Account', header: true }, ...trustedGithubAccounts] + [{ data: 'Github Account', header: true }], + ...trustedGithubAccounts ] core.info('Koalalab-inc-bolt-config>>>') @@ -26394,6 +26395,8 @@ async function generateSummary() { core.summary.emptyBuffer() let summary = core.summary + .addSeparator() + .addEOL() .addHeading('⚑ Egress Report - powered by Bolt', 2) .addRaw( ` @@ -26434,10 +26437,12 @@ ${configTableString} } if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) - .addRaw(` + summary = summary.addHeading( + '🚨 Requests to untrusted GitHub accounts found', + 3 + ).addRaw(` > [!CAUTION] -> If you do not recognize these Github Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. +> If you do not recognize these GitHub Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. `) for (const account of untrustedGithubAccounts) { @@ -26483,6 +26488,7 @@ ${knownDestinationsTableString} 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' ) + .addSeparator() summary.write() } diff --git a/src/summary.js b/src/summary.js index 3137794..97f7c82 100644 --- a/src/summary.js +++ b/src/summary.js @@ -145,7 +145,8 @@ async function generateSummary() { ] const trustedGithubAccountsData = [ - [{ data: 'Github Account', header: true }, ...trustedGithubAccounts] + [{ data: 'Github Account', header: true }], + ...trustedGithubAccounts ] core.info('Koalalab-inc-bolt-config>>>') @@ -201,6 +202,8 @@ async function generateSummary() { core.summary.emptyBuffer() let summary = core.summary + .addSeparator() + .addEOL() .addHeading('⚑ Egress Report - powered by Bolt', 2) .addRaw( ` @@ -241,10 +244,12 @@ ${configTableString} } if (untrustedGithubAccounts.length > 0) { - summary = summary.addHeading('🚨 Untrusted Github Accounts Found', 3) - .addRaw(` + summary = summary.addHeading( + '🚨 Requests to untrusted GitHub accounts found', + 3 + ).addRaw(` > [!CAUTION] -> If you do not recognize these Github Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. +> If you do not recognize these GitHub Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. `) for (const account of untrustedGithubAccounts) { @@ -290,6 +295,7 @@ ${knownDestinationsTableString} 'View detailed analysis of this run on Koalalab!', 'https://www.koalalab.com' ) + .addSeparator() summary.write() } From ddb41e3ddacf3bfeae7bdfba6ca1afa38d60ab8d Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 19:28:32 +0530 Subject: [PATCH 26/36] fixed gh accounts table --- badges/coverage.svg | 2 +- dist/index.js | 2 +- src/summary.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index 8373463..b08bfe2 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 8.06%Coverage8.06% \ No newline at end of file +Coverage: 8.03%Coverage8.03% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 8f0e293..d8e4c36 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26339,7 +26339,7 @@ async function generateSummary() { const trustedGithubAccountsData = [ [{ data: 'Github Account', header: true }], - ...trustedGithubAccounts + ...trustedGithubAccounts.map(account => [account]) ] core.info('Koalalab-inc-bolt-config>>>') diff --git a/src/summary.js b/src/summary.js index 97f7c82..49c4378 100644 --- a/src/summary.js +++ b/src/summary.js @@ -146,7 +146,7 @@ async function generateSummary() { const trustedGithubAccountsData = [ [{ data: 'Github Account', header: true }], - ...trustedGithubAccounts + ...trustedGithubAccounts.map(account => [account]) ] core.info('Koalalab-inc-bolt-config>>>') From 05f1482ac893c233537c1da0d7e1cbc85d53c124 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 19:39:52 +0530 Subject: [PATCH 27/36] fixed shell-check issue --- .github/workflows/release.yml | 2 +- README.md | 84 ++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d025bc..e1edd2b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Get release version id: releaseVersion - run: echo "releaseVersion=\"$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)\"" >> $GITHUB_ENV + run: echo "releaseVersion=\"$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)\"" >> "$GITHUB_ENV" - name: Check if releaseVersion is same as tag run: | if [ "${{ env.tag }}" != "${{ env.releaseVersion }}" ]; then diff --git a/README.md b/README.md index 4d7231e..aa449f1 100644 --- a/README.md +++ b/README.md @@ -94,23 +94,67 @@ It is an ordered list of rules. The first rule that matches the destination will ## Report Once the job is over, bolt will add a egress traffic report to the job summary. The report will show the egress traffic and the rules that were applied. A sample report is shown below. -### Egress Report - powered by Bolt -#### Bolt Configuration - -|Option | Value | -|---|---| -| Mode | audit | -| Default Policy | block-all | -| Allow HTTP | false | - -#### Custom Egress Rules -```yaml -- name: 'Allow ifconfig.me' - action: 'allow' - destinatiom: 'ifconfig.me' -``` -#### Egress Traffic -> [!NOTE] -> -> Running in Audit mode. Unverified destinations will be blocked in Active mode. -
DestinationSchemeRuleAction
github.comhttpsReqd by GitHub Actionβœ…
packages.microsoft.comhttpsDefault Policy - block-allUnknown Destination
results-receiver.actions.githubusercontent.comhttpsReqd by GitHub Actionβœ…
ppa.launchpadcontent.nethttpsDefault Policy - block-allUnknown Destination
esm.ubuntu.comhttpsDefault Policy - block-allUnknown Destination
azure.archive.ubuntu.comhttpallow_http is FalseUnknown Destination
www.google.comhttpsDefault Policy - block-allUnknown Destination
ifconfig.mehttpsAllow ifconfig.meβœ…
pipelinesghubeus6.actions.githubusercontent.comhttpsReqd by GitHub Actionβœ…
+
+ +

⚑ Egress Report - powered by Bolt

+ +
+ +

πŸ› οΈ Bolt Configuration

+ +
+
Modeaudit
Allow HTTPfalse
Default Policyblock-all
+ +
+ +
+ +

πŸ”’ Trusted Github Accounts

+ +
+
Github Account
akto-api-security
+ +
+
NOTE: The account in which workflow runs is always trusted.
+

πŸ“ Egress rules

+
- destination: google.com
+  action: block
+  name: Block Google
+- destination: ifconfig.me
+  action: allow
+  name: Allow ifconfig.me
+

🚨 Requests to untrusted GitHub accounts found

+ +> [!CAUTION] +> If you do not recognize these GitHub Accounts, you may want to investigate further. Add them to your trusted GitHub accounts if this is expected. See [Docs](https://github.com/koalalab-inc/bolt?tab=readme-ov-file#configure) for more information. + +
+ + razorpay + +
    +
  • /orgs/razorpay/repos
  • +
+
+

Egress Traffic

+
NOTE: Running in Audit mode. Unknown/unverified destinations will be blocked in Active mode.
+ +
+ +

🚨 Unknown Destinations

+ +
+
DestinationSchemeRuleAction
www.google.comhttpsDefault Policy - block-allUnknown Destination
+ +
+ +
+ +

βœ… Known Destinations

+ +
+
DestinationSchemeRuleAction
github.comhttpsReqd by Github Actionβœ…
pipelinesghubeus6.actions.githubusercontent.comhttpsReqd by Github Actionβœ…
results-receiver.actions.githubusercontent.comhttpsReqd by Github Actionβœ…
ifconfig.mehttpsAllow ifconfig.meβœ…
api.github.comhttpsReqd by Github Actionβœ…
+ +
+ View detailed analysis of this run on Koalalab! +
\ No newline at end of file From ef337a09dae58b947b2fa250cbaf874f3d1fbc8b Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 19:45:49 +0530 Subject: [PATCH 28/36] removed light logo for marketplace compatibility --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index aa449f1..58e33f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -![Bolt](assets/imgs/bolt-header-light.png#gh-light-mode-only) -![Bolt](assets/imgs/bolt-header-dark.png#gh-dark-mode-only) +![Bolt](assets/imgs/bolt-header-dark.png) ## Secure GitHub actions with 1 line of code Add this step to jobs in your GitHub workflow file(s) to secure your runner: ```yaml From 741ef066ab627083ce00cb5267386601194bf7be Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 19:51:46 +0530 Subject: [PATCH 29/36] pinned actions --- .github/workflows/check-dist.yml | 6 +++--- .github/workflows/ci.yml | 6 +++--- .github/workflows/linter.yml | 6 +++--- .github/workflows/release.yml | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml index 580613f..f7fae3e 100644 --- a/.github/workflows/check-dist.yml +++ b/.github/workflows/check-dist.yml @@ -30,11 +30,11 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 - name: Setup Node.js id: setup-node - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # actions/setup-node@v4 | v4.0.2 with: node-version-file: .node-version cache: npm @@ -62,7 +62,7 @@ jobs: - if: ${{ failure() && steps.diff.outcome == 'failure' }} name: Upload Artifact id: upload - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # actions/upload-artifact@v4 | v4.3.1 with: name: dist path: dist/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23e1cc5..07f624c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,11 +17,11 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 - name: Setup Node.js id: setup-node - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # actions/setup-node@v4 | v4.0.2 with: node-version-file: .node-version cache: npm @@ -49,4 +49,4 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 6cb7c3e..d0962e8 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -19,13 +19,13 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 with: fetch-depth: 0 - name: Setup Node.js id: setup-node - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # actions/setup-node@v4 | v4.0.2 with: node-version-file: .node-version cache: npm @@ -36,7 +36,7 @@ jobs: - name: Lint Codebase id: super-linter - uses: super-linter/super-linter/slim@v6 + uses: super-linter/super-linter/slim@e0fc164bba85f4b58c6cd17ba1dfd435d01e8a06 # super-linter/super-linter/slim@v6 env: DEFAULT_BRANCH: main FILTER_REGEX_EXCLUDE: dist/**/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e1edd2b..d562690 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: arch: x86_64 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 - name: Get release version id: releaseVersion run: echo "releaseVersion=\"$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)\"" >> "$GITHUB_ENV" @@ -40,7 +40,7 @@ jobs: rm -rf mitmproxy bolt rm mitmproxy-10.2.2-linux-x86_64.tar.gz - name: Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # softprops/action-gh-release@v2 with: files: bolt-${{ env.tag }}-${{ env.os }}-${{ env.arch }}.tar.gz tag_name: ${{ env.tag }} From 2edd3893870d921030fd7b00a529c5a0c4b35016 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 21:43:35 +0530 Subject: [PATCH 30/36] added checks for linux platform --- __tests__/index.test.js | 12 +++- badges/coverage.svg | 2 +- dist/index.js | 125 +++++++++++++++++++++++++++++----------- src/index.js | 47 ++++++++++++--- src/main.js | 11 +++- src/summary.js | 22 +++++-- 6 files changed, 169 insertions(+), 50 deletions(-) diff --git a/__tests__/index.test.js b/__tests__/index.test.js index 0b20ef9..7296dea 100644 --- a/__tests__/index.test.js +++ b/__tests__/index.test.js @@ -10,9 +10,17 @@ jest.mock('../src/main', () => ({ })) describe('index', () => { - it('calls run when imported', async () => { - require('../src/index') + it('calls run when imported on linux', async () => { + const { init } = require('../src/index') + init('linux', 'x64') expect(run).toHaveBeenCalled() }) + + it('fails when imported on platform other than linux', async () => { + const { init } = require('../src/index') + init('darwin', 'x64') + + expect(run).not.toHaveBeenCalled() + }) }) diff --git a/badges/coverage.svg b/badges/coverage.svg index b08bfe2..2f6382b 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 8.03%Coverage8.03% \ No newline at end of file +Coverage: 11.82%Coverage11.82% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index d8e4c36..e82dfa7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -25974,6 +25974,65 @@ WantedBy=multi-user.target module.exports = { boltService } +/***/ }), + +/***/ 4351: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * The entrypoint for the action. + */ +const { run } = __nccwpck_require__(1713) +const { generateSummary } = __nccwpck_require__(7259) +const core = __nccwpck_require__(2186) +const os = __nccwpck_require__(2037) + +const isPost = core.getState('isPost') +const flag = isPost === 'true' +const boltFailed = core.getState('boltFailed') +const failedFlag = boltFailed === 'true' + +function init(platform, arch) { + if (flag) { + if (failedFlag) { + core.info('Skipping post action as bolt failed') + return + } + // Post + generateSummary() + } else { + if (!isPost) { + core.saveState('isPost', 'true') + } + + // 'win32' | 'darwin' | 'linux' | 'freebsd' | 'openbsd' | 'android' | 'cygwin' | 'sunos' + if (['linux'].indexOf(platform) === -1) { + core.saveState('boltFailed', 'true') + core.setFailed(`This action is not supported on ${platform}`) + return + } + // Possible Archs + // 'x64' | 'arm' | 'arm64' | 'ia32' | 'mips' | 'mipsel' | 'ppc' | 'ppc64' | 'riscv64' | 's390' | 's390x' + const allowedArch = ['x64', 'arm64', 'arm'] + if (allowedArch.indexOf(arch) === -1) { + core.saveState('boltFailed', 'true') + core.setFailed(`This action is not supported on ${arch}`) + return + } + + run() + } +} + +const platform = os.platform() +const arch = os.arch() +init(platform, arch) + +module.exports = { + init +} + + /***/ }), /***/ 1713: @@ -26008,9 +26067,17 @@ async function run() { // Changing boltUser will require changes in bolt.service and intercept.py const boltUser = 'bolt' + core.saveState('boltUser', boltUser) + + const outputFile = 'output.log' + core.saveState('outputFile', outputFile) + + const homeDir = `/home/${boltUser}` + core.saveState('homeDir', homeDir) + const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt const repoOwner = repoName.split('/')[0]; // e.g. koalalab-inc - core.saveState('boltUser', boltUser) + core.startGroup('create-bolt-user') core.info('Creating bolt user...') @@ -26177,6 +26244,7 @@ async function run() { benchmark('setup-iptables-redirection') } catch (error) { // Fail the workflow run if an error occurs + core.saveState('boltFailed', 'true') core.setFailed(error.message) } } @@ -26196,11 +26264,7 @@ const { exec } = __nccwpck_require__(1514) const fs = __nccwpck_require__(7147) const YAML = __nccwpck_require__(4083) -async function generateTestResults(boltUser) { - const filePath = 'output.log' - await exec(`sudo cp /home/${boltUser}/${filePath} output.log`) - await exec(`sudo chown -R runner:docker ${filePath}`) - +async function generateTestResults(filePath) { try { // Read the entire file synchronously and split it into an array of lines const fileContent = fs.readFileSync(filePath, 'utf-8') @@ -26256,12 +26320,26 @@ function resultToRow(result) { } async function generateSummary() { + const outputFile = core.getState('outputFile') + const homeDir = core.getState('homeDir') const boltUser = core.getState('boltUser') const mode = core.getInput('mode') const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') + + if (!outputFile || !boltUser || !homeDir) { + core.info(`Invalid Bold run. Missing required state variables`) + return + } + if (!fs.existsSync(`${homeDir}/${outputFile}`)) { + core.info(`Bolt output file not found`) + return + } + + await exec(`sudo cp ${homeDir}/${outputFile} ${outputFile}`) + // Verify that egress_rules_yaml is valid YAML let egressRules let trustedGithubAccounts @@ -26272,7 +26350,7 @@ async function generateSummary() { core.info(`Invalid YAML: ${error.message}`) } - const results = await generateTestResults(boltUser) + const results = await generateTestResults(outputFile) const uniqueResults = getUniqueBy(results, ['destination', 'scheme']) // const uniqueResultRows = uniqueResults.map(resultToRow) @@ -36887,31 +36965,12 @@ exports.visitAsync = visitAsync; /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; /******/ /************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -/** - * The entrypoint for the action. - */ -const { run } = __nccwpck_require__(1713) -const { generateSummary } = __nccwpck_require__(7259) -const core = __nccwpck_require__(2186) - -const isPost = core.getState('isPost') -const flag = isPost === 'true' - -if (flag) { - // Post - generateSummary() -} else { - if (!isPost) { - core.saveState('isPost', 'true') - } - run() -} - -})(); - -module.exports = __webpack_exports__; +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(4351); +/******/ module.exports = __webpack_exports__; +/******/ /******/ })() ; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 023250d..90825bd 100644 --- a/src/index.js +++ b/src/index.js @@ -4,16 +4,49 @@ const { run } = require('./main') const { generateSummary } = require('./summary') const core = require('@actions/core') +const os = require('os') const isPost = core.getState('isPost') const flag = isPost === 'true' +const boltFailed = core.getState('boltFailed') +const failedFlag = boltFailed === 'true' -if (flag) { - // Post - generateSummary() -} else { - if (!isPost) { - core.saveState('isPost', 'true') +function init(platform, arch) { + if (flag) { + if (failedFlag) { + core.info('Skipping post action as bolt failed') + return + } + // Post + generateSummary() + } else { + if (!isPost) { + core.saveState('isPost', 'true') + } + + // 'win32' | 'darwin' | 'linux' | 'freebsd' | 'openbsd' | 'android' | 'cygwin' | 'sunos' + if (['linux'].indexOf(platform) === -1) { + core.saveState('boltFailed', 'true') + core.setFailed(`This action is not supported on ${platform}`) + return + } + // Possible Archs + // 'x64' | 'arm' | 'arm64' | 'ia32' | 'mips' | 'mipsel' | 'ppc' | 'ppc64' | 'riscv64' | 's390' | 's390x' + const allowedArch = ['x64', 'arm64', 'arm'] + if (allowedArch.indexOf(arch) === -1) { + core.saveState('boltFailed', 'true') + core.setFailed(`This action is not supported on ${arch}`) + return + } + + run() } - run() +} + +const platform = os.platform() +const arch = os.arch() +init(platform, arch) + +module.exports = { + init } diff --git a/src/main.js b/src/main.js index f40a536..03601b5 100644 --- a/src/main.js +++ b/src/main.js @@ -27,9 +27,17 @@ async function run() { // Changing boltUser will require changes in bolt.service and intercept.py const boltUser = 'bolt' + core.saveState('boltUser', boltUser) + + const outputFile = 'output.log' + core.saveState('outputFile', outputFile) + + const homeDir = `/home/${boltUser}` + core.saveState('homeDir', homeDir) + const repoName = process.env.GITHUB_REPOSITORY; // e.g. koalalab-inc/bolt const repoOwner = repoName.split('/')[0]; // e.g. koalalab-inc - core.saveState('boltUser', boltUser) + core.startGroup('create-bolt-user') core.info('Creating bolt user...') @@ -196,6 +204,7 @@ async function run() { benchmark('setup-iptables-redirection') } catch (error) { // Fail the workflow run if an error occurs + core.saveState('boltFailed', 'true') core.setFailed(error.message) } } diff --git a/src/summary.js b/src/summary.js index 49c4378..43d89b8 100644 --- a/src/summary.js +++ b/src/summary.js @@ -3,11 +3,7 @@ const { exec } = require('@actions/exec') const fs = require('fs') const YAML = require('yaml') -async function generateTestResults(boltUser) { - const filePath = 'output.log' - await exec(`sudo cp /home/${boltUser}/${filePath} output.log`) - await exec(`sudo chown -R runner:docker ${filePath}`) - +async function generateTestResults(filePath) { try { // Read the entire file synchronously and split it into an array of lines const fileContent = fs.readFileSync(filePath, 'utf-8') @@ -63,12 +59,26 @@ function resultToRow(result) { } async function generateSummary() { + const outputFile = core.getState('outputFile') + const homeDir = core.getState('homeDir') const boltUser = core.getState('boltUser') const mode = core.getInput('mode') const allowHTTP = core.getInput('allow_http') const defaultPolicy = core.getInput('default_policy') const egressRulesYAML = core.getInput('egress_rules') const trustedGithubAccountsYAML = core.getInput('trusted_github_accounts') + + if (!outputFile || !boltUser || !homeDir) { + core.info(`Invalid Bold run. Missing required state variables`) + return + } + if (!fs.existsSync(`${homeDir}/${outputFile}`)) { + core.info(`Bolt output file not found`) + return + } + + await exec(`sudo cp ${homeDir}/${outputFile} ${outputFile}`) + // Verify that egress_rules_yaml is valid YAML let egressRules let trustedGithubAccounts @@ -79,7 +89,7 @@ async function generateSummary() { core.info(`Invalid YAML: ${error.message}`) } - const results = await generateTestResults(boltUser) + const results = await generateTestResults(outputFile) const uniqueResults = getUniqueBy(results, ['destination', 'scheme']) // const uniqueResultRows = uniqueResults.map(resultToRow) From 7ab01327c2fe85ba159982766b0eab0ea8a5270e Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 21:58:29 +0530 Subject: [PATCH 31/36] platform related failure message --- badges/coverage.svg | 2 +- dist/index.js | 9 +++++++-- src/index.js | 9 +++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index 2f6382b..cacfd2e 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 11.82%Coverage11.82% \ No newline at end of file +Coverage: 5.71%Coverage5.71% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index e82dfa7..9e5c45f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -25986,6 +25986,7 @@ const { run } = __nccwpck_require__(1713) const { generateSummary } = __nccwpck_require__(7259) const core = __nccwpck_require__(2186) const os = __nccwpck_require__(2037) +const { releaseVersion } = __nccwpck_require__(9554) const isPost = core.getState('isPost') const flag = isPost === 'true' @@ -26008,7 +26009,9 @@ function init(platform, arch) { // 'win32' | 'darwin' | 'linux' | 'freebsd' | 'openbsd' | 'android' | 'cygwin' | 'sunos' if (['linux'].indexOf(platform) === -1) { core.saveState('boltFailed', 'true') - core.setFailed(`This action is not supported on ${platform}`) + core.setFailed( + `Koalalab-inc/bolt@${releaseVersion} is not supported on ${platform}` + ) return } // Possible Archs @@ -26016,7 +26019,9 @@ function init(platform, arch) { const allowedArch = ['x64', 'arm64', 'arm'] if (allowedArch.indexOf(arch) === -1) { core.saveState('boltFailed', 'true') - core.setFailed(`This action is not supported on ${arch}`) + core.setFailed( + `Koalalab-inc/bolt@${releaseVersion} is not supported on ${arch}` + ) return } diff --git a/src/index.js b/src/index.js index 90825bd..b62c700 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ const { run } = require('./main') const { generateSummary } = require('./summary') const core = require('@actions/core') const os = require('os') +const { releaseVersion } = require('./version') const isPost = core.getState('isPost') const flag = isPost === 'true' @@ -27,7 +28,9 @@ function init(platform, arch) { // 'win32' | 'darwin' | 'linux' | 'freebsd' | 'openbsd' | 'android' | 'cygwin' | 'sunos' if (['linux'].indexOf(platform) === -1) { core.saveState('boltFailed', 'true') - core.setFailed(`This action is not supported on ${platform}`) + core.setFailed( + `Koalalab-inc/bolt@${releaseVersion} is not supported on ${platform}` + ) return } // Possible Archs @@ -35,7 +38,9 @@ function init(platform, arch) { const allowedArch = ['x64', 'arm64', 'arm'] if (allowedArch.indexOf(arch) === -1) { core.saveState('boltFailed', 'true') - core.setFailed(`This action is not supported on ${arch}`) + core.setFailed( + `Koalalab-inc/bolt@${releaseVersion} is not supported on ${arch}` + ) return } From 544e0cc9dcb14600481cdfc40a75fd31ec0bcc6f Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 22:02:06 +0530 Subject: [PATCH 32/36] fix tests --- badges/coverage.svg | 2 +- dist/index.js | 39 +++++---------------------------------- src/version.js | 6 +++++- 3 files changed, 11 insertions(+), 36 deletions(-) diff --git a/badges/coverage.svg b/badges/coverage.svg index cacfd2e..578d43c 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 5.71%Coverage5.71% \ No newline at end of file +Coverage: 12.81%Coverage12.81% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 9e5c45f..e6e3c17 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26582,15 +26582,14 @@ module.exports = { generateSummary } /***/ }), /***/ 9554: -/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { +/***/ ((module) => { -"use strict"; -__nccwpck_require__.r(__webpack_exports__); -/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "releaseVersion": () => (/* binding */ releaseVersion) -/* harmony export */ }); const releaseVersion = 'v1.3.0-rc' +module.exports = { + releaseVersion +} + /***/ }), @@ -36937,34 +36936,6 @@ exports.visitAsync = visitAsync; /******/ } /******/ /************************************************************************/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __nccwpck_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __nccwpck_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ /******/ /* webpack/runtime/compat */ /******/ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; diff --git a/src/version.js b/src/version.js index ef99e26..5ab1798 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1,5 @@ -export const releaseVersion = 'v1.3.0-rc' +const releaseVersion = 'v1.3.0-rc' + +module.exports = { + releaseVersion +} From b5013e0ed4f9d5e60e3bb3f219f3d12c6e8bd12c Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 22:07:18 +0530 Subject: [PATCH 33/36] release version check fix --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d562690..7050b7a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # actions/checkout@v4 | 1567,v4.1.1 - name: Get release version id: releaseVersion - run: echo "releaseVersion=\"$(awk -F\' '/export const releaseVersion/ { print $2 }' src/version.js)\"" >> "$GITHUB_ENV" + run: echo "releaseVersion=\"$(awk -F\' '/const releaseVersion/ { print $2 }' src/version.js)\"" >> "$GITHUB_ENV" - name: Check if releaseVersion is same as tag run: | if [ "${{ env.tag }}" != "${{ env.releaseVersion }}" ]; then From 7b57230cb3053e5b94e64ddb5dac8dc2e7c0c989 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 22:20:47 +0530 Subject: [PATCH 34/36] added example workflow --- README.md | 3 ++- examples/bolt.yml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 examples/bolt.yml diff --git a/README.md b/README.md index 58e33f5..a220a22 100644 --- a/README.md +++ b/README.md @@ -156,4 +156,5 @@ Once the job is over, bolt will add a egress traffic report to the job summary. View detailed analysis of this run on Koalalab! -
\ No newline at end of file +
+This report was generated using this workflow file: [bolt-sample.yml](./examples/bolt.yml) \ No newline at end of file diff --git a/examples/bolt.yml b/examples/bolt.yml new file mode 100644 index 0000000..5b23bca --- /dev/null +++ b/examples/bolt.yml @@ -0,0 +1,47 @@ +############################################ +# Move this file to .github/worklows/bolt.yml +# in your repository to see Bolt in action. +############################################ +name: Bolt Example +permissions: + contents: read +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Bolt + uses: koalalab-inc/bolt@v1.3.0 + with: + trusted_github_accounts: | + - akto-api-security + egress_rules: | + - destination: google.com + action: block + name: Block Google + - destination: ifconfig.me + action: allow + name: Allow ifconfig.me + continue-on-error: true + - name: Checkout + uses: actions/checkout@v4 + - name: Curl Banned Domain + run: curl https://www.google.com + continue-on-error: true + - name: Curl Allowed Domain + run: curl https://ifconfig.me + continue-on-error: true + - name: Curl Some other Github Account API + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/orgs/akto-api-security/repos + continue-on-error: true + - name: Curl Some other Github Account + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/orgs/razorpay/repos + continue-on-error: true \ No newline at end of file From cdaa2e5a712ee3729d5098a37ae1c00de1bac3b1 Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 22:24:28 +0530 Subject: [PATCH 35/36] added ref of examples in readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a220a22..25ed648 100644 --- a/README.md +++ b/README.md @@ -157,4 +157,5 @@ Once the job is over, bolt will add a egress traffic report to the job summary. View detailed analysis of this run on Koalalab!
-This report was generated using this workflow file: [bolt-sample.yml](./examples/bolt.yml) \ No newline at end of file + +This report was generated using this workflow file: [bolt-sample.yml](examples/bolt.yml) \ No newline at end of file From e67091a978c99430bf010e4e761ab4232141a62d Mon Sep 17 00:00:00 2001 From: Abhishek Anand Date: Tue, 2 Apr 2024 22:30:37 +0530 Subject: [PATCH 36/36] version bump 1.3.0 --- dist/index.js | 2 +- src/version.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index e6e3c17..b7a1901 100644 --- a/dist/index.js +++ b/dist/index.js @@ -26584,7 +26584,7 @@ module.exports = { generateSummary } /***/ 9554: /***/ ((module) => { -const releaseVersion = 'v1.3.0-rc' +const releaseVersion = 'v1.3.0' module.exports = { releaseVersion diff --git a/src/version.js b/src/version.js index 5ab1798..06b625f 100644 --- a/src/version.js +++ b/src/version.js @@ -1,4 +1,4 @@ -const releaseVersion = 'v1.3.0-rc' +const releaseVersion = 'v1.3.0' module.exports = { releaseVersion