neetob 0.5.16 → 0.5.17
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/.env +4 -0
- data/.neetoci/default.yml +1 -1
- data/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +108 -109
- data/lib/neetob/cli/cloudflare/always_use_https.rb +7 -2
- data/lib/neetob/cli/cloudflare/bot_fight_mode.rb +7 -2
- data/lib/neetob/cli/cloudflare/dns_proxy_status.rb +8 -2
- data/lib/neetob/cli/cloudflare/min_tls_version.rb +8 -2
- data/lib/neetob/cli/cloudflare/ssl_mode.rb +4 -1
- data/lib/neetob/cli/cloudflare/verify_spf.rb +21 -8
- data/lib/neetob/cli/code/audit.rb +19 -7
- data/lib/neetob/cli/cronitor/base.rb +49 -0
- data/lib/neetob/cli/cronitor/get_all_monitors.rb +21 -0
- data/lib/neetob/cli/github/base.rb +3 -2
- data/lib/neetob/cli/github/brakeman.rb +7 -3
- data/lib/neetob/cli/github/bundle_audit.rb +47 -0
- data/lib/neetob/cli/github/make_pr/base.rb +6 -2
- data/lib/neetob/cli/github/repositories/get_security_details.rb +45 -0
- data/lib/neetob/cli/github/repositories/pull_requests.rb +34 -0
- data/lib/neetob/cli/github/yarn_audit.rb +47 -0
- data/lib/neetob/cli/monthly_audit/commands.rb +19 -0
- data/lib/neetob/cli/monthly_audit/databases/main.rb +29 -0
- data/lib/neetob/cli/monthly_audit/databases/users_unique_email_index.rb +40 -0
- data/lib/neetob/cli/monthly_audit/databases/uuid_primary_key.rb +45 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb +32 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/bot_protection_enabled.rb +32 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb +41 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/main.rb +38 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/minimum_tls_version_is_one_point_two.rb +34 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/spf_records_are_valid.rb +41 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/ssl_tls_encryption_mode_set_to_full.rb +34 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/main.rb +29 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_apps.rb +54 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_help_center.rb +53 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_landing_pages.rb +53 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/honeybadger/main.rb +23 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/honeybadger/setup_correctly_for_apps.rb +49 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/main.rb +40 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/auto_scaling_enabled.rb +46 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/cloudfront_cdn_enabled.rb +56 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/essential_environment_variables_set.rb +43 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/main.rb +35 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/scheduled_exports_enabled.rb +43 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy/ssl_certificates_over_thirty_days_from_expiry.rb +41 -0
- data/lib/neetob/cli/monthly_audit/misc/main.rb +32 -0
- data/lib/neetob/cli/monthly_audit/misc/redirections_working_correctly.rb +30 -0
- data/lib/neetob/cli/monthly_audit/misc/sparkpost_sub_account_used_for_all_apps.rb +32 -0
- data/lib/neetob/cli/monthly_audit/misc/ssl_certs_setup_for_auto_renewal.rb +29 -0
- data/lib/neetob/cli/monthly_audit/perform.rb +41 -0
- data/lib/neetob/cli/monthly_audit/security/code/brakeman.rb +38 -0
- data/lib/neetob/cli/monthly_audit/security/code/bundle_audit.rb +40 -0
- data/lib/neetob/cli/monthly_audit/security/code/main.rb +29 -0
- data/lib/neetob/cli/monthly_audit/security/code/yarn_audit.rb +44 -0
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_prs_merged.rb +48 -0
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_turned_on.rb +44 -0
- data/lib/neetob/cli/monthly_audit/security/github/main.rb +26 -0
- data/lib/neetob/cli/monthly_audit/security/main.rb +31 -0
- data/lib/neetob/cli/neeto_deploy/autoscaling_config.rb +6 -1
- data/lib/neetob/cli/neeto_deploy/certificates.rb +3 -0
- data/lib/neetob/cli/neeto_deploy/config_vars/list.rb +8 -2
- data/lib/neetob/cli/neeto_deploy/scheduled_exports.rb +6 -1
- data/lib/neetob/cli/redirections/check.rb +13 -3
- data/lib/neetob/cli/sre/base.rb +10 -0
- data/lib/neetob/cli/sre/check_essential_env.rb +18 -3
- data/lib/neetob/cli/ui.rb +43 -3
- data/lib/neetob/cli.rb +4 -0
- data/lib/neetob/version.rb +1 -1
- metadata +48 -5
@@ -16,8 +16,11 @@ module Neetob
|
|
16
16
|
|
17
17
|
def run
|
18
18
|
matching_apps = find_all_matching_apps_or_repos(apps, :github, sandbox)
|
19
|
-
ui.info(
|
19
|
+
ui.info(
|
20
|
+
"\nListing apps and their tables that doesn't have uuid as primary key type:-",
|
21
|
+
print_to_audit_log: false)
|
20
22
|
has_found_tables_without_uuid = false
|
23
|
+
data = []
|
21
24
|
matching_apps.each do |app|
|
22
25
|
begin
|
23
26
|
db_schema = Base64.decode64(client.contents(app, path: "./db/schema.rb").content)
|
@@ -26,14 +29,21 @@ module Neetob
|
|
26
29
|
has_found_tables_without_uuid = true
|
27
30
|
print_app_and_tables(app, tables_without_uuid)
|
28
31
|
end
|
29
|
-
verify_unique_email_index(db_schema)
|
32
|
+
unique_email_index_result = verify_unique_email_index(db_schema)
|
33
|
+
data << { tables_without_uuid:, unique_email_index_result: }
|
30
34
|
rescue Octokit::NotFound
|
31
35
|
ui.error("There is no \"db/schema.rb\" file in the \"#{app}\" app.")
|
36
|
+
data << { error: "There is no \"db/schema.rb\" file in the \"#{app}\" app." }
|
32
37
|
rescue StandardError => e
|
33
38
|
ExceptionHandler.new(e).process
|
34
39
|
end
|
35
40
|
end
|
36
|
-
ui.info(
|
41
|
+
ui.info(
|
42
|
+
"No apps found to have tables without uuid as primary key type",
|
43
|
+
print_to_audit_log: false) if !has_found_tables_without_uuid
|
44
|
+
if Thread.current[:audit_mode]
|
45
|
+
data
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
39
49
|
private
|
@@ -62,15 +72,17 @@ module Neetob
|
|
62
72
|
)
|
63
73
|
/mx
|
64
74
|
|
65
|
-
|
66
|
-
|
75
|
+
index_pattern_matched = db_schema.match(index_pattern)
|
76
|
+
if index_pattern_matched
|
77
|
+
ui.success("\nUsers are indexed properly", print_to_audit_log: false)
|
67
78
|
else
|
68
|
-
ui.error("\nUsers are not indexed")
|
79
|
+
ui.error("\nUsers are not indexed", print_to_audit_log: false)
|
69
80
|
end
|
81
|
+
index_pattern_matched
|
70
82
|
end
|
71
83
|
|
72
84
|
def print_app_and_tables(app, tables)
|
73
|
-
ui.info("\n#{app}:-")
|
85
|
+
ui.info("\n#{app}:-", print_to_audit_log: false)
|
74
86
|
tables.each do |table|
|
75
87
|
ui.say(" ↳#{table}")
|
76
88
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Cronitor
|
8
|
+
class Base < CLI::Base
|
9
|
+
MONITORS_URL = "https://cronitor.io/api/monitors"
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(*args)
|
16
|
+
raise(StandardError, "CRONITOR_ONE_API_KEY is not given") if ENV["CRONITOR_ONE_API_KEY"].nil?
|
17
|
+
raise(StandardError, "CRONITOR_THREE_API_KEY is not given") if ENV["CRONITOR_THREE_API_KEY"].nil?
|
18
|
+
|
19
|
+
run(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse_response(http_result)
|
25
|
+
case http_result
|
26
|
+
when Net::HTTPSuccess
|
27
|
+
JSON.parse(http_result.body, symbolize_names: true)
|
28
|
+
else
|
29
|
+
error_message = JSON.parse(http_result.body)["errors"][0]["message"]
|
30
|
+
raise(StandardError, "Request failed with status code #{http_result.code}: #{error_message}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(username:, password:, headers: { "Accept" => "application/json" })
|
35
|
+
uri = URI(MONITORS_URL)
|
36
|
+
request = Net::HTTP::Get.new(uri)
|
37
|
+
headers.each { |key, value| request[key] = value }
|
38
|
+
request.basic_auth(username, password)
|
39
|
+
|
40
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
|
41
|
+
http.request(request)
|
42
|
+
end
|
43
|
+
|
44
|
+
parse_response(response)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Cronitor
|
8
|
+
class GetAllMonitors < Base
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
cronitor_one_monitors = get(username: ENV["CRONITOR_ONE_API_KEY"], password: "")[:monitors]
|
15
|
+
cronitor_three_monitors = get(username: ENV["CRONITOR_THREE_API_KEY"], password: "")[:monitors]
|
16
|
+
cronitor_one_monitors + cronitor_three_monitors
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -12,7 +12,7 @@ module Neetob
|
|
12
12
|
module Github
|
13
13
|
class Base < CLI::Base
|
14
14
|
include Utils
|
15
|
-
attr_accessor :client
|
15
|
+
attr_accessor :client, :access_token
|
16
16
|
|
17
17
|
def initialize
|
18
18
|
super()
|
@@ -20,7 +20,8 @@ module Neetob
|
|
20
20
|
unless auth_client.token_persisted?
|
21
21
|
auth_client.start_oauth2_device_flow
|
22
22
|
end
|
23
|
-
@
|
23
|
+
@access_token = auth_client.access_token
|
24
|
+
@client = Octokit::Client.new(access_token:)
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
@@ -17,15 +17,16 @@ module Neetob
|
|
17
17
|
|
18
18
|
def run
|
19
19
|
matching_repos = find_all_matching_apps_or_repos(repos, :github, sandbox)
|
20
|
+
report = nil
|
20
21
|
matching_repos.each do |repo|
|
21
22
|
begin
|
22
|
-
ui.info("\nWorking on repo #{repo}")
|
23
|
+
ui.info("\nWorking on repo #{repo}", print_to_audit_log: false)
|
23
24
|
clone_repo_in_tmp_dir(repo)
|
24
25
|
bundle_install!(repo)
|
25
26
|
report = run_brakeman(repo)
|
26
|
-
ui.success("Successfully executed brakeman for #{repo}")
|
27
|
+
ui.success("Successfully executed brakeman for #{repo}", print_to_audit_log: false)
|
27
28
|
warnings = report.split("\n\n== Warnings ==\n\n").last&.split("\n\n")
|
28
|
-
if !report.include?("No warnings found") && !report.blank?
|
29
|
+
if !report.include?("No warnings found") && !report.blank? && !Thread.current[:audit_mode]
|
29
30
|
issue = client.create_issue(repo, DESCRIPTION, parse_description(warnings))
|
30
31
|
ui.success("Issue created at #{issue.html_url}")
|
31
32
|
end
|
@@ -34,6 +35,9 @@ module Neetob
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
`rm -rf /tmp/neetob`
|
38
|
+
if Thread.current[:audit_mode]
|
39
|
+
report
|
40
|
+
end
|
37
41
|
end
|
38
42
|
|
39
43
|
private
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./make_pr/base"
|
4
|
+
require "pry"
|
5
|
+
|
6
|
+
module Neetob
|
7
|
+
class CLI
|
8
|
+
module Github
|
9
|
+
class BundleAudit < MakePr::Base
|
10
|
+
DESCRIPTION = "Fix security vulnerabilities reported by bundle audit"
|
11
|
+
attr_accessor :repos, :sandbox
|
12
|
+
|
13
|
+
def initialize(repos, sandbox = false)
|
14
|
+
super()
|
15
|
+
@repos = repos
|
16
|
+
@sandbox = sandbox
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
matching_repos = find_all_matching_apps_or_repos(repos, :github, sandbox)
|
21
|
+
report = nil
|
22
|
+
matching_repos.each do |repo|
|
23
|
+
begin
|
24
|
+
ui.info("\nWorking on repo #{repo}", print_to_audit_log: false)
|
25
|
+
clone_repo_in_tmp_dir(repo)
|
26
|
+
bundle_install!(repo)
|
27
|
+
report = run_bundle_audit(repo)
|
28
|
+
ui.success("Successfully executed bundle audit for #{repo}", print_to_audit_log: false)
|
29
|
+
rescue StandardError => e
|
30
|
+
ExceptionHandler.new(e).process
|
31
|
+
end
|
32
|
+
end
|
33
|
+
`rm -rf /tmp/neetob`
|
34
|
+
if Thread.current[:audit_mode]
|
35
|
+
report
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def run_bundle_audit(repo)
|
42
|
+
`#{cd_to_repo(repo)} & rbenv local 3.3.5 & bundle-audit check`
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -19,8 +19,12 @@ module Neetob
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
def bundle_install!(repo, local_repo)
|
23
|
-
execute_command!("#{cd_to_repo(repo, local_repo)}
|
22
|
+
def bundle_install!(repo, local_repo = false)
|
23
|
+
execute_command!("#{cd_to_repo(repo, local_repo)} & rbenv local 3.3.5 & bundle install")
|
24
|
+
end
|
25
|
+
|
26
|
+
def yarn_install!(repo, local_repo = false)
|
27
|
+
execute_command!("#{cd_to_repo(repo, local_repo)} & yarn install")
|
24
28
|
end
|
25
29
|
|
26
30
|
def delete_and_create_temp_neetob_dir
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Github
|
8
|
+
module Repositories
|
9
|
+
class GetSecurityDetails < Base
|
10
|
+
attr_accessor :repos, :sandbox
|
11
|
+
|
12
|
+
def initialize(repos, sandbox = false)
|
13
|
+
super()
|
14
|
+
@repos = repos
|
15
|
+
@sandbox = sandbox
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
matching_repos = find_all_matching_apps_or_repos(repos, :github, sandbox)
|
20
|
+
data = []
|
21
|
+
matching_repos.each do |repo|
|
22
|
+
begin
|
23
|
+
uri = URI("https://api.github.com/repos/#{repo}/code-security-configuration")
|
24
|
+
request = Net::HTTP::Get.new(uri)
|
25
|
+
headers = {
|
26
|
+
"Accept" => "application/vnd.github+json",
|
27
|
+
"Authorization" => "Bearer #{@access_token}"
|
28
|
+
}
|
29
|
+
headers.each { |key, value| request[key] = value }
|
30
|
+
|
31
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
|
32
|
+
http.request(request)
|
33
|
+
end
|
34
|
+
JSON.parse(response.body, symbolize_names: true)
|
35
|
+
rescue StandardError => e
|
36
|
+
ExceptionHandler.new(e).process
|
37
|
+
end
|
38
|
+
end
|
39
|
+
data
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Github
|
8
|
+
module Repositories
|
9
|
+
class PullRequests < Base
|
10
|
+
attr_accessor :repos, :sandbox
|
11
|
+
|
12
|
+
def initialize(repos, sandbox = false)
|
13
|
+
super()
|
14
|
+
@repos = repos
|
15
|
+
@sandbox = sandbox
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
matching_repos = find_all_matching_apps_or_repos(repos, :github, sandbox)
|
20
|
+
data = []
|
21
|
+
matching_repos.each do |repo|
|
22
|
+
begin
|
23
|
+
data << client.pull_requests(repo)
|
24
|
+
rescue StandardError => e
|
25
|
+
ExceptionHandler.new(e).process
|
26
|
+
end
|
27
|
+
end
|
28
|
+
data
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./make_pr/base"
|
4
|
+
require "pry"
|
5
|
+
|
6
|
+
module Neetob
|
7
|
+
class CLI
|
8
|
+
module Github
|
9
|
+
class YarnAudit < MakePr::Base
|
10
|
+
DESCRIPTION = "Fix security vulnerabilities reported by yarn audit"
|
11
|
+
attr_accessor :repos, :sandbox
|
12
|
+
|
13
|
+
def initialize(repos, sandbox = false)
|
14
|
+
super()
|
15
|
+
@repos = repos
|
16
|
+
@sandbox = sandbox
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
matching_repos = find_all_matching_apps_or_repos(repos, :github, sandbox)
|
21
|
+
report = nil
|
22
|
+
matching_repos.each do |repo|
|
23
|
+
begin
|
24
|
+
ui.info("\nWorking on repo #{repo}", print_to_audit_log: false)
|
25
|
+
clone_repo_in_tmp_dir(repo)
|
26
|
+
yarn_install!(repo)
|
27
|
+
report = run_yarn_audit(repo)
|
28
|
+
ui.success("Successfully executed yarn audit for #{repo}", print_to_audit_log: false)
|
29
|
+
rescue StandardError => e
|
30
|
+
ExceptionHandler.new(e).process
|
31
|
+
end
|
32
|
+
end
|
33
|
+
`rm -rf /tmp/neetob`
|
34
|
+
if Thread.current[:audit_mode]
|
35
|
+
report
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def run_yarn_audit(repo)
|
42
|
+
`#{cd_to_repo(repo)} && yarn audit`
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require_relative "perform"
|
5
|
+
|
6
|
+
module Neetob
|
7
|
+
class CLI
|
8
|
+
module MonthlyAudit
|
9
|
+
class Commands < Thor
|
10
|
+
desc "perform", "Perform the audit"
|
11
|
+
option :month, type: :string, aliases: "-m", required: true, desc: "Month. Example: June-2024"
|
12
|
+
|
13
|
+
def perform
|
14
|
+
Perform.new(options[:month], options[:sandbox]).run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "uuid_primary_key"
|
4
|
+
require_relative "users_unique_email_index"
|
5
|
+
|
6
|
+
module Neetob
|
7
|
+
class CLI
|
8
|
+
module MonthlyAudit
|
9
|
+
module Databases
|
10
|
+
class Main < CLI::Base
|
11
|
+
def initialize
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
ui.success("# 2. Running databases audit")
|
17
|
+
ui.info "\n"
|
18
|
+
ui.success("## 2.1. Checking whether all database tables use UUID as the primary key type")
|
19
|
+
ui.info "\n"
|
20
|
+
UuidPrimaryKey.new.run
|
21
|
+
ui.success("## 2.2. Checking whether unique email index is present for the users table")
|
22
|
+
ui.info "\n"
|
23
|
+
UsersUniqueEmailIndex.new.run
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neetob
|
4
|
+
class CLI
|
5
|
+
module MonthlyAudit
|
6
|
+
module Databases
|
7
|
+
class UsersUniqueEmailIndex < CLI::Base
|
8
|
+
def initialize
|
9
|
+
super()
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
repo_data = [[
|
14
|
+
"Repository",
|
15
|
+
"User table is indexed properly",
|
16
|
+
"Comments",
|
17
|
+
"Audit Passed"
|
18
|
+
]
|
19
|
+
]
|
20
|
+
NeetoCompliance::NeetoRepos.products.keys.each do |repo|
|
21
|
+
ui.info "Checking #{repo}...", print_to_audit_log: false
|
22
|
+
code_audit_result = Neetob::CLI::Code::Audit.new([repo]).run[0]
|
23
|
+
if code_audit_result[:error]
|
24
|
+
repo_data << [repo, nil, code_audit_result[:error], "No"]
|
25
|
+
next
|
26
|
+
end
|
27
|
+
unique_email_index_result = code_audit_result[:unique_email_index_result]
|
28
|
+
if unique_email_index_result
|
29
|
+
repo_data << [repo, "Yes", nil, "Yes"]
|
30
|
+
else
|
31
|
+
repo_data << [repo, "No", "Unique email index is not present for the users table", "No"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
ui.print_table(repo_data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neetob
|
4
|
+
class CLI
|
5
|
+
module MonthlyAudit
|
6
|
+
module Databases
|
7
|
+
class UuidPrimaryKey < CLI::Base
|
8
|
+
def initialize
|
9
|
+
super()
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
repo_data = [[
|
14
|
+
"Repository",
|
15
|
+
"All tables have UUID primary keys",
|
16
|
+
"Comments",
|
17
|
+
"Audit Passed"
|
18
|
+
]
|
19
|
+
]
|
20
|
+
NeetoCompliance::NeetoRepos.products.keys.each do |repo|
|
21
|
+
ui.info "Checking #{repo}...", print_to_audit_log: false
|
22
|
+
code_audit_result = Neetob::CLI::Code::Audit.new([repo]).run[0]
|
23
|
+
if code_audit_result[:error]
|
24
|
+
repo_data << [repo, nil, code_audit_result[:error], "No"]
|
25
|
+
next
|
26
|
+
end
|
27
|
+
tables_without_uuid = code_audit_result[:tables_without_uuid]
|
28
|
+
tables_without_uuid.reject! { |table|
|
29
|
+
table == "data_migrations" ||
|
30
|
+
table == "server_side_sessions" ||
|
31
|
+
table.include?("solid_queue") ||
|
32
|
+
table.include?("active_storage")
|
33
|
+
}
|
34
|
+
all_tables_have_uuid_primary_keys = tables_without_uuid.empty? ? "Yes" : "No"
|
35
|
+
audit_passed = all_tables_have_uuid_primary_keys == "Yes" ? "Yes" : "No"
|
36
|
+
comments = tables_without_uuid.empty? ? nil : "Tables without UUID primary keys: #{tables_without_uuid.join(', ')}"
|
37
|
+
repo_data << [repo, all_tables_have_uuid_primary_keys, comments, audit_passed]
|
38
|
+
end
|
39
|
+
ui.print_table(repo_data)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neetob
|
4
|
+
class CLI
|
5
|
+
module MonthlyAudit
|
6
|
+
module InstancesAndAddons
|
7
|
+
module Cloudflare
|
8
|
+
class AlwaysUseHttpsIsEnabled < CLI::Base
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
ui.success "### 3.2.4. Checking whether always use HTTPS is enabled"
|
15
|
+
|
16
|
+
domains_data = [["Domain", "Always use HTTPS", "Audit Passed"]]
|
17
|
+
ui.info("\n", print_to_audit_log: false)
|
18
|
+
Neetob::CLI::Cloudflare::Base::ZONE_IDS.keys.select { |domain|
|
19
|
+
domain.to_s.include?(".com") }.map do |domain|
|
20
|
+
ui.info("Checking Always use HTTPS value for #{domain}", print_to_audit_log: false)
|
21
|
+
always_use_https_value = Neetob::CLI::Cloudflare::AlwaysUseHttps.new(domain).run
|
22
|
+
audit_passed = always_use_https_value.to_s == "on" ? "Yes" : "No"
|
23
|
+
domains_data << [domain, always_use_https_value, audit_passed]
|
24
|
+
end
|
25
|
+
ui.print_table(domains_data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neetob
|
4
|
+
class CLI
|
5
|
+
module MonthlyAudit
|
6
|
+
module InstancesAndAddons
|
7
|
+
module Cloudflare
|
8
|
+
class BotProtectionEnabled < CLI::Base
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
ui.success "### 3.2.6. Checking whether Bot Protection is enabled"
|
15
|
+
|
16
|
+
domains_data = [["Domain", "Bot protection", "Audit Passed"]]
|
17
|
+
ui.info("\n", print_to_audit_log: false)
|
18
|
+
Neetob::CLI::Cloudflare::Base::ZONE_IDS.keys.select { |domain|
|
19
|
+
domain.to_s.include?(".com") }.map do |domain|
|
20
|
+
bot_fight_mode = Neetob::CLI::Cloudflare::BotFightMode.new(domain).run
|
21
|
+
ui.info("Checking Bot fight mode for #{domain}", print_to_audit_log: false)
|
22
|
+
audit_passed = bot_fight_mode == "on" ? "Yes" : "No"
|
23
|
+
domains_data << [domain, bot_fight_mode, audit_passed]
|
24
|
+
end
|
25
|
+
ui.print_table(domains_data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neetob
|
4
|
+
class CLI
|
5
|
+
module MonthlyAudit
|
6
|
+
module InstancesAndAddons
|
7
|
+
module Cloudflare
|
8
|
+
class DnsEntryHasProxyStatus < CLI::Base
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
ui.success "### 3.2.2. Checking whether DNS entry has proxy status"
|
15
|
+
|
16
|
+
domains_data = [["Domain", "DNS proxy status", "Audit Passed"]]
|
17
|
+
ui.info("\n", print_to_audit_log: false)
|
18
|
+
Neetob::CLI::Cloudflare::Base::ZONE_IDS.keys.select { |domain|
|
19
|
+
domain.to_s.include?(".com") }.map do |domain|
|
20
|
+
ui.info("Checking proxy status for DNS entries for #{domain}", print_to_audit_log: false)
|
21
|
+
domain = domain.to_s
|
22
|
+
proxiable_records = Neetob::CLI::Cloudflare::DnsProxyStatus.new(domain).run
|
23
|
+
record_to_check = proxiable_records.select { |record| record[:name] == "*.#{domain}" }.first
|
24
|
+
if record_to_check.nil?
|
25
|
+
domains_data << [domain, "No * records found", "No"]
|
26
|
+
else
|
27
|
+
is_wildcard_subdomain_proxied = record_to_check[:proxied]
|
28
|
+
audit_passed = is_wildcard_subdomain_proxied ? "Yes" : "No"
|
29
|
+
proxy_status = is_wildcard_subdomain_proxied ? "on" : "off"
|
30
|
+
domains_data << [domain, "#{record_to_check[:name]} has proxying turned #{proxy_status}",
|
31
|
+
audit_passed]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
ui.print_table(domains_data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "ssl_tls_encryption_mode_set_to_full"
|
4
|
+
require_relative "dns_entry_has_proxy_status"
|
5
|
+
require_relative "minimum_tls_version_is_one_point_two"
|
6
|
+
require_relative "always_use_https_is_enabled"
|
7
|
+
require_relative "spf_records_are_valid"
|
8
|
+
require_relative "bot_protection_enabled"
|
9
|
+
|
10
|
+
module Neetob
|
11
|
+
class CLI
|
12
|
+
module MonthlyAudit
|
13
|
+
module InstancesAndAddons
|
14
|
+
module Cloudflare
|
15
|
+
class Main < CLI::Base
|
16
|
+
def initialize
|
17
|
+
super()
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
SslTlsEncryptionModeSetToFull.new.run
|
22
|
+
ui.info "\n"
|
23
|
+
DnsEntryHasProxyStatus.new.run
|
24
|
+
ui.info "\n"
|
25
|
+
MinimumTlsVersionIsOnePointTwo.new.run
|
26
|
+
ui.info "\n"
|
27
|
+
AlwaysUseHttpsIsEnabled.new.run
|
28
|
+
ui.info "\n"
|
29
|
+
SpfRecordsAreValid.new.run
|
30
|
+
ui.info "\n"
|
31
|
+
BotProtectionEnabled.new.run
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|