neetob 0.5.67 → 0.5.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/neetob/cli/base.rb +32 -0
- data/lib/neetob/cli/code/audit.rb +18 -3
- data/lib/neetob/cli/github/issues/helpers.rb +27 -0
- data/lib/neetob/cli/monthly_audit/commands.rb +2 -1
- data/lib/neetob/cli/monthly_audit/databases/users_unique_email_index.rb +6 -1
- data/lib/neetob/cli/monthly_audit/databases/uuid_primary_key.rb +8 -0
- data/lib/neetob/cli/monthly_audit/github_issue_creation.rb +35 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb +11 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/bot_protection_enabled.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/minimum_tls_version_is_one_point_two.rb +11 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/spf_records_are_valid.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/ssl_tls_encryption_mode_set_to_full.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_apps.rb +10 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_help_center.rb +12 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_landing_pages.rb +12 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/auto_scaling_enabled.rb +7 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/cloudfront_cdn_enabled.rb +11 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/essential_environment_variables_set.rb +12 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/scheduled_exports_enabled.rb +6 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/ssl_certificates_over_thirty_days_from_expiry.rb +12 -0
- data/lib/neetob/cli/monthly_audit/misc/redirections_working_correctly.rb +14 -1
- data/lib/neetob/cli/monthly_audit/perform.rb +7 -2
- data/lib/neetob/cli/monthly_audit/security/code/active_record_doctor.rb +9 -4
- data/lib/neetob/cli/monthly_audit/security/code/brakeman.rb +5 -0
- data/lib/neetob/cli/monthly_audit/security/code/bundle_audit.rb +6 -2
- data/lib/neetob/cli/monthly_audit/security/code/checks_for_unused_assets.rb +5 -0
- data/lib/neetob/cli/monthly_audit/security/code/fasterer.rb +8 -0
- data/lib/neetob/cli/monthly_audit/security/code/yarn_audit.rb +5 -0
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_prs_merged.rb +5 -0
- data/lib/neetob/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fe5407c19ee902b9471fcd4c0774823a93e43a84dbd6ca26d017a4f0fe300dc
|
4
|
+
data.tar.gz: 2c0f79f96f0bfe02b6c4bc4c2c755381556aef67f046282850f8854f5d0e1cc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9e1fe5ca8b58144913a7635fc3376b6197f0851659b002cc5403b7c3dbb4d2ee3ee40e624193c81081f43138f23370c174a23dc00c32abef17a783f622283cb
|
7
|
+
data.tar.gz: 4c98377780c60fa3873155d025353bdddbb96a50329c78c797047c1f97f452ad33368bc52a292284efbb23926855a54dd8a6899ad53569451f3ce8e44bbc0e90
|
data/Gemfile.lock
CHANGED
data/lib/neetob/cli/base.rb
CHANGED
@@ -19,6 +19,38 @@ module Neetob
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
+
def strip_ansi_codes(str)
|
23
|
+
str.gsub(/\e\[[\d;]*m/, "")
|
24
|
+
end
|
25
|
+
|
26
|
+
def domain_to_repo(domain)
|
27
|
+
domain = domain.gsub(".com", "")
|
28
|
+
|
29
|
+
if domain == "neeto"
|
30
|
+
return "neeto-website"
|
31
|
+
end
|
32
|
+
|
33
|
+
if domain == "bigbinary"
|
34
|
+
return "bigbinary-website"
|
35
|
+
end
|
36
|
+
|
37
|
+
if domain.start_with?("neeto")
|
38
|
+
app = domain.sub("neeto", "neeto-")
|
39
|
+
else
|
40
|
+
app = domain
|
41
|
+
end
|
42
|
+
"#{app}-web"
|
43
|
+
end
|
44
|
+
|
45
|
+
def app_to_repo(app_name)
|
46
|
+
app_name = app_name.downcase
|
47
|
+
|
48
|
+
if app_name.start_with?("neeto")
|
49
|
+
app = app_name.sub("neeto", "neeto-")
|
50
|
+
end
|
51
|
+
"#{app}-web"
|
52
|
+
end
|
53
|
+
|
22
54
|
def find_all_matching_apps_or_repos(apps, platform_name, sandbox_mode, quiet = false)
|
23
55
|
all_neeto_repos = apps == ["all"]
|
24
56
|
inform_about_current_working_mode(sandbox_mode, quiet)
|
@@ -50,13 +50,28 @@ module Neetob
|
|
50
50
|
|
51
51
|
def find_tables_without_uuid_as_primary_key(db_schema)
|
52
52
|
create_table_regex = /create_table.*?,\s*force:\s*:cascade\s*do\s*\|t\|/
|
53
|
+
|
53
54
|
db_schema.scan(create_table_regex).map do |create_table_line|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
keys = extract_primary_keys(create_table_line)
|
56
|
+
!(
|
57
|
+
create_table_line.include?("id: :uuid") ||
|
58
|
+
create_table_line.include?("id: false") ||
|
59
|
+
(keys.length > 0 && create_table_line.include?("primary_key") && !keys.include?("id"))
|
60
|
+
) ?
|
61
|
+
create_table_line.scan(/"([^"]+)"/).flatten.first :
|
62
|
+
nil
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
66
|
+
def extract_primary_keys(table_def)
|
67
|
+
# Match the part inside primary_key: [ ... ]
|
68
|
+
match = table_def[/primary_key:\s*\[(.*?)\]/, 1]
|
69
|
+
return [] unless match
|
70
|
+
|
71
|
+
# Extract each string inside quotes
|
72
|
+
match.scan(/"([^"]+)"/).flatten
|
73
|
+
end
|
74
|
+
|
60
75
|
def verify_unique_email_index(db_schema)
|
61
76
|
index_pattern = /
|
62
77
|
create_table\s+"users".*?
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Github
|
8
|
+
module Issues
|
9
|
+
class Helpers < Base
|
10
|
+
def initialize
|
11
|
+
super()
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_issue_with_title(repo, title)
|
15
|
+
begin
|
16
|
+
issues = client.issues(repo, state: "open")
|
17
|
+
issue = issues.find { |issue| issue.title == title }
|
18
|
+
issue
|
19
|
+
rescue StandardError => e
|
20
|
+
ExceptionHandler.new(e).process
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -9,9 +9,10 @@ module Neetob
|
|
9
9
|
class Commands < Thor
|
10
10
|
desc "perform", "Perform the audit"
|
11
11
|
option :month, type: :string, aliases: "-m", required: true, desc: "Month. Example: June-2024"
|
12
|
+
option :skip_issue, type: :boolean, default: false, desc: "Skip creating GitHub issues"
|
12
13
|
|
13
14
|
def perform
|
14
|
-
Perform.new(options[:month], options[:sandbox]).run
|
15
|
+
Perform.new(options[:month], options[:sandbox], options[:skip_issue]).run
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -28,7 +29,11 @@ module Neetob
|
|
28
29
|
if unique_email_index_result
|
29
30
|
repo_data << [repo, "Yes", nil, "Yes"]
|
30
31
|
else
|
31
|
-
|
32
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
33
|
+
repo:, title: "Add unique index on users email",
|
34
|
+
description: "Unique email index is not present for the users table")
|
35
|
+
audit_passed = "No" + " #{issue_url}"
|
36
|
+
repo_data << [repo, "No", "Unique email index is not present for the users table", audit_passed]
|
32
37
|
end
|
33
38
|
end
|
34
39
|
ui.print_table(repo_data)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -40,6 +42,12 @@ module Neetob
|
|
40
42
|
all_tables_have_uuid_primary_keys = tables_without_uuid.empty? ? "Yes" : "No"
|
41
43
|
audit_passed = all_tables_have_uuid_primary_keys == "Yes" ? "Yes" : "No"
|
42
44
|
comments = tables_without_uuid.empty? ? nil : "Tables without UUID primary keys: #{tables_without_uuid.join(', ')}"
|
45
|
+
if audit_passed == "No"
|
46
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
47
|
+
repo:, title: "Use UUID primary keys for all tables",
|
48
|
+
description: comments)
|
49
|
+
audit_passed += " #{issue_url}"
|
50
|
+
end
|
43
51
|
same_as_last_comment = audit_passed == "No" && comments == last_comment
|
44
52
|
last_comment = comments
|
45
53
|
if same_as_last_comment
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../github/base"
|
4
|
+
require_relative "../github/issues/helpers"
|
5
|
+
class GithubIssueCreation < Neetob::CLI::Github::Base
|
6
|
+
def initialize
|
7
|
+
super()
|
8
|
+
@helpers = Neetob::CLI::Github::Issues::Helpers.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_issue(repo:, title:, description:, labels: "")
|
12
|
+
return if Thread.current[:skip_issue]
|
13
|
+
|
14
|
+
month = Thread.current[:month].capitalize.gsub("-", " ")
|
15
|
+
title = "#{month} Audit - #{title}"
|
16
|
+
|
17
|
+
# Checking if the issue already exists
|
18
|
+
issue = @helpers.get_issue_with_title("bigbinary/#{repo}", title)
|
19
|
+
if issue
|
20
|
+
return issue.html_url
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
issue = client.create_issue(
|
25
|
+
"bigbinary/#{repo}",
|
26
|
+
title,
|
27
|
+
"## #{title} \n #{description}",
|
28
|
+
{ labels: }
|
29
|
+
)
|
30
|
+
issue.html_url
|
31
|
+
rescue StandardError => e
|
32
|
+
ExceptionHandler.new(e).process
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -20,6 +22,15 @@ module Neetob
|
|
20
22
|
ui.info("Checking Always use HTTPS value for #{domain}", print_to_audit_log: false)
|
21
23
|
always_use_https_value = Neetob::CLI::Cloudflare::AlwaysUseHttps.new(domain).run
|
22
24
|
audit_passed = always_use_https_value.to_s == "on" ? "Yes" : "No"
|
25
|
+
|
26
|
+
if audit_passed == "No"
|
27
|
+
repo = domain_to_repo(domain.to_s)
|
28
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
29
|
+
repo:, title: "Enable HTTPS for domain",
|
30
|
+
description: "HTTPs is not enabled for #{domain}.")
|
31
|
+
audit_passed += " #{issue_url}"
|
32
|
+
end
|
33
|
+
|
23
34
|
domains_data << [domain, always_use_https_value, audit_passed]
|
24
35
|
end
|
25
36
|
ui.print_table(domains_data)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -20,6 +21,14 @@ module Neetob
|
|
20
21
|
bot_fight_mode = Neetob::CLI::Cloudflare::BotFightMode.new(domain).run
|
21
22
|
ui.info("Checking Bot fight mode for #{domain}", print_to_audit_log: false)
|
22
23
|
audit_passed = bot_fight_mode == "on" ? "Yes" : "No"
|
24
|
+
|
25
|
+
if audit_passed == "No"
|
26
|
+
repo = domain_to_repo(domain.to_s)
|
27
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
28
|
+
repo:, title: "Enable bot protection for #{domain}",
|
29
|
+
description: "Bot Protection is not enabled for #{domain}.")
|
30
|
+
audit_passed += " #{issue_url}"
|
31
|
+
end
|
23
32
|
domains_data << [domain, bot_fight_mode, audit_passed]
|
24
33
|
end
|
25
34
|
ui.print_table(domains_data)
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -39,6 +41,13 @@ module Neetob
|
|
39
41
|
dns_proxy_status = "* record has proxying turned #{proxy_status}"
|
40
42
|
same_as_last_dns_proxy_status = dns_proxy_status == last_dns_proxy_status
|
41
43
|
last_dns_proxy_status = dns_proxy_status
|
44
|
+
if audit_passed == "No"
|
45
|
+
repo = domain_to_repo(domain.to_s)
|
46
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
47
|
+
repo:, title: "Enable proxying for wildcard DNS on #{domain}",
|
48
|
+
description: dns_proxy_status)
|
49
|
+
audit_passed += " #{issue_url}"
|
50
|
+
end
|
42
51
|
if same_as_last_dns_proxy_status
|
43
52
|
dns_proxy_status = "''"
|
44
53
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../cloudflare/min_tls_version"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -22,6 +23,16 @@ module Neetob
|
|
22
23
|
ui.info("Checking Minimum TLS version for #{domain}", print_to_audit_log: false)
|
23
24
|
min_tls_version = Neetob::CLI::Cloudflare::MinTlsVersion.new(domain).run
|
24
25
|
audit_passed = min_tls_version.to_s == "1.2" ? "Yes" : "No"
|
26
|
+
|
27
|
+
if audit_passed == "No"
|
28
|
+
repo = domain_to_repo(domain.to_s)
|
29
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
30
|
+
repo:, title: "Set minimum TLS version to 1.2 for #{domain}",
|
31
|
+
description: "Minimum TLS version for #{domain} is set to #{min_tls_version}. It should be set to '1.2'."
|
32
|
+
)
|
33
|
+
audit_passed += " #{issue_url}"
|
34
|
+
end
|
35
|
+
|
25
36
|
domains_data << [domain, min_tls_version, audit_passed]
|
26
37
|
end
|
27
38
|
ui.print_table(domains_data)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -29,6 +30,14 @@ module Neetob
|
|
29
30
|
data = spf_records_verification_data[:spf_txt_records].map { |record|
|
30
31
|
"#{record[:name]} => #{record[:content]}"
|
31
32
|
}.join(", ")
|
33
|
+
|
34
|
+
if audit_passed == "No"
|
35
|
+
repo = domain_to_repo(domain.to_s)
|
36
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
37
|
+
repo:, title: "Fix invalid SPF records for #{domain}",
|
38
|
+
description: "#{comments} \n\n SPF records data: #{data}")
|
39
|
+
audit_passed += " #{issue_url}"
|
40
|
+
end
|
32
41
|
domains_data << [domain, data, comments, audit_passed]
|
33
42
|
end
|
34
43
|
ui.print_table(domains_data)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../cloudflare/ssl_mode"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -22,6 +23,14 @@ module Neetob
|
|
22
23
|
ui.info("Checking SSL/TLS encryption mode for #{domain}", print_to_audit_log: false)
|
23
24
|
ssl_mode = Neetob::CLI::Cloudflare::SSLMode.new(domain).run
|
24
25
|
audit_passed = ssl_mode.to_s == "full" ? "Yes" : "No"
|
26
|
+
repo = domain_to_repo(domain.to_s)
|
27
|
+
if audit_passed == "No"
|
28
|
+
comments = "SSL/TLS encryption mode is set to #{ssl_mode}. It should be set to 'Full'."
|
29
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
30
|
+
repo:, title: "Set SSL TLS mode to Full for #{domain}",
|
31
|
+
description: comments)
|
32
|
+
audit_passed += " #{issue_url}"
|
33
|
+
end
|
25
34
|
domains_data << [domain, ssl_mode, audit_passed]
|
26
35
|
end
|
27
36
|
ui.print_table(domains_data)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../cronitor/get_all_monitors"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -42,6 +43,15 @@ module Neetob
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
if audit_passed == "No"
|
47
|
+
repo = app_to_repo(app.to_s)
|
48
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
49
|
+
repo:, title: "Fix missing or paused Cronitor monitor for #{app}",
|
50
|
+
description: " Monitor for Application present:#{monitor_for_app_present}
|
51
|
+
\n Monitor for Application enabled:#{monitor_for_app_enabled} \n #{comments}")
|
52
|
+
audit_passed += " #{issue_url}"
|
53
|
+
end
|
54
|
+
|
45
55
|
apps_data << [app, monitor_for_app_present, monitor_for_app_enabled, comments, audit_passed]
|
46
56
|
end
|
47
57
|
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_help_center.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -47,6 +49,16 @@ module Neetob
|
|
47
49
|
audit_passed = "Ignored"
|
48
50
|
end
|
49
51
|
|
52
|
+
if audit_passed == "No"
|
53
|
+
repo = app_to_repo(app.to_s)
|
54
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
55
|
+
repo:, title: "Fix missing or paused Cronitor monitor for #{app} help center",
|
56
|
+
description: " Monitor for Application help center present:#{monitor_for_app_help_center_present}
|
57
|
+
\n Monitor for Application help center enabled:#{monitor_for_app_help_center_enabled} \n #{comments}"
|
58
|
+
)
|
59
|
+
audit_passed += " #{issue_url}"
|
60
|
+
end
|
61
|
+
|
50
62
|
apps_data << [app, monitor_for_app_help_center_present, monitor_for_app_help_center_enabled, comments,
|
51
63
|
audit_passed]
|
52
64
|
end
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_landing_pages.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -49,6 +51,16 @@ module Neetob
|
|
49
51
|
audit_passed = "Ignored"
|
50
52
|
end
|
51
53
|
|
54
|
+
if audit_passed == "No"
|
55
|
+
repo = app_to_repo(app.to_s)
|
56
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
57
|
+
repo:, title: "Fix missing or paused Cronitor monitor for #{app} landing page",
|
58
|
+
description: " Monitor for Application landing page present:#{monitor_for_app_landing_page_present}
|
59
|
+
\n Monitor for Application landing page enabled:#{monitor_for_app_landing_page_enabled} \n #{comments}"
|
60
|
+
)
|
61
|
+
audit_passed += " #{issue_url}"
|
62
|
+
end
|
63
|
+
|
52
64
|
apps_data << [app, monitor_for_app_landing_page_present, monitor_for_app_landing_page_enabled,
|
53
65
|
comments, audit_passed]
|
54
66
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -22,6 +24,7 @@ module Neetob
|
|
22
24
|
audit_passed = nil
|
23
25
|
comments = nil
|
24
26
|
autoscaling_config = nil
|
27
|
+
repo = app.gsub("-production", "")
|
25
28
|
if autoscaling_config_result.is_a?(Hash) && autoscaling_config_result["error"] == "Forbidden"
|
26
29
|
audit_passed = "No"
|
27
30
|
comments = "You do not have permission to access the config for this app."
|
@@ -32,6 +35,10 @@ module Neetob
|
|
32
35
|
audit_passed = autoscaling_turned_on_for_web ? "Yes" : "No"
|
33
36
|
if audit_passed == "No"
|
34
37
|
comments = "Auto-scaling is not enabled for web dynos."
|
38
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
39
|
+
repo:, title: "Enable auto scaling for web dynos",
|
40
|
+
description: comments)
|
41
|
+
audit_passed += " #{issue_url}"
|
35
42
|
same_as_last_comment = comments == last_comment
|
36
43
|
last_comment = comments
|
37
44
|
comments = "''" if same_as_last_comment
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -26,6 +27,7 @@ module Neetob
|
|
26
27
|
audit_passed = nil
|
27
28
|
comments = nil
|
28
29
|
asset_host_value = nil
|
30
|
+
repo = app.gsub("-production", "")
|
29
31
|
if config_vars.is_a?(Hash) && config_vars["error"] == "Forbidden"
|
30
32
|
audit_passed = "No"
|
31
33
|
comments = "You do not have permission to access the config vars for this app."
|
@@ -34,6 +36,10 @@ module Neetob
|
|
34
36
|
if asset_host_line.nil?
|
35
37
|
audit_passed = "No"
|
36
38
|
comments = "ASSET_HOST value not found."
|
39
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
40
|
+
repo:, title: "Cloudfront CDN audit failed",
|
41
|
+
description: comments)
|
42
|
+
audit_passed += " #{issue_url}"
|
37
43
|
else
|
38
44
|
asset_host_value = asset_host_line.split("|")[2].strip
|
39
45
|
is_direct_cloudfront_asset_host = asset_host_value.include?("cloudfront.net")
|
@@ -41,9 +47,14 @@ module Neetob
|
|
41
47
|
audit_passed = is_direct_cloudfront_asset_host || is_cdn_subdomain_asset_host ? "Yes" : "No"
|
42
48
|
if audit_passed == "No"
|
43
49
|
comments = "ASSET_HOST value is not a Cloudfront CDN URL or a CDN subdomain URL."
|
50
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
51
|
+
repo:, title: "Set ASSET_HOST to a valid Cloudfront CDN URL",
|
52
|
+
description: comments)
|
53
|
+
audit_passed += " #{issue_url}"
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
57
|
+
|
47
58
|
apps_data << [app, asset_host_value, comments, audit_passed]
|
48
59
|
end
|
49
60
|
Neetob::CLI::Sre::Base::APPS_LIST[:heroku].select { |app| app.include?("production") }.each do |app|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -15,12 +16,14 @@ module Neetob
|
|
15
16
|
|
16
17
|
apps_data = [["App", "All essential env variables set", "Comments", "Audit Passed"]]
|
17
18
|
ui.info("\n", print_to_audit_log: false)
|
19
|
+
|
18
20
|
Neetob::CLI::Sre::Base::APPS_LIST[:neetodeploy].select { |app| app.include?("production") }.each do |app|
|
19
21
|
ui.info("Checking essential env variables for #{app}", print_to_audit_log: false)
|
20
22
|
essential_env_variables_result = Neetob::CLI::Sre::CheckEssentialEnv.new(app).run
|
21
23
|
audit_passed = nil
|
22
24
|
comments = nil
|
23
25
|
all_essential_env_variables_set = nil
|
26
|
+
repo = app.gsub("-production", "")
|
24
27
|
if essential_env_variables_result["error"] == "Forbidden"
|
25
28
|
audit_passed = "No"
|
26
29
|
comments = "You do not have permission to access the config vars for this app."
|
@@ -29,6 +32,10 @@ module Neetob
|
|
29
32
|
audit_passed = all_essential_env_variables_set ? "Yes" : "No"
|
30
33
|
if audit_passed == "No"
|
31
34
|
comments = "Missing keys: #{essential_env_variables_result[:missing_keys].join(", ")}"
|
35
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
36
|
+
repo:, title: "Missing essential environment variables",
|
37
|
+
description: comments)
|
38
|
+
audit_passed += " #{issue_url}"
|
32
39
|
end
|
33
40
|
end
|
34
41
|
apps_data << [app, all_essential_env_variables_set, comments, audit_passed]
|
@@ -38,8 +45,13 @@ module Neetob
|
|
38
45
|
essential_env_variables_result = Neetob::CLI::Sre::CheckEssentialEnv.new(app).run
|
39
46
|
all_essential_env_variables_set = essential_env_variables_result[:all_keys_present]
|
40
47
|
audit_passed = all_essential_env_variables_set ? "Yes" : "No"
|
48
|
+
repo = app.gsub("-production", "")
|
41
49
|
if audit_passed == "No"
|
42
50
|
comments = "Missing keys: #{essential_env_variables_result[:missing_keys].join(", ")}"
|
51
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
52
|
+
repo:, title: "Add missing essential environment variables",
|
53
|
+
description: comments)
|
54
|
+
audit_passed += " #{issue_url}"
|
43
55
|
end
|
44
56
|
apps_data << [app, all_essential_env_variables_set, comments, audit_passed]
|
45
57
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
3
4
|
module Neetob
|
4
5
|
class CLI
|
5
6
|
module MonthlyAudit
|
@@ -22,6 +23,7 @@ module Neetob
|
|
22
23
|
audit_passed = nil
|
23
24
|
comments = nil
|
24
25
|
scheduled_exports_config = nil
|
26
|
+
repo = app.gsub("-production", "")
|
25
27
|
if scheduled_exports_result.include? "Forbidden"
|
26
28
|
audit_passed = "No"
|
27
29
|
comments = "You do not have permission to access the config for this app."
|
@@ -34,6 +36,10 @@ module Neetob
|
|
34
36
|
audit_passed = scheduled_exports_config.include?("turned on") ? "Yes" : "No"
|
35
37
|
if audit_passed == "No"
|
36
38
|
comments = scheduled_exports_config
|
39
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
40
|
+
repo:, title: "Enable scheduled exports",
|
41
|
+
description: strip_ansi_codes(comments))
|
42
|
+
audit_passed += " #{issue_url}"
|
37
43
|
end
|
38
44
|
same_as_last_scheduled_export_config = scheduled_exports_config == last_scheduled_exports_config
|
39
45
|
last_scheduled_exports_config = scheduled_exports_config
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
@@ -53,6 +55,11 @@ module Neetob
|
|
53
55
|
"#{certificate["name"]}(#{certificate["domains"].map { |domain| domain["hostname"] }.join(", ")})"
|
54
56
|
}
|
55
57
|
comments = "Certificates #{certificates_failing_audit.join(", ")} are expiring in less than 30 days."
|
58
|
+
repo = app.gsub("-production", "")
|
59
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
60
|
+
repo:, title: "SSL certificates over 30 days from expiry",
|
61
|
+
description: comments)
|
62
|
+
audit_passed += " #{issue_url}"
|
56
63
|
end
|
57
64
|
end
|
58
65
|
apps_data << [app, certificates_expiring_in_less_than_30_days, comments, audit_passed]
|
@@ -68,6 +75,11 @@ module Neetob
|
|
68
75
|
audit_passed = "Yes"
|
69
76
|
else
|
70
77
|
comments = "Certificates #{certificates_expiring_in_less_than_30_days.map { |certificate| certificate[:name] }.join(", ")} are expiring in less than 30 days."
|
78
|
+
repo = app.gsub("-production", "")
|
79
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
80
|
+
repo:, title: "Renew SSL certificates expiring in less than 30 days",
|
81
|
+
description: comments)
|
82
|
+
audit_passed += " #{issue_url}"
|
71
83
|
certificates_expiring_in_less_than_30_days_present = "Yes"
|
72
84
|
end
|
73
85
|
apps_data << [app, certificates_expiring_in_less_than_30_days_present, comments, audit_passed]
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../github_issue_creation"
|
4
|
+
|
3
5
|
module Neetob
|
4
6
|
class CLI
|
5
7
|
module MonthlyAudit
|
6
8
|
module Misc
|
7
9
|
class RedirectionsWorkingCorrectly < CLI::Base
|
8
10
|
REDIRECTIONS_LIST = [
|
9
|
-
{
|
11
|
+
{
|
12
|
+
source: "https://academy.bigbinary.com", destination: "https://bigbinaryacademy.com",
|
13
|
+
repo: "bigbinary-website"
|
14
|
+
},
|
10
15
|
]
|
11
16
|
def initialize
|
12
17
|
super()
|
@@ -19,6 +24,14 @@ module Neetob
|
|
19
24
|
status = check.run ? "Working" : "Not working"
|
20
25
|
audit_passed = status == "Working" ? "Yes" : "No"
|
21
26
|
|
27
|
+
if audit_passed == "No"
|
28
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
29
|
+
repo: redirection[:repo], title: "Fix broken redirection",
|
30
|
+
description: "Redirection from #{redirection[:source]} to #{redirection[:destination]} is not working."
|
31
|
+
)
|
32
|
+
audit_passed += " #{issue_url}"
|
33
|
+
end
|
34
|
+
|
22
35
|
table_data << [redirection[:source], redirection[:destination], status, audit_passed]
|
23
36
|
end
|
24
37
|
ui.print_table(table_data)
|
@@ -9,20 +9,25 @@ module Neetob
|
|
9
9
|
class CLI
|
10
10
|
module MonthlyAudit
|
11
11
|
class Perform < CLI::Base
|
12
|
-
attr_accessor :sandbox, :month
|
12
|
+
attr_accessor :sandbox, :month, :skip_issue
|
13
13
|
|
14
|
-
def initialize(month, sandbox = false)
|
14
|
+
def initialize(month, sandbox = false, skip_issue = false)
|
15
15
|
super()
|
16
16
|
@month = month
|
17
17
|
@sandbox = sandbox
|
18
|
+
@skip_issue = skip_issue
|
18
19
|
end
|
19
20
|
|
20
21
|
def run
|
22
|
+
Thread.current[:month] = month
|
23
|
+
Thread.current[:skip_issue] = skip_issue
|
21
24
|
Thread.current[:audit_mode] = true
|
22
25
|
markdown_file_name = "audit-report-#{DateTime.now.to_i}.md"
|
23
26
|
Thread.current[:markdown_file_name] = markdown_file_name
|
24
27
|
ui.success("## Starting the audit for #{month}")
|
25
28
|
ui.info "\n"
|
29
|
+
ui.say("## Issue creation is #{skip_issue ? 'disabled' : 'enabled'}")
|
30
|
+
ui.info "\n"
|
26
31
|
Security::Main.new.run
|
27
32
|
ui.info "\n"
|
28
33
|
Databases::Main.new.run
|
@@ -16,18 +16,23 @@ module Neetob
|
|
16
16
|
ui.success("### 1.1.4. Checking whether running `rake active_record_doctor` throws any vulnerabilities")
|
17
17
|
repo_data = [["Repository", "Issues Found", "Comments", "Audit Passed"]]
|
18
18
|
ui.info "\n"
|
19
|
-
NeetoCompliance::NeetoRepos.products.keys.
|
19
|
+
NeetoCompliance::NeetoRepos.products.keys.each do |repo|
|
20
20
|
ui.info("Checking ActiveRecordDoctor run results for #{repo}", print_to_audit_log: false)
|
21
21
|
active_record_doctor_run_result = Neetob::CLI::Github::ActiveRecordDoctor.new([repo]).run
|
22
|
-
|
22
|
+
audit_passed = "No"
|
23
23
|
if active_record_doctor_run_result.blank?
|
24
|
-
|
24
|
+
audit_passed = "Yes"
|
25
25
|
comments = nil
|
26
26
|
else
|
27
27
|
issues_found = "Yes"
|
28
28
|
comments = "#{active_record_doctor_run_result.lines.first.strip} ..."
|
29
|
+
|
30
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
31
|
+
repo:, title: "Fix issues reported by active_record_doctor",
|
32
|
+
description: comments)
|
33
|
+
audit_passed += " #{issue_url}"
|
29
34
|
end
|
30
|
-
|
35
|
+
|
31
36
|
repo_data << [repo, issues_found, comments, audit_passed]
|
32
37
|
end
|
33
38
|
ui.print_table(repo_data)
|
@@ -25,6 +25,11 @@ module Neetob
|
|
25
25
|
else
|
26
26
|
vulnerabilities_found = "Yes"
|
27
27
|
comments = brakeman_run_result.gsub("\n", "<br>")
|
28
|
+
|
29
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
30
|
+
repo:, title: "Fix vulnerabilities reported by Brakeman",
|
31
|
+
description: comments)
|
32
|
+
audit_passed += " #{issue_url}"
|
28
33
|
end
|
29
34
|
repo_data << [repo, vulnerabilities_found, comments, audit_passed]
|
30
35
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../github/bundle_audit"
|
4
|
-
|
4
|
+
require_relative "../../github_issue_creation"
|
5
5
|
module Neetob
|
6
6
|
class CLI
|
7
7
|
module MonthlyAudit
|
@@ -26,9 +26,13 @@ module Neetob
|
|
26
26
|
if bundle_audit_result && bundle_audit_result.include?("No vulnerabilities found")
|
27
27
|
audit_passed = "Yes"
|
28
28
|
else
|
29
|
+
|
29
30
|
vulnerabilities_found = "Yes"
|
30
31
|
comments = bundle_audit_result.gsub("\n", "<br>").gsub("~", "\\~")
|
31
|
-
|
32
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
33
|
+
repo:, title: "Fix vulnerabilities reported by bundle-audit",
|
34
|
+
description: comments)
|
35
|
+
audit_passed += " #{issue_url}"
|
32
36
|
same_as_last_vulnerabilities = comments == last_comment
|
33
37
|
last_comment = comments
|
34
38
|
if same_as_last_vulnerabilities
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../github/unused_assets_audit"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -24,6 +25,10 @@ module Neetob
|
|
24
25
|
unused_assets_found = "Yes"
|
25
26
|
audit_passed = "No"
|
26
27
|
comments = unused_files.join("<br>")
|
28
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
29
|
+
repo:, title: "Remove unused assets",
|
30
|
+
description: comments)
|
31
|
+
audit_passed += " #{issue_url}"
|
27
32
|
else
|
28
33
|
unused_assets_found = "No"
|
29
34
|
audit_passed = "Yes"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../github/fasterer_audit"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -27,6 +28,13 @@ module Neetob
|
|
27
28
|
comments = "Vulnerabilities not detected"
|
28
29
|
else
|
29
30
|
optimizations_needed = "Yes"
|
31
|
+
comments = strip_ansi_codes(fasterer_exec_result).gsub("\n", "<br>")
|
32
|
+
|
33
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
34
|
+
repo:, title: "Fasterer suggestions to improve performance",
|
35
|
+
description: comments)
|
36
|
+
audit_passed += " #{issue_url}"
|
37
|
+
|
30
38
|
comments = "Vulnerabilities detected"
|
31
39
|
end
|
32
40
|
repo_data << [repo, optimizations_needed, comments, audit_passed]
|
@@ -31,6 +31,11 @@ line.include?("Severity:") }.first&.strip&.gsub("|", ",")
|
|
31
31
|
vulnerabilities = yarn_audit_result.split("\n").select { |line|
|
32
32
|
line.include?("vulnerabilities found") }.first&.strip
|
33
33
|
comments = "#{vulnerabilities}<br>#{severity}"
|
34
|
+
|
35
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
36
|
+
repo:, title: "Yarn audit: High/Critical vulnerabilities found",
|
37
|
+
description: comments)
|
38
|
+
audit_passed += " #{issue_url}"
|
34
39
|
end
|
35
40
|
repo_data << [repo, vulnerabilities_found, comments, audit_passed]
|
36
41
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../../github/repositories/pull_requests"
|
4
|
+
require_relative "../../github_issue_creation"
|
4
5
|
|
5
6
|
module Neetob
|
6
7
|
class CLI
|
@@ -35,6 +36,10 @@ module Neetob
|
|
35
36
|
audit_passed = dependabot_prs_older_than_2_days_merged = "Yes"
|
36
37
|
else
|
37
38
|
comments = "PRs older than 2 days: #{dependabot_prs_older_than_2_days.map { |pr| pr[:number] }.join(', ')}"
|
39
|
+
issue_url = GithubIssueCreation.new.create_issue(
|
40
|
+
repo:, title: "Merge Dependabot PRs older than 2 days",
|
41
|
+
description: comments)
|
42
|
+
audit_passed += " #{issue_url}"
|
38
43
|
end
|
39
44
|
repo_data << [repo, dependabot_prs_older_than_2_days_merged, comments, audit_passed]
|
40
45
|
end
|
data/lib/neetob/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neetob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.69
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Udai Gupta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- lib/neetob/cli/github/issues/commands.rb
|
246
246
|
- lib/neetob/cli/github/issues/create.rb
|
247
247
|
- lib/neetob/cli/github/issues/create_product_sub_issues.rb
|
248
|
+
- lib/neetob/cli/github/issues/helpers.rb
|
248
249
|
- lib/neetob/cli/github/issues/list.rb
|
249
250
|
- lib/neetob/cli/github/labels/commands.rb
|
250
251
|
- lib/neetob/cli/github/labels/delete.rb
|
@@ -287,6 +288,7 @@ files:
|
|
287
288
|
- lib/neetob/cli/monthly_audit/databases/main.rb
|
288
289
|
- lib/neetob/cli/monthly_audit/databases/users_unique_email_index.rb
|
289
290
|
- lib/neetob/cli/monthly_audit/databases/uuid_primary_key.rb
|
291
|
+
- lib/neetob/cli/monthly_audit/github_issue_creation.rb
|
290
292
|
- lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb
|
291
293
|
- lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/bot_protection_enabled.rb
|
292
294
|
- lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb
|